home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / asmutl / chkif.lbr / CHKIF.PZS / CHKIF.PAS
Pascal/Delphi Source File  |  1987-09-09  |  6KB  |  248 lines

  1. program chkif(ifil,output);
  2. {
  3. CHKIF v0.1 by J.Loke 87Sep06
  4. Checks an ASM or PRN program for correct conditional assembly
  5. and macro balance.
  6.  
  7. Vers Date    Name       Notes
  8. 0.10 87Sep06 J.Loke     Original version in TURBO Pascal
  9.      Known bug: Will not process statements with non-comment ';'
  10.      Known bug: Will not process COMMENT <flg> properly
  11. }
  12. type
  13.   str=string[255];
  14. var
  15.   cmd: string[127] absolute $80;
  16.   ifil: text;
  17.   p,v: boolean;
  18.   i,m,n: byte;
  19.   l: integer;
  20.   lif,lelse,lmacro,nmacro: array [1..16] of integer;
  21.   a,b,c: str;
  22. function kwd(wrd: str): boolean;
  23. {
  24.   KWD uses global variable b: str
  25.   KWD returns true if WRD is a keyword in string B
  26.   WRD must be delimited by chars belonging to the set PUNC,
  27.   else KWD returns false
  28. }
  29.   const
  30.     punc: set of char = [#0..'?','['..'`','{'..'~'];
  31.   var
  32.     i: byte;
  33.     f: boolean;
  34.   begin
  35.     i:=pos(wrd,b);
  36.     if (i=0) then
  37. {
  38. WRD not in string B
  39. }
  40.       f:=false
  41.     else
  42.     begin
  43.       f:=true;
  44. {
  45. Test if a PUNCtuation char precedes WRD
  46. }
  47.       if (i>1) then
  48.         f:=(b[i-1] in punc);
  49. {
  50. Test if a PUNCtuation char follows WRD
  51. }
  52.       if (f) then
  53.         if (i<length(b)-length(wrd)) then
  54.           f:=(b[i+length(wrd)] in punc);
  55.     end; {if (i=0) else}
  56.     kwd:=f;
  57.   end; {function kwd}
  58. begin
  59.   writeln('CHKIF v0.1 by J.Loke 87Sep06');
  60. {
  61. Check quiet option specifier
  62. }
  63.   while (copy(cmd,1,1)=' ') do
  64.     delete(cmd,1,1);
  65.   if (copy(cmd,1,2)='-Q') then
  66.   begin
  67.     v:=false;
  68.     delete(cmd,1,2);
  69.     while (copy(cmd,1,1)=' ') do
  70.       delete(cmd,1,1);
  71.   end
  72.   else
  73.     v:=true;
  74. {
  75. No parameter invokes USAGE display
  76. }
  77.   if (length(cmd)=0) then
  78.     writeln('Usage:  CHKIF [-Q] <file>     -Q=quiet')
  79.   else
  80.   begin
  81. {
  82. Open file for sequential read
  83. }
  84.     assign(ifil,cmd);
  85.     reset(ifil);
  86. {
  87. Set P flag if PRN output truncation needed
  88. }
  89.     p:=(pos('.PRN',cmd)>0);
  90. {
  91. Initialize line counter, IF/ELSE and MACRO level pointers
  92. }
  93.     l:=0;
  94.     n:=0;
  95.     m:=0;
  96. {
  97. Process each line of the file
  98. }
  99.     while not(eof(ifil)) do
  100.     begin
  101.       readln(ifil,c);
  102.       l:=l+1;
  103. {
  104. If .PRN file, strip address and HEX display
  105. }
  106.       if (p) then begin
  107.         i:=16;
  108.         if (copy(c,1,1)=#12) then
  109.           i:=i+1;
  110.         delete(c,1,i);
  111.       end; {if (p)}
  112. {
  113. Process each statement of the file
  114. }
  115.       while (length(c)>0) do
  116.       begin
  117. {
  118. Strip statement from multi-statement line
  119. }
  120.         i:=pos('!',c+'!')-1;
  121.         a:=copy(c,1,i);
  122.         delete(c,1,i+1);
  123. {
  124. Ignore assembly directives or comment lines
  125. }
  126.         if (copy(a,1,1)='$') or (copy(a,1,1)='*') then
  127.           i:=0
  128.         else begin
  129. {
  130. Strip leading spaces and tabs
  131. }
  132.           while (copy(a,1,1)=' ') or (copy(a,1,1)=#9) do
  133.             delete(a,1,1);
  134.           i:=pos(';',a+';')-1
  135.         end;
  136.         if (i>0) then
  137.         begin
  138. {
  139. Process non-empty statements, convert to upper case
  140. }
  141.           b:=copy(a,1,i);
  142.           for i:=1 to length(b) do
  143.             b[i]:=upcase(b[i]);
  144. {
  145. ENDIF keyword
  146. }
  147.           if kwd('ENDIF') then
  148.           begin
  149.             if v then
  150.               writeln(l:5+n+m,' ',a);
  151.             if (n=0) then
  152.               writeln(l:5+n+m,'*ENDIF: No matching IF')
  153.             else
  154.               n:=n-1;
  155.           end {if kwd('ENDIF') then }
  156. {
  157. IF keyword
  158. }
  159.           else if kwd('IF') then
  160.           begin
  161.             if v then
  162.               writeln(l:6+n+m,' ',a);
  163.             if (n=8) then
  164.               writeln(l:6+n+m,'*IF: Too many IF''s');
  165.             n:=n+1;
  166.             lif[n]:=l;
  167.             lelse[n]:=0;
  168.           end {else if kwd('IF')}
  169. {
  170. ELSE keyword
  171. }
  172.           else if kwd('ELSE') then
  173.           begin
  174.             if v then
  175.               writeln(l:5+n+m,' ',a);
  176.             if (n=0) then
  177.               writeln(l:5+n+m,'*ELSE: Missing IF')
  178.             else begin
  179.               if (lelse[n]<>0) then
  180.                 writeln(l:5+n+m,'*ELSE: Missing ENDIF');
  181.               lelse[n]:=l;
  182.             end
  183.           end {else if kwd('ELSE')}
  184. {
  185. MACRO keywords
  186. }
  187.           else if kwd('MACRO')or kwd('IRP')or kwd('IRPC')or kwd('REPT') then
  188.           begin
  189.             if v then
  190.               writeln(l:6+n+m,' ',a);
  191.             if (m=8) then
  192.               writeln(l:6+n+m,'*MACRO: Too many MACRO''s');
  193.             m:=m+1;
  194.             lmacro[m]:=l;
  195.             nmacro[m]:=n;
  196.           end {else if kwd('MACRO')or kwd('IRP')or kwd('IRPC')or kwd('REPT')}
  197. {
  198. EXITM keyword
  199. }
  200.           else if kwd('EXITM') then
  201.           begin
  202.             if v then
  203.               writeln(l:5+n+m,' ',a);
  204.             if (m=0) then
  205.               writeln(l:5+n+m,'*EXITM: Missing MACRO')
  206.           end {else if kwd('EXITM')}
  207. {
  208. ENDM keyword
  209. }
  210.           else if kwd('ENDM') then
  211.           begin
  212.             if v then
  213.               writeln(l:5+n+m,' ',a);
  214.             if (m=0) then
  215.               writeln(l:5+n+m,'*ENDM: Missing MACRO')
  216.             else
  217.               m:=m-1
  218.           end {else if kwd('ENDM')}
  219. {
  220. Process next statement on this line
  221. }
  222.         end {if (i>0)}
  223.       end {length(c)=0}
  224.     end; {while not(eof(ifil))}
  225.     writeln;
  226. {
  227. IF/ELSE/ENDIF balance error
  228. }
  229.     if (n>0) then
  230.       for i:=n downto 1 do begin
  231.         write('CHKIF: Missing ENDIF.  Unmatched IF at line',lif[i]:6);
  232.         if (lelse[i]<>0) then
  233.           write(' Unmatched ELSE at line',lelse[i]:6);
  234.         writeln
  235.       end; {for i:=n downto 1}
  236. {
  237. MACRO/ENDM balance error
  238. }
  239.     if (m>0) then
  240.       for i:=m downto 1 do
  241.         writeln('CHKIF: Missing ENDM.  Unmatched MACRO at line',lmacro[i]:6);
  242.   end; {if (length(cmd)=0)}
  243. {
  244. End of Program
  245. }
  246.   writeln('CHKIF: Done');
  247. end.
  248.