home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / TURBOPM.ZIP / TURBOPRT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-11-01  |  26.0 KB  |  818 lines

  1. program TURBOPRT;
  2. (*
  3.   Written by: Michael Roberts
  4.               3103 Glenview
  5.               Royal Oak, Mi 48073
  6.               Compuserve : 74226,3045
  7.  
  8.             Please let me know if you run into any problems or
  9.             have any suggestions!  This program is built on a listing
  10.             program by Rick Schaeffer of Washington.
  11. *)
  12.  
  13. (* Supported pseudo operations:
  14.     1) Listing control: {.L-} turns it off, {.L+} turns it back on,
  15.        must be in column 1
  16.     2. Page ejection: {.PAGE}, must be in column 1.
  17.     *)
  18.  
  19.  { When program is first run will check for a file
  20.    name passed by DOS, and will try to open that file.  If no name is
  21.    passed, will ask operator for a file name to open.  Proc will tell
  22.    operator if file doesn't exist and will allow multiple retrys.
  23.  
  24.    Optionally the file name can be passed via the command line.  Typing
  25.    a "/I" after the filename will expand includes. Examples:
  26.  
  27.      TURBOPRT  -  will invoke program and ask for file name to be listed
  28.  
  29.      TURBOPRT MYPROG.PAS  -  will list file "MYPROG.PAS"
  30.                              and not expand includes
  31.  
  32.      TURBOPRT MYPROG /I  -  will list file "MYPROG.PAS" and will expand
  33.                             includes.
  34.  
  35.    On 2nd and later executions, proc will not check for DOS passed file
  36.    name.  In all cases, proc will assume a file type of .PAS if file
  37.    type is not specified.
  38.    PROGRAM EXIT from this proc when a null string is encountered in
  39.    response to a file name request. }
  40.  
  41. {.PAGE}
  42. const
  43.   monthmask  = $000F;
  44.   daymask    = $001F;
  45.   minutemask = $003F;
  46.   secondmask = $001F;
  47.   First      : boolean = true;    {true when prog is run}
  48.  
  49. { to customize code for your printer - adjust the next items }
  50.  
  51.   maxline = 58;
  52.   cp = #15;         {compressed print}
  53.   rp = #18;         {regular width }
  54.   cr = #13;
  55.   lf = #10;
  56.   ff = #12;
  57.  
  58. type
  59.    ResWordPtr = ^ResWordRec;
  60.  
  61.    ResWordRec = Record
  62.                 ResWord: String[20];
  63.                 Next   : ResWordPtr;
  64.                 end;
  65.  
  66.    XrefWordptr = ^XrefwordRec;
  67.  
  68.    XrefNumPtr  = ^XrefNumRec;
  69.  
  70.    XrefWordRec = Record
  71.                  XrefWord: string[20];
  72.                  FirstXrefNum: XrefNumPtr;
  73.                  LastXrefNum : XrefNumPtr;
  74.                  NextXrefWord: XrefwordPtr;
  75.                  end;
  76.  
  77.    XrefNumRec  = record
  78.                  XrefNum : Integer;
  79.                  NextXrefNum:XrefNumPtr;
  80.                  end;
  81.  
  82.    alfa        = string[15];
  83.    two_letters = string[2];
  84.    dtstr       = string[8];
  85.    fnmtype     = string[40];
  86.    instring    = string[135];
  87.    IntPtrType  = ^Integer;
  88.    regpack     = record
  89.       ax,bx,cx,dx,bp,si,di,ds,es,flags : integer;
  90.    end;
  91.  
  92. Var
  93.   answer    : char;
  94.   Buff1     : instring;          {input line buffer}
  95.  
  96.   FirstResWord, LastResWord, NewResWord, SrchResWord: ResWordPtr;
  97.  
  98.   FirstxRefWord, NewxRefWord, PrevXrefWord, SrchxRefWord: XRefWordPtr;
  99.  
  100.   NewXRefnum, SrchXRefNum: XRefNumPtr;
  101.  
  102.   ResWord   : string[20];
  103.   XrefWord  : string[20];
  104.   XrefNum   : Integer;
  105.   wordchk   : alfa;
  106.   heaptop   : IntPtrType;
  107.   listfil   : text;              {FIB for LST: or CON: output}
  108.   infile    : text;              {FIB for input file}
  109.   initfile  : text;              {FIB for reserved word file}
  110.   fnam      : fnmtype;            {input file name}
  111.   file_path : fnmtype;           {path to input file}
  112.   bcount    : integer;           {begin/end counter}
  113.   kcount    : integer;           {comment counter}
  114.   linect    : integer;           {output file line counter}
  115.   RefLine   : integer;           {Line Reference number counter}
  116.   pageno    : integer;           {page counter}
  117.   offset    : integer;
  118.   print     : boolean;           (* {.L-} don't print *)
  119.                                  (* {.L+} print       *)
  120.   print_head : boolean;
  121.   Print_Xref : boolean;
  122.   path_found : boolean;
  123.   Word_switch: Boolean;
  124.   c,Print_opt: char;
  125.  
  126.   month, day, year,
  127.   hour, minute, second : two_letters;
  128.  
  129.   sysdate, systime,
  130.   filedate, filetime : dtstr;
  131.  
  132.   Lower_Right_X : Byte Absolute Cseg:$16A;
  133.   Lower_Right_Y : Byte Absolute Cseg:$16B;
  134.  
  135.   expand_includes    : boolean;
  136.   holdarg            : instring;
  137.   allregs            : regpack;
  138. {.page}
  139.  
  140. function parse_cmd(argno : integer) : instring;
  141. var
  142.    i,j : integer;
  143.    wkstr : instring;
  144.    done : boolean;
  145.    cmdline : ^instring;
  146. begin
  147.    cmdline := ptr(CSEG,$0080);
  148.    wkstr := '';
  149.    done := false; i := 1; j := 0;
  150.    if length(cmdline^) < i then done := true;
  151.    repeat
  152.       while ((cmdline^[i] = ' ') and (not done)) do begin
  153.          i := i + 1;
  154.          if i > length(cmdline^) then done := true;
  155.       end;
  156.       if not done then j := j + 1;
  157.       while ((cmdline^[i] <> ' ') and (not done)) do begin
  158.          wkstr := wkstr + cmdline^[i];
  159.          i := i + 1;
  160.          if i > length(cmdline^) then done := true;
  161.       end;
  162.       if (j <> argno) then wkstr := '';
  163.    until (done or (j = argno));
  164.    for i := 1 to length(wkstr) do
  165.       wkstr[i] := upcase(wkstr[i]); {all arguments forced to upper case}
  166.    parse_cmd := wkstr;
  167. end;
  168.  
  169. procedure getchar(var char_value : char);
  170.    begin
  171.      allregs.ax := $0000;
  172.      intr($16, allregs);
  173.      char_value := chr(ord(lo(allregs.ax)));
  174.    end; {getchar}
  175.  
  176. procedure fill_blanks (var line: dtstr);
  177.   var
  178.     i : integer;
  179. begin
  180.   for i:= 1 to 8 do if line[i] = ' ' then line[i]:= '0';
  181. end;  {fill_blanks}
  182.  
  183. Procedure Release_heap (a_heap_pointer : IntPtrType);
  184. var
  185.    i : integer;
  186.  
  187. begin
  188.    i := ((seg(heapptr^) - seg(a_heap_pointer^)) shl 4) +
  189.         (ofs(heapptr^) - ofs(a_heap_pointer^));
  190.    FreeMem(a_heap_pointer,i);
  191. end; {release_heap}
  192.  
  193. procedure getdate(var date : dtstr);
  194.  
  195. begin
  196.    allregs.ax := $2A * 256;
  197.    MsDos(allregs);
  198.    str((allregs.dx div 256):2,month);
  199.    str((allregs.dx mod 256):2,day);
  200.    str((allregs.cx - 1900):2,year);
  201.    date := month + '/' + day + '/' + year;
  202.    fill_blanks (date);
  203. end;  {getdate}
  204.  
  205. procedure gettime(var time : dtstr);
  206.  
  207. begin
  208.    allregs.ax := $2C * 256;
  209.    MsDos(allregs);
  210.    str((allregs.cx div 256):2,hour);
  211.    str((allregs.cx mod 256):2,minute);
  212.    str((allregs.dx div 256):2,second);
  213.    time := hour + ':' + minute + ':' + second;
  214.    fill_blanks (time);
  215. end;  {gettime}
  216.  
  217. procedure WhenCreated (var date, time: dtstr; var infile: text);
  218.  
  219. var fulltime,fulldate: integer;
  220.  
  221. begin
  222.  
  223. {fulldate gets the area of the FIB which corresponds to bytes 20-21
  224.  of the FCB. Format is: bits 0 - 4: day of month
  225.                              5 - 8: month of year
  226.                              9 -15: year - 1980                     }
  227.  
  228.     fulldate:= memw [seg(infile):ofs(infile)+31];
  229.     str(((fulldate shr 9) + 80):2,year);
  230.     str(((fulldate shr 5) and monthmask):2,month);
  231.     str((fulldate and daymask):2,day);
  232.     date:= month + '/' + day + '/' + year;
  233.     fill_blanks(date);
  234.  
  235. {fulltime gets the area of the FIB which corresponds to bytes 22-23
  236.  of the FCB. Format is: bits 0 - 4: seconds/2
  237.                              5 -10: minutes
  238.                              11-15: hours                          }
  239.  
  240.     fulltime:= memw [seg(infile):ofs(infile)+33];
  241.     str((fulltime shr 11):2,hour);
  242.     str(((fulltime shr 5) and minutemask):2,minute);
  243.     str(((fulltime and secondmask) * 2):2,second);
  244.     time:= hour + ':' + minute + ':' + second;
  245.     fill_blanks (time);
  246. end;  {WhenCreated}
  247.  
  248. PROCEDURE Initialize;
  249.  
  250. {Here we load in the reserved word file and create a linked list}
  251.  
  252. BEGIN
  253.      assign(initfile,'TURBOPAS.RES');
  254.      {$I-} reset(initfile) {$I+};
  255.      if IOresult <> 0 then begin
  256.         writeln('File TURBOPAS.RES not found... Program aborted!!!');
  257.         halt;
  258.      end;
  259.      FirstResWord := nil;
  260.      while not eof(initfile) do
  261.      begin
  262.           readln(initfile,ResWord);
  263.           if length(ResWord) <> 0 then
  264.              begin
  265.                   New(NewResWord);
  266.                   NewResWord^.ResWord := Resword;
  267.                   if FirstResWord = nil then
  268.                      FirstResWord := NewResWord
  269.                   else
  270.                      LastResWord^.next := NewResWord;
  271.                   LastResWord := NewResWord;
  272.                   LastResWord^.Next := Nil;
  273.              end;
  274.      end;
  275.      close(initfile);
  276. END; {of Initialize}
  277.  
  278. Function Find_in_Reserve(var kword: alfa) : boolean;
  279.  
  280. { This routine returns a boolean true false if the word passed to it is found
  281.   in the linked list of reserved words }
  282.  
  283. Begin
  284.     SrchResWord := firstresword;
  285.  
  286.     while ((kword > srchresword^.resword) and (srchresword <> nil)) do
  287.           srchresword := srchresword^.next;
  288.  
  289.     if srchresword = nil then
  290.        Find_in_Reserve := FALSE
  291.     else
  292.         if kword = srchresword^.resword then
  293.            Find_in_reserve := true
  294.         else
  295.             Find_in_reserve := False;
  296. End;
  297.  
  298. Procedure BuildXref;
  299.  
  300. Procedure NewNum(var current, last: xrefnumptr);
  301. Begin
  302.      new(NewXrefNum);
  303.      current := NewXrefNum;
  304.      Last    := NewXrefNum;
  305.      NewXrefNum^.NextXrefNum := nil;
  306.      NewXrefNum^.XrefNum := RefLine;
  307. end;
  308.  
  309. Begin
  310.      if ((FirstXrefWord = nil) or (FirstXrefWord^.XrefWord > wordchk)) then
  311.         begin
  312.              new(newxrefword);
  313.              NewXrefWord^.NextXrefWord := FirstXrefWord;
  314.              FirstXrefWord := NewXrefWord;
  315.              FirstXrefWord^.XrefWord := wordchk;
  316.              NewNum(FirstXrefWord^.FirstXrefNum, FirstXrefWord^.LastXrefNum);
  317.          end
  318.      else
  319.      begin
  320.           If firstXrefWord^.xrefword = wordchk then
  321.                NewNum(FirstXrefWord^.LastXrefNum^.NextXrefNum,
  322.                       FirstXrefWord^.LastXrefNum)
  323.           else
  324.           Begin
  325.                SrchXrefWord := FirstXrefword^.NextXrefWord;
  326.                PrevXrefWord := FirstXrefWord;
  327.                While ((SrchXrefWord <> Nil) and
  328.                (SrchXrefWord^.XrefWord < WordChk)) do
  329.                begin
  330.                     PrevXrefWord := SrchXrefWord;
  331.                     SrchXrefWord := SrchXrefWord^.NextXrefWord;
  332.                end;
  333.                If ((SrchXrefWord = nil) and
  334.                   (PrevXrefWord^.XrefWord < wordchk)) then
  335.                   Begin
  336.                        new(newxrefword);
  337.                        NewXrefWord^.NextXrefWord := Nil;
  338.                        PrevXrefWord^.NextXrefWord := NewXrefWord;
  339.                        NewXrefWord^.XrefWord := wordchk;
  340.                        NewNum(NewXrefWord^.FirstXrefNum,
  341.                               NewXrefWord^.LastXrefNum);
  342.                   end
  343.                   else
  344.                       if SrchXrefWord^.XrefWord > Wordchk Then
  345.                       Begin
  346.                            new(newxrefword);
  347.                            NewXrefWord^.NextXrefWord := SrchXrefWord;
  348.                            PrevXrefWord^.NextXrefWord := NewXrefWord;
  349.                            NewXrefWord^.XrefWord := wordchk;
  350.                            NewXrefWord^.LastXrefNum := Nil;
  351.                            NewNum(NewXrefWord^.FirstXrefNum,
  352.                                   NewXrefWord^.LastXrefNum);
  353.                       end
  354.                       else
  355.                            If SrchXrefword^.lastxrefnum^.Xrefnum <> RefLine
  356.                            then
  357.                                 NewNum(SrchXrefWord^.LastXrefNum^.NextXrefNum,
  358.                                        SrchXrefWord^.LastXrefNum);
  359.           end;
  360.      end;
  361. end;
  362.  
  363. procedure print_heading(filename : fnmtype);
  364.  
  365. var offset_inc: integer;
  366.  
  367. begin
  368.    if print then
  369.      begin
  370.        pageno := pageno + 1;
  371.        write(listfil, ff);  {top of form}
  372.        writeln(listfil);
  373.        write(listfil,'     TURBO Pascal Program Lister');
  374.        writeln(listfil,' ':8,'Printed: ',sysdate,'  ',
  375.                systime,'   Page ',pageno:4);
  376.        if filename <> fnam then begin
  377.           offset_inc:= 21 - length (filename);
  378.           write(listfil,'     Include File: ',filename,' ':offset_inc,
  379.              'Created: ',filedate,'  ',filetime);
  380.        end
  381.        else write(listfil,'     Main File: ',fnam,' ':offset,
  382.              'Created: ',filedate,'  ',filetime);
  383.        writeln(listfil); writeln(listfil);
  384.        If Print_Xref then
  385.           Writeln(Listfil,' ':32,'CROSS-REFERENCE')
  386.        else
  387.            writeln(listfil, '      K  B');
  388.        writeln(listfil);
  389.        linect := 6;
  390.      end; {check for print}
  391. end;  {print_heading}
  392.  
  393. procedure printline(iptline : instring; filename : fnmtype);
  394. begin
  395.    if print then
  396.      begin
  397.        if linect < 56 then
  398.          begin
  399.           writeln(listfil,'     ',iptline);
  400.           linect := linect + 1;
  401.          end
  402.           else
  403.            begin
  404.              print_heading(filename);
  405.            end;
  406.      end; {check for print}
  407. end;  {printline}
  408.  
  409. {.page}
  410. function chkinc(var iptline : instring; var incflname : fnmtype) : boolean;
  411. var
  412.    done : boolean;
  413.    i, j : integer;
  414. begin
  415.    i := 4; j := 1; incflname := '';
  416.    if ((copy(iptline, 1, 3) = '{$I') or
  417.        (copy(iptline, 1, 4) = '(*$I')) then begin
  418.          if copy(iptline, 1, 4) = '(*$I' then i := 5;
  419.          incflname := '';
  420.          while (iptline[i] = ' ') and (i <= length(iptline)) do i := i + 1;
  421.          done := false;
  422.          while not done do begin
  423.                if i <= length(iptline) then begin
  424.                   if not (iptline[i] in [' ','}','+','-','*']) then begin
  425.                      incflname[j] := iptline[i];
  426.                      i := i + 1; j := j + 1;
  427.                   end else done := true;
  428.               end else done := true;
  429.               if j > 14 then done := true;
  430.          end;
  431.          incflname[0] := chr(j - 1);
  432.    end;
  433.    if incflname <> '' then
  434.      begin
  435.           chkinc := true;
  436.           for i := 1 to length(Incflname) do
  437.               incflname[i] := upcase(incflname[i]);
  438.      end
  439.      else
  440.          chkinc := false;
  441. end;  {chkinc}
  442.  
  443.  
  444.  PROCEDURE GET_IN_FILE;     {GETS INPUT FILE NAME }
  445.    var
  446.     existing : boolean;
  447.     i        : integer;
  448.   begin
  449.     repeat             {until file exists}
  450.       holdarg := parse_cmd(1); {get command line argument # 1}
  451.       if (length(holdarg) in [1..40]) and first then
  452.         fnam := holdarg  {move possible file name to fnam}
  453.       else
  454.         begin
  455.           clrscr;
  456.           gotoxy(1,1);
  457.           write(' ':30,'TURBOPRT - Release 1.0');
  458.           gotoxy(1,3);
  459.           write(' ENTER FILE NAME TO LIST or <cr> to EXIT  ');
  460.           readln(fnam);
  461.           if fnam <> '' then
  462.              begin
  463.                   writeln;write(' EXPAND INCLUDES? (Y/N) ');
  464.                   readln(answer);
  465.                   if upcase(answer) = 'Y' then
  466.                      expand_includes := true
  467.                   else
  468.                       expand_includes := false
  469.              end
  470.         end;
  471.  
  472.      for i := 1 to length(fnam) do
  473.          fnam[i] := upcase(fnam[i]);
  474.  
  475.      if fnam = '' then          {***** EXIT *****}
  476.      begin
  477.           clrscr;
  478.           halt;
  479.      end;
  480.  
  481.      if pos('.',fnam) = 0 then       {file type given?}
  482.        fnam := concat(fnam,'.PAS');  {file default to .PAS type}
  483.  
  484.      {get optional command line argument # 2}
  485.      if (length(holdarg) in [1..14]) and first then
  486.        begin
  487.          holdarg := parse_cmd(2);
  488.          if holdarg = '/I' then expand_includes := true
  489.             else expand_includes := false;
  490.        end;
  491.  
  492.      first := false;                 {get passed file name only once}
  493.      assign( infile, fnam);
  494.        {$I-}
  495.      reset( infile );                {check for existence of file}
  496.        {$I+}
  497.      existing := (ioresult = 0);     {true if file found}
  498.      if not existing then
  499.        begin
  500.         writeln;
  501.         writeln(' FILE DOESN''T EXIST'); {tell operator the sad news}
  502.         sound(500);
  503.         delay(250);
  504.         nosound;
  505.         delay(2000);
  506.        end;
  507.      if existing then
  508.        begin                             {obtain path for include files}
  509.           I := length(fnam);
  510.           path_found := false;
  511.           while ((I > 0) and Not Path_found) do
  512.              if (fnam[i] in ['\',':']) then Path_found := true
  513.              else I := I - 1;
  514.  
  515.           if Path_found then
  516.           begin
  517.              file_path := copy(fnam,1,I);
  518.              fnam := copy(fnam,(i+1),(length(fnam)));
  519.           end;
  520.        end;
  521.     until existing;                     {until file exists}
  522.  
  523.  
  524.  end; {GET_IN_FILE}
  525.  
  526. { GET_OUT_FILE procedure asks operator to select output to console
  527.   device or list device, and then assigns and resets a file control
  528.   block to the appropriate device.  'C' or 'P' is only correct
  529.   response, and multiple retrys are allowed. }
  530.  
  531. Procedure Get_Out_File;
  532.   begin
  533.     repeat    {until good selection}
  534.       gotoxy(1,7);
  535.       clreol;
  536.       write(' OUTPUT LISTING TO (C)ONSOLE OR (P)RINTER ?  ');
  537.       getchar(c);
  538.       c := upcase(c); write(c);
  539.    until c in ['C', 'P'];
  540.  
  541.    writeln;
  542.    if c = 'C' then
  543.       assign (listfil, 'CON:')
  544.    else
  545.       assign (listfil, 'LST:');
  546.  
  547.    reset(listfil);
  548.    if c = 'P' then begin
  549.      repeat
  550.       gotoxy(1,9);
  551.       clreol;
  552.       Write(' (C)OMPRESSED PRINT OR (R)EGULAR PRINT ? ');
  553.       getchar(print_opt);
  554.       print_opt := upcase(print_opt);
  555.       write(print_opt);
  556.     until print_opt in ['C','R'];
  557.     writeln;
  558.     if print_opt = 'R' then write(listfil,rp);
  559.    end;
  560.  end;  {GET_OUT_FILE}
  561. {.page}
  562. Procedure ListIt(filename : fnmtype); forward;
  563. { SCAN_LINE procedure scans one line of Turbo Pascal source code
  564.   looking for BEGIN/END pairs, CASE/END pairs, LITERAL fields
  565.   and COMMENT fields.  BCOUNT is begin/end and case/end counter.
  566.   KCOUNT is comment counter.  Begin/case/ends are only valid
  567.   outside of comment fields and literal constant fields (KCOUNT = 0
  568.   and NOT LITERAL).
  569.   Some of the code in the SCAN_LINE procedure appears at first glance
  570.   to be repitive and/or redundant, but was added to speed up the
  571.   process of scanning each line of source code.}
  572.  
  573. Procedure SCAN_LINE;
  574.   var
  575.     literal : boolean;          { true if in literal field}
  576.     tmp     : string[7];        { tmp work area }
  577.     i       : integer;          {loop variable index}
  578.     buff2   : instring;         {working line buffer}
  579.     incflname : fnmtype;        {in file name}
  580.     filedate_save : dtstr;
  581.     filetime_save : dtstr;
  582.   begin
  583.     literal := false;
  584.  
  585.     buff2[0] := buff1[0];  {copy input buffer to working buffer}
  586.     for i := 1 to length(buff1) do
  587.      buff2[i] := upcase(buff1[i]);  {and translate to upper case}
  588.  
  589.     if chkinc(buff2, incflname) and expand_includes then
  590.        begin
  591.        for i := 1 to length(incflname) do
  592.            incflname[i] := upcase(incflname[i]);
  593.           if pos('.',incflname) = 0 then incflname := incflname + '.PAS';
  594.           printline('*************************************',incflname);
  595.           printline('    Including "'+incflname+'"', incflname);
  596.           printline('*************************************',incflname);
  597.           filedate_save := filedate;  {save filedate & filetime for}
  598.           filetime_save := filetime;  {main file                   }
  599.           listit(incflname);
  600.           filedate := filedate_save;  {restore}
  601.           filetime := filetime_save;
  602.           printline('*************************************',incflname);
  603.           printline('    End of    "'+incflname+'"', incflname);
  604.           printline('*************************************',incflname);
  605.           RefLine := RefLine - 1;
  606.          end;  {include file check}
  607.  
  608.     if copy(buff2,1,5) = '{.L-}' then
  609.        begin
  610.             print := false;
  611.             if length(buff2) = 5 then
  612.                RefLine := RefLine - 1;
  613.        end;
  614.  
  615.     if copy(buff2,1,5) = '{.L+}' then
  616.        begin
  617.             print := true;
  618.             if length(buff2) = 5 then
  619.                RefLine := RefLine - 1;
  620.        end;
  621.  
  622.     if copy(buff2,1,7) = '{.PAGE}' then
  623.        begin
  624.             print_head := true;
  625.             if length(buff2) = 7 then
  626.                RefLine := RefLine - 1;
  627.        end;
  628.  
  629.     if length(buff2) > 0 then
  630.        RefLine := RefLine + 1;
  631.  
  632.     buff2 := concat('  ', buff2, '      ');  {add on some working space}
  633.     for i := 1 to length(buff2) - 6 do
  634.       begin
  635.         tmp := copy(buff2, i, 7);
  636.         if not literal then   {possible to find comment delim}
  637.           begin
  638.            {determine if comment area delim}
  639.            if tmp[1] in ['{', '}', '(', '*'] then
  640.              begin
  641.                if (tmp[1] = '{') or (copy(tmp,1,2)='(*') then
  642.                  kcount := succ(kcount);  {count comment opens}
  643.                if (tmp[1] = '}') or (copy(tmp,1,2)='*)') then
  644.                  kcount := pred(kcount);  {un-count comment closes}
  645.              end;
  646.           end;
  647.  
  648.          if kcount = 0 then  {we aren't in a comment area}
  649.            begin
  650.             if tmp[1] = chr(39) then
  651.               literal := not literal;   {toggle literal flag}
  652.             if not literal then
  653.             begin
  654.               if ((not Word_switch) and
  655.                  (buff2[i] in ['A'..'Z']) and
  656.                  (not (buff2[i-1] in ['0'..'9','A'..'Z']))) then
  657.                            Begin
  658.                                 Word_switch := true;
  659.                                 wordchk := '';
  660.                            end;
  661.               if word_switch then
  662.                  if (buff2[i] in ['A'..'Z','0'..'9','_']) then
  663.                     wordchk := concat(wordchk,Buff2[i])
  664.                  else
  665.                  begin
  666.                       word_switch := false;
  667.                       if not find_in_reserve(wordchk) then
  668.                          BuildXref;
  669.                  end;
  670.               end;
  671.            if not literal and (tmp[2] in ['B','C','E']) then
  672.              begin
  673.                if (tmp = ' BEGIN ') or (copy(tmp,1,6) = ' CASE ') then
  674.                 begin
  675.                  bcount := succ(bcount);  {count BEGIN}
  676.                  i := i + 5;              {skip rest of begin}
  677.                 end;
  678.                if (copy(tmp,1,4) = ' END') and
  679.                   (tmp[5] in ['.', ' ', ';']) and
  680.                    (bcount > 0) then
  681.                 begin
  682.                  bcount := pred(bcount);   {un-count for END}
  683.                  i := i + 4;
  684.                 end;
  685.  
  686.               end;  {if not literal}
  687.            end;  { if kcount = 0 }
  688.         end;  { for i := }
  689.     end;  {SCAN_LINE}
  690. {.page}
  691. Procedure ListIt;
  692.   var
  693.     infile : text;
  694.     full_filename : fnmtype;
  695.   begin
  696.     if path_found then
  697.        full_filename := concat(file_path,filename)
  698.     else
  699.        Full_filename := filename;
  700.      assign(infile, full_filename);
  701.    {$I-} reset(infile) {$I+} ;
  702.    if IOresult <> 0 then begin
  703.       writeln ('File ',filename,' not found.');
  704.       halt;
  705.    end;
  706.      WhenCreated (filedate,filetime,infile);
  707.      if filename = fnam then
  708.          print_heading(filename);
  709.          while not eof(infile) do
  710.            begin
  711.             readln(infile, buff1);
  712.             scan_line;
  713.             if print_head then
  714.                 print_heading(filename);
  715.             if print and (not print_head) then
  716.               begin
  717.                 if length(buff1) > 0 then
  718.                    if print_opt = 'C' then
  719.                       writeln(listfil,RefLine:4, kcount:3,bcount:3,
  720.                       ' ',cp,buff1,rp)
  721.                    else
  722.                        writeln(listfil,RefLine:4, kcount:3,bcount:3,
  723.                        ' ',buff1)
  724.                 else
  725.                    writeln(listfil,'        ',buff1);
  726.                 linect := succ(linect);
  727.                 if linect > maxline then
  728.                   begin
  729.                     print_heading(filename);
  730.                   end;
  731.               end;
  732.             print_head := false;
  733.          end;     {while not eof}
  734.   end; {ListIt}
  735.  
  736. Procedure ListXref;
  737. Const
  738.      blnk = ' ';
  739. Var
  740.    x, y: Integer;
  741.  
  742. Begin
  743.      Print_Xref := True;
  744.      Print_heading(fnam);
  745.      Srchxrefword := Firstxrefword;
  746.      while SrchXrefWord <> Nil Do
  747.      Begin
  748.           x := 20 - Length(SrchXrefWord^.XrefWord);
  749.           for y := 1 to x do
  750.               SrchXrefWord^.XrefWord := concat(SrchXrefWord^.XrefWord,blnk);
  751.           Write(listfil,srchxrefword^.XrefWord);
  752.           x := 0;
  753.           SrchXrefNum := SrchXrefWord^.FirstXrefNum;
  754.           while SrchXrefNum <> Nil do
  755.           begin
  756.                if X < 10 then
  757.                begin
  758.                     Write(listfil,SrchXrefNum^.XrefNum:5);
  759.                     x := X + 1;
  760.                end
  761.                else
  762.                begin
  763.                     Writeln(listfil);
  764.                     Linect := linect + 1;
  765.                     if linect > maxline then Print_heading(fnam);
  766.                     Write(listfil,blnk:20,SrchxrefNum^.XrefNum:5);
  767.                     x := 0;
  768.                end;
  769.                SrchXrefNum := SrchXrefNum^.NextXrefNum;
  770.           end;
  771.           writeln(listfil);
  772.           Linect := linect+1;
  773.           if linect > Maxline then Print_heading(fnam);
  774.           SrchXrefWord := SrchXrefWord^.NextXrefWord;
  775.      end;
  776. end;
  777. {.page}
  778.   begin {main procedure}
  779.      getdate(sysdate);
  780.      gettime(systime);
  781.      expand_includes := false;       {default settings}
  782.      print := true;
  783.      initialize;
  784.      Mark(heaptop);
  785.  
  786.    repeat {forever}
  787.  
  788.      Print_opt := ' ';
  789.      FirstXrefWord := nil;
  790.      ClrScr;
  791.      GotoXY(2, 2);
  792.      get_in_file;      {file to list}
  793.      offset := 24 - length(fnam);
  794.      get_out_file;     {where to list it}
  795.      pageno := 0;
  796.      linect := 1;      {output line counter}
  797.      kcount := 0;
  798.      RefLine := 0;
  799.      bcount := 0;
  800.      print_head := false;
  801.      Print_xref := False;
  802.      word_switch:= False;
  803.      listit(fnam);
  804.      Listxref;
  805.      writeln(listfil);
  806.      Release_Heap(heaptop); {purge previous cross reference}
  807.      write(cr, lf, 'HIT ANY KEY TO CONTINUE ');  {allow op to see end
  808.                                                  of listing}
  809.     getchar(c);
  810.     until false {repeat forever - exit is in GET_IN_FILE PROCEDURE}
  811.  end.  {main procedure}
  812. includes := false;       {default settings}
  813.      print := true;
  814.      initialize;
  815.      Mark(heaptop);
  816.  
  817.    repeat {forever}
  818.