home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 24 / CD_ASCQ_24_0995.iso / dos / tools / inter47 / int2whlp / int2whlp.pas < prev    next >
Pascal/Delphi Source File  |  1995-07-31  |  46KB  |  1,303 lines

  1. (*
  2.   Interrupt List -> WinHelp converter (c) 1994 by Christian Müller-Planitz
  3.   ------------------------------------------------------------------------
  4.   e-mail address: see CONST "e_mail"
  5.  
  6.  
  7.   The source and the compiled EXE-file can be freely distributed as long as
  8.   no changes are made without my knowledge.
  9.  
  10.   --------------------------------
  11.   Notes:
  12.    The program was tested with INTLIST38 and INTLIST39 and its output
  13.      was successfully compiled with the MS-Help-compiler "HC31.EXE" V3.10.445.
  14.  
  15.    The program needs the file "INTWHLP.DAT" in the 'source' directory.
  16.  
  17.    The program converted all sourcefiles (INTERRUP.* and *.LST) to
  18.      13 RTF files which needed 11MB on my harddrive.
  19.  
  20.    Compiling the RTF-files without compression took 13 minutes in
  21.      a DOS-Window under Win/NT on a 486-50 (if you run it under DOS
  22.      and if you have a fast hardrive cache, it might be faster).
  23.  
  24.    The (uncompressed) compiled HLP-File was approximately 7MB large.
  25.    If you want to create a compressed HLP-file, you have to exchange the
  26.      comments in the generated help-project file ("RB.HPJ"). Compressing
  27.      reduces the size of the HLP-file to 3MB but it takes
  28.      *more* (?? 28MB ??)  space on your harddrive while compiling.
  29.      In order to speed up compiling the compressed file, I've included a
  30.      temporary file ("INTWIN.PH") of the helpcompiler in this archive.
  31.      Copy this file into the directory containing all the RTF files
  32.      before starting the compiler. This file is specific for INTERLIST39, so
  33.      if you want to get maximal compression in future versions, remove it.
  34.  
  35.    After the compilation finishes, you will find the file "INTWIN.HLP".
  36.      Start Windows, create an icon in the program manager and double-click on it.
  37.  
  38.    Version 1.11:
  39.    The compressed INTWIN.HLP file compiled from Ralf Brown's Interrupt List
  40.      release 42 occupies appr. 4.6 MB.
  41.  
  42.   --------------------------------
  43.  
  44.    If you find this program usefull, if it does not work or if you have ideas
  45.    how to expand its functionality, feel fee to write an e-mail to me.
  46.  
  47.    As usual, I do not take any responsibility for possible damages done by
  48.    this program.
  49.  
  50.  
  51.   Two questions and their answers :
  52.   ---------------------------------
  53.    WHY is the HLP-file so large ?
  54.      In contrast to other programs that convert the interrupt list to
  55.      DOS-based hypertext systems, this program generates a large
  56.      index file that allows you to search for keywords.
  57.  
  58.    WHY did I wrote this program in Pascal and not in C ?
  59.      I think Pascal is a pretty nice language for small projects.
  60.      Another reason is the availability of efficient string handling under Pascal.
  61. *)
  62.  
  63. {$A+,B-,D+,E-,F-,I+,L+,N-,O-,R-,S-,V-}
  64. {$M 16384,25000,200000}
  65. (* minimum heap estimate (1994): 60*(6+10)+(30+40)*(43+10)+50*256=16770 *)
  66. (* (average entry size times (number of entries + 10) for FLAGS, CATEGORIES,
  67.    and CATEGORYKEYS entries) or times 256 for titles.
  68.    Each string in the [*ALIASES] sections requires (length of string) + 5.
  69. *)
  70.  
  71. Program INT2WHLP;
  72.  
  73. uses DOS;
  74.  
  75. { Version 1.00 - 1994
  76.   v. 1.01 -
  77.   v. 1.01a - 1994-02-16:
  78.     published with Ralf Brown's Interrupt List release 40.
  79.   v. 1.02 - 1994-04-07:
  80.     Changed program name from RB2HLP/INTWHLP to INT2WHLP.
  81.     Reduced the amount of RTF control codes.
  82.     Introduced program parameter controlled behaviour.
  83.     Improved flexibility by use of constants for parts of the control.
  84.     Changed and added some windows.
  85.     Extended search key facilities.
  86.   v. 1.03 - 1994-04-17:
  87.     Expanded/Compressed index switch.
  88.     Multi columns compressed index.
  89.     Interrupt titles OVERVIEW.LST.
  90.   v. 1.04 - 1994-04-29:
  91.     Configuration file including:
  92.       Program parameters can be defined in the configuration file. Such
  93.         definitions are overriden by program parameters.
  94.       Several WINHELP parameters, like font and size, can be specified.
  95.       Supplementary information "windows" can be included.
  96.       An ALIAS list can be compiled and written to the HPJ file.
  97.       A BUILDTAG list can be copied from the configuration to the HPJ file.
  98.   v. 1.05 - 1994-05-07:
  99.     Reconsidered default directories.
  100.   v. 1.06 - 1994-05-26:
  101.     Cross-references to tables.
  102.   v. 1.07 - 1994-05-29:
  103.     Edited procedure explain.
  104.     Skip "Section" file break sections (from a "--------!-Section--.."
  105.       divider line up to the next divider line).
  106.     Executable code released with Interrupt List release 41.
  107.     (ProgVers erroneously = '1.06').
  108.   v. 1.08 - 1994-07-10:
  109.     Tables as separate topics.
  110.   v. 1.10 - 1994-07-20:
  111.     Interrupt List release number dependent compilation.
  112.     Published with Interrupt List release 42.
  113.   v. 1.11 - 1994-09-20:
  114.     [INTWINCONFIG] section in configuration file.
  115.   v. 1.12 - 1994-11-04:
  116.     Test for long graphics lines in ReadLine().
  117.     Published with Interrupt List release 43.
  118.   v. 1.13 - 1994-12-26:
  119.     Transformation of DOS graphics in ReadLine().
  120.     Check for duplicate keywords (from CATEGORYKEYS) in NewHlpPage().
  121.     Secondary register references as keywords.
  122.     Separate RTF files for interrupts and tables, check for direct/inderect
  123.       references to tables from current interrupt.
  124.   v. 1.14 - 1995-03-07:
  125.     Return errorlevel 1 for warnings and >= 2 for errors.
  126.   v. 1.15 - 1995-05-29:
  127.     Avoid empty topic in the beginning of .RTF files.
  128.         Made more tools-tolerant: RTF files for expanded and compressed
  129.         indexes reversed. It is easier for some tools to digest the very
  130.         long expanded index when it is compiled at a later state so all its
  131.         phrases are already known.
  132.     [BAGGAGE] section handling.
  133.     Expanded list of registered warnings.
  134.     Copyright message and credits window include Bent Lynggaard as
  135.     coauthor.
  136.   v. 1.16 - 1995-07-31:
  137.     Christian's new e-mail address.
  138. }
  139.  
  140. const
  141.   progName  = 'INT2WHLP';
  142.   progVers  = '1.16';
  143.   hfName    = 'INTWIN'; { helpfile name }
  144.   copyright = 'Copyright (C) 1994, 1995 by Christian Müller-Planitz and Bent Lynggaard';
  145.   e_mail    = '"cmp@cs.utah.edu" or "cmueller@techfak.uni-bielefeld.de"';
  146.     { e-mail address in Intro/Explain windows }
  147.   e_mailCredits = '"cmp@cs.utah.edu" or "cmueller@techfak.uni-bielefeld.de"';
  148.     { e-mail address in the Credits window }
  149.   e_mailCredits2 = '"lynggaard@risoe.dk"';
  150.     { e-mail address in the Credits window, coauthor }
  151.  
  152.   { the strings ack01 ... are displayed in the Credits window }
  153.  
  154.   { thanks to (excuse the format): }
  155.   ack01 = '';
  156. (*
  157.   '\par{\b Bent Lynggaard} for ideas, parts of the code, and the "Miscellaneous Information" entry.';
  158. *)
  159.   ack02 = '';
  160.   ack03 = '';
  161.   ack04 = '';
  162.   ack05 = '';
  163.   {if extended, update procedure "Credits"}
  164.  
  165.   {"errorlevel" constants:}
  166.   aliasErr    = 241; (* alias not found, or table exceeded *)
  167.   fileErr    = 242; (* cannot open file *)
  168.   formatErr    = 243; (* table exceeded, or fatal error in input file *)
  169.   paramErr    = 244; (* error in program parameter *)
  170.   rtfErr    = 245; (* unable to open output file *)
  171.   userErr    = 240; (* terminated by user *)
  172.  
  173. {$I INT2WHLP.INC }
  174.  
  175.   Procedure NewHlpPage(VAR F : Text; S, ID, BrowseID : String; Classification : Char);
  176.     type
  177.       intRec = record (* used for fast test and transfer of string *)
  178.     ln: byte;    (* string length *)
  179.     l: longint;  (* 'INT ' *)
  180.     n: word;     (* 'nn' *)
  181.     c7: char;    (* ' ' *)
  182.     l2: longint; (* 'ahal' or 'List' *)
  183.     c12: char;   (* ' ' *)
  184.     w: word;     (* '- ' *)
  185.       end; (* record intRec *)
  186.       nnRec = record ln: byte; w: word; (* for 'nn' *) end;
  187.       ahalRec = record ln: byte; l: longint; (* for 'ahal' *) end;
  188.     const
  189.       linebreak = #13#10'\par\tab';
  190.       intC = ord('I')+ord('N')*$100+ord('T')*$10000+ord(' ')*$1000000;
  191.       listC = ord('L')+ord('i')*$100+ord('s')*$10000+ord('t')*$1000000;
  192.       sepC = ord('-')+ord(' ')*$100;
  193.       int:  string[3] = 'nn';   (* preset length to 2, never changed *)
  194.     VAR
  195.       intR: nnRec absolute int; (* type cast *)
  196.       p,q : Word;
  197.       func: string[5];
  198.       funcR: ahalRec absolute func; (* type cast *)
  199.       ss: string;
  200.       ssR: intRec absolute ss;
  201.  
  202.     Procedure FootNote(Note: Char; ID : String);
  203.       begin
  204.     writeln(F, Note,'{\footnote{',Note,'} ', ID, '}');
  205.       end;
  206.  
  207.  
  208.     procedure insertInt;
  209.       begin
  210.     insert('INT '+int+equStr+func+';'+int+' '+func+';',ss,11);
  211.       (* "INT nn Ar = XXxx;nn XXxx;"  (XXxx = ahal, ah, or --al) *)
  212.     if equStr[3]='L' then delete(ss,21+equBlanks,2);
  213.       (* "--" from AL = --al *)
  214.     insert(copy(ss,18,6+equBlanks+2*ord(equStr[3]='X')),ss,11);
  215.       (* "Ar = XXxx;" *)
  216.       end; (* procedure insertInt in NewHlpPage *)
  217.     procedure insertSecReg(p, l: word);
  218.     (* duplicates part of SS and inserts secondary register *)
  219.       begin
  220.     insert(copy(ss,p,l),ss,p); (* duplicate *)
  221.     insert(secReg,ss,p+l+l-1); (* SXnnnn *)
  222.     insert(secReg,ss,p+l+p-5);
  223.     insert(equStr2,ss,p+l+p-2); (* SX = nnnn *)
  224.     insert(copy(secReg,2,7)+';',ss,p);   (* SXnnnn; *)
  225.     insert(equStr2,ss,p+2);    (* SX = nnnn; *)
  226.       end; (* procedure insertSecReg in NewHlpPage *)
  227.  
  228.     begin
  229.       PageRTF(F); (* insert '\page' if appropriate *)
  230.       writeln(F, '\pard\keepn\li'+indent+'\fi-'+indent);
  231.       FootNote('#', ID);
  232.       if S<>'' then FootNote('$', S);
  233.       if BrowseID<>'' then FootNote('+', BrowseID);
  234.       if (Classification <> nullClassification) then begin
  235.     ss:=s;
  236.     if (ssR.l=intC) AND (ssR.c7=' ') then begin
  237.       if (length(ss)>14) AND (ssR.c12=' ') AND (ssR.w=sepC) then begin
  238.         (* insert highlight in s *)
  239.         insert('}}',s,7);
  240.         insert('{'+highlightInt+'{',s,1);
  241.           (* 2nd '{' terminates attribute, a ' ' distorts if attrib. is empty *)
  242.         (* insert tiny, short, and full form of INT *)
  243.         intR.w:=ssR.n;   (* length of "int" is preset to 2 *)
  244.         (* same as "int:=copy(ss,5,2);": nn from INT nn ahal - xxxx ... *)
  245.         funcR.l:=ssR.l2;
  246.         funcR.ln:=4;     (* func = 'ahal' *)
  247.         ss[7]:=';';      (* INT nn;ahal - xxxx ... *)
  248.         ss[8]:=int[1];
  249.         ss[9]:=int[2];
  250.         ss[10]:=';';     (* INT nn;nn;l - xxxx ... *)
  251.         delete(ss,11,4); (* INT nn;nn;xxxx ... *)
  252.         if func<>'----' then begin
  253.           if func[3]='-' then begin equStr[3]:='H'; func[0]:=#2; end
  254.           else if func[1]='-' then equStr[3]:='L'
  255.           else equStr[3]:='X';
  256.           insertInt;
  257.     (* INT nn;nn;AX = ahal;INT nn AX = ahal;nn ahal;xxxx ... or
  258.        INT nn;nn;AH = ah;INT nn AH = ah;nn ah;xxxx ... or
  259.        INT nn;nn;AL = al;INT nn AL = al;nn --al;xxxx ...
  260.     *)
  261.           if equStr[3]='H'then begin
  262.         insert(copy(ss,29+equBlanks+equBlanks,6)+'--',
  263.           ss,35+equBlanks+equBlanks);
  264.         insert('AX'+equStr2+copy(ss,39+equBlanks+equBlanks,5),
  265.           ss,17+equBlanks);
  266. (* INT nn;nn;AH = ah;AX = ah--;INT nn AH = ah;nn ah;nn ah--;xxxx ... *)
  267.           end; (* equStr[3]='H' *)
  268.           (* duplicate INT nn Ar = ... and insert secondary register
  269.          if appropriate.
  270.           *)
  271.           if secReg<>'' then case equStr[3] of
  272.         'X': insertSecReg(19+equBlanks, 23+equBlanks);
  273.         'H': insertSecReg(17+equBlanks, 19+equBlanks);
  274.         else insertSecReg(17+equBlanks, 21+equBlanks);
  275.           end; (* if secReg<>'' then case equStr[3] of *)
  276.           if equStr[3]='X' then begin (* insert also the AH values *)
  277.         equStr[3]:='H';
  278.         func[0]:=#2;
  279.         insertInt;
  280. (* INT nn;nn;AH = ah;INT nn AH = ah;nn ah;AX = ahal;INT nn AX = ahal;nn ahal;xxxx ... *)
  281.           end; (* if equStr[3]='X' *)
  282.         end (* if func<>'----' *)
  283.         else if secReg<>'' then insertSecReg(1, 10);
  284.       end (* if length(ss)>14 ... *)
  285.       else if (length(s)=11) and (ssR.l2=listC) then begin
  286.         insert(copy(ss,1,6)+';',ss,1); (* INT nn;INT nn List *)
  287.         insert(copy(ss,5,3),ss,8); (* INT nn;nn;INT nn List *)
  288.       end; (* else if ... *)
  289.     end; (* if (ssR.l=intC) ... *)
  290.     if Classification=tableClassification then begin
  291.       delete(ss,1,8); (* 'II SUBF ' *)
  292.       insert('#'+currentTable+';',ss,1);
  293.     end (* if Classification=tableClassification *)
  294.     else repeat
  295.       p := POS(' - ', ss);
  296.       if p <> 0 then
  297.         begin
  298.           ss[p] := ';';
  299.           delete(ss,succ(p),2);
  300.         end;
  301.     until p=0;
  302.     if (Classification <> InvalidClassification)
  303.         AND (Classification > ' ') then begin
  304.       if categoryKeyStrings[Classification]^<>'' then begin
  305.         (* check for duplicate before inserting *)
  306.         p:=pos(categoryKeyStrings[Classification]^,ss);
  307.         q:=length(categoryKeyStrings[Classification]^);
  308.         if (p=0) OR ((p+q<>length(ss)) AND (ss[p+q]<>';')) then
  309.           insert(categoryKeyStrings[Classification]^+';',ss,1);
  310.       end; (* if categoryKeyStrings[Classification]^<>'' *)
  311.       if (Classification<'A') OR (Classification>'Z') then
  312.         insert(Classification+';',ss,1)
  313.       else insert(Classification+'!;',ss,1);
  314.     end; (* if (Classification<>InvalidClassification) ... *)
  315.     FootNote('K', SS);
  316.       end; (* if (Classification<>nullClassification) *)
  317.  
  318.       write(F, '{\f0'+headerAttrib,headerSize,' ');
  319.       if classification=specialClassification then write(F, indexHeader);
  320.       writeln(F, S,'}');
  321.       writeln(F, '\par\pard\keep');
  322.  
  323.     end;
  324.  
  325.  
  326.   Procedure AddTopic(VAR F: Text; ST, S, ID: String);
  327.   { print: ST as a string (normally "\par " for new line), S as a hotspot,
  328.     ID as the corresponding jump address or macro.
  329.   }
  330.     const sp: array[0..7] of string[7] =
  331.       ('       ','      ','     ','    ','   ','  ',' ','');
  332.     var p: integer;
  333.     begin
  334.       repeat
  335.     (* detab S, otherwise the string cannot be selected with the cursor
  336.        in a tab position.
  337.     *)
  338.     p:=pos(#9,S);
  339.     if p<>0 then begin S[p]:=' '; insert(sp[(p-1) AND 7],S,p); end;
  340.       until p=0;
  341.       writeln(F, ST,'{\uldb ', S, '}{\v ', ID, '}');
  342.     end;
  343.  
  344.  
  345.   Procedure CheckKeyWords(VAR s : STring);
  346.     CONST KeyWords = 11;
  347.     CONST Keys : Array[1..KeyWords] of String[10] = ('Desc:', 'Notes:',
  348.       'Note:', 'Warning:', 'Index:', 'SeeAlso:', 'Return:', 'BUG:', 'BUGS:',
  349.       'Program:', 'Range:');
  350.     CONST IStr = '{\b ';
  351.     VAR q,p : Integer;
  352.  
  353.     begin
  354.  
  355.       if length(s)<251 then for q:= 1 to KeyWords do
  356.     begin
  357.       p := POS(Keys[q], S);
  358.       if p <> 0 then
  359.         begin
  360.           insert(IStr, S, p);
  361.           insert('}', S, p+Length(Keys[q]) + Length(IStr));
  362.           exit;
  363.         end;
  364.     end;
  365.     end;
  366.  
  367.  
  368.   Function GetSpecialNote(Note : Char)  : String;
  369.     begin
  370.       if flagStrings[Note]^='' then GetSpecialNote:='<unknown note in header>'
  371.       else GetSpecialNote:=flagStrings[Note]^;
  372.     end;
  373.  
  374.  
  375. procedure insertQueued;
  376.   var i,j: word;
  377.   begin
  378.     if (indexColumns>1) OR (queuedEntry='') then exit;
  379.     val('$'+lastSection,i,j);
  380.     if singlesInMain AND (INTcounts[i]=1) then
  381.       AddTopic(IndexFile, nl, queuedEntry, lastSection+'_1')
  382.     else AddTopic(IndexFile, nl, title, lastSection+'_0');
  383.     queuedEntry:='';
  384.   end; (* procedure insertQueued *)
  385.  
  386. function inArray(n: integer; var arr: tableArray; var top: integer): boolean;
  387. (* returns true if n is in arr, else false *)
  388.   var i: integer;
  389.   begin
  390.     i:=1;
  391.     while (i<=top) AND (arr[i]<>n) do inc(i);
  392.     inArray:=i<=top;
  393.   end; (* function inStack in function ProcessIntList *)
  394.  
  395. procedure toArray(n: integer; var arr: tableArray; var top: integer);
  396. (* inserts n in arr if not already present *)
  397.   begin
  398.     if inArray(n, arr, top) then exit;
  399.     if top=tableArraySize then errorExit('Table array exceeded',formatErr);
  400.     inc(top);
  401.     arr[top]:=n;
  402.   end; (* procedure toStack in function ProcessIntList *)
  403.  
  404.   Function ProcessIntList(FName : PathStr) : Boolean;
  405.     LABEL STOP, error_Exit, endOfLoop, table, fobi, noTable;
  406.     type
  407.       kind = (firstPart,inOverview,inFlags,inCategories,inKeys,
  408.     inFileBreakSection,pastTest);
  409.       tableId = array[1..4] of char;
  410.       sRec = record
  411.     l: byte; (* length *)
  412.     w: word; (* with '(T' *)
  413.     d: longint; (* with 'able' *)
  414.     c1: char; (* ' ' *)
  415.     ti: tableId;
  416.     c2: char; (* ')' *)
  417.       end; (* record sRec *)
  418.       castRec = record
  419.     l: byte;
  420.     case byte of
  421.       1: (w: word);
  422.       2: (d: longint);
  423.       3: (c: char (* space *); r: word; rv: longint);
  424.       end; (* record castRec *)
  425.       dividerRec = record
  426.     s: string[8];    (* '--------' *)
  427.     cat: char;    (* category *)
  428.     c: char;    (* '-' *)
  429.     w: word;    (* Interrupt number, 2 hex digits *)
  430.     d: longint;    (* sub function, 4 hex digits or '-' *)
  431.     r: word;    (* secondary register name, two letters or '--' *)
  432.     rv: longint;    (* sec. reg. value, 4 hex digits or '-' *)
  433.       end; (* record dividerRec *)
  434.     const
  435.       INTno:     integer = 0;
  436.       bufferString: string = ''; (* transfers part of split string *)
  437.       ta = ord('(')+ord('T')*$100; (* (Table nnnn) *)
  438.       able = ord('a')+ord('b')*$100+ord('l')*$10000+ord('e')*$1000000;
  439.       fo = ord('F')+ord('o')*$100; (* Format of ... *)
  440.       bi = ord('B')+ord('i')*$100; (* Bitfields for ... *)
  441.       Section: String[3] = '--'; (* initialize to length 2 *)
  442.       SubFunc: String[5] = '----'; (* length 4 *)
  443.       allMessages: boolean = false;
  444.  
  445.     VAR
  446.     tP:          ^tableID;
  447.     hLineP,tLineP : ^string; (* pointers to header and (Table) lines *)
  448.     p,q        : integer;
  449.     curTab     : integer;
  450.     lineCount  : word; (* for error report *)
  451.     NewSection : Boolean;
  452.     Classification,c      : Char;
  453.     current    : kind;
  454.     inTable    : boolean;
  455.     table_Id   : String[7];
  456.     tableTitle : String[119];
  457.     s          : String;
  458.     SpecialNote : String;
  459.     sR         : sRec absolute s; (* for type cast *)
  460.     sectionR   : castRec absolute Section;
  461.     subFuncR   : castRec absolute SubFunc;
  462.     secRegR    : castRec absolute secReg;
  463.     dR         : dividerRec absolute s;
  464.  
  465.     F1         : Text;
  466.  
  467.     function isNumber(var ti: tableId): integer;
  468.     (* returns the table number, or negative value if illegal number *)
  469.       var i,res: integer;
  470.       begin
  471.     res:=0;
  472.     for i:=1 to 4 do case ti[i] of
  473.       '0'..'9': res:=res*10+ord(ti[i])-ord('0');
  474.       else begin isNumber:=-1; exit; end;
  475.     end; (* for ... do case ... *)
  476.     isNumber:=res;
  477.       end; (* function isNumber in function ProcessIntList *)
  478.     procedure insertRef;
  479.       begin
  480.     if inTable then AddTopic(TabTopics,nl,'INT '+Section+' '+SubFunc, TopicStr+mainW)
  481.     else if IntTopicStr<>'' then AddTopic(IntTopics,nl,copy(title,1,6),IntTopicStr);
  482.       end; (* procedure insertRef in function ProcessIntList *)
  483.     procedure wrSection; (* show progress *)
  484.       begin write(Section,#13); end;
  485.  
  486.     begin
  487.      {$I-}
  488.       assign(F1, InPath + FName);
  489.       reset(F1);
  490.      {$I+}
  491.       if IOResult <> 0 then
  492.     begin
  493.       ProcessIntList := FALSE;
  494.       EXIT;
  495.     end;
  496.  
  497.       writeln('Processing : ', InPath + FName);
  498.       write(LastSection,#13);
  499.  
  500.       readLine(F1, s);    { ignore copyright in 1st two lines }
  501.       readLine(F1, s);
  502.       lineCount:=2;
  503.       current:=firstPart;
  504.       inTable:=false;
  505.  
  506.       SpecialNote := '';
  507.  
  508.  
  509.       while not(EOF(F1)) do
  510.     begin
  511.       readLine(F1, s);
  512.       inc(lineCount);
  513.       NewSection := (s[1]= '-') and (Pos('--------', s) <> 0);
  514.  
  515.       if NewSection then
  516.         begin
  517.           if inTable then insertRef;
  518.           for p:=1 to tabTop do begin
  519.         q:=tabArray[p];
  520.         if NOT inArray(q, refArray, refTop) then begin
  521.           str(10000+q,table_Id); (* 1nnnn *)
  522.           delete(table_Id,1,1);  (* nnnn  *)
  523.           AddTopic(intTopics,nl,'Table #'+table_Id,'t'+table_Id+tableW);
  524.           inc(insertCounter);
  525.         end; (* if NOT inArray() *)
  526.           end; (* for p:=1 *)
  527.           inTable:=false;
  528.           insertRef;
  529.           if tabTop>maxTabTop then maxTabTop:=tabTop;
  530.           tabTop:=0;
  531.           if refTop>maxRefTop then maxRefTop:=refTop;
  532.           refTop:=0;
  533.  
  534.           SectionR.w:=dR.w; (* chars 11..12 of divider line *)
  535.           SubFuncR.d:=dR.d; (* chars 13..16 of divider line *)
  536.           secRegR.r:=dR.r;  (* chars 17..18 of divider line *)
  537.           if secReg[2]='-' then secReg[0]:=#0
  538.           else begin
  539.         secRegR.rv:=dR.rv; (* chars 19..22 of divider line *)
  540.         if secReg[6]='-' then secReg[0]:=#5 else secReg[0]:=#7;
  541.           end; (* else *)
  542.           Classification := s[9];
  543.           if Classification = '!' then
  544.         begin
  545.           delete(s,1,12);
  546.  
  547.           q:=0;
  548.           while (s[q] <> '-') and (q < Length(s)) do
  549.             Inc(q);
  550.           s[0] := chr(q-1);  { remove '-' chars at the end }
  551.           if s='OVERVIEW' then current:=inOverview
  552.           else if s='FLAGS' then current:=inFlags
  553.           else if s='CATEGORIES' then current:=inCategories
  554.           else if s='CATEGORYKEYS' then current:=inKeys
  555.           else if s='Section' then begin
  556.             current:=inFileBreakSection;
  557.             Section:=LastSection;
  558.             IntTopicStr:='';
  559.             goto endOfLoop; (* skip file break section *)
  560.           end (* if s='Section' *)
  561.           else current:=firstPart;
  562.           (* Interrupt List release 41 does not include OVERVIEW
  563.              and CATEGORYKEYS as sections, but as separate files.
  564.              The program is prepared for this information being
  565.              parts of the List.
  566.           *)
  567.  
  568.           if s = '' then s:= 'Note';   { shit ! }
  569.  
  570.           if EOF(F1)  then   { last line of document ?}
  571.             goto STOP;
  572.           inc(TopicNo);
  573.           str(TopicNo, TopicStr);
  574.         end { if Classification = '!' }
  575.           else
  576.         begin
  577.           if section<>lastSection then begin
  578.             val('$'+section,INTno,q);
  579.             if q<>0 then begin
  580.               writeln('Cannot interpret interrupt number in line ',
  581.             lineCount,': "',section,'".');
  582.               goto error_Exit;
  583.             end; (* if q<>0 *)
  584.           end; (* if section<>lastSection *)
  585.           current:=pastTest;
  586.           readLine(F1, s);
  587.           inc(lineCount);
  588.           inc(INTcounts[INTno]);
  589.           str(INTcounts[INTno], TopicStr);
  590.           insert(section+'_',TopicStr,1);
  591. (* We could compare already here: "while aliasString=s do ..." if we want to
  592.    use the orginal interrupt header line to find aliases. However,
  593.      1. it is easier to identify the original position of an alias line,
  594.      2. it is easier to determine the alias sequense in the config. file,
  595.      3. it is easier to track the reason for a "not found" error, and
  596.      4. the chance for an alias line to be unique is higher
  597.    if we compare after the manipulation of the header line. Also, if we copy
  598.    from the INTWIN index rather than from the original list, the lines are
  599.    already manipulated.
  600. *)
  601.           while (s[8] <> '-') do   { special flags in titel-line ? }
  602.             begin
  603.               if s[8] <> ' ' then
  604.             SpecialNote:=SpecialNote+#13#10'\par '+GetSpecialNote(s[8]);
  605.               delete(s, 8, 1);
  606.             end;
  607.  
  608.           Insert(subFunc+' ', S, 8);
  609.           while aliasString=S do begin
  610.             saveAlias(nextAliasPP,aliasId+TopicStr);
  611.             getNextAlias(aliasP,aliasId,aliasString);
  612.           end; (* while aliasString=S *)
  613.         end; { else (Classification<>'!') }
  614.  
  615.           if LastSection <> Section then
  616.         begin
  617.           if Classification = '!' then begin
  618.             if indexColumns=1 then insertQueued;
  619.             IntTopicStr:='N_'+TopicStr;
  620.             title:='Notes';
  621.             if (notesCount MOD indexColumns)=0 then write(IndexFile,'\par ')
  622.             else  write(IndexFile,'\tab ');
  623.             inc(notesCount);
  624.             writeln(IndexFile,'{\uldb Notes}{\v ',IntTopicStr,'}');
  625.           end (* if Classification = '!' *)
  626.           else begin (* (Classification <> '!'*)
  627.             if INTno<lastINTno then begin
  628.               (* we cannot tolerate inconsistent sorting in a
  629.              multi-column index.
  630.               *)
  631.               writeln('Inconsistent sorting in file ',FName,
  632.             ' line ',lineCount);
  633.               writeln('INT ',section,' appears after INT ',lastSection);
  634.               if indexColumns>1 then begin
  635.             wl('This can be tolerated only with a single column index.');
  636.          error_Exit:
  637.             errorExit('Please correct the file and try again.',fileErr);
  638.               end; (* if indexColumns>1 *)
  639.               wl(#7'It is recommended to correct the file.');
  640.               inc(warnings);
  641.             end; (* if INTno<lastINTno *)
  642.             if INTno<>lastINTno then begin
  643.               wrSection;
  644.               IntTopicStr:=Section+'_0';
  645.               if indexColumns=1 then begin
  646.             insertQueued;
  647.             queuedEntry:=s;
  648.               end; (* if indexColumns=1 *)
  649.               title:=INTtitles[INTno]^;
  650.               if title='' then title:='INT '+Section;
  651.               lastINTno:=INTno;
  652.             end; (* if INTno<>lastINTno *)
  653.           end; (* else (Classification <> '!') *)
  654.  
  655.           if backRef then AddTopic(SubIntFile,nl,'Interrupts','idInterrupts');
  656.             (* don't insert a backward reference the very first time *)
  657.           backRef:=true; (* but in all the rest *)
  658.           NewHlpPage(SubIntFile, title, IntTopicStr,'i:0', specialClassification);
  659.           if twoIndexes AND indexHeaders then
  660.             OutLn(IntFile,'\par '+title);
  661.           LastSection := Section;
  662.         end; { if LastSection <> Section }
  663.  
  664.  
  665.           if TopicNo=1 then c:=specialClassification
  666.         (* The initial Interrupt List section should cary the
  667.            indexHeader.
  668.         *)
  669.           else c:=Classification;
  670.           NewHlpPage(IntTopics, s, TopicStr,'l:0', c);
  671.           if SpecialNote <> '' then
  672.         begin
  673.           writeln(IntTopics, '{\cf0 ', SpecialNote, '}'#13#10'\par ');
  674.           SpecialNote := '';
  675.         end; { if SpecialNote <> '' }
  676.  
  677.           OutLN(IntTopics, '{\cf0 Category: '+ Classification +
  678.         ' - ' + categoryStrings[Classification]^ + '}\par');
  679.           if Classification='!' then setTabs(IntTopics, 8, deciPoints, 10)
  680.         (* we will set tabs in the few Notes, but not in all the
  681.            INT entries.
  682.         *)
  683.           else if markKeys then OutLN(IntTopics,'{\b Inp.:}');
  684.           if twoIndexes then AddTopic(IntFile, indentIndex, s, TopicStr);
  685.           AddTopic(SubIntFile, nl, s, TopicStr);
  686.         end { if NewSection }
  687.       else          { no new section }
  688.        begin
  689.          case current of
  690.            pastTest:     begin
  691.       { this paragraph is un-indented to gain space for code }
  692.       if markKeys then CheckKeyWords(s);
  693.  
  694.       { check the first two characters and react on '(T'[able nnnn)],
  695.     'Fo'[rmat of ...] and 'Bi'[tfields for ...]
  696.       }
  697.       if tables then case sR.w of
  698.     ta: if (length(s)>=12) AND (sR.d=able) AND (sR.c1=' ') AND (sR.c2=')')
  699.       AND (isNumber(sR.ti)>=0) then begin
  700.         hLineP:=@bufferString;
  701.         tLineP:=@s;
  702.       table:
  703.         if eof(F1) then begin
  704.           writeln('Unextected end of file in table at INT ',Section,
  705.         ' Subfunc ',SubFunc);
  706.           wrSection;
  707.           goto Stop;
  708.         end; (* if eof(F1) *)
  709.         readln(F1, bufferString);
  710.         inc(lineCount);
  711.         p:=pos('(Table ',tLineP^);
  712.         if (p=0) OR  (length(tLineP^)<p+11) OR (tLineP^[p+11]<>')')then begin
  713.       noTable:
  714.           inc(missingTableCounter);
  715.           if allMessages OR (missingTableCounter<=missingTableLimit) then begin
  716.         writeln('Missing "(Table nnnn)" in INT ',Section,
  717.           ' Subfunc ',SubFunc,' (line ',lineCount,'):');
  718.         writeln(pred(lineCount):5,s:succ(length(s)));
  719.         writeln(lineCount:5,bufferString:succ(length(bufferString)));
  720.         if missingTableCounter=missingTableLimit then begin
  721.           wl(#13#10'Several missing tables encountered. If '
  722.             +progName+' is used on release 40 or lower');
  723.           wl('of the List, it should be started with the program '
  724.             +'parameter -r40, or with key');
  725.           wl('releaseNo=40 in section [OPTIONS] of the configuration file.');
  726.           write('s=stop; m=messages; else continue without messages: ');
  727.           ProcessTime:=ProcessTime-memL[$40:$6C];
  728.           p:=readKeyWd;
  729.           ProcessTime:=ProcessTime+memL[$40:$6C];
  730.             (* sets ProcessTime "pause" ticks later than original *)
  731.           if word(p)<$100 then writeln (* function key *)
  732.           else begin
  733.             writeln(char(p));
  734.             case upcase(char(p)) of
  735.               'S': errorExit('Terminated by user',userErr);
  736.               'M': allMessages:=true;
  737.             end; (* if ... case ... of *)
  738.           end; (* if word(p)>$ff *)
  739.         end; (* if missingTableCounter=missingTableLimit *)
  740.         wrSection;
  741.           end; (* if allMessages ... *)
  742.           insert(nl,bufferString,1); (* force newline *)
  743.         end (* if (p=0) ... *)
  744.         else begin
  745.           tP:=@tLineP^[p+7];
  746.           curTab:=isNumber(tP^);
  747.           if curTab<0 then goto noTable;
  748.           toArray(curTab, tabArray, tabTop);
  749.           currentTable:=tP^;
  750.           table_Id:='t'+currentTable;
  751.           if inTable then insertRef;
  752.           inTable:=true;
  753.           tableTitle:=Section+' '+SubFunc+' '+hLineP^;
  754.           while tableAliasString=tableTitle do begin
  755.         saveAlias(nextAliasPP,tableAliasId+table_id);
  756.         getNextAlias(tableAliasP,tableAliasId,tableAliasString);
  757.           end; (* while ... *)
  758.           NewHlpPage(TabTopics, tableTitle, table_Id,'t:0', tableClassification);
  759.           if tableWindow then begin
  760.         AddTopic(TabTopics,nl,'Copy to Main',table_Id+mainW);
  761.         OutLn(TabTopics,'');
  762.           end; (* if tableWindow *)
  763.           if sR.w=ta then begin (* bold Table nnnn *)
  764.         s[1]:='{';  (* substitutes '(' *)
  765.         s[12]:='}'; (*   and ')'       *)
  766.         insert('\b ',s,2);
  767.           end (* if sR.w=ta *)
  768.           else begin
  769.         writeln(TabTopics,'\par {\b Table ',currentTable,'}');
  770.         bufferString[0]:=char(pred(p)); (* delete '(Table nnnn)' *)
  771.           end; (* else *)
  772.           AddTopic(TableFile,nl+currentTable+'  ',tableTitle,table_Id);
  773.         end; (* else *)
  774.     end; (* case ta *)
  775.     fo: if pos('Format of ',s)=1 then begin
  776.       fobi:
  777.       hLineP:=@s;
  778.       tLineP:=@bufferString;
  779.       goto table;
  780.     end; (* case fo *)
  781.     bi: if pos('Bitfields for ',s)=1 then goto fobi;
  782.     else begin
  783.       p:=length(s)-4;
  784.       for q:=p downto 1 do begin
  785.         if (s[q]='#') AND ((q=p) OR (s[q+5]<'0') OR (s[q+5]>'9')) then begin
  786.           tP:=@s[q+1];
  787.           curTab:=isNumber(tP^);
  788.           if curTab>=0 then begin
  789.         toArray(curTab, refArray, refTop);
  790.         insert('}{\v t'+tP^+tableW+'}', S, q+5);
  791.         insert('{\uldb ', S, q);
  792.         if (length(s)-q>150) AND (q>20) then begin
  793.           (* we must ensure keeping length(S)<256 *)
  794.           bufferString:=copy(S, q, 255);
  795.           S[0]:=char(pred(q)); (* delete the copied part *)
  796.         end; (* if (length(s)-q>150)... *)
  797.           end; (* if isNumber *)
  798.         end; (* if (s[q]='#')... *)
  799.       end; (* for q=p *)
  800.     end; (* else *)
  801.       end; (* case sR.w of *)
  802.       { indent again }
  803.                  end; (* case pastTest *)
  804.            firstPart:    check1st(s);
  805.            inOverview:   getINTtitle(s,INTtitles);
  806.            inFlags:      scan(s,flagStrings);
  807.            inCategories: scan(s,categoryStrings);
  808.            inKeys:       scan(s,categoryKeyStrings);
  809.            inFileBreakSection: goto endOfLoop;
  810.          end; (* case current of *)
  811.          if inTable then OutLN(TabTopics, s) else OutLN(IntTopics, s);
  812.          if bufferString<>'' then begin
  813.            if inTable then OutLn(TabTopics, bufferString) (* with "newline" *)
  814.            else writeln(IntTopics, bufferString); (* no "newline" (\par ) *)
  815.            bufferString:='';
  816.          end; (* if bufferString<>'' *)
  817.        end; { else (no new section) }
  818.  
  819.       endOfLoop:
  820.     end; { while not(EOF(F1)) }
  821.  
  822.       STOP:
  823.       if inTable then insertRef;
  824.       inTable:=false;
  825.       insertRef;
  826.       close(F1);
  827.       ProcessIntList := TRUE;
  828.     end;
  829.  
  830.  
  831.   Procedure NewPage(VAR F: Text; Title : String);
  832.     VAR TopicStr : String;
  833.  
  834.       begin
  835.     Inc(TopicNo);
  836.     str(TopicNo, TopicStr);
  837.     AddTopic(IndexFile, nl, Title, TopicStr);
  838.     NewHlpPage(F, Title, TopicStr,'p:0', InvalidClassification);
  839.     setTabs(F, 8, deciPoints, 10);
  840.       end;
  841.  
  842.  
  843.   Procedure ProcessPorts(FName : String);
  844.     LABEL STOP;
  845.     VAR i          : integer;
  846.     s          : String;
  847.     TopicStr   : String;
  848.     NewSection : Boolean;
  849.     F1         : Text;
  850.  
  851.  
  852.  
  853.     begin
  854.       defaultDir(FName,InPath);
  855.      {$I-}
  856.       assign(F1, FName);
  857.       reset(F1);
  858.      {$I+}
  859.       if IOResult <> 0 then
  860.     begin
  861.       writeln('Unable to open ', FName);
  862.       EXIT;
  863.     end;
  864.  
  865.       writeln('Processing : ', FName);
  866.  
  867.       i:=length(FName);
  868.       while FName[i]<>'\' do dec(i);
  869.       NewPage(IntTopics, copy(FName,succ(i),255)+' Note');
  870.  
  871.       while not(EOF(F1)) do
  872.     begin
  873.       readLine(F1, s);
  874.       NewSection := (s[1]= '-') and (Pos('---------', s) <> 0);
  875.  
  876.       if NewSection then
  877.         begin
  878.           readLine(F1, s);
  879.  
  880.           if EOF(F1)  then   { last line of document ?}
  881.         goto STOP;
  882.  
  883.           if s <> '' then                { why does this happend }
  884.         NewPage(IntTopics, s);
  885.         end
  886.       else
  887.         begin
  888.          CheckKeyWords(s);
  889.          OutLN(IntTopics, s);
  890.         end;
  891.     end;
  892.  
  893.       STOP:
  894.       close(F1);
  895.     end;
  896.  
  897.  
  898.   Procedure ProcessFile(FName : String; Title : String);
  899.     VAR s          : String;
  900.     F1, F2     : Text;
  901.  
  902.     begin
  903.       defaultDir(FName,InPath);
  904.      {$I-}
  905.       assign(F1, FName);
  906.       reset(F1);
  907.      {$I+}
  908.       if IOResult <> 0 then
  909.     begin
  910.       writeln('Unable to open ', FName);
  911.       EXIT;
  912.     end;
  913.  
  914.       writeln('Processing : ', FName);
  915.       setTabs(IndexFile, 8, deciPoints, 10);
  916.  
  917.       while not(EOF(F1)) do
  918.     begin
  919.       readLine(F1, s);
  920.       OutLN(IndexFile, s);
  921.     end;
  922.  
  923.       close(F1);
  924.     end;
  925.  
  926.  
  927.   Procedure Credits;
  928.     begin
  929.       OutLn(IndexFile,'');
  930.       AddTopic(IndexFile, nl, 'Credits', 'idCredits');
  931.       OutLn(IndexFile,'');
  932.       OutLn(IndexFile,compilationStr);
  933.       NewHlpPage(IndexFile, 'Credits', 'idCredits','m:1', InvalidClassification);
  934.       OutLn(IndexFile,'\pard{\f0'+headerSize+
  935.     '\qc\par Interrupt List (c) by {\b Ralf Brown}\par'); { \qc=centered }
  936.       OutLn(IndexFile,'\par This list was converted from the released ASCII file'#13#10
  937.             + '\par to the Windows Help-Format by \par\par'#13#10
  938.             + '\par {\b Christian M\''81ller-Planitz}'
  939.                     + '{' + header2ndSize + '\par ' + e_mailCredits + '}'
  940.             + '\par and'
  941.                     + '\par {\b Bent Lynggaard}'+header2ndSize);
  942.       OutLn(IndexFile,e_mailCredits2);
  943. (* an alternative format of the last few lines:
  944.             + '\par {\b Christian M\''81ller-Planitz}'
  945.             + '   and   {\b Bent Lynggaard}'+header2ndSize);
  946.       OutLn(IndexFile,e_mailCredits + '  and  ' + e_mailCredits2);}
  947. *)
  948.       if ack01<>'' then begin
  949.     writeIndex('\par\par Thanks to:');
  950.     writeIndex(ack01);
  951.     writeIndex(ack02);
  952.     writeIndex(ack03);
  953.     writeIndex(ack04);
  954.     writeIndex(ack05);
  955.       end; (* if ack01<>'' *)
  956.       writeIndex('\par}');
  957.     end;
  958.  
  959.  
  960. procedure processTopics(n: integer);
  961. (* inserts references to n topics in the CONTENTS main index *)
  962.   var i: integer; w: string[13]; title,id: string[39];
  963.   begin
  964.     for i:=1 to n do begin
  965.       str(i,w);
  966.       insert('WINDOW ',w,1);
  967.       title:='';
  968.       profileString(w,'title',title,pred(sizeOf(title)));
  969.       id:='';
  970.       profileString(w,'id',id,pred(sizeOf(id)));
  971.       if (title<>'') AND (id<>'') then AddTopic(IndexFile,nl,title,id);
  972.     end; (* for i:=1 *)
  973.   end; (* procedure processTopics *)
  974.  
  975. procedure processPages(n: integer);
  976. (* processes n "windows" as defined in the configuration file *)
  977.   var
  978.     i,j,wType,files,fType: integer;
  979.     w: string[13];
  980.     f: string[17];
  981.     id: string[17];
  982.     fId,chain: string[21];
  983.     title,fTitle: string[39];
  984.     fileName: pathStr;
  985.   begin
  986.     for i:=1 to n do begin
  987.       str(i,w);
  988.       insert('WINDOW ',w,1);
  989.       title:='';
  990.       profileString(w,'title',title,pred(sizeOf(title)));
  991.       id:='';
  992.       profileString(w,'id',id,pred(sizeOf(id)));
  993.       if (title<>'') AND (id<>'') then begin
  994.     wType:=1;
  995.     profileInt(w,'type',wType);
  996.     files:=1;
  997.     profileInt(w,'files',files);
  998.     case wType of
  999.       1: NewHlpPage(IndexFile,title,id,'f:0',InvalidClassification);
  1000.         (* Single entry windows *)
  1001.       2: NewHlpPage(IndexFile,title,id,'m:9',InvalidClassification);
  1002.         (* Multi entries windows *)
  1003.       3: ; (* nop *)   (* Windows with own contents list *)
  1004.     end; (* case wType of *)
  1005.     for j:=1 to files do begin
  1006.       str(j,f);
  1007.       insert('file ',f,1);
  1008.       fileName:='';
  1009.       profileString(w,f,fileName,pred(sizeOf(fileName)));
  1010.       if fileName<>'' then begin
  1011.         fType:=wType;
  1012.         profileInt(w,f+' type',fType);
  1013.         case fType of
  1014.           1: ProcessFile(fileName,title);
  1015.           2: ProcessPorts(fileName);
  1016.           3: begin
  1017.         (* the RTF file is expecte to be in:
  1018.              a. the current directory.
  1019.              b. the program's home directory
  1020.            if no drive or root is specified.
  1021.         *)
  1022.         if ((length(fileName)<2) OR (fileName[2]<>':'))
  1023.           AND (fileName[1]<>'\') AND (fileName[1]<>'.') then begin
  1024.           if exist(filename) OR NOT exist(homeDir+filename) then
  1025.             insert(currentDir,filename,1)
  1026.           else insert(homeDir,filename,1);
  1027.         end; (* if (fileName[2]<':'... *)
  1028.         fileName:=fExpand(fileName);
  1029.         if NOT exist(fileName) then begin
  1030.           writeln(#7'File ',fileName,' not found, copy to ',currentDir);
  1031.                   inc(warnings);
  1032.                 end; (* if NOT exist(filename) *)
  1033.         writeln(HPJ,fileName); (* include the file name *)
  1034.           end;
  1035.           4: begin (* ASCII file in multi file entry *)
  1036.         str(j,fTitle);
  1037.         str(j,fId);
  1038.         insert(title+' - ',fTitle,1);
  1039.         insert(id+'_',fId,1);
  1040.         chain:=id+':5';
  1041.         profileString(w,f+' title',fTitle,pred(sizeOf(fTitle)));
  1042.         profileString(w,f+' id',fId,pred(sizeOf(fId)));
  1043.         profileString(w,f+' chain',chain,pred(sizeOf(chain)));
  1044.         NewHlpPage(IndexFile,fTitle,fId,chain,InvalidClassification);
  1045.         defaultDir(fileName,currentDir);
  1046.         ProcessFile(fileName,fTitle);
  1047.           end; (* case 4 *)
  1048.         end; (* case fType of *)
  1049.       end (* if fileName<>'' *)
  1050.       else begin
  1051.         writeln(#7'Missing file name for [',w,'] ',f);
  1052.         inc(warnings);
  1053.       end; (* else *)
  1054.     end; (* for j:=1 *)
  1055.       end (* if (title<>'') ... *)
  1056.       else begin
  1057.     writeln(#7'Missing title or identifier in ',w);
  1058.     inc(warnings);
  1059.       end; (* else *)
  1060.     end; (* for i:=1 *)
  1061.   end; (* procedure processPages *)
  1062.  
  1063. procedure processFilter;
  1064.   var d: dirStr;
  1065.   begin
  1066.     PageRTF(IndexFile); (* insert '\page' if appropriate *)
  1067.     writeIndex('\pard');
  1068.     writeIndex('#{\footnote{#} idPartComp}');
  1069.     writeIndex('{\f0'+header2ndSize+' This compilation of the Interrupt List does '+#13#10
  1070.       +'not contain all the information in the List, see the '#13#10
  1071.       +'{\uldb INTERRUP.1ST File}{\v id1st} for the availability of the ');
  1072.     writeIndex('complete list.\par\par');
  1073.     writeIndex('See {\uldb Filter Method}{\v idFlt_meth} and '#13#10
  1074.       +'{\uldb Filter File}{\v idFlt_file} for details.\par}');
  1075.     d:=currentDir;
  1076.     if NOT exist('FLT_METH.RTF') then begin
  1077.       if exist(homeDir+'FLT_METH.RTF') then d:=homeDir
  1078.       else begin
  1079.     writeln(#7'File FLT_METH.RTF not found, copy to ',d);
  1080.     inc(warnings);
  1081.       end; (* else *)
  1082.     end; (* if NOT exist() *)
  1083.     writeln(HPJ,d,'FLT_METH.RTF');
  1084.     NewHlpPage(IndexFile, 'Filter File', 'idFlt_file','flt:1', invalidClassification);
  1085.     processFile(filterFileName,'Filter File');
  1086.   end; (* procedure processFilter *)
  1087.  
  1088. procedure readCategoryKeys;
  1089. (* Opens file CATEGORY.KEY if available, and reads definitions to
  1090.    categoryKeyStrings. Definitions are of the type
  1091.       A - definition A, B - definition B,
  1092.    The definitions are inserted as search keys for the appropriate
  1093.    categories. Note that more than one keyword per entry is accepted,
  1094.    separated by a semicolon, e.g. " c - cachers;spoolers,".
  1095.  
  1096.    Reads also title file OVERVIEW.LST.
  1097.  
  1098.    CATEGORY.KEY and OVERVIEW.LST are separate files in Interrupt List
  1099.    release 41+.
  1100. *)
  1101.   var t: text; s: string;
  1102.   begin
  1103. (*$I-*)
  1104.     assign(t,InPath+'category.key');
  1105.     reset(t);
  1106. (*$I+*)
  1107.     if IOresult<>0 then writeln('Unable to open ',InPath,'CATEGORY.KEY')
  1108.     else begin
  1109.       while NOT eof(t) do begin readln(t,s); scan(s,categoryKeyStrings); end;
  1110.       close(t);
  1111.     end; (* else *)
  1112. (*$I-*)
  1113.     assign(t,InPath+'overview.lst');
  1114.     reset(t);
  1115. (*$I+*)
  1116.     if IOresult<>0 then writeln('Unable to open ',InPath,'OVERVIEW.LST')
  1117.     else begin
  1118.       while NOT eof(t) do begin readln(t,s); getINTtitle(s,INTtitles); end;
  1119.       close(t);
  1120.     end; (* else *)
  1121.   end; (* procedure readCategoryKeys *)
  1122.  
  1123. procedure INTsToIndex;
  1124.   var i,j,k,l: word; s: string[3];
  1125.   begin
  1126.     for k:=0 to pred(indexPages) do begin
  1127.       l:=k*indexRows*indexColumns;
  1128.       for i:=0 to pred(indexRows) do begin
  1129.     OutLn(IndexFile, '');
  1130.     for j:=0 to pred(indexColumns) do begin
  1131.       if INTcounts[l+i+j*16]<>0 then begin
  1132.         write(IndexFile,'{\uldb INT ',HEX(l+i+j*16));
  1133.         if indexColumns=4 then write(IndexFile,' List');
  1134.         write(IndexFile,'}{\v ',HEX(l+i+j*16),'_0}');
  1135.       end (* if INTcounts[]<>0 *)
  1136.       else if indexColumns=4 then write(IndexFile,'\tab ');
  1137.       if j<pred(indexColumns) then write(IndexFile,'\tab ');
  1138.     end; (* for j:=0 *)
  1139.       end; (* for i:=0 *)
  1140.       if k<pred(indexPages) then OutLn(IndexFile, '');
  1141.     end; (* for k:=0 *)
  1142.   end; (* procedure INTsToIndex *)
  1143.  
  1144.   const
  1145.     windows: integer = 0;
  1146.  
  1147.   var
  1148.     i: integer;
  1149.     ch: char;
  1150.  
  1151.   begin
  1152.     Intro;
  1153.     if (paramStr(1)='?') OR (paramStr(1)='-?') OR (paramStr(1)='/?')
  1154.       then Explain; (* and exit *)
  1155.  
  1156.     fSplit(paramStr(0),homeDir,currentDir,currentDir);
  1157.       (* works only with DOS 3.30+ - currentDir is used as a dummy *)
  1158.     currentDir:=fExpand('.');
  1159.     if length(currentDir)>3 then begin
  1160.       inc(currentDir[0]);
  1161.       currentDir[length(currentDir)]:='\';
  1162.     end; (* if length()... *)
  1163.     interpretParameters;
  1164.     initializeArrays;
  1165.     nextAliasPP:=@firstAliasP;
  1166.  
  1167.     if InPath='' then begin
  1168.       write('Source directory: ');
  1169.       readln(InPath);
  1170.     end; (* if InPath='' *)
  1171.     if InPath<>'' then begin
  1172.       ch:=InPath[length(InPath)];
  1173.       if (ch<>':') AND (ch<>'\') then
  1174.     begin inc(InPath[0]); InPath[length(InPath)]:='\'; end;
  1175.     end; (* if InPath<>'' *)
  1176.  
  1177.     if OutPath='' then begin
  1178.       write('Dest. directory (has to be created in advance) : ');
  1179.       readln(OutPath);
  1180.     end; (* if OutPath='' *)
  1181.     if OutPath<>'' then begin
  1182.       ch:=OutPath[length(OutPath)];
  1183.       if (ch<>':') AND (ch<>'\') then
  1184.     begin inc(OutPath[0]); OutPath[length(OutPath)]:='\'; end;
  1185.     end; (* if OutPath<>'' *)
  1186.  
  1187.     ProcessTime:=memL[$40:$6C]; { timer ticks since midnight }
  1188.     findDateAndCopyright;
  1189.     CreateHPJ;
  1190.  
  1191.     OpenRTF(IndexFile, 'INDEX.RTF');
  1192.     NewHlpPage(IndexFile, 'Contents:', 'CONTENTS','m:2', specialClassification);
  1193.  
  1194.     readCategoryKeys; (* reads also titles *)
  1195.     OpenRTF(SubIntFile,'SUBINT.RTF');
  1196.     OpenRTF(IntTopics, 'INTTOPIC.RTF');
  1197.     if twoIndexes then OpenRTF(IntFile, 'INT.RTF');
  1198.  
  1199.     if twoIndexes then
  1200.       AddTopic(IndexFile, nl, 'Interrupt Index',
  1201.     '!IfThenElse(IsMark("Compressed_Index"), '
  1202.     +'`JumpId("","idInterrupts")'', `JumpId("","idIndex")'')')
  1203.     else AddTopic(IndexFile, nl, 'Interrupts', 'idInterrupts');
  1204.     if tables then AddTopic(IndexFile, nl, 'Tables', 'idTables');
  1205.     AddTopic(IndexFile, nl, 'FILELIST', '1');
  1206.     AddTopic(IndexFile, nl, 'INTERRUP.1ST File', 'id1st');
  1207.     if filtered then begin
  1208.       AddTopic(IndexFile, nl, 'Filter Method', 'idFlt_meth');
  1209.       AddTopic(IndexFile, nl, 'Filter File', 'idFlt_file');
  1210.     end; (* if filtered *)
  1211.  
  1212.     profileInt('WINDOWS','number',windows);
  1213.     processTopics(windows); (* insert Ports, Memory etc. in index *)
  1214.  
  1215.     Credits;
  1216.  
  1217.     if twoIndexes then begin
  1218.       NewHlpPage(IntFile, 'Interrupt Index', 'idIndex','m:3', specialClassification);
  1219.       AddTopic(IntFile, nl, 'Compress index',
  1220.     '!SaveMark("Compressed_Index");JumpId("","idInterrupts")');
  1221.       { the program adds all following entries }
  1222.     end; (* if twoIndexes *)
  1223.     NewHlpPage(IndexFile, 'Interrupts', 'idInterrupts','m:4', specialClassification);
  1224.     if twoIndexes then begin
  1225.       AddTopic(IndexFile, nl, 'Expand index','!IfThen(IsMark("Compressed_Index"),'
  1226.     +' `DeleteMark("Compressed_Index")'');JumpId("","idIndex")');
  1227.       OutLn(IndexFile, '');
  1228.       if indexColumns>1 then setTabs(IndexFile, succ(ord(indexColumns<=4))*8,
  1229.     deciPoints, pred(indexColumns));
  1230.     end; (* if twoIndexes *)
  1231.  
  1232.     if tables then begin
  1233.       OpenRTF(TableFile, 'TABLE.RTF');
  1234.       OpenRTF(TabTopics, 'TABTOPIC.RTF');
  1235.       NewHlpPage(TableFile,'Tables\f1'+fontSize+'\par\par Tab# INT Func Title',
  1236.     'idTables','m:5', invalidClassification);
  1237.       (* "Tab# INT Func Title" in normal text font and size *)
  1238.     end; (* if tables *)
  1239.  
  1240.     profileList('ALIAS',aliasP); (* read [ALIAS] section from config. file *)
  1241.     getNextAlias(aliasP,aliasId,aliasString); (* get the first one (if any) *)
  1242.     profileList('TABLEALIAS',tableAliasP);
  1243.     getNextAlias(tableAliasP,tableAliasId,tableAliasString);
  1244.  
  1245.     (* process either "interrup.lst" or "interrup.a".."interrup.?" *)
  1246.     if NOT ProcessIntList('interrup.lst') then begin
  1247.       ch := 'a';
  1248.       while ProcessIntList('interrup.'+ch) do inc(ch);
  1249.     end; (* if NOT ProcessIntList() *)
  1250.  
  1251.     if aliasString<>'' then begin
  1252.       writeln(#7'Alias string not found:'#13#10+'  "',aliasString,'"');
  1253.       inc(warnings);
  1254.       if aliasP<>NIL then
  1255.     wl('One or more alias strings not processed.');
  1256.     end; (* if aliasP<>NIL *)
  1257.     if tableAliasString<>'' then begin
  1258.       writeln(#7'Table alias string not found:'#13#10+'  "',
  1259.     tableAliasString,'"');
  1260.       inc(warnings);
  1261.       if tableAliasP<>NIL then
  1262.     wl('One or more table alias strings not processed.');
  1263.     end; (* if tableAliasP<>NIL *)
  1264.  
  1265.     if indexColumns=1 then insertQueued
  1266.     else INTsToIndex;
  1267.  
  1268.     NewHlpPage(IndexFile, 'INTERRUP.1ST File', 'id1st','f:0', invalidClassification);
  1269.       { the program adds all following entries }
  1270.     ProcessFile('interrup.1st', 'INTERRUP.1ST File');
  1271.     if filtered then processFilter;
  1272.  
  1273.     processPages(windows); (* process Ports, Memory etc. *)
  1274.  
  1275.     if firstAliasP<>NIL then begin
  1276.       writeln(HPJ,#13#10'[ALIAS]');
  1277.       processAliasList(firstAliasP);
  1278.     end; (* if (firstAliasP<>NIL)... *)
  1279.     if twoIndexes then closeRTF(IntFile);
  1280.     closeRTF(SubIntFile);
  1281.     closeRTF(IntTopics);
  1282.     if tables then begin
  1283.       closeRTF(TableFile);
  1284.       closeRTF(TabTopics);
  1285.     end; (* if tables *)
  1286.     closeRTF(IndexFile);
  1287.     close(HPJ);
  1288.     if missingTableCounter>=missingTableLimit then
  1289.       writeln(missingTableCounter,' missing tables encountered.');
  1290.     ProcessTime:=memL[$40:$6C]-ProcessTime;
  1291.     writeln('The processing took ',(ProcessTime*10+91) DIV 182,' seconds.');
  1292.       (* 18.2 clock ticks per second, rounded *)
  1293.     i:=(maxTabTop*100) DIV tableArraySize;
  1294.     if i>60 then writeln(i,'% table array usage.');
  1295.     i:=(maxRefTop*100) DIV tableArraySize;
  1296.     if i>60 then writeln(i,'% reference array usage.');
  1297.     if insertCounter<>0 then writeln('Inserted ',insertCounter,' table references.');
  1298.     if warnings<>0 then begin
  1299.       writeln('Issued ',warnings,' warning(s).');
  1300.       halt(1);
  1301.     end; (* if warnings<>0 *)
  1302.   end.
  1303.