123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- {
- Inno Setup Preprocessor
- Copyright (C) 2001-2002 Alex Yackimoff
-
- Inno Setup
- Copyright (C) 1997-2024 Jordan Russell
- Portions by Martijn Laan
- For conditions of distribution and use, see LICENSE.TXT.
- }
- unit ISPP.Preprocess;
- interface
- uses
- Shared.PreprocInt;
- function ISPreprocessScript(var Params: TPreprocessScriptParams): Integer; stdcall;
- implementation
- uses
- SysUtils, Shared.CommonFunc, PathFunc,
- ISPP.Base, ISPP.Preprocessor, ISPP.Sessions, ISPP.Intf,
- ISPP.IdentMan, ISPP.VarUtils, ISPP.Consts;
- procedure ReadScript(const Params: TPreprocessScriptParams;
- const Preprocessor: TPreprocessor);
- var
- I: Integer;
- LineText: PChar;
- LineTextStr: String;
- begin
- I := 0;
- while True do
- begin
- LineText := Params.LineInProc(Params.CompilerData, 0, I);
- if LineText = nil then
- Break;
- LineTextStr := LineText;
- Preprocessor.QueueLine(LineTextStr);
- Inc(I);
- end;
- end;
- function CleanupProc(CleanupProcData: Pointer): Integer; stdcall;
- begin
- if PopPreproc = nil then
- Result := 0
- else
- Result := 1; { should never get here }
- end;
- function DecodeStringOptions(const S: String; var Options: TOptions): Boolean;
- var
- I: Integer;
- begin
- Options := [];
- Result := True;
- for I := 1 to Length(S) do begin
- case S[I] of
- 'a'..'z': Include(Options, Ord(S[I]) - Ord('a'));
- else
- Result := False;
- end;
- end;
- end;
- function ISPreprocessScript(var Params: TPreprocessScriptParams): Integer; stdcall;
- const
- Delta = Ord('a');
- DefaultOptions: TIsppOptions =
- (ParserOptions: (Options: [Ord('b') - Delta, Ord('p') - Delta]);
- Options: [Ord('c') - Delta, Ord('e') - Delta]; VerboseLevel: 0;
- InlineStart: '{#'; InlineEnd: '}'; SpanSymbol: #0);
- var
- ISPPOptions: TIsppOptions;
- Definitions, IncludePath, IncludeFiles: String;
- Preprocessor: TPreprocessor;
- V: TIsppVariant;
- function ParseOption(const OptName, OptValue: String): Boolean;
- begin
- Result := True;
- if OptName = 'ISPP:ParserOptions' then
- Result := DecodeStringOptions(OptValue, ISPPOptions.ParserOptions.Options)
- else if OptName = 'ISPP:Options' then
- Result := DecodeStringOptions(OptValue, ISPPOptions.Options)
- else if OptName = 'ISPP:VerboseLevel' then
- ISPPOptions.VerboseLevel := StrToIntDef(OptValue, 0)
- else if OptName = 'ISPP:InlineStart' then
- ISPPOptions.InlineStart := OptValue
- else if OptName = 'ISPP:InlineEnd' then
- ISPPOptions.InlineEnd := OptValue
- else if OptName = 'ISPP:Definitions' then
- Definitions := OptValue
- else if OptName = 'ISPP:IncludePath' then
- IncludePath := OptValue
- else if OptName = 'ISPP:IncludeFiles' then
- IncludeFiles := OptValue
- else
- Result := False;
- end;
- function ParseOptions(P: PChar): Boolean;
- var
- EqPos: PChar;
- OptName: String;
- begin
- Result := True;
- if P = nil then
- Exit;
- while P^ <> #0 do begin
- EqPos := StrScan(P, '=');
- if EqPos = nil then begin
- Result := False;
- Break;
- end;
- SetString(OptName, P, EqPos - P);
- P := EqPos + 1;
- if not ParseOption(OptName, P) then begin
- Result := False;
- Break;
- end;
- Inc(P, StrLen(P) + 1);
- end;
- end;
- function ParseDefinitions(Definitions: PChar; VarMan: TIdentManager): Boolean;
- procedure ParseDefinition(const S: string);
- var
- I: Integer;
- Name, V: string;
- Value: TIsppVariant;
- begin
- Value := NULL;
- I := Pos('=', S);
- if I > 0 then
- begin
- Name := Copy(S, 1, I - 1);
- V := Copy(S, I + 1, MaxInt);
- if V <> '' then
- MakeStr(Value, V)
- end
- else
- Name := Trim(S);
- VarMan.DefineVariable(Name, -1, Value, dsPublic);
- end;
- var
- DelimPos: PChar;
- N: Integer;
- Definition: string;
- begin
- Result := True;
- while Definitions^ <> #0 do begin
- DelimPos := StrScan(Definitions, #1);
- if DelimPos = nil then begin
- Result := False;
- Break;
- end;
- N := DelimPos - Definitions;
- if N > 0 then begin
- SetString(Definition, Definitions, N);
- ParseDefinition(Definition);
- end;
- Inc(Definitions, N + 1);
- end;
- end;
- function IncludeBuiltinsAndParseIncludeFiles(BuiltinsDir: String; IncludeFiles: PChar; Options: TOptions): Boolean;
- function Escape(const S: string): string;
- var
- I: Integer;
- begin
- Result := '';
- for I := 1 to Length(S) do
- begin
- Result := Result + S[I];
- if S[I] = '\' then Result := Result + '\';
- end;
- end;
- procedure Include(FileName: String; Builtins: Boolean);
- begin
- if not GetOption(Options, 'P') then
- FileName := Escape(FileName);
- Preprocessor.IncludeFile(FileName, Builtins, False, True);
- end;
- const
- SBuiltins = {$IFDEF DEBUG} '..\..\Files\ISPPBuiltins.iss' {$ELSE} 'ISPPBuiltins.iss' {$ENDIF};
- var
- DelimPos: PChar;
- N: Integer;
- IncludeFile: String;
- begin
- Result := True;
- IncludeFile := BuiltinsDir + SBuiltins;
- if FileExists(IncludeFile) then
- Include(IncludeFile, True)
- else
- Preprocessor.WarningMsg(SFileNotFound, [SBuiltins]);
- while IncludeFiles^ <> #0 do begin
- DelimPos := StrScan(IncludeFiles, #1);
- if DelimPos = nil then begin
- Result := False;
- Break;
- end;
- N := DelimPos - IncludeFiles;
- if N > 0 then begin
- SetString(IncludeFile, IncludeFiles, N);
- Include(IncludeFile, False);
- end;
- Inc(IncludeFiles, N + 1);
- end;
- end;
- var
- SourcePath, CompilerPath, LineFilename, LineText: string;
- LineNumber: Integer;
- begin
- if (Params.Size <> SizeOf(Params)) or
- (Params.InterfaceVersion <> 3) then
- begin
- Result := ispeInvalidParam;
- Exit;
- end;
- SourcePath := Params.SourcePath;
- CompilerPath := Params.CompilerPath;
- ISPPOptions := DefaultOptions;
- Definitions := '';
- IncludePath := RemoveBackslashUnlessRoot(CompilerPath);
- IncludeFiles := '';
- if not ParseOptions(Params.Options) then
- begin
- Result := ispeInvalidParam;
- Exit;
- end;
- { Hack: push a dummy item onto the stack to defer deletion of temp. files }
- PushPreproc(nil);
- try
- Preprocessor := TPreprocessor.Create(Params, nil, ISPPOptions, SourcePath,
- CompilerPath, Params.Filename);
- try
- Preprocessor.IncludePath := IncludePath;
- MakeStr(V, SourcePath);
- Preprocessor.VarMan.DefineVariable('SourcePath', -1, V, dsPublic);
- MakeStr(V, CompilerPath);
- Preprocessor.VarMan.DefineVariable('CompilerPath', -1, V, dsPublic);
- MakeInt(V, Params.CompilerBinVersion);
- Preprocessor.VarMan.DefineVariable('Ver', -1, V, dsPublic);
- if not ParseDefinitions(PChar(Definitions), Preprocessor.VarMan) or
- not IncludeBuiltinsAndParseIncludeFiles(Params.CompilerPath, PChar(IncludeFiles),
- Preprocessor.FOptions.ParserOptions.Options) then
- begin
- Result := ispeInvalidParam;
- Exit;
- end;
- ReadScript(Params, Preprocessor);
- Preprocessor.Stack.Resolved;
- if not GetOption(Preprocessor.FOptions.Options, 'C') then
- Result := ispeSilentAbort
- else
- begin
- Preprocessor.GetNextOutputLineReset;
- while Preprocessor.GetNextOutputLine(LineFilename, LineNumber, LineText) do
- Params.LineOutProc(Params.CompilerData, PChar(LineFilename),
- LineNumber, PChar(LineText));
- Result := ispeSuccess;
- end;
- finally
- Preprocessor.Free;
- end;
- except
- on E: EPreprocError do {preprocessor (syntax most likely) error}
- begin
- Params.ErrorProc(Params.CompilerData, PChar(E.Message),
- PChar(E.FileName), E.LineNumber, E.ColumnNumber);
- Result := ispePreprocessError;
- end;
- on E: Exception do
- begin
- Params.ErrorProc(Params.CompilerData,
- PChar(Format('Unexpected exception of class %s in ISPP.' +
- #13#10#13#10'%s.', [E.ClassName, E.Message])), nil, 0, 0);
- Result := ispePreprocessError;
- end;
- end;
- if Result = ispeSuccess then
- Params.PreprocCleanupProc := CleanupProc
- else
- PopPreproc;
- end;
- end.
|