瀏覽代碼

Автодок: уйма вещей

Arthur Yefimov 2 年之前
父節點
當前提交
23ef84aba6
共有 9 個文件被更改,包括 174 次插入65 次删除
  1. 16 5
      src/Args.Mod
  2. 29 4
      src/Autodoc/Autodoc.Mod
  3. 19 11
      src/Autodoc/AutodocHtml.Mod
  4. 43 21
      src/Autodoc/AutodocParser.Mod
  5. 1 1
      src/Autodoc/Data/Langs/en.dat
  6. 1 1
      src/Autodoc/Data/Langs/ru.dat
  7. 47 19
      src/Dir.Mod
  8. 3 3
      src/Graph.Mod
  9. 15 0
      src/docs/generate_docs.sh

+ 16 - 5
src/Args.Mod

@@ -1,12 +1,15 @@
 MODULE Args;
 MODULE Args;
-(** Access to command line arguments *)
+(** Access to command line arguments
+%RU Доступ к аргументам командной строки *)
 IMPORT CmdArgs, Int, Utf8;
 IMPORT CmdArgs, Int, Utf8;
 
 
 TYPE SHORTCHAR = Utf8.SHORTCHAR;
 TYPE SHORTCHAR = Utf8.SHORTCHAR;
 VAR count: INTEGER;
 VAR count: INTEGER;
 
 
 (** Return the number of command line arguments.
 (** Return the number of command line arguments.
-     If Count() returns N, then you can call Get(x) with 0 <= x <= N. *)
+     If Count() returns N, then you can call Get(x) with 0 <= x <= N.
+%RU Возвращает количество аргументов командной строки.
+     Если Count() возвращает N, то можно вызвать Get(x), где 0 <= x <= N. *)
 PROCEDURE Count*(): INTEGER;
 PROCEDURE Count*(): INTEGER;
 BEGIN
 BEGIN
   IF count = -1 THEN count := CmdArgs.Count END
   IF count = -1 THEN count := CmdArgs.Count END
@@ -14,8 +17,14 @@ RETURN count END Count;
 
 
 (** Given the number `n` returns the nth argument as string `s`.
 (** Given the number `n` returns the nth argument as string `s`.
      `n` must be in range 0 <= n <= Count().
      `n` must be in range 0 <= n <= Count().
-     Argument 0 is the name of the program how it was executed.
-     The real arguments start with index 1 *)
+     Argument 0 is the name of the program as it was executed
+    from the console.
+     The proper arguments start with index 1
+%RU При заданном числе `n` возвращает n-й аргумент в виде строки `s`.
+     `n` должно находиться в диапазоне 0 <= n <= Count().
+     Аргумент 0 -- это имя программы в том виде, в котором она была запущена
+    из консоли.
+     Собственно аргументы начинаются с индекса 1 *)
 PROCEDURE Get*(n: INTEGER; VAR s: ARRAY OF CHAR);
 PROCEDURE Get*(n: INTEGER; VAR s: ARRAY OF CHAR);
 VAR q: ARRAY 4096 OF SHORTCHAR;
 VAR q: ARRAY 4096 OF SHORTCHAR;
 BEGIN
 BEGIN
@@ -24,7 +33,9 @@ BEGIN
 END Get;
 END Get;
 
 
 (** Given the number `n` returns the nth argument as integer `i`.
 (** Given the number `n` returns the nth argument as integer `i`.
-     If the argument is not a valid integer, returns 0 *)
+     If the argument is not a valid integer, returns 0
+%RU При заданном числе `n` возвращает n-й аргумент в виде целого числа `i`.
+     Если аргумент не является корректной записью целого числа, возвращает 0 *)
 PROCEDURE GetInt*(n: INTEGER): INTEGER;
 PROCEDURE GetInt*(n: INTEGER): INTEGER;
 VAR s: ARRAY 30 OF CHAR;
 VAR s: ARRAY 30 OF CHAR;
   i: INTEGER;
   i: INTEGER;

+ 29 - 4
src/Autodoc/Autodoc.Mod

@@ -91,7 +91,7 @@ BEGIN
   Out.String(' by Arthur Yefimov and others.'); Out.Ln;
   Out.String(' by Arthur Yefimov and others.'); Out.Ln;
   Out.String('Usage:'); Out.Ln; Args.Get(0, s);
   Out.String('Usage:'); Out.Ln; Args.Get(0, s);
   Out.String('  '); Out.String(s);
   Out.String('  '); Out.String(s);
-  Out.String(' { "-o" outputPath | "--lang" code | otherParam | sourceFile}');
+  Out.String(' {"-o" outputPath | "--lang" code | otherParam | sourceFile}');
   Out.Ln; Out.Ln;
   Out.Ln; Out.Ln;
   Out.String('outputPath may be a file name or a directory. It must be');
   Out.String('outputPath may be a file name or a directory. It must be');
   Out.Ln;
   Out.Ln;
@@ -106,12 +106,16 @@ BEGIN
   Out.Ln;
   Out.Ln;
   Out.String('           Put extension in the end to change it: Program/.cp');
   Out.String('           Put extension in the end to change it: Program/.cp');
   Out.Ln;
   Out.Ln;
-  Out.String('--pal <pal> .............. Supply a named palette.'); Out.Ln;
+  Out.String('--intro <intro> .......... Supply an introduction text file');
+  Out.Ln;
+  Out.String('--title   or'); Out.Ln;
+  Out.String('-t <title> ............... Supply the index page title'); Out.Ln;
+  Out.String('--pal <pal> .............. Supply a named palette'); Out.Ln;
   Out.String('  <pal> is one of: default, bw, horror'); Out.Ln;
   Out.String('  <pal> is one of: default, bw, horror'); Out.Ln;
   Out.String('--template <filename> .... Use <filename> as HTML-file'); Out.Ln;
   Out.String('--template <filename> .... Use <filename> as HTML-file'); Out.Ln;
   Out.String('  with placeholders: %TITLE% %HEADING% %MENU% %BODY% %DATE%');
   Out.String('  with placeholders: %TITLE% %HEADING% %MENU% %BODY% %DATE%');
   Out.Ln;
   Out.Ln;
-  Out.String('--debug .................. Produce debug output in console.');
+  Out.String('--debug .................. Produce debug output in console');
   Out.Ln; Out.Ln; Out.Ln;
   Out.Ln; Out.Ln; Out.Ln;
   Out.String('Examples:'); Out.Ln;
   Out.String('Examples:'); Out.Ln;
   Out.String('  '); Out.String(s);
   Out.String('  '); Out.String(s);
@@ -207,6 +211,23 @@ BEGIN
   IF i = len THEN Strings.Copy(s, m[i]); INC(len) END
   IF i = len THEN Strings.Copy(s, m[i]); INC(len) END
 END AddFname;
 END AddFname;
 
 
+PROCEDURE SetIntro(fname: ARRAY OF CHAR);
+VAR T: Texts.Text;
+  R: Texts.Reader;
+  ch: CHAR;
+  i: INTEGER;
+BEGIN
+  NEW(T); Texts.Open(T, fname);
+  Texts.OpenReader(R, T, 0);
+  Texts.Read(R, ch);
+  i := 0;
+  WHILE ~R.eot DO
+    IF i < LEN(indexComment) - 1 THEN indexComment[i] := ch; INC(i) END;
+    Texts.Read(R, ch)
+  END;
+  indexComment[i] := 0X
+END SetIntro;
+
 PROCEDURE Do;
 PROCEDURE Do;
 VAR i, count, len: INTEGER;
 VAR i, count, len: INTEGER;
   out, s: ARRAY 256 OF CHAR;
   out, s: ARRAY 256 OF CHAR;
@@ -236,9 +257,12 @@ BEGIN
       ELSIF (s = '--external-style') OR (s = '-e') THEN
       ELSIF (s = '--external-style') OR (s = '-e') THEN
         H.SetExternalStyle(TRUE)
         H.SetExternalStyle(TRUE)
       ELSIF (s = '--no-index') OR (s = '-n') THEN
       ELSIF (s = '--no-index') OR (s = '-n') THEN
-        createIndex := FALSE
+        createIndex := FALSE;
+        H.LinkToIndex(FALSE)
       ELSIF (s = '--title') OR (s = '-t') THEN
       ELSIF (s = '--title') OR (s = '-t') THEN
         IF i < count THEN INC(i); Args.Get(i, indexTitle); END
         IF i < count THEN INC(i); Args.Get(i, indexTitle); END
+      ELSIF (s = '--intro') OR (s = '-i') THEN
+        IF i < count THEN INC(i); Args.Get(i, s); SetIntro(s) END
       ELSIF s = '--pal' THEN
       ELSIF s = '--pal' THEN
         IF i < count THEN INC(i); Args.Get(i, s); H.SetPalette(s) END
         IF i < count THEN INC(i); Args.Get(i, s); H.SetPalette(s) END
       ELSIF s = '--template' THEN (* Template HTML file *)
       ELSIF s = '--template' THEN (* Template HTML file *)
@@ -272,6 +296,7 @@ BEGIN
       END
       END
     ELSE (* Single file given and "-o" is a file name *)
     ELSE (* Single file given and "-o" is a file name *)
       IF out[0] = 0X THEN FnameToHtml(fnames[0], out) END;
       IF out[0] = 0X THEN FnameToHtml(fnames[0], out) END;
+      H.LinkToIndex(FALSE);
       HandleFile(fnames[0], out)
       HandleFile(fnames[0], out)
     END
     END
   END
   END

+ 19 - 11
src/Autodoc/AutodocHtml.Mod

@@ -55,6 +55,7 @@ VAR
   (** Module names of modules to which <a href> will work *)
   (** Module names of modules to which <a href> will work *)
   linkMods: ARRAY 256 OF ARRAY 64 OF CHAR;
   linkMods: ARRAY 256 OF ARRAY 64 OF CHAR;
   linkModCount: INTEGER; (** Actual length of array linkMods *)
   linkModCount: INTEGER; (** Actual length of array linkMods *)
+  linkToIndex: BOOLEAN; (** TRUE if link to "Get Started" should be added *)
 
 
 (** List of Declared Names **)
 (** List of Declared Names **)
 
 
@@ -102,6 +103,10 @@ PROCEDURE ClearLinkMods*;
 BEGIN linkModCount := 0;
 BEGIN linkModCount := 0;
 END ClearLinkMods;
 END ClearLinkMods;
 
 
+PROCEDURE LinkToIndex*(yes: BOOLEAN);
+BEGIN linkToIndex := yes
+END LinkToIndex;
+
 (** Language **)
 (** Language **)
 
 
 PROCEDURE TryLoadLang(): BOOLEAN;
 PROCEDURE TryLoadLang(): BOOLEAN;
@@ -253,17 +258,20 @@ BEGIN
   WriteLn('</section>')
   WriteLn('</section>')
 END PrintComment;
 END PrintComment;
 
 
-PROCEDURE PrintModIndex(showIndex: BOOLEAN);
+(** If modName is an empty string, the index page is considered current *)
+PROCEDURE PrintModIndex(modName: ARRAY OF CHAR; showIndex: BOOLEAN);
 VAR i: INTEGER;
 VAR i: INTEGER;
   s: ARRAY 64 OF CHAR;
   s: ARRAY 64 OF CHAR;
 BEGIN
 BEGIN
   WriteLn('<ul class="modules-index">');
   WriteLn('<ul class="modules-index">');
-  IF showIndex THEN
-    Write('<li><a href="index.html">');
-    Lang.Get('indexLink', s); Write(s); WriteLn('</a></li>')
-  END;
+  Write('<li');
+  IF modName[0] = 0X THEN Write(' class="cur"') END;
+  Write('><a href="index.html">');
+  Lang.Get('indexLink', s); Write(s); WriteLn('</a></li>');
   FOR i := 0 TO linkModCount - 1 DO
   FOR i := 0 TO linkModCount - 1 DO
-    Write('<li><a href="'); Write(linkMods[i]); Write('.html">');
+    Write('<li');
+    IF linkMods[i] = modName THEN Write(' class="cur"') END;
+    Write('><a href="'); Write(linkMods[i]); Write('.html">');
     Write(linkMods[i]); WriteLn('</a></li>')
     Write(linkMods[i]); WriteLn('</a></li>')
   END;
   END;
   WriteLn('</ul>')
   WriteLn('</ul>')
@@ -607,7 +615,7 @@ BEGIN
 
 
   IF ~index THEN
   IF ~index THEN
     WriteLn('<nav class="module-menu">');
     WriteLn('<nav class="module-menu">');
-    PrintModIndex(TRUE);
+    PrintModIndex(modName, TRUE);
     WriteLn('</nav>')
     WriteLn('</nav>')
   END;
   END;
   WriteLn('</div></header>');
   WriteLn('</div></header>');
@@ -759,8 +767,8 @@ BEGIN
     ELSE Heading(M.name, FALSE)
     ELSE Heading(M.name, FALSE)
     END
     END
   ELSIF tag = 'MENU' THEN
   ELSIF tag = 'MENU' THEN
-    IF renderingIndex THEN PrintModIndex(FALSE)
-    ELSE PrintModIndex(TRUE)
+    IF renderingIndex THEN PrintModIndex('', FALSE)
+    ELSE PrintModIndex(M.name, TRUE)
     END
     END
   ELSIF tag = 'BODY' THEN
   ELSIF tag = 'BODY' THEN
     IF renderingIndex THEN PrintIndexComment
     IF renderingIndex THEN PrintIndexComment
@@ -952,7 +960,7 @@ BEGIN
     Write('<h2>');
     Write('<h2>');
     Lang.Get('indexHeading', s); Write(s);
     Lang.Get('indexHeading', s); Write(s);
     WriteLn('</h2>');
     WriteLn('</h2>');
-    PrintModIndex(FALSE);
+    PrintModIndex('', FALSE);
 
 
     Write('<h2>');
     Write('<h2>');
     Lang.Get('overview', s); Write(s);
     Lang.Get('overview', s); Write(s);
@@ -970,6 +978,6 @@ RETURN TRUE END CreateIndex;
 
 
 BEGIN
 BEGIN
   PrintObject := PrintObject0;
   PrintObject := PrintObject0;
-  externalStyle := FALSE;
+  externalStyle := FALSE; linkToIndex := TRUE;
   lang[0] := 0X; palette[0] := 0X; tpl[0] := 0X
   lang[0] := 0X; palette[0] := 0X; tpl[0] := 0X
 END AutodocHtml.
 END AutodocHtml.

+ 43 - 21
src/Autodoc/AutodocParser.Mod

@@ -374,13 +374,20 @@ END SaveAllComments;
     if lastLine is equal to the line where the comment started (= docLine).
     if lastLine is equal to the line where the comment started (= docLine).
      Parameter lastLine should be equal to the line number of the last symbol
      Parameter lastLine should be equal to the line number of the last symbol
     of the declaration (the semicolon), or -1 when saving a pre-comment.
     of the declaration (the semicolon), or -1 when saving a pre-comment.
-     See AppendComment for more info on what "the first comment" means. *)
+     See AppendComment for more info on what "the first comment" means.
+     If comment should be saved, but o = NIL, removes the comment from doc *)
 PROCEDURE SaveComment(o: Object; lastLine: INTEGER);
 PROCEDURE SaveComment(o: Object; lastLine: INTEGER);
+VAR s: ARRAY 4096 OF CHAR;
 BEGIN
 BEGIN
-  IF (o # NIL) & (doc[0] # 0X) & ((lastLine = -1) OR (docLine = lastLine)) THEN
-    IF o.comment[0] = 0X THEN AppendComment(o.comment)
-    ELSIF (lastLine = -1) OR (docLine = lastLine) THEN
-      Strings.Append(0AX, o.comment); AppendComment(o.comment)
+    Out.String('Save comment?'); Out.Int(docLine, 5); Out.Int(lastLine, 5);Out.Ln;
+  IF (doc[0] # 0X) & ((lastLine = -1) OR (docLine = lastLine)) THEN
+    Out.String('IN!');Out.Ln;
+    IF o # NIL THEN
+      IF o.comment[0] = 0X THEN AppendComment(o.comment)
+      ELSIF (lastLine = -1) OR (docLine = lastLine) THEN
+        Strings.Append(0AX, o.comment); AppendComment(o.comment)
+      END
+    ELSE AppendComment(s)
     END
     END
   END
   END
 END SaveComment;
 END SaveComment;
@@ -392,6 +399,7 @@ PROCEDURE Read;
 BEGIN
 BEGIN
   IF c = 0AX THEN INC(line); col := 0 END;
   IF c = 0AX THEN INC(line); col := 0 END;
   IF ~R.eof THEN Files.ReadChar(R, c); INC(col) ELSE c := 0X END
   IF ~R.eof THEN Files.ReadChar(R, c); INC(col) ELSE c := 0X END
+  ;Out.String('          READ[');Out.Char(c);Out.Char(']'); Out.Int(col, 0);Out.Ln;
 END Read;
 END Read;
 
 
 PROCEDURE IsLetter*(x: CHAR): BOOLEAN;
 PROCEDURE IsLetter*(x: CHAR): BOOLEAN;
@@ -522,7 +530,8 @@ BEGIN
   IF pre THEN
   IF pre THEN
     IF docLen < LEN(doc) - 4 THEN
     IF docLen < LEN(doc) - 4 THEN
       doc[docLen] := 0AX; INC(docLen); doc[docLen] := '`'; INC(docLen);
       doc[docLen] := 0AX; INC(docLen); doc[docLen] := '`'; INC(docLen);
-      doc[docLen] := '`'; INC(docLen); doc[docLen] := '`'; INC(docLen)
+      doc[docLen] := '`'; INC(docLen); doc[docLen] := '`'; INC(docLen);
+      doc[docLen] := 0X
     END;
     END;
     pre := FALSE
     pre := FALSE
   END
   END
@@ -549,15 +558,14 @@ BEGIN
       ELSE AppendDocChar(0AX)
       ELSE AppendDocChar(0AX)
       END
       END
     ELSIF c <= ' ' THEN AppendDocChar(' ')
     ELSIF c <= ' ' THEN AppendDocChar(' ')
-    ELSIF docNewLine & (c = '%') & (langMark < 0) THEN (* Begin of curLang mark *)
-      AppendDocChar(0AX); AppendDocChar(' ');
-      langMark := 0
+    ELSIF docNewLine & (c = '%') & (langMark < 0) THEN (* Begin curLang mark *)
+      AppendDocChar(0AX); AppendDocChar(' '); langMark := 0
     ELSIF docNewLine & (langMark >= 0) &
     ELSIF docNewLine & (langMark >= 0) &
           (('A' <= c) & (c <= 'Z') OR ('a' <= c) & (c <= 'z')) THEN
           (('A' <= c) & (c <= 'Z') OR ('a' <= c) & (c <= 'z')) THEN
       curLang[langMark] := CAP(c); INC(langMark); curLang[langMark] := 0X;
       curLang[langMark] := CAP(c); INC(langMark); curLang[langMark] := 0X;
       IF langMark = 2 THEN (* End of language mark *)
       IF langMark = 2 THEN (* End of language mark *)
         langMark := -1;
         langMark := -1;
-        IF curLang = lang THEN ClearComments END
+        IF curLang = lang THEN doc[0] := 0X; docLen := 0 END
       END;
       END;
       AppendDocChar(' ')
       AppendDocChar(' ')
     ELSE
     ELSE
@@ -567,7 +575,10 @@ BEGIN
           ELSE AppendDocChar(' ')
           ELSE AppendDocChar(' ')
           END
           END
         ELSIF col = docCol + 1 THEN EndPre; AppendDocChar(0AX)
         ELSIF col = docCol + 1 THEN EndPre; AppendDocChar(0AX)
-        ELSE DocTrimRight; AppendDocChar(0AX); BeginPre;
+        ELSE
+          Out.String('col, docCol ====== '); Out.Int(col, 0);
+          Out.String(', '); Out.Int(docCol, 0); Out.Ln;
+          DocTrimRight; AppendDocChar(0AX); BeginPre;
           FOR i := 1 TO col - docCol DO AppendDocChar(' ') END
           FOR i := 1 TO col - docCol DO AppendDocChar(' ') END
         END;
         END;
         docNewLine := FALSE
         docNewLine := FALSE
@@ -612,7 +623,9 @@ PROCEDURE ReadComment(toplevel: BOOLEAN);
 VAR closed, tmp: BOOLEAN;
 VAR closed, tmp: BOOLEAN;
   title: BOOLEAN;
   title: BOOLEAN;
 BEGIN
 BEGIN
-  IF toplevel & (docLen = 0) THEN docLine := line END;
+  Out.String('docLen = '); Out.Int(docLen, 0);Out.String(' <-------');Out.Ln;
+  IF toplevel & (docLen = 0) THEN docLine := line; Out.String('docline=');Out.Int(docLine,0);Out.Ln; END;
+
   Read; closed := FALSE; writingDoc := FALSE;
   Read; closed := FALSE; writingDoc := FALSE;
   docNewLine := FALSE; docCol := -1; pre := FALSE;
   docNewLine := FALSE; docCol := -1; pre := FALSE;
   curLang[0] := 0X; langMark := -1;
   curLang[0] := 0X; langMark := -1;
@@ -627,6 +640,8 @@ BEGIN
   IF ~closed THEN
   IF ~closed THEN
     WHILE (c # 0X) & (c = ' ') DO Read END;
     WHILE (c # 0X) & (c = ' ') DO Read END;
     docCol := col;
     docCol := col;
+    Out.String('>>>>> set docCol := '); Out.Int(docCol, 0);
+    Out.String(' (c = '); Out.Char(c); Out.Char(')'); Out.Ln;
     REPEAT
     REPEAT
       WHILE (c # 0X) & (c # '*') DO
       WHILE (c # 0X) & (c # '*') DO
         IF c = '(' THEN Read;
         IF c = '(' THEN Read;
@@ -664,6 +679,7 @@ BEGIN
     END
     END
   END;
   END;
   IF pre & writingDoc THEN EndPre END;
   IF pre & writingDoc THEN EndPre END;
+  ;Out.String(doc);Out.Ln;
   doc[docLen] := 0X
   doc[docLen] := 0X
 END ReadComment;
 END ReadComment;
 
 
@@ -1129,10 +1145,10 @@ END ConstructChar;
     cast to integer and stored in intVal. *)
     cast to integer and stored in intVal. *)
 PROCEDURE ParseConstExpr(VAR s: ARRAY OF CHAR;
 PROCEDURE ParseConstExpr(VAR s: ARRAY OF CHAR;
     VAR isOrdinal: BOOLEAN; VAR intVal: INTEGER);
     VAR isOrdinal: BOOLEAN; VAR intVal: INTEGER);
-VAR start, end, i: INTEGER;
+VAR start, end, i, tmpCol, tmpLine: INTEGER;
   x, tmpC: CHAR;
   x, tmpC: CHAR;
 BEGIN isOrdinal := FALSE; intVal := 0; i := 0; x := constExprBeginC;
 BEGIN isOrdinal := FALSE; intVal := 0; i := 0; x := constExprBeginC;
-  REPEAT end := Files.Pos(R); tmpC := c; GetSym
+  REPEAT end := Files.Pos(R); tmpC := c; tmpCol := col; tmpLine := line; GetSym
   UNTIL (sym = semicol) OR (sym = of) OR (sym = eot) OR (sym = comma);
   UNTIL (sym = semicol) OR (sym = of) OR (sym = eot) OR (sym = comma);
   IF sym # eot THEN
   IF sym # eot THEN
     IF constExprBeginPos < end THEN
     IF constExprBeginPos < end THEN
@@ -1147,8 +1163,8 @@ BEGIN isOrdinal := FALSE; intVal := 0; i := 0; x := constExprBeginC;
       UNTIL Files.Pos(R) >= end;
       UNTIL Files.Pos(R) >= end;
       IF i > 0 THEN DEC(i) END
       IF i > 0 THEN DEC(i) END
     END;
     END;
-    Files.Set(R, Files.Base(R), end); c := tmpC;
-    IF col # 0 THEN DEC(col) END;
+    Files.Set(R, Files.Base(R), end);
+    c := tmpC; col := tmpCol; line := tmpLine;
     GetSym
     GetSym
   END;
   END;
   WHILE (i # 1) & (s[i - 1] <= ' ') DO DEC(i) END;
   WHILE (i # 1) & (s[i - 1] <= ' ') DO DEC(i) END;
@@ -1191,7 +1207,12 @@ BEGIN L := NewList(); stop := FALSE;
       WHILE x # NIL DO x(Var).type := T; x := x.next END
       WHILE x # NIL DO x(Var).type := T; x := x.next END
     END;
     END;
     IF (sym = semicol) OR ~isVarDecl THEN line2 := line;
     IF (sym = semicol) OR ~isVarDecl THEN line2 := line;
-      IF sym = semicol THEN GetSym; SaveComment(first, line2)
+      IF sym = semicol THEN GetSym;
+      ;Out.String('line2=');Out.Int(line2, 0);Out.Ln;
+      SaveComment(first, line2)
+      ;IF first = NIL THEN Out.String('first IS NIL'); Out.Ln; ELSE
+      ;Out.String('first.comment=');Out.String(first.comment);Out.Ln;
+      END;
       ELSE stop := TRUE; SaveAllComments(first)
       ELSE stop := TRUE; SaveAllComments(first)
       END;
       END;
       IF (first # NIL) & (first.comment[0] # 0X) THEN x := first.next;
       IF (first # NIL) & (first.comment[0] # 0X) THEN x := first.next;
@@ -1310,7 +1331,10 @@ VAR T, T1: Type;
   isInt: BOOLEAN;
   isInt: BOOLEAN;
   tmp: INTEGER;
   tmp: INTEGER;
 BEGIN ASSERT(sym = array);
 BEGIN ASSERT(sym = array);
-  constExprBeginPos := Files.Pos(R); constExprBeginC := c; GetSym;
+  constExprBeginPos := Files.Pos(R); constExprBeginC := c;
+  Out.String('constExprBeginPos=');Out.Int(constExprBeginPos, 0);
+  Out.String('   constExprBeginC='); Out.Char(c);Out.Ln;
+  GetSym;
   T := NewType(arrayType); T1 := T; CheckDirective(T);
   T := NewType(arrayType); T1 := T; CheckDirective(T);
   IF (sym # of) THEN
   IF (sym # of) THEN
     ParseConstExpr(T.len, isInt, tmp)
     ParseConstExpr(T.len, isInt, tmp)
@@ -1595,11 +1619,9 @@ END SortGroups;
 PROCEDURE SortModule(M: Module);
 PROCEDURE SortModule(M: Module);
 BEGIN
 BEGIN
   SortGroups(M.consts);
   SortGroups(M.consts);
-  (*
   SortGroups(M.vars);
   SortGroups(M.vars);
-  SortGroups(M.types);
+  (* SortGroups(M.types); *)
   SortGroups(M.procedures)
   SortGroups(M.procedures)
-  *)
 END SortModule;
 END SortModule;
 
 
 PROCEDURE ParseModule*(VAR r: Files.Rider; VAR err: ARRAY OF CHAR): Module;
 PROCEDURE ParseModule*(VAR r: Files.Rider; VAR err: ARRAY OF CHAR): Module;

+ 1 - 1
src/Autodoc/Data/Langs/en.dat

@@ -18,7 +18,7 @@ headingSubtitle "Reference"
 indexHeadingSubtitle "Library Reference"
 indexHeadingSubtitle "Library Reference"
 overview "Overview"
 overview "Overview"
 sectionEmpty "This section is empty."
 sectionEmpty "This section is empty."
-indexLink "Main Page"
+indexLink "Get Started"
 
 
 tableColName "Name"
 tableColName "Name"
 tableColValue "Value"
 tableColValue "Value"

+ 1 - 1
src/Autodoc/Data/Langs/ru.dat

@@ -18,7 +18,7 @@ headingSubtitle "Справочный лист"
 indexHeadingSubtitle "Документация к библиотеке"
 indexHeadingSubtitle "Документация к библиотеке"
 overview "Введение"
 overview "Введение"
 sectionEmpty "Этот раздел пуст."
 sectionEmpty "Этот раздел пуст."
-indexLink "Главный лист"
+indexLink "Начало"
 
 
 tableColName "Имя"
 tableColName "Имя"
 tableColValue "Значение"
 tableColValue "Значение"

+ 47 - 19
src/Dir.Mod

@@ -1,5 +1,6 @@
 MODULE Dir;
 MODULE Dir;
-(** This module includes procedures to read directory contents. *)
+(** This module includes procedures to read directory contents.
+%RU Этот модуль включает в себя процедуры для чтения содержимого каталога. *)
 IMPORT SYSTEM, Platform, Out, Utf8;
 IMPORT SYSTEM, Platform, Out, Utf8;
 
 
 TYPE
 TYPE
@@ -11,32 +12,45 @@ TYPE
   INT32 = SYSTEM.INT32;
   INT32 = SYSTEM.INT32;
 
 
   (** Directory rider record. Holds data of a single file or directory
   (** Directory rider record. Holds data of a single file or directory
-      entry while reading contents of a directory. *)
+      entry while reading contents of a directory.
+%RU   Запись бегунка по каталогу. Содержит данные одного файла или входа в
+      каталог при чтении содержимого каталога. *)
   Rec* = RECORD
   Rec* = RECORD
-    eod*: BOOLEAN; (** TRUE if end of directory is reached *)
-    isDir*: BOOLEAN; (** TRUE if current entry is a directory *)
-    res*: INTEGER; (** Result. 0 means no error *)
-    name*: ARRAY 512 OF CHAR; (** File or directory name *)
-    path: ARRAY 1024 OF CHAR;
+    eod*: BOOLEAN; (** TRUE if end of directory is reached
+%RU                    TRUE, если достигнут конец каталога *)
+    isDir*: BOOLEAN; (** TRUE if current entry is a directory
+%RU                      TRUE, если текущая запись является каталогом *)
+    res*: INTEGER; (** Result. 0 means no error
+%RU                    Результат. 0 означает отсутствие ошибки *)
+    name*: ARRAY 512 OF CHAR; (** File or directory name
+%RU                               Имя файла или каталога *)
+    path*: ARRAY 1024 OF CHAR; (** HELLO
+%RU                                ПРИВЕТ *)
     pathlen: INTEGER;
     pathlen: INTEGER;
     dir: DIR
     dir: DIR
   END;
   END;
 
 
 PROCEDURE -AAincludeDirent "#include <dirent.h>";
 PROCEDURE -AAincludeDirent "#include <dirent.h>";
 
 
-PROCEDURE -opendir(name: ARRAY OF SHORTCHAR): DIR "(SYSTEM_ADRINT) opendir((const char *)name)";
+PROCEDURE -opendir(name: ARRAY OF SHORTCHAR): DIR
+  "(SYSTEM_ADRINT) opendir((const char *)name)";
 PROCEDURE -closedir(dir: DIR) "closedir((DIR*) dir)";
 PROCEDURE -closedir(dir: DIR) "closedir((DIR*) dir)";
 PROCEDURE -readdir(dir: DIR): DIRENT "(SYSTEM_ADRINT) readdir((DIR*) dir)";
 PROCEDURE -readdir(dir: DIR): DIRENT "(SYSTEM_ADRINT) readdir((DIR*) dir)";
 PROCEDURE -rewinddir(dir: DIR) "rewinddir((DIR*) dir)";
 PROCEDURE -rewinddir(dir: DIR) "rewinddir((DIR*) dir)";
-PROCEDURE -getdirname(ent: DIRENT): PString "(CHAR *)(((struct dirent *) ent) -> d_name)";
-PROCEDURE -getdirtype(ent: DIRENT): INT32 "(int)((struct dirent *) ent) -> d_type)";
+PROCEDURE -getdirname(ent: DIRENT): PString
+  "(CHAR *)(((struct dirent *) ent) -> d_name)";
+PROCEDURE -getdirtype(ent: DIRENT): INT32
+  "(int)((struct dirent *) ent) -> d_type)";
 PROCEDURE -typeDir "DT_DIR";
 PROCEDURE -typeDir "DT_DIR";
 PROCEDURE -typeReg "DT_REG";
 PROCEDURE -typeReg "DT_REG";
 PROCEDURE -typeLink "DT_LNK";
 PROCEDURE -typeLink "DT_LNK";
 
 
 (** Close a directory.
 (** Close a directory.
      MUST BE CALLED to avoid leaking C directory streams.
      MUST BE CALLED to avoid leaking C directory streams.
-     !TODO add this to finalization *)
+     !TODO add this to finalization
+%RU Закрыть каталог.
+     ДОЛЖЕН БЫТЬ ВЫЗВАН, чтобы избежать утечки потоков каталога C.
+     !TODO добавить это в финализацию *)
 PROCEDURE Close*(VAR r: Rec);
 PROCEDURE Close*(VAR r: Rec);
 BEGIN
 BEGIN
   IF r.dir # 0 THEN closedir(r.dir); r.dir := 0 END
   IF r.dir # 0 THEN closedir(r.dir); r.dir := 0 END
@@ -51,7 +65,10 @@ END CopyToArray;
 
 
 (** Reads the next directory entry after the one refered by `r`.
 (** Reads the next directory entry after the one refered by `r`.
      First call `First(r, path)` with the same `r` and a path to a directory.
      First call `First(r, path)` with the same `r` and a path to a directory.
-    Then use `r.eod` and `Next(r)` to iterate all of the entries. *)
+    Then use `r.eod` and `Next(r)` to iterate through the entries.
+%RU Читает следующую запись каталога после той, на которую ссылается `r`.
+     Сначала вызовите `First(r, path)` с тем же `r` и путем к каталогу.
+    Затем используйте `r.eod` и `Next(r)` для перебора записей. *)
 PROCEDURE Next*(VAR r: Rec);
 PROCEDURE Next*(VAR r: Rec);
 VAR ent: DIRENT;
 VAR ent: DIRENT;
   i, j: INTEGER;
   i, j: INTEGER;
@@ -66,7 +83,6 @@ BEGIN
 
 
       (* To set the value of r.isDir, we (maybe) append '/' and name to path,
       (* To set the value of r.isDir, we (maybe) append '/' and name to path,
          pass it to DirExists and then restore the original value of path. *)
          pass it to DirExists and then restore the original value of path. *)
-
       i := 0; j := r.pathlen;
       i := 0; j := r.pathlen;
       IF r.path[j] # Platform.PathDelimiter THEN
       IF r.path[j] # Platform.PathDelimiter THEN
         r.path[j] := Platform.PathDelimiter; INC(j)
         r.path[j] := Platform.PathDelimiter; INC(j)
@@ -92,7 +108,13 @@ END Next;
      After the call to First the directory entry rider `r` holds data
      After the call to First the directory entry rider `r` holds data
     about the first entry of the directory at `path`. Check if `r.res = 0`
     about the first entry of the directory at `path`. Check if `r.res = 0`
     to make sure `First` was successful. Use `Next` with the same `r` and
     to make sure `First` was successful. Use `Next` with the same `r` and
-    used check `r.eod` to see when it is time to stop reading the directory. *)
+    used check `r.eod` to see when it is time to stop reading the directory.
+%RU Инициирует чтение каталога с заданным путем.
+     При вызове First в бегунок (по каталогу) `r` записываются данные о
+    первой записи каталога по адресу `path`. Проверьте, что `r.res = 0`, чтобы
+    убедиться, что вызов `First` прошёл успешно. Для перехода к следующей
+    записи используйте `Next` с тем же `r`. Проверяйте `r.eod`, чтобы узнать,
+    когда чтение каталога пора прекратить. *)
 PROCEDURE First*(VAR r: Rec; path: ARRAY OF CHAR);
 PROCEDURE First*(VAR r: Rec; path: ARRAY OF CHAR);
 VAR i: INTEGER;
 VAR i: INTEGER;
   s: ARRAY 2048 OF SHORTCHAR;
   s: ARRAY 2048 OF SHORTCHAR;
@@ -100,7 +122,8 @@ BEGIN r.isDir := FALSE; r.name[0] := 0X;
   i := 0; WHILE path[i] # 0X DO INC(i) END;
   i := 0; WHILE path[i] # 0X DO INC(i) END;
   IF i < LEN(r.path) - 13 THEN
   IF i < LEN(r.path) - 13 THEN
     IF path[0] = 0X THEN r.dir := opendir('.'); r.path := './'; r.pathlen := 2
     IF path[0] = 0X THEN r.dir := opendir('.'); r.path := './'; r.pathlen := 2
-    ELSE Utf8.Encode(path, s); r.dir := opendir(s); r.path := path; r.pathlen := i
+    ELSE Utf8.Encode(path, s); r.dir := opendir(s);
+      r.path := path; r.pathlen := i
     END;
     END;
     IF r.dir # 0 THEN r.eod := FALSE; Next(r)
     IF r.dir # 0 THEN r.eod := FALSE; Next(r)
     ELSE r.res := 1; r.eod := TRUE; r.path[0] := 0X
     ELSE r.res := 1; r.eod := TRUE; r.path[0] := 0X
@@ -109,7 +132,9 @@ BEGIN r.isDir := FALSE; r.name[0] := 0X;
   END
   END
 END First;
 END First;
 
 
-(** Start reading directory contents from the beginning. *)
+(** Starts reading directory contents from the beginning.
+%RU Перематывает бегунок так, что чтение записей в каталоге начинается
+    с самого начала. *)
 PROCEDURE Rewind*(VAR r: Rec);
 PROCEDURE Rewind*(VAR r: Rec);
 BEGIN
 BEGIN
   IF r.dir # 0 THEN rewinddir(r.dir); r.res := 0; r.eod := FALSE; Next(r)
   IF r.dir # 0 THEN rewinddir(r.dir); r.res := 0; r.eod := FALSE; Next(r)
@@ -117,19 +142,22 @@ BEGIN
   END
   END
 END Rewind;
 END Rewind;
 
 
-(** Returns TRUE if the file with the given name exists. *)
+(** Returns TRUE if the file with the given name exists.
+%RU Возвращает TRUE, если файл с данным именем существует. *)
 PROCEDURE FileExists*(name: ARRAY OF CHAR): BOOLEAN;
 PROCEDURE FileExists*(name: ARRAY OF CHAR): BOOLEAN;
 VAR s: ARRAY 2048 OF SYSTEM.CHAR8;
 VAR s: ARRAY 2048 OF SYSTEM.CHAR8;
 BEGIN Utf8.Encode(name, s)
 BEGIN Utf8.Encode(name, s)
 RETURN Platform.FileExists(s) END FileExists;
 RETURN Platform.FileExists(s) END FileExists;
 
 
-(** Returns TRUE if the given file name refers to a directory. *)
+(** Returns TRUE if the given file name refers to a directory.
+%RU Возвращает TRUE, если данное имя файла относится к каталогу. *)
 PROCEDURE IsDir*(name: ARRAY OF CHAR): BOOLEAN;
 PROCEDURE IsDir*(name: ARRAY OF CHAR): BOOLEAN;
 VAR s: ARRAY 2048 OF SYSTEM.CHAR8;
 VAR s: ARRAY 2048 OF SYSTEM.CHAR8;
 BEGIN Utf8.Encode(name, s)
 BEGIN Utf8.Encode(name, s)
 RETURN (name[0] = 0X) OR Platform.DirExists(s) END IsDir;
 RETURN (name[0] = 0X) OR Platform.DirExists(s) END IsDir;
 
 
-(** Returns a full path to the current working directory. *)
+(** Returns a full path to the current working directory.
+%RU Возвращает полный путь к текущему рабочему каталогу. *)
 PROCEDURE GetCwd*(VAR dir: ARRAY OF CHAR);
 PROCEDURE GetCwd*(VAR dir: ARRAY OF CHAR);
 VAR i: INTEGER;
 VAR i: INTEGER;
 BEGIN i := 0;
 BEGIN i := 0;

+ 3 - 3
src/Graph.Mod

@@ -208,10 +208,10 @@ TYPE
   Window* = POINTER TO WindowDesc;
   Window* = POINTER TO WindowDesc;
   WindowDesc* = RECORD(BitmapDesc) (** This is a window. *)
   WindowDesc* = RECORD(BitmapDesc) (** This is a window. *)
     display: Al.Display; (** Allegro Display *)
     display: Al.Display; (** Allegro Display *)
-    winW, winH: INTEGER; (** Window size in real pixels *)
-    initX*, initY: INTEGER; (** Window position upon its creation *)
+    winW, winH*: INTEGER; (** Window size in real pixels *)
+    initX*, initY*: INTEGER; (** Window position upon its creation *)
     initW, initH: INTEGER; (** Window size upon its creation *)
     initW, initH: INTEGER; (** Window size upon its creation *)
-    fsW, fsH*: INTEGER; (** Window size upon its creation *)
+    fsW*, fsH*: INTEGER; (** Fullscreen size *)
     wantZoom: REAL; (** Window zoom upon its creation *)
     wantZoom: REAL; (** Window zoom upon its creation *)
     lastX, lastY: INTEGER; (** Last mouse position in virtual pixels *)
     lastX, lastY: INTEGER; (** Last mouse position in virtual pixels *)
     lastW, lastH: INTEGER; (** Last stepped size in virtual pixels *)
     lastW, lastH: INTEGER; (** Last stepped size in virtual pixels *)

+ 15 - 0
src/docs/generate_docs.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+
+OUTPATH=/var/www/freeoberon
+OUTPATH_ru=$OUTPATH/docs
+OUTPATH_en=$OUTPATH/en/docs
+MODULES="Args.Mod Dir.Mod Env.Mod Files.Mod Graph.Mod In.Mod Int.Mod Out.Mod \
+  OV.Mod Random.Mod Reals.Mod Strings.Mod TermBox.Mod \
+  Term.Mod Texts.Mod Time.Mod Utf8.Mod"
+
+cd ..
+Autodoc -o $OUTPATH_ru --template $OUTPATH_ru/TEMPLATE.html \
+  -t "Фри Оберон" --lang ru -i docs/INTRO.html $MODULES
+Autodoc -o $OUTPATH_en --template $OUTPATH_en/TEMPLATE.html \
+  -t "Free Oberon" --lang en -i docs/INTRO_en.html $MODULES
+cd docs