ISCC.dpr 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. program ISCC;
  2. {$APPTYPE CONSOLE}
  3. {
  4. Inno Setup
  5. Copyright (C) 1997-2025 Jordan Russell
  6. Portions by Martijn Laan
  7. For conditions of distribution and use, see LICENSE.TXT.
  8. Command-line compiler
  9. }
  10. {x$DEFINE STATICCOMPILER}
  11. { For debugging purposes, remove the 'x' to have it link the compiler code
  12. into this program and not depend on ISCmplr.dll. You will also need to add the
  13. ..\Components and Src folders to the Delphi Compiler Search path in the project
  14. options. Also see IDE.MainForm's STATICCOMPILER and Compiler.Compile's STATICPREPROC. }
  15. uses
  16. SafeDLLPath in '..\Components\SafeDLLPath.pas',
  17. Windows,
  18. SysUtils,
  19. Classes,
  20. {$IFDEF STATICCOMPILER} Compiler.Compile, {$ENDIF}
  21. PathFunc in '..\Components\PathFunc.pas',
  22. TrustFunc in '..\Components\TrustFunc.pas',
  23. Shared.CommonFunc in 'Src\Shared.CommonFunc.pas',
  24. Shared.CompilerInt in 'Src\Shared.CompilerInt.pas',
  25. Shared.CompilerInt.Struct in 'Src\Shared.CompilerInt.Struct.pas',
  26. Shared.FileClass in 'Src\Shared.FileClass.pas',
  27. Shared.ConfigIniFile in 'Src\Shared.ConfigIniFile.pas',
  28. Shared.SignToolsFunc in 'Src\Shared.SignToolsFunc.pas',
  29. Shared.LicenseFunc in 'Src\Shared.LicenseFunc.pas',
  30. SHA256 in '..\Components\SHA256.pas',
  31. ECDSA in '..\Components\ECDSA.pas',
  32. ISSigFunc in '..\Components\ISSigFunc.pas',
  33. StringScanner in '..\Components\StringScanner.pas',
  34. UnsignedFunc in '..\Components\UnsignedFunc.pas';
  35. {$SETPEOSVERSION 6.1}
  36. {$SETPESUBSYSVERSION 6.1}
  37. {$WEAKLINKRTTI ON}
  38. {$R Res\ISCC.manifest.res}
  39. {$R Res\ISCC.versionandicon.res}
  40. type
  41. PScriptLine = ^TScriptLine;
  42. TScriptLine = record
  43. LineText: String;
  44. Next: PScriptLine;
  45. end;
  46. TOptionID = 0..25;
  47. TOptions = set of TOptionID;
  48. TIsppOptions = record
  49. ParserOptions: TOptions;
  50. Options: TOptions;
  51. VerboseLevel: Integer;
  52. InlineStart: String;
  53. InlineEnd: String;
  54. end;
  55. var
  56. StdOutHandle, StdErrHandle: THandle;
  57. StdOutHandleIsConsole, StdErrHandleIsConsole: Boolean;
  58. ScriptFilename: String;
  59. Definitions, IncludePath, IncludeFiles, Output, OutputPath, OutputFilename: String;
  60. SignTools: TStringList;
  61. ScriptLines, NextScriptLine: PScriptLine;
  62. CurLine: String;
  63. StartTime, EndTime: DWORD;
  64. Quiet, ShowProgress, WantAbort: Boolean;
  65. ProgressPoint: TPoint;
  66. LastProgress: String;
  67. IsppOptions: TIsppOptions;
  68. IsppMode: Boolean;
  69. procedure WriteToStdHandle(const Handle: THandle; const HandleIsConsole: Boolean; S: String);
  70. begin
  71. if Copy(S, 1, 1) <> #13 then
  72. S := S + #13#10;
  73. if HandleIsConsole then begin
  74. var CharsWritten: DWORD;
  75. WriteConsole(Handle, @S[1], ULength(S), CharsWritten, nil);
  76. end else begin
  77. var Utf8S := Utf8Encode(S);
  78. var BytesWritten: DWORD;
  79. WriteFile(Handle, Utf8S[1], ULength(Utf8S), BytesWritten, nil);
  80. end;
  81. end;
  82. procedure WriteStdOut(const S: String; const Warning: Boolean = False);
  83. var
  84. CSBI: TConsoleScreenBufferInfo;
  85. DidSetColor: Boolean;
  86. begin
  87. DidSetColor := Warning and StdOutHandleIsConsole and GetConsoleScreenBufferInfo(StdOutHandle, CSBI) and
  88. SetConsoleTextAttribute(StdOutHandle, FOREGROUND_INTENSITY or FOREGROUND_RED or FOREGROUND_GREEN);
  89. try
  90. WriteToStdHandle(StdOutHandle, StdOutHandleIsConsole, S);
  91. finally
  92. if DidSetColor then
  93. SetConsoleTextAttribute(StdOutHandle, CSBI.wAttributes);
  94. end;
  95. end;
  96. procedure WriteStdErr(const S: String; const Error: Boolean = False);
  97. var
  98. CSBI: TConsoleScreenBufferInfo;
  99. DidSetColor: Boolean;
  100. begin
  101. DidSetColor := Error and StdErrHandleIsConsole and GetConsoleScreenBufferInfo(StdErrHandle, CSBI) and
  102. SetConsoleTextAttribute(StdErrHandle, FOREGROUND_INTENSITY or FOREGROUND_RED);
  103. try
  104. WriteToStdHandle(StdErrHandle, StdErrHandleIsConsole, S);
  105. finally
  106. if DidSetColor then
  107. SetConsoleTextAttribute(StdErrHandle, CSBI.wAttributes);
  108. end;
  109. end;
  110. function GetCursorPos: TPoint;
  111. var
  112. CSBI: TConsoleScreenBufferInfo;
  113. begin
  114. if not StdOutHandleIsConsole or not GetConsoleScreenBufferInfo(StdOutHandle, CSBI) then
  115. Exit;
  116. Result.X := CSBI.dwCursorPosition.X;
  117. Result.Y := CSBI.dwCursorPosition.Y;
  118. end;
  119. procedure SetCursorPos(const P: TPoint);
  120. var
  121. Coords: TCoord;
  122. CSBI: TConsoleScreenBufferInfo;
  123. begin
  124. if not StdOutHandleIsConsole or not GetConsoleScreenBufferInfo(StdOutHandle, CSBI) then
  125. Exit;
  126. if P.X < 0 then Exit;
  127. if P.Y < 0 then Exit;
  128. if P.X > CSBI.dwSize.X then Exit;
  129. if P.Y > CSBI.dwSize.Y then Exit;
  130. Coords.X := SHORT(P.X);
  131. Coords.Y := SHORT(P.Y);
  132. SetConsoleCursorPosition(StdOutHandle, Coords);
  133. end;
  134. procedure WriteProgress(const S: String);
  135. var
  136. CSBI: TConsoleScreenBufferInfo;
  137. Str: String;
  138. begin
  139. if StdOutHandleIsConsole and GetConsoleScreenBufferInfo(StdOutHandle, CSBI) then begin
  140. if Length(S) > CSBI.dwSize.X then
  141. Str := Copy(S, 1, CSBI.dwSize.X)
  142. else
  143. Str := Format('%-' + IntToStr(CSBI.dwSize.X) + 's', [S]);
  144. end else
  145. Str := S;
  146. WriteToStdHandle(StdOutHandle, StdOutHandleIsConsole, Str);
  147. end;
  148. function ConsoleCtrlHandler(dwCtrlType: DWORD): BOOL; stdcall;
  149. begin
  150. { Abort gracefully when Ctrl+C/Break is pressed }
  151. WantAbort := True;
  152. Result := True;
  153. end;
  154. procedure ReadScriptLines(const F: TTextFileReader);
  155. var
  156. LineNumber: Integer;
  157. PrevLine, L: PScriptLine;
  158. begin
  159. LineNumber := 1;
  160. PrevLine := nil;
  161. while not F.Eof do begin
  162. New(L);
  163. try
  164. L.LineText := F.ReadLine;
  165. if Pos(#0, L.LineText) <> 0 then
  166. raise Exception.CreateFmt('Illegal null character on line %d', [LineNumber]);
  167. L.Next := nil;
  168. except
  169. Dispose(L);
  170. raise;
  171. end;
  172. if Assigned(PrevLine) then
  173. PrevLine.Next := L
  174. else begin
  175. ScriptLines := L;
  176. NextScriptLine := L;
  177. end;
  178. PrevLine := L;
  179. Inc(LineNumber);
  180. end;
  181. end;
  182. procedure FreeScriptLines;
  183. var
  184. L, NextLine: PScriptLine;
  185. begin
  186. L := ScriptLines;
  187. ScriptLines := nil;
  188. NextScriptLine := nil;
  189. while Assigned(L) do begin
  190. NextLine := L.Next;
  191. Dispose(L);
  192. L := NextLine;
  193. end;
  194. end;
  195. function CompilerCallbackProc(Code: Integer; var Data: TCompilerCallbackData;
  196. AppData: NativeInt): Integer; stdcall;
  197. procedure PrintProgress(Progress: String);
  198. var
  199. Pt: TPoint;
  200. begin
  201. if (Progress = '') or (LastProgress = Progress) then
  202. Exit;
  203. Pt := GetCursorPos;
  204. if Pt.Y <= ProgressPoint.Y then
  205. Exit
  206. else if ProgressPoint.X < 0 then begin
  207. ProgressPoint := Pt;
  208. WriteStdOut('');
  209. Pt := GetCursorPos;
  210. end;
  211. SetCursorPos(ProgressPoint);
  212. WriteProgress(#13 + Progress);
  213. LastProgress := Progress;
  214. SetCursorPos(Pt);
  215. end;
  216. var
  217. S, BytesCompressedPerSecond, SecondsRemaining: String;
  218. begin
  219. if WantAbort then begin
  220. Result := iscrRequestAbort;
  221. Exit;
  222. end;
  223. Result := iscrSuccess;
  224. case Code of
  225. iscbReadScript: begin
  226. { Note: In Inno Setup 3.0.1 and later we can ignore Data.Reset since
  227. it is only True once (when reading the first line). }
  228. if Assigned(NextScriptLine) then begin
  229. CurLine := NextScriptLine.LineText;
  230. NextScriptLine := NextScriptLine.Next;
  231. Data.LineRead := PChar(CurLine);
  232. end;
  233. end;
  234. iscbNotifyStatus:
  235. if not Quiet then
  236. WriteStdOut(Data.StatusMsg, Data.Warning)
  237. else if ShowProgress then
  238. PrintProgress(Trim(Data.StatusMsg));
  239. iscbNotifySuccess: begin
  240. EndTime := GetTickCount;
  241. if not Quiet then begin
  242. WriteStdOut('');
  243. if Data.OutputExeFilename <> '' then begin
  244. WriteStdOut(Format('Successful compile (%.3f sec). ' +
  245. 'Resulting Setup program filename is:',
  246. [(EndTime - StartTime) / 1000]));
  247. WriteStdOut(Data.OutputExeFilename);
  248. end else
  249. WriteStdOut(Format('Successful compile (%.3f sec). ' +
  250. 'Output was disabled.',
  251. [(EndTime - StartTime) / 1000]));
  252. end;
  253. end;
  254. iscbNotifyError:
  255. if Assigned(Data.ErrorMsg) then begin
  256. S := 'Error';
  257. if Data.ErrorLine <> 0 then
  258. S := S + Format(' on line %d', [Data.ErrorLine]);
  259. if Assigned(Data.ErrorFilename) then
  260. S := S + ' in ' + Data.ErrorFilename
  261. else if ScriptFilename <> '' then
  262. S := S + ' in ' + ScriptFilename;
  263. S := S + ': ' + Data.ErrorMsg;
  264. WriteStdErr(S, True);
  265. end;
  266. iscbNotifyIdle:
  267. if ShowProgress and (Data.CompressProgress <> 0) then begin
  268. if Data.BytesCompressedPerSecond <> 0 then
  269. BytesCompressedPerSecond := Format(' at %.2f kb/s', [Data.BytesCompressedPerSecond / 1024])
  270. else
  271. BytesCompressedPerSecond := '';
  272. if Data.SecondsRemaining <> -1 then
  273. SecondsRemaining := Format(', %d seconds remaining', [Data.SecondsRemaining])
  274. else
  275. SecondsRemaining := '';
  276. PrintProgress(Format('Compressing: %.2f%% done%s%s', [Data.CompressProgress / Data.CompressProgressMax * 100, BytesCompressedPerSecond, SecondsRemaining]));
  277. end;
  278. end;
  279. end;
  280. procedure ProcessCommandLine;
  281. procedure SetOption(var Options: TOptions; Option: Char; Value: Boolean);
  282. begin
  283. if Value then
  284. Include(Options, Ord(UpCase(Option)) - Ord('A'))
  285. else
  286. Exclude(Options, Ord(UpCase(Option)) - Ord('A'))
  287. end;
  288. procedure InitIsppOptions(var Opt: TIsppOptions; var Definitions, IncludePath, IncludeFiles: String);
  289. begin
  290. with Opt do begin
  291. SetOption(Options, 'C', True);
  292. SetOption(ParserOptions, 'B', True);
  293. SetOption(ParserOptions, 'P', True);
  294. VerboseLevel := 0;
  295. InlineStart := '{#';
  296. InlineEnd := '}';
  297. end;
  298. Definitions := 'ISCC_INVOKED'#1'ISPPCC_INVOKED'#1;
  299. IncludePath := PathExtractDir(NewParamStr(0));
  300. IncludeFiles := '';
  301. end;
  302. procedure ReadOptionsParam(var Options: TOptions; Symbol: Char);
  303. var
  304. I: Integer;
  305. S: String;
  306. begin
  307. for I := 1 to NewParamCount do
  308. begin
  309. S := NewParamStr(I);
  310. if Length(S) = 4 then
  311. if ((S[1] = '/') or (S[1] = '-')) and (UpCase(S[2]) = Symbol) then
  312. case S[4] of
  313. '-': SetOption(Options, S[3], False);
  314. '+': SetOption(Options, S[3], True)
  315. else
  316. raise Exception.CreateFmt('Invalid command line option: %s', [S]);
  317. end;
  318. end;
  319. end;
  320. function IsParam(const S: String): Boolean;
  321. begin
  322. Result := (Length(S) >= 2) and ((S[1] = '/') or (S[1] = '-'));
  323. end;
  324. function GetParam(var S: String; Symbols: String): Boolean;
  325. begin
  326. Result := IsParam(S) and
  327. (CompareText(Copy(S, 2, Length(Symbols)), Symbols) = 0);
  328. if Result then
  329. S := Copy(S, 2 + Length(Symbols), MaxInt);
  330. end;
  331. function FindParam(var Index: Integer; Symbols: String): String;
  332. var
  333. I: Integer;
  334. S: String;
  335. begin
  336. for I := Index to NewParamCount do
  337. begin
  338. S := NewParamStr(I);
  339. if IsParam(S) and (CompareText(Copy(S, 2, Length(Symbols)), Symbols) = 0) then
  340. begin
  341. Result := Copy(S, 2 + Length(Symbols), MaxInt);
  342. Index := I + 1;
  343. Exit;
  344. end;
  345. end;
  346. Index := MaxInt;
  347. Result := '';
  348. end;
  349. procedure ShowBanner;
  350. begin
  351. WriteStdOut('Inno Setup 7 Command-Line Compiler');
  352. WriteStdOut('Copyright (C) 1997-2026 Jordan Russell. All rights reserved.');
  353. WriteStdOut('Portions Copyright (C) 2000-2026 Martijn Laan. All rights reserved.');
  354. if IsppMode then
  355. WriteStdOut('Portions Copyright (C) 2001-2004 Alex Yackimoff. All rights reserved.');
  356. WriteStdOut('https://www.innosetup.com');
  357. WriteStdOut('');
  358. end;
  359. procedure ShowUsage;
  360. begin
  361. WriteStdErr('Usage: iscc [options] scriptfile.iss');
  362. WriteStdErr('or to read from standard input: iscc [options] -');
  363. WriteStdErr('Options:');
  364. WriteStdErr(' /O(+|-) Enable or disable output (overrides Output)');
  365. WriteStdErr(' /O<path> Output files to specified path (overrides OutputDir)');
  366. WriteStdErr(' /F<filename> Specifies an output filename (overrides OutputBaseFilename)');
  367. WriteStdErr(' /S<name>=<command> Sets a SignTool with the specified name and command');
  368. WriteStdErr(' (Any Sign Tools configured using the Compiler IDE will be specified automatically)');
  369. WriteStdErr(' /Q Quiet compile (print error messages only)');
  370. WriteStdErr(' /Qp Enable quiet compile while still displaying progress');
  371. if IsppMode then begin
  372. WriteStdErr(' /D<name>[=<value>] Emulate #define public <name> <value>');
  373. WriteStdErr(' /$<letter>(+|-) Emulate #pragma option -<letter>(+|-)');
  374. WriteStdErr(' /P<letter>(+|-) Emulate #pragma parseroption -<letter>(+|-)');
  375. WriteStdErr(' /I<paths> Emulate #pragma include <paths>');
  376. WriteStdErr(' /J<filename> Emulate #include <filename>');
  377. WriteStdErr(' /{#<string> Emulate #pragma inlinestart <string>');
  378. WriteStdErr(' /}<string> Emulate #pragma inlineend <string>');
  379. WriteStdErr(' /V<number> Emulate #pragma verboselevel <number>');
  380. end;
  381. WriteStdErr(' /? Show this help screen');
  382. WriteStdErr('');
  383. WriteStdErr('Examples: iscc "c:\isetup\samples\my script.iss"');
  384. WriteStdErr(' iscc /Qp /O"My Output" /F"MyProgram-1.0" /Sbyparam=$p "c:\isetup\samples\my script.iss"');
  385. if IsppMode then begin
  386. WriteStdErr(' iscc /$c- /Pu+ "/DLic=Trial Lic.txt" /IC:\INC;D:\INC scriptfile.iss');
  387. WriteStdErr('');
  388. end;
  389. end;
  390. var
  391. I: Integer;
  392. S: String;
  393. begin
  394. if IsppMode then begin
  395. InitIsppOptions(IsppOptions, Definitions, IncludePath, IncludeFiles);
  396. { Also see below }
  397. ReadOptionsParam(IsppOptions.Options, '$');
  398. ReadOptionsParam(IsppOptions.ParserOptions, 'P');
  399. end;
  400. for I := 1 to NewParamCount do begin
  401. S := NewParamStr(I);
  402. if (S = '') or IsParam(S) then begin
  403. if GetParam(S, 'Q') then begin
  404. Quiet := True;
  405. ShowProgress := CompareText(S, 'P') = 0;
  406. end
  407. else if GetParam(S, 'O') then begin
  408. if S = '-' then Output := 'no'
  409. else if S = '+' then Output := 'yes'
  410. else OutputPath := S;
  411. end
  412. else if GetParam(S, 'F') then
  413. OutputFilename := S
  414. else if GetParam(S, 'S') then begin
  415. if Pos('=', S) = 0 then begin
  416. ShowBanner;
  417. WriteStdErr('Invalid option: ' + S, True);
  418. Halt(1);
  419. end;
  420. SignTools.Add(S);
  421. end else if IsppMode and GetParam(S, 'D') then begin
  422. Definitions := Definitions + S + #1;
  423. end
  424. else if IsppMode and GetParam(S, 'I') then begin
  425. IncludePath := IncludePath + ';' + S;
  426. end
  427. else if IsppMode and GetParam(S, 'J') then begin
  428. IncludeFiles := IncludeFiles + S + #1;
  429. end
  430. else if IsppMode and GetParam(S, '{#') then begin
  431. if S <> '' then IsppOptions.InlineStart := S;
  432. end
  433. else if IsppMode and GetParam(S, '}') then begin
  434. if S <> '' then IsppOptions.InlineEnd := S;
  435. end
  436. else if IsppMode and GetParam(S, 'V') then begin
  437. if S <> '' then IsppOptions.VerboseLevel := StrToIntDef(S, 0);
  438. end
  439. else if IsppMode and (GetParam(S, '$') or GetParam(S, 'P')) then begin
  440. { Already handled above }
  441. end
  442. else if S = '/?' then begin
  443. ShowBanner;
  444. ShowUsage;
  445. Halt(1);
  446. end
  447. else begin
  448. ShowBanner;
  449. WriteStdErr('Unknown option: ' + S, True);
  450. Halt(1);
  451. end;
  452. end
  453. else begin
  454. { Not a switch; must be the script filename }
  455. if ScriptFilename <> '' then begin
  456. ShowBanner;
  457. WriteStdErr('You may not specify more than one script filename.', True);
  458. Halt(1);
  459. end;
  460. ScriptFilename := S;
  461. end;
  462. end;
  463. if ScriptFilename = '' then begin
  464. ShowBanner;
  465. ShowUsage;
  466. Halt(1);
  467. end;
  468. if not Quiet then
  469. ShowBanner;
  470. end;
  471. procedure Go;
  472. procedure AppendOption(var Opts: String; const OptName, OptValue: String);
  473. begin
  474. Opts := Opts + OptName + '=' + OptValue + #0;
  475. end;
  476. function ConvertOptionsToString(const Options: TOptions): String;
  477. var
  478. I: TOptionID;
  479. begin
  480. Result := '';
  481. for I := 0 to 25 do
  482. if I in Options then
  483. Result := Result + Chr(Ord('a') + I);
  484. end;
  485. procedure IsppOptionsToString(var S: String; Opt: TIsppOptions; Definitions, IncludePath, IncludeFiles: String);
  486. begin
  487. with Opt do begin
  488. AppendOption(S, 'ISPP:ParserOptions', ConvertOptionsToString(ParserOptions));
  489. AppendOption(S, 'ISPP:Options', ConvertOptionsToString(Options));
  490. AppendOption(S, 'ISPP:VerboseLevel', IntToStr(VerboseLevel));
  491. AppendOption(S, 'ISPP:InlineStart', InlineStart);
  492. AppendOption(S, 'ISPP:InlineEnd', InlineEnd);
  493. end;
  494. AppendOption(S, 'ISPP:Definitions', Definitions);
  495. AppendOption(S, 'ISPP:IncludePath', IncludePath);
  496. AppendOption(S, 'ISPP:IncludeFiles', IncludeFiles);
  497. end;
  498. var
  499. ScriptPath: String;
  500. ExitCode: Word;
  501. Ver: PCompilerVersionInfo;
  502. F: TTextFileReader;
  503. Params: TCompileScriptParamsEx;
  504. Options: String;
  505. Res: Integer;
  506. I: Integer;
  507. IDESignTools: TStringList;
  508. begin
  509. if ScriptFilename <> '-' then begin
  510. ScriptFilename := PathExpand(ScriptFilename);
  511. ScriptPath := PathExtractPath(ScriptFilename);
  512. end
  513. else begin
  514. { Read from standard input }
  515. ScriptFilename := '<stdin>';
  516. ScriptPath := GetCurrentDir;
  517. end;
  518. {$IFNDEF STATICCOMPILER}
  519. try
  520. InitISCmplrLibrary;
  521. except
  522. begin
  523. WriteStdErr(Format('Could not load %s: %s', [ISCmplrDLL, GetExceptMessage]), True);
  524. Halt(1);
  525. end;
  526. end;
  527. Ver := ISDllGetVersion;
  528. {$ELSE}
  529. Ver := ISGetVersion;
  530. {$ENDIF}
  531. if Ver.BinVersion < $05000500 then begin
  532. { 5.0.5 or later is required since we use TCompileScriptParamsEx }
  533. WriteStdErr('Incompatible compiler engine version.', True);
  534. Halt(1);
  535. end;
  536. ProgressPoint.X := -1;
  537. ExitCode := 0;
  538. try
  539. if ScriptFilename <> '<stdin>' then
  540. F := TTextFileReader.Create(ScriptFilename, fdOpenExisting, faRead, fsRead)
  541. else
  542. F := TTextFileReader.CreateWithExistingHandle(GetStdHandle(STD_INPUT_HANDLE));
  543. try
  544. ReadScriptLines(F);
  545. finally
  546. F.Free;
  547. end;
  548. if not Quiet then begin
  549. WriteStdOut('Compiler engine version: ' + String(Ver.Title) + ' ' + String(Ver.Version));
  550. if IsLicensed then
  551. WriteStdOut('Licensee name: ' + GetLicenseeDescription)
  552. else
  553. WriteStdOut(GetLicenseeDescription);
  554. WriteStdOut('');
  555. end;
  556. FillChar(Params, SizeOf(Params), 0);
  557. Params.Size := SizeOf(Params);
  558. Params.SourcePath := PChar(ScriptPath);
  559. Params.CallbackProc := CompilerCallbackProc;
  560. Options := '';
  561. if Output <> '' then
  562. AppendOption(Options, 'Output', Output);
  563. if OutputPath <> '' then
  564. AppendOption(Options, 'OutputDir', OutputPath);
  565. if OutputFilename <> '' then
  566. AppendOption(Options, 'OutputBaseFilename', OutputFilename);
  567. for I := 0 to SignTools.Count-1 do
  568. Options := Options + AddSignToolParam(SignTools[I]);
  569. IDESignTools := TStringList.Create;
  570. try
  571. { Also automatically read and add SignTools defined using the IDE. Adding
  572. these after the command line SignTools so that the latter are always
  573. found first by the compiler. }
  574. ReadSignTools(IDESignTools);
  575. for I := 0 to IDESignTools.Count-1 do
  576. Options := Options + AddSignToolParam(IDESignTools[I]);
  577. finally
  578. IDESignTools.Free;
  579. end;
  580. if IsppMode then
  581. IsppOptionsToString(Options, IsppOptions, Definitions, IncludePath, IncludeFiles);
  582. Params.Options := PChar(Options);
  583. StartTime := GetTickCount;
  584. {$IFNDEF STATICCOMPILER}
  585. Res := ISDllCompileScript(Params);
  586. {$ELSE}
  587. Res := ISCompileScript(Params, False);
  588. {$ENDIF}
  589. case Res of
  590. isceNoError: ;
  591. isceCompileFailure: begin
  592. ExitCode := 2;
  593. WriteStdErr('Compile aborted.', True);
  594. end;
  595. else
  596. ExitCode := 1;
  597. WriteStdErr(Format('Internal error: ISDllCompileScript returned ' +
  598. 'unexpected result (%d).', [Res]), True);
  599. end;
  600. finally
  601. FreeScriptLines;
  602. end;
  603. if ExitCode <> 0 then
  604. Halt(ExitCode);
  605. end;
  606. function ISPPInstalled: Boolean;
  607. begin
  608. Result := NewFileExists(PathExtractPath(NewParamStr(0)) + 'ISPP.dll');
  609. end;
  610. begin
  611. {$IFDEF DEBUG}
  612. ReportMemoryLeaksOnShutdown := True;
  613. {$ENDIF}
  614. SignTools := TStringList.Create;
  615. try
  616. StdOutHandle := GetStdHandle(STD_OUTPUT_HANDLE);
  617. StdErrHandle := GetStdHandle(STD_ERROR_HANDLE);
  618. var Mode: DWORD;
  619. StdOutHandleIsConsole := GetConsoleMode(StdOutHandle, Mode);
  620. StdErrHandleIsConsole := GetConsoleMode(StdErrHandle, Mode);
  621. SetConsoleCtrlHandler(@ConsoleCtrlHandler, True);
  622. try
  623. ReadLicense;
  624. IsppMode := ISPPInstalled;
  625. ProcessCommandLine;
  626. Go;
  627. except
  628. { Show a friendlier exception message. (By default, Delphi prints out
  629. the exception class and address.) }
  630. WriteStdErr(GetExceptMessage, True);
  631. Halt(2);
  632. end;
  633. finally
  634. SignTools.Free;
  635. end;
  636. end.