instantfpc.pas 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. { Compile and run a pascal program.
  2. Copyright (C) 2011 Mattias Gaertner [email protected]
  3. This source is free software; you can redistribute it and/or modify it under
  4. the terms of the GNU General Public License as published by the Free
  5. Software Foundation; either version 2 of the License, or (at your option)
  6. any later version.
  7. This code is distributed in the hope that it will be useful, but WITHOUT ANY
  8. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. details.
  11. A copy of the GNU General Public License is available on the World Wide Web
  12. at <http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by writing
  13. to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  14. MA 02111-1307, USA.
  15. }
  16. program instantfpc;
  17. {$mode objfpc}{$H+}
  18. uses
  19. Classes, SysUtils, InstantFPTools;
  20. const
  21. Version = '1.0';
  22. Procedure Usage;
  23. begin
  24. writeln('instantfpc '+Version);
  25. writeln;
  26. writeln('instantfpc -h');
  27. writeln(' This help message.');
  28. writeln;
  29. writeln('instantfpc -v');
  30. writeln(' Print version and exit.');
  31. writeln;
  32. writeln('instantfpc [compiler options] <source file> [program parameters]');
  33. writeln(' Compiles source and runs program.');
  34. writeln(' Source is compared with the cache. If cache is not valid then');
  35. writeln(' source is copied to cache with the shebang line commented and');
  36. writeln(' cached source is compiled.');
  37. writeln(' If compilation fails the fpc output is written to stdout and');
  38. writeln(' instantfpc exits with error code 1.');
  39. writeln(' If compilation was successful the program is executed.');
  40. writeln(' If the compiler options contains -B the program is always');
  41. writeln(' compiled.');
  42. writeln;
  43. writeln('instantfpc --get-cache');
  44. writeln(' Prints cache directory to stdout.');
  45. writeln;
  46. writeln('instantfpc --set-cache=<path to cache>');
  47. writeln(' Set the cache to be used.');
  48. writeln;
  49. writeln('instantfpc --compiler=<path to compiler>');
  50. writeln(' Normally fpc is searched in PATH and used as compiler.');
  51. writeln;
  52. writeln('Normal usage is to add as first line ("shebang") "#!/usr/bin/instantfpc"');
  53. writeln('to a program source file. Then you can execute the source like a script.');
  54. Halt(0);
  55. end;
  56. Procedure DisplayCache;
  57. begin
  58. write(GetCacheDir);
  59. Halt(0);
  60. end ;
  61. var
  62. i,j: Integer;
  63. p: String;
  64. Filename: String;
  65. Src: TStringList;
  66. CacheDir: String;
  67. CacheFilename: String;
  68. OutputFilename: String;
  69. ExeExt: String;
  70. E : String;
  71. // Return true if filename found.
  72. Function InterpretParam(p : String) : boolean;
  73. begin
  74. Result:=False;
  75. if (P='') then exit;
  76. if p='-v' then
  77. begin
  78. writeln('instantfpc '+Version);
  79. Halt(1);
  80. end
  81. else if p='-h' then
  82. usage
  83. else if p='--get-cache' then
  84. DisplayCache
  85. else if copy(p,1,11)='--compiler=' then
  86. begin
  87. delete(P,1,11);
  88. SetCompiler(p);
  89. end
  90. else if copy(p,1,12)='--set-cache=' then
  91. begin
  92. delete(P,1,12);
  93. SetCacheDir(p);
  94. end
  95. else if (P<>'') and (p[1]<>'-') then
  96. begin
  97. Filename:=p;
  98. Result:=True;
  99. end;
  100. end;
  101. begin
  102. Filename:='';
  103. { For example:
  104. /usr/bin/instantfpc -MObjFpc -Sh ./envvars.pas param1
  105. }
  106. for i:=1 to Paramcount do
  107. begin
  108. p:=ParamStr(i);
  109. if p='' then
  110. continue
  111. else
  112. begin
  113. if (I<>1) then
  114. begin
  115. if InterpretParam(p) then
  116. Break;
  117. end
  118. else
  119. begin
  120. // The linux kernel passes the whole shebang line as 1 argument.
  121. // We must parse and split it ourselves.
  122. Repeat
  123. J:=Pos(' ',P);
  124. if (J=0) then
  125. J:=Length(P)+1;
  126. if InterpretParam(Copy(P,1,J-1)) then
  127. Break;
  128. Delete(P,1,J);
  129. Until (P='');
  130. if (FileName<>'') then
  131. Break;
  132. end;
  133. end;
  134. end;
  135. if (Filename='') then
  136. begin
  137. writeln('missing source file');
  138. Halt(1);
  139. end;
  140. CheckSourceName(Filename);
  141. Src:=TStringList.Create;
  142. try
  143. Src.LoadFromFile(Filename);
  144. CommentShebang(Src);
  145. CacheDir:=GetCacheDir;
  146. // check cache
  147. CacheFilename:=CacheDir+ExtractFileName(Filename);
  148. E:=LowerCase(ExtractFileExt(CacheFileName));
  149. if (E<>'.pp') and (E<>'.pas') and (E<>'.lpr') then
  150. CacheFileName:=CacheFileName+'.pas';
  151. ExeExt:='';
  152. OutputFilename:=CacheDir+ChangeFileExt(ExtractFileName(Filename),ExeExt);
  153. if not IsCacheValid(Src,CacheFilename,OutputFilename) then begin
  154. // save source in cache to find out next time if something changed
  155. Src.SaveToFile(CacheFilename);
  156. Compile(CacheFilename,OutputFilename);
  157. end;
  158. // run
  159. Run(OutputFilename);
  160. finally
  161. // memory is freed by OS, but for debugging puposes you can do it manually
  162. {$IFDEF IFFreeMem}
  163. Proc.Free;
  164. Src.Free;
  165. {$ENDIF}
  166. end;
  167. end.