瀏覽代碼

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

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;
-(** Access to command line arguments *)
+(** Access to command line arguments
+%RU Доступ к аргументам командной строки *)
 IMPORT CmdArgs, Int, Utf8;
 
 TYPE SHORTCHAR = Utf8.SHORTCHAR;
 VAR count: INTEGER;
 
 (** 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;
 BEGIN
   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`.
      `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);
 VAR q: ARRAY 4096 OF SHORTCHAR;
 BEGIN
@@ -24,7 +33,9 @@ BEGIN
 END Get;
 
 (** 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;
 VAR s: ARRAY 30 OF CHAR;
   i: INTEGER;

+ 29 - 4
src/Autodoc/Autodoc.Mod

@@ -91,7 +91,7 @@ BEGIN
   Out.String(' by Arthur Yefimov and others.'); Out.Ln;
   Out.String('Usage:'); Out.Ln; Args.Get(0, 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.String('outputPath may be a file name or a directory. It must be');
   Out.Ln;
@@ -106,12 +106,16 @@ BEGIN
   Out.Ln;
   Out.String('           Put extension in the end to change it: Program/.cp');
   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('--template <filename> .... Use <filename> as HTML-file'); Out.Ln;
   Out.String('  with placeholders: %TITLE% %HEADING% %MENU% %BODY% %DATE%');
   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.String('Examples:'); Out.Ln;
   Out.String('  '); Out.String(s);
@@ -207,6 +211,23 @@ BEGIN
   IF i = len THEN Strings.Copy(s, m[i]); INC(len) END
 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;
 VAR i, count, len: INTEGER;
   out, s: ARRAY 256 OF CHAR;
@@ -236,9 +257,12 @@ BEGIN
       ELSIF (s = '--external-style') OR (s = '-e') THEN
         H.SetExternalStyle(TRUE)
       ELSIF (s = '--no-index') OR (s = '-n') THEN
-        createIndex := FALSE
+        createIndex := FALSE;
+        H.LinkToIndex(FALSE)
       ELSIF (s = '--title') OR (s = '-t') THEN
         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
         IF i < count THEN INC(i); Args.Get(i, s); H.SetPalette(s) END
       ELSIF s = '--template' THEN (* Template HTML file *)
@@ -272,6 +296,7 @@ BEGIN
       END
     ELSE (* Single file given and "-o" is a file name *)
       IF out[0] = 0X THEN FnameToHtml(fnames[0], out) END;
+      H.LinkToIndex(FALSE);
       HandleFile(fnames[0], out)
     END
   END

+ 19 - 11
src/Autodoc/AutodocHtml.Mod

@@ -55,6 +55,7 @@ VAR
   (** Module names of modules to which <a href> will work *)
   linkMods: ARRAY 256 OF ARRAY 64 OF CHAR;
   linkModCount: INTEGER; (** Actual length of array linkMods *)
+  linkToIndex: BOOLEAN; (** TRUE if link to "Get Started" should be added *)
 
 (** List of Declared Names **)
 
@@ -102,6 +103,10 @@ PROCEDURE ClearLinkMods*;
 BEGIN linkModCount := 0;
 END ClearLinkMods;
 
+PROCEDURE LinkToIndex*(yes: BOOLEAN);
+BEGIN linkToIndex := yes
+END LinkToIndex;
+
 (** Language **)
 
 PROCEDURE TryLoadLang(): BOOLEAN;
@@ -253,17 +258,20 @@ BEGIN
   WriteLn('</section>')
 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;
   s: ARRAY 64 OF CHAR;
 BEGIN
   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
-    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>')
   END;
   WriteLn('</ul>')
@@ -607,7 +615,7 @@ BEGIN
 
   IF ~index THEN
     WriteLn('<nav class="module-menu">');
-    PrintModIndex(TRUE);
+    PrintModIndex(modName, TRUE);
     WriteLn('</nav>')
   END;
   WriteLn('</div></header>');
@@ -759,8 +767,8 @@ BEGIN
     ELSE Heading(M.name, FALSE)
     END
   ELSIF tag = 'MENU' THEN
-    IF renderingIndex THEN PrintModIndex(FALSE)
-    ELSE PrintModIndex(TRUE)
+    IF renderingIndex THEN PrintModIndex('', FALSE)
+    ELSE PrintModIndex(M.name, TRUE)
     END
   ELSIF tag = 'BODY' THEN
     IF renderingIndex THEN PrintIndexComment
@@ -952,7 +960,7 @@ BEGIN
     Write('<h2>');
     Lang.Get('indexHeading', s); Write(s);
     WriteLn('</h2>');
-    PrintModIndex(FALSE);
+    PrintModIndex('', FALSE);
 
     Write('<h2>');
     Lang.Get('overview', s); Write(s);
@@ -970,6 +978,6 @@ RETURN TRUE END CreateIndex;
 
 BEGIN
   PrintObject := PrintObject0;
-  externalStyle := FALSE;
+  externalStyle := FALSE; linkToIndex := TRUE;
   lang[0] := 0X; palette[0] := 0X; tpl[0] := 0X
 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).
      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.
-     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);
+VAR s: ARRAY 4096 OF CHAR;
 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 SaveComment;
@@ -392,6 +399,7 @@ PROCEDURE Read;
 BEGIN
   IF c = 0AX THEN INC(line); col := 0 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;
 
 PROCEDURE IsLetter*(x: CHAR): BOOLEAN;
@@ -522,7 +530,8 @@ BEGIN
   IF pre THEN
     IF docLen < LEN(doc) - 4 THEN
       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;
     pre := FALSE
   END
@@ -549,15 +558,14 @@ BEGIN
       ELSE AppendDocChar(0AX)
       END
     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) &
           (('A' <= c) & (c <= 'Z') OR ('a' <= c) & (c <= 'z')) THEN
       curLang[langMark] := CAP(c); INC(langMark); curLang[langMark] := 0X;
       IF langMark = 2 THEN (* End of language mark *)
         langMark := -1;
-        IF curLang = lang THEN ClearComments END
+        IF curLang = lang THEN doc[0] := 0X; docLen := 0 END
       END;
       AppendDocChar(' ')
     ELSE
@@ -567,7 +575,10 @@ BEGIN
           ELSE AppendDocChar(' ')
           END
         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
         END;
         docNewLine := FALSE
@@ -612,7 +623,9 @@ PROCEDURE ReadComment(toplevel: BOOLEAN);
 VAR closed, tmp: BOOLEAN;
   title: BOOLEAN;
 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;
   docNewLine := FALSE; docCol := -1; pre := FALSE;
   curLang[0] := 0X; langMark := -1;
@@ -627,6 +640,8 @@ BEGIN
   IF ~closed THEN
     WHILE (c # 0X) & (c = ' ') DO Read END;
     docCol := col;
+    Out.String('>>>>> set docCol := '); Out.Int(docCol, 0);
+    Out.String(' (c = '); Out.Char(c); Out.Char(')'); Out.Ln;
     REPEAT
       WHILE (c # 0X) & (c # '*') DO
         IF c = '(' THEN Read;
@@ -664,6 +679,7 @@ BEGIN
     END
   END;
   IF pre & writingDoc THEN EndPre END;
+  ;Out.String(doc);Out.Ln;
   doc[docLen] := 0X
 END ReadComment;
 
@@ -1129,10 +1145,10 @@ END ConstructChar;
     cast to integer and stored in intVal. *)
 PROCEDURE ParseConstExpr(VAR s: ARRAY OF CHAR;
     VAR isOrdinal: BOOLEAN; VAR intVal: INTEGER);
-VAR start, end, i: INTEGER;
+VAR start, end, i, tmpCol, tmpLine: INTEGER;
   x, tmpC: CHAR;
 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);
   IF sym # eot THEN
     IF constExprBeginPos < end THEN
@@ -1147,8 +1163,8 @@ BEGIN isOrdinal := FALSE; intVal := 0; i := 0; x := constExprBeginC;
       UNTIL Files.Pos(R) >= end;
       IF i > 0 THEN DEC(i) 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
   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
     END;
     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)
       END;
       IF (first # NIL) & (first.comment[0] # 0X) THEN x := first.next;
@@ -1310,7 +1331,10 @@ VAR T, T1: Type;
   isInt: BOOLEAN;
   tmp: INTEGER;
 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);
   IF (sym # of) THEN
     ParseConstExpr(T.len, isInt, tmp)
@@ -1595,11 +1619,9 @@ END SortGroups;
 PROCEDURE SortModule(M: Module);
 BEGIN
   SortGroups(M.consts);
-  (*
   SortGroups(M.vars);
-  SortGroups(M.types);
+  (* SortGroups(M.types); *)
   SortGroups(M.procedures)
-  *)
 END SortModule;
 
 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"
 overview "Overview"
 sectionEmpty "This section is empty."
-indexLink "Main Page"
+indexLink "Get Started"
 
 tableColName "Name"
 tableColValue "Value"

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

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

+ 47 - 19
src/Dir.Mod

@@ -1,5 +1,6 @@
 MODULE Dir;
-(** This module includes procedures to read directory contents. *)
+(** This module includes procedures to read directory contents.
+%RU Этот модуль включает в себя процедуры для чтения содержимого каталога. *)
 IMPORT SYSTEM, Platform, Out, Utf8;
 
 TYPE
@@ -11,32 +12,45 @@ TYPE
   INT32 = SYSTEM.INT32;
 
   (** 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
-    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;
     dir: DIR
   END;
 
 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 -readdir(dir: DIR): DIRENT "(SYSTEM_ADRINT) readdir((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 -typeReg "DT_REG";
 PROCEDURE -typeLink "DT_LNK";
 
 (** Close a directory.
      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);
 BEGIN
   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`.
      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);
 VAR ent: DIRENT;
   i, j: INTEGER;
@@ -66,7 +83,6 @@ BEGIN
 
       (* 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. *)
-
       i := 0; j := r.pathlen;
       IF r.path[j] # Platform.PathDelimiter THEN
         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
     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
-    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);
 VAR i: INTEGER;
   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;
   IF i < LEN(r.path) - 13 THEN
     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;
     IF r.dir # 0 THEN r.eod := FALSE; Next(r)
     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 First;
 
-(** Start reading directory contents from the beginning. *)
+(** Starts reading directory contents from the beginning.
+%RU Перематывает бегунок так, что чтение записей в каталоге начинается
+    с самого начала. *)
 PROCEDURE Rewind*(VAR r: Rec);
 BEGIN
   IF r.dir # 0 THEN rewinddir(r.dir); r.res := 0; r.eod := FALSE; Next(r)
@@ -117,19 +142,22 @@ BEGIN
   END
 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;
 VAR s: ARRAY 2048 OF SYSTEM.CHAR8;
 BEGIN Utf8.Encode(name, s)
 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;
 VAR s: ARRAY 2048 OF SYSTEM.CHAR8;
 BEGIN Utf8.Encode(name, s)
 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);
 VAR i: INTEGER;
 BEGIN i := 0;

+ 3 - 3
src/Graph.Mod

@@ -208,10 +208,10 @@ TYPE
   Window* = POINTER TO WindowDesc;
   WindowDesc* = RECORD(BitmapDesc) (** This is a window. *)
     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 *)
-    fsW, fsH*: INTEGER; (** Window size upon its creation *)
+    fsW*, fsH*: INTEGER; (** Fullscreen size *)
     wantZoom: REAL; (** Window zoom upon its creation *)
     lastX, lastY: INTEGER; (** Last mouse position 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