PROGRAM P3EXT; { File: [22,310]P3EXT.PAS Author: Phil Hannay oct-87 Last Edit: 12-APR-1989 08:55:42 History: Phil Hannay -- 26-Jan-84 Fixed bug where leading characters were not ignored when searching for procedure or function keyword. Phil Hannay -- 19-Oct-83 Changed output file name to a max of 9 chars from the old max of 6 chars. Phil Hannay -- 7-Oct-83 Fixed bug where a procedure name starting with a lower case letter was not found. } {Error handling is done a little differently than normal. We will work away assuming all is in order until proven otherwise. When proven otherwise, we will issue an error message, and then continue as normal, which will cause us to crash the program by attempting some fatal action. This way we need not provide any means of funneling errors to the normal program exit. Since all errors are unrecoverable, there is no need to come to a controlled stop, and further, we can then put this program in a command file that can then use to see if we terminated normally or not.} %INCLUDE pas$ext:General.typ PROCEDURE EXITST(STATUS:INTEGER);EXTERNAL; {OMSI supplied external to exit w/status} CONST TRANFILNAME='TRANEXT.DAT;1'; VAR PASFIL,EXTFIL:TEXT; PASFILNAME,EXTFILDEV:PACKED ARRAY [1..25] OF CHAR; ENTRY,ENTRYHOLD:CH10; ENTRYLEN:INTEGER; DONE:BOOLEAN; PROCEDURE GET_PARAMETERS; VAR TRANFIL:TEXT; I,FILSTAT:INTEGER; BEGIN RESET(TRANFIL,TRANFILNAME,,FILSTAT); IF FILSTAT<=0 THEN BEGIN WRITELN('P3EXT> Error: could not open file "',TRANFILNAME,'"'); EXITST(4) END; READLN(TRANFIL,PASFILNAME); READLN(TRANFIL,ENTRY); ENTRYLEN:=1; ENTRY[10]:=' '; WHILE ENTRY[ENTRYLEN]<>' ' DO ENTRYLEN:=ENTRYLEN+1; {Blank out any letters following the first occurring space} FOR I:=ENTRYLEN TO 10 DO ENTRY[I]:=' '; ENTRYLEN:=ENTRYLEN-1; READLN(TRANFIL,EXTFILDEV); CLOSE(TRANFIL); END; {PROCEDURE GET_PARAMETERS} PROCEDURE PUT_EXTERNAL_CALL; VAR I,COUNT:INTEGER; BUFFER:PACKED ARRAY [1..133] OF CHAR; PROCHOLD:CH9; FOUND_HEADER:BOOLEAN; PROCEDURE PUT_CALL; VAR SYMBOL:CHAR; I,LINELEN:INTEGER; BEGIN WRITELN(EXTFIL); WHILE NOT((BUFFER[COUNT]=';')OR(BUFFER[COUNT]='(')OR(BUFFER[COUNT]=':')) DO BEGIN IF COUNT>132 THEN BEGIN LINELEN:=133; WHILE (LINELEN>1) AND (BUFFER[LINELEN]=' ') DO LINELEN:=LINELEN-1; FOR I:=1 TO LINELEN DO WRITE(EXTFIL,BUFFER[I]); WRITELN(EXTFIL); IF EOF(PASFIL) THEN BEGIN WRITELN('P3EXT> Error: no ";" after ', 'procedure (function) header'); EXITST(4) END; READLN(PASFIL,BUFFER); BUFFER[133]:=' '; IF BUFFER[1]=';' THEN BUFFER[1]:=' '; COUNT:=1 END ELSE BEGIN COUNT:=COUNT+1 END END; CASE BUFFER[COUNT] OF '(':SYMBOL:=')'; ':':SYMBOL:=';'; ';': BEGIN SYMBOL:=';'; COUNT:=COUNT-1 END; OTHERWISE SYMBOL:=';' END; {CASE} REPEAT IF COUNT>132 THEN BEGIN LINELEN:=133; WHILE (LINELEN>1) AND (BUFFER[LINELEN]=' ') DO LINELEN:=LINELEN-1; FOR I:=1 TO LINELEN DO WRITE(EXTFIL,BUFFER[I]); WRITELN(EXTFIL); IF EOF(PASFIL) THEN BEGIN WRITELN('P3EXT> Error: no "',SYMBOL,'" found'); EXITST(4) END; READLN(PASFIL,BUFFER); BUFFER[133]:=' '; IF BUFFER[1]=';' THEN BUFFER[1]:=' '; COUNT:=1 END ELSE BEGIN COUNT:=COUNT+1 END; IF BUFFER[COUNT]=')' THEN SYMBOL:=';' UNTIL BUFFER[COUNT]=SYMBOL; {We are now at the end of the procedure call. We will copy just up to this terminating semi-colon, and not the rest of the line, since it may or may not (in macro file) contain an external statement. We then will blank out the call, but leave the rest of the line, since the comment may begin on the same line.} LINELEN:=COUNT; FOR I:=1 TO LINELEN DO WRITE(EXTFIL,BUFFER[I]); WRITELN(EXTFIL); FOR I:=1 TO LINELEN DO BUFFER[I]:=' '; BUFFER[133]:=' '; IF BUFFER[1]=';' THEN BUFFER[1]:=' '; COUNT:=0; WRITELN(EXTFIL,' EXTERNAL;'); {Now we seek out the comment. Look first for the open bracket.} SYMBOL:='{'; REPEAT IF COUNT>132 THEN BEGIN {We are at the end of the line.} IF SYMBOL='}' THEN BEGIN {We are inside the comment looking for the end, so this is a valid line to write to the EXT file.} LINELEN:=133; WHILE (LINELEN>1) AND (BUFFER[LINELEN]=' ') DO LINELEN:=LINELEN-1; FOR I:=1 TO LINELEN DO WRITE(EXTFIL,BUFFER[I]); WRITELN(EXTFIL) END; IF EOF(PASFIL) THEN BEGIN {Still working on the comment. Cannot have end of file yet.} WRITELN('P3EXT> Error: Did not find a comment'); WRITELN('P3EXT> Error: the "',SYMBOL, '" bracket not found'); EXITST(4) END; READLN(PASFIL,BUFFER); BUFFER[133]:=' '; IF BUFFER[1]=';' THEN BUFFER[1]:=' '; COUNT:=1 END ELSE BEGIN {Continue scanning the line for the SYMBOL} COUNT:=COUNT+1 END; IF BUFFER[COUNT]=SYMBOL THEN SYMBOL:='}' UNTIL BUFFER[COUNT]=SYMBOL; {We are done with the comment. All that remains is to write the last line of the comment to the EXT file. Note that we write just up thru the close bracket symbol, because there could be a statement following it on the same line.} LINELEN:=COUNT; FOR I:=1 TO LINELEN DO WRITE(EXTFIL,BUFFER[I]); {A couple of blank lines for pretty formatting, and we are done.} WRITELN(EXTFIL); WRITELN(EXTFIL); CLOSE(EXTFIL); DONE:=TRUE END; {PROCEDURE PUT_CALL} BEGIN {MAIN - PUT_EXTERNAL_CALL} FOUND_HEADER:=FALSE; {Make ENTRY all uppercase.} FOR I:=1 TO ENTRYLEN DO IF ORD(ENTRY[I])>=97 THEN ENTRY[I]:=CHR(ORD(ENTRY[I])-32); WHILE (NOT(EOF(PASFIL))) AND (DONE=FALSE) DO BEGIN READLN(PASFIL,BUFFER); BUFFER[133]:=' '; IF BUFFER[1]=';' THEN BUFFER[1]:=' '; COUNT:=1; {Disregard leading semi-colons if they occur in column one. This allows us to imbed pascal call headers and comments in macro source programs.} {Ignore leading blanks or tabs} WHILE ((BUFFER[COUNT]=' ')OR(BUFFER[COUNT]=CHR(9))) AND (COUNT<=132) DO COUNT:=COUNT+1; IF ((BUFFER[COUNT]='P')OR(BUFFER[COUNT]='p')OR(BUFFER[COUNT]='F') OR(BUFFER[COUNT]='f')) AND (COUNT<=122) THEN BEGIN {A word beginning with P (Procedure?) or F (Function?) encountered. Let's see if it is what we think it is.} FOR I:=1 TO 9 DO PROCHOLD[I]:=BUFFER[COUNT+I-1]; {Make PROCHOLD all uppercase.} FOR I:=1 TO 9 DO IF ORD(PROCHOLD[I])>=97 THEN PROCHOLD[I]:=CHR(ORD(PROCHOLD[I])-32); IF (PROCHOLD='PROCEDURE') OR (PROCHOLD='FUNCTION ') THEN BEGIN IF PROCHOLD[1]='P' THEN COUNT:=COUNT+9 ELSE COUNT:=COUNT+8; WHILE (BUFFER[COUNT]=' ') AND (COUNT<=132) DO COUNT:=COUNT+1; IF ((BUFFER[COUNT]=ENTRY[1])OR(BUFFER[COUNT]=CHR(ORD(ENTRY[1])+32))) AND (COUNT<=133-ENTRYLEN) THEN BEGIN ENTRYHOLD:=' '; FOR I:=1 TO ENTRYLEN DO ENTRYHOLD[I]:=BUFFER[COUNT+I-1]; {Make ENTRYHOLD all uppercase.} FOR I:=1 TO ENTRYLEN DO IF ORD(ENTRYHOLD[I])>=97 THEN ENTRYHOLD[I]:=CHR(ORD(ENTRYHOLD[I])-32); {Note that both ENTRYHOLD and ENTRY have been forced to uppercase, that way we have no problem with upper/lower case mismatches for identical letters.} IF ENTRYHOLD=ENTRY THEN BEGIN {The procedure or function was found and verified, now we will generate the external call from the procedure header, and add the first encountered comment} FOUND_HEADER:=TRUE; COUNT:=COUNT+ENTRYLEN; PUT_CALL END END END END END; IF FOUND_HEADER=FALSE THEN BEGIN WRITELN('P3EXT> Error: Could not find procedure or ', 'function named "',ENTRY,'"'); EXITST(4) END; END; {PROCEDURE PUT_EXTERNAL_CALL} PROCEDURE EXTRACT_EXTERNAL_CALL; VAR EXTFILNAME:CH15; FILSTAT,I,COUNT:INTEGER; BEGIN EXTFILNAME:=' .EXT;1'; FOR I:=1 TO 9 DO EXTFILNAME[I]:=ENTRY[I]; FILSTAT:=0; REWRITE(EXTFIL,EXTFILDEV,EXTFILNAME,FILSTAT); IF FILSTAT<0 THEN BEGIN WRITELN('P3EXT> Error: Unable to open EXT file "', EXTFILDEV,EXTFILNAME,'"'); EXITST(4) END; PUT_EXTERNAL_CALL; CLOSE(EXTFIL) END; {PROCEDURE EXTRACT_EXTERNAL_CALL} PROCEDURE EXT_FILE_EXTRACT; VAR FILSTAT:INTEGER; BEGIN RESET(PASFIL,PASFILNAME,,FILSTAT); IF FILSTAT<0 THEN BEGIN WRITELN('P3EXT> Error: Unable to open source file "',PASFILNAME,'"'); EXITST(4) END; IF ENTRYLEN<=0 THEN BEGIN WRITELN('P3EXT> Error: A blank entry point name specified'); EXITST(4) END; EXTRACT_EXTERNAL_CALL; CLOSE(PASFIL) END; {PROCEDURE EXT_FILE_EXTRACT} BEGIN DONE:=FALSE; GET_PARAMETERS; EXT_FILE_EXTRACT; END.