home *** CD-ROM | disk | FTP | other *** search
- program MPREP;
- { Macro Preprocessor and version control program to give C-like preprocessing
- to programs written in any language (or general text).
- The following commands can be embedded in any ASCII file
- (They must start with a '#' as the first character of a new line):
- #define identifier [string]
- #ifdef identifier
- #ifndef identifier
- #endif
- In addition, using the identifier in any text following its definition
- results in replacement of the identifier by the string that followed
- it in the #define statement. (Macros can contain references to previously-
- defined macros.) MPREP is invoked as:
- MPREP [-E ext] [-D identifier] filename [filename2] [filename3] ...
- where ext is an optional filename extension, which is used to name the
- output file (the default is PAS). For example, the command:
- MPREP MAIN.PRE
- would result in the creation of an output file named MAIN.PAS.
- Identifiers specified with the -D flag will define the identifier.
- Note that all identifiers that are defined on the command line and
- in the files are defined for all files listed. Also, it should be noted
- that all commands in MPREP are case-sensitive. Thus, an identifier specified
- in capital letters will not be confused with the same identifier in lower
- case. The only exception is the letters '-D' and '-E' on the command line,
- which may be specified in either upper or lower case.
- I won't bother going into specifics on how to use the #define, #ifdef,
- #ifndef, and #endif commands. Any book on the C language can tell you how
- they work. (The only differences between my version and standard C are
- (1) In mine, macro definitions that contain previously-defined macros are
- expanded; and (2) I have not bothered to implement the optional designation
- of an identifier after #endif. It always goes with the last open #ifdef or
- #ifndef.)
- Ken Van Camp
- P.O. Box 784
- Stroudsburg, PA 18360
- MPREP may be freely distributed, or distributed at nominal copying/mailing
- fee, but may not be otherwise charged for. It may not be incorporated into
- commercial software without express written permission of the author.
- }
-
- const MAXDEF = 200; { max # defines }
-
- type nametype = string[40];
- stringtype = string[70];
- filetype = string[40];
-
- var Defname: array[1..MAXDEF] of nametype; { defined names }
- Defstring: array[1..MAXDEF] of stringtype; { strings defined by Defname}
- Extension: string[4]; { filename extension for output files }
- Param: integer; { cmmd-line parameter # }
- Filin: text; { input files }
- Filout: text; { output files }
- Numdef: integer; { # defined names }
- Nextext: boolean; { flag that next param is an extension }
- Nextdef: boolean; { flag that next param is a definition }
- Line: string[255]; { line inputted from file }
- Lenline: integer; { length of line }
- Startstr: integer; { start pos of define string }
- Endstr: integer; { end pos of define string }
- Defined: boolean; { flag OK to echo lines to file }
- Name: nametype; { name of define macro }
- Def: integer; { define # }
- Found: boolean; { flag found define name }
- Nif: integer; { # open ifdef's or ifndef's }
- Ifdef: integer; { flag the ifdef that stopped echoing }
- Fdpos: integer; { position where macro name was found }
- Fileread: boolean; { flag that a file was read }
- Nextc: integer; { next character after macro names }
-
- procedure USAGE;
- begin
- writeln ('usage: PREP [-E ext] [-D defname] flnm [flnm2] [flnm3] ...');
- halt;
- end; { procedure USAGE }
-
- procedure MAXEXCEED;
- begin
- writeln ('PREP: Maximum # of defines (',MAXDEF,') exceeded.');
- halt;
- end; { procedure MAXEXCEED }
-
- function ISALPHANUM (c: char): boolean;
- { Returns TRUE if c is alphanumeric }
- begin
- if ((c>='0') and (c<='9')) or ((c>='A') and (c<='Z')) or
- ((c>='a') and (c<='z')) then
- ISALPHANUM := TRUE
- else
- ISALPHANUM := FALSE;
- end; { function ISALPHANUM }
-
- procedure OPENFILIN (Filename: filetype; var Filin: text);
- { Open the input file, with error checking }
-
- var Flnm: filetype;
- Fileopen: boolean;
-
- begin
- Fileopen := FALSE;
- Flnm := Filename;
- while (NOT Fileopen) do begin
- assign (Filin, Flnm);
- {$I-}
- reset (Filin);
- {$I+}
- if (ioresult <> 0) then begin
- write ('Input file ',Flnm,' cannot be opened. Enter new filename: ');
- readln (Flnm);
- if (Flnm = '') then
- halt;
- end else
- Fileopen := TRUE;
- end; { while }
- end; { procedure OPENFILIN }
-
- procedure OPENFILOUT (Filename: filetype; var Filout: text);
- { Open the output file, with error checking}
-
- var Flnm: filetype;
- Fileopen: boolean;
- Period: integer; { location of period in file name }
-
- begin
- Fileopen := FALSE;
- Flnm := Filename;
- while (NOT Fileopen) do begin
- Period := pos ('.', Flnm);
- if (Period > 0) then
- Flnm := copy (Flnm, 1, Period-1);
- { Check to see if the user put a period in the filename extension }
- if (Extension[1] = '.') then
- Flnm := Flnm + Extension
- else
- Flnm := Flnm + '.' + Extension;
- if (Flnm = Filename) then begin
- writeln ('MPREP: Input and output filenames (',Flnm,') are same.');
- halt;
- end;
- assign (Filout, Flnm);
- {$I-}
- rewrite (Filout);
- {$I+}
- if (ioresult <> 0) then begin
- write ('Output file ',Flnm,' cannot be opened. Enter new file name: ');
- readln (Flnm);
- if (Flnm = '') then
- halt;
- end else
- Fileopen := TRUE;
- end; { while }
- end; { procedure OPENFILOUT }
-
- begin { program PREP }
- { Initializations }
- Fileread := FALSE;
- Extension := 'PAS'; { default is for Pascal file extension }
- Nextext := FALSE;
- Nextdef := FALSE;
- Numdef := 0;
- Defined := TRUE;
- Nif := 0;
- Ifdef := 0;
-
- for Param := 1 to paramcount do begin
- if (Nextext) then begin
- { Last parameter was -E, so this parameter is the filename extension. }
- if (length (paramstr (Param)) > 3) then
- usage;
- Extension := paramstr (Param);
- Nextext := FALSE;
- end else if (Nextdef) then begin
- { Last parameter was -D, so this parameter is a definition. }
- Numdef := Numdef + 1;
- if (Numdef > MAXDEF) then
- maxexceed;
- Defname[Numdef] := paramstr (Param);
- Defstring[Numdef] := '';
- Nextdef := FALSE;
- end else if (copy (paramstr(Param),1,2) = '-e') or
- (copy (paramstr(Param),1,2) = '-E') then begin
- { -E flag found; next parameter should contain filename extension }
- Nextext := TRUE;
- end else if (copy (paramstr(Param),1,2) = '-d') or
- (copy (paramstr(Param),1,2) = '-D') then begin
- { -D flag found; next parameter should contain definition }
- Nextdef := TRUE;
- end else begin
- { Just a normal file name }
- openfilin (paramstr (Param), Filin);
- openfilout(paramstr (Param), Filout);
- Fileread := TRUE;
-
- { Now read the file & process the define's }
- repeat
- readln (Filin, Line);
- Lenline := length (Line);
- if (copy (Line,1,8) = '#define ') then begin
- { Find the #define name }
- { (Starts at first non-blank & non-tab.) }
- Startstr := 9;
- while (Startstr <= Lenline) and ((Line[Startstr] = ' ') or
- (Line[Startstr] = ^I)) do
- Startstr := Startstr + 1;
- if (Startstr <= Lenline) then begin
- { Name was found; define it }
- Numdef := Numdef + 1;
- if (Numdef > MAXDEF) then
- maxexceed;
- Endstr := Startstr + 1;
- while (Endstr <= Lenline) and (Line[Endstr] <> ' ') and
- (Line[Endstr] <> ^I) do
- Endstr := Endstr + 1;
- if (Endstr > Lenline) then
- Endstr := Lenline;
- Defname[Numdef] := copy (Line, Startstr, Endstr-Startstr);
-
- { Now find the string defined, if it exists }
- Startstr := Endstr + 1;
- while (Startstr <= Lenline) and ((Line[Startstr] = ' ') or
- (Line[Startstr] = ^I)) do
- Startstr := Startstr + 1;
- if (Startstr <= Lenline) then begin
- { Definition was found }
- Defstring[Numdef] := copy (Line, Startstr, Lenline);
- { Check for any other macros within the definition }
- for Def := 1 to Numdef-1 do
- if (Defstring[Def] <> '') then begin
- Fdpos := pos (Defname[Def], Defstring[Numdef]);
- if (Fdpos > 0) then begin
- Found := TRUE;
- if (Fdpos > 1) then
- if isalphanum (Defstring[Numdef][Fdpos-1]) then
- Found := FALSE;
- Nextc := Fdpos + length (Defname[Def]);
- if (Found) and (Nextc <= length(Defstring[Numdef])) then
- if isalphanum (Defstring[Numdef][Nextc]) then
- Found := FALSE;
- if (Found) then
- Defstring[Numdef] := copy (Defstring[Numdef],1,Fdpos-1)
- + Defstring[Def] +
- copy (Defstring[Numdef],Fdpos+length(Defname[Def]),
- length(Defstring[Numdef]));
- end; { if Fdpos }
- end; { if Defstring[Def] }
- { for Def }
- end else
- { No definition }
- Defstring[Numdef] := '';
- end; { if Startstr }
- end else if (copy (Line,1,7) = '#ifdef ') then begin
- Nif := Nif + 1;
- if (Defined) then begin
- Startstr := 8;
- while (Startstr <= Lenline) and ((Line[Startstr] = ' ') or
- (Line[Startstr] = ^I)) do
- Startstr := Startstr + 1;
- if (Startstr <= Lenline) then begin
- { Name was found; find the end of it }
- Endstr := Startstr + 1;
- while (Endstr <= Lenline) and (Line[Endstr] <> ' ') and
- (Line[Endstr] <> ^I) do
- Endstr := Endstr + 1;
- if (Endstr > Lenline) then
- Endstr := Lenline;
- Name := copy (Line, Startstr, Endstr-Startstr+1);
- { Now see if the name was defined }
- Found := FALSE;
- for Def := 1 to Numdef do
- if (Defname[Def] = Name) then
- Found := TRUE;
- if (Found) then
- Defined := TRUE
- else begin
- Defined := FALSE;
- Ifdef := Nif;
- end; { if Found }
- end; { if Startstr }
- end; { if Defined }
- end else if (copy (Line,1,8) = '#ifndef ') then begin
- Nif := Nif + 1;
- if (Defined) then begin
- Startstr := 9;
- while (Startstr <= Lenline) and ((Line[Startstr] = ' ') or
- (Line[Startstr] = ^I)) do
- Startstr := Startstr + 1;
- if (Startstr <= Lenline) then begin
- { Name was found; find the end of it }
- Endstr := Startstr + 1;
- while (Endstr <= Lenline) and (Line[Endstr] <> ' ') and
- (Line[Endstr] <> ^I) do
- Endstr := Endstr + 1;
- if (Endstr > Lenline) then
- Endstr := Lenline;
- Name := copy (Line, Startstr, Endstr-Startstr+1);
- { Now see if the name was defined }
- Found := FALSE;
- for Def := 1 to Numdef do
- if (Defname[Def] = Name) then
- Found := TRUE;
- if (Found) then begin
- Defined := FALSE;
- Ifdef := Nif;
- end else
- Defined := TRUE;
- end; { if Startstr }
- end; { if Defined }
- end else if (copy (Line,1,6) = '#endif') then begin
- if (Ifdef = Nif) then begin
- Defined := TRUE;
- Ifdef := 0;
- end;
- Nif := Nif - 1;
- end else if (Defined) then begin
- { No preprocessor directives; just a normal line }
- { Check for any defined macros }
- Def := 1;
- Found := FALSE;
- while (Def <= Numdef) and (NOT Found) do begin
- if (Defstring[Def] <> '') then begin
- Fdpos := pos (Defname[Def], Line);
- if (Fdpos > 0) then begin
- Found := TRUE;
- if (Fdpos > 1) then
- if (isalphanum (Line[Fdpos-1])) then
- Found := FALSE;
- Nextc := Fdpos + length(Defname[Def]);
- if (Found) and (Nextc <= Lenline) then
- if (isalphanum (Line[Nextc])) then
- Found := FALSE;
- Line := copy (Line,1,Fdpos-1) + Defstring[Def] +
- copy (Line,Fdpos+length(Defname[Def]),Lenline);
- end; { if Fdpos > 0 }
- end; { if Defstring[Def] }
- Def := Def + 1;
- end; { while Def... }
- writeln (Filout, Line);
- end; { if copy(Line,1,8)... }
-
- until eof (Filin);
- close (Filin);
- close (Filout);
- end; { if Nextext... }
- end; { for Param }
- if (NOT Fileread) then
- usage;
- end. { program PREP }