webidl2pas.pp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. {
  2. This file is part of the Free Component Library
  3. WEBIDL to pascal code converter program
  4. Copyright (c) 2022 by Michael Van Canneyt [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. program webidl2pas;
  12. {$mode objfpc}{$H+}
  13. uses
  14. Classes, SysUtils, CustApp, webidlscanner, webidltopas, pascodegen, typinfo,
  15. webidltopas2js, webidltowasmjob, webidltowasmstub;
  16. type
  17. TWebIDLToPasFormat = (
  18. wifPas2js,
  19. wifWasmJob,
  20. wifWasmJobStub
  21. );
  22. const
  23. WebIDLToPasFormatNames: array[TWebIDLToPasFormat] of string = (
  24. 'pas2js',
  25. 'wasmjob',
  26. 'wasmjobstub'
  27. );
  28. type
  29. { TWebIDLToPasApplication }
  30. TWebIDLToPasApplication = class(TCustomApplication)
  31. private
  32. FOutputFormat: TWebIDLToPasFormat;
  33. FWebIDLToPas: TBaseWebIDLToPas;
  34. function CheckBaseOption(C: TBaseConversionOption;
  35. const AShort: Char; const aLong: String): Boolean;
  36. function CheckPas2jsOption(C: TPas2jsConversionOption;
  37. const AShort: Char; const aLong: String): Boolean;
  38. procedure DoConvertLog(Sender: TObject; {%H-}LogType: TCodegenLogType; const Msg: String);
  39. function GetInputFileName: String;
  40. function GetOutputFileName: String;
  41. function GetUnitName: String;
  42. procedure SetinputFileName(AValue: String);
  43. procedure SetOutputFileName(AValue: String);
  44. procedure SetunitName(AValue: String);
  45. protected
  46. procedure DoRun; override;
  47. procedure InitWebIDLToPas; virtual;
  48. Protected
  49. Property WebIDLToPas : TBaseWebIDLToPas Read FWebIDLToPas;
  50. public
  51. constructor Create(TheOwner: TComponent); override;
  52. destructor Destroy; override;
  53. procedure WriteHelp(Const Msg : string); virtual;
  54. Property UnitName : String Read GetUnitName Write SetunitName;
  55. property InputFileName : String Read GetInputFileName Write SetinputFileName;
  56. property OutputFileName : String Read GetOutputFileName Write SetOutputFileName;
  57. property OutputFormat: TWebIDLToPasFormat read FOutputFormat write FOutputFormat;
  58. end;
  59. { TWebIDLToPasApplication }
  60. function TWebIDLToPasApplication.GetInputFileName: String;
  61. begin
  62. Result:=FWebIDLToPas.InputFileName;
  63. end;
  64. procedure TWebIDLToPasApplication.DoConvertLog(Sender: TObject;
  65. LogType: TCodegenLogType; const Msg: String);
  66. begin
  67. {AllowWriteln}
  68. Writeln(Msg);
  69. {AllowWriteln-}
  70. end;
  71. function TWebIDLToPasApplication.GetOutputFileName: String;
  72. begin
  73. Result:=FWebIDLToPas.OutputFileName
  74. end;
  75. function TWebIDLToPasApplication.GetUnitName: String;
  76. begin
  77. Result:=FWebIDLToPas.OutputUnitName;
  78. end;
  79. procedure TWebIDLToPasApplication.SetinputFileName(AValue: String);
  80. begin
  81. FWebIDLToPas.InputFileName:=aValue;
  82. end;
  83. procedure TWebIDLToPasApplication.SetOutputFileName(AValue: String);
  84. begin
  85. FWebIDLToPas.OutputFileName:=aValue;
  86. end;
  87. procedure TWebIDLToPasApplication.SetunitName(AValue: String);
  88. begin
  89. FWebIDLToPas.OutputUnitName:=aValue;
  90. end;
  91. function TWebIDLToPasApplication.CheckBaseOption(C: TBaseConversionOption;
  92. const AShort: Char; const aLong: String): Boolean;
  93. begin
  94. Result:=HasOption(aShort,ALong);
  95. if Result then
  96. FWebIDLToPas.BaseOptions:=FWebIDLToPas.BaseOptions+[C];
  97. end;
  98. function TWebIDLToPasApplication.CheckPas2jsOption(C: TPas2jsConversionOption;
  99. const AShort: Char; const aLong: String): Boolean;
  100. begin
  101. if not (FWebIDLToPas is TWebIDLToPas2js) then exit;
  102. Result:=HasOption(aShort,ALong);
  103. if Result then
  104. TWebIDLToPas2js(FWebIDLToPas).Pas2jsOptions:=TWebIDLToPas2js(FWebIDLToPas).Pas2jsOptions+[C];
  105. end;
  106. procedure TWebIDLToPasApplication.DoRun;
  107. var
  108. A,ErrorMsg: String;
  109. I : Integer;
  110. ok: Boolean;
  111. f: TWebIDLToPasFormat;
  112. begin
  113. Terminate;
  114. // quick check parameters
  115. ErrorMsg:=CheckOptions('ced::f:g:hi:m:n:o:pt:u:vw:x:r', [
  116. 'help',
  117. 'constexternal',
  118. 'dicttoclass::',
  119. 'expandunionargs',
  120. 'outputformat:',
  121. 'globals:',
  122. 'input:',
  123. 'implementation:',
  124. 'include:',
  125. 'output:',
  126. 'optionsinheader',
  127. 'typealiases:',
  128. 'unitname:',
  129. 'verbose',
  130. 'webidlversion:',
  131. 'extra:',
  132. 'chrome'
  133. ]);
  134. if (ErrorMsg<>'') or HasOption('h','help') then
  135. begin
  136. ErrorMsg:='Missing input filename';
  137. WriteHelp(ErrorMsg);
  138. Exit();
  139. end;
  140. // first read outputformat and create FWebIDLToPas
  141. if HasOption('f','outputformat') then
  142. begin
  143. A:=GetOptionValue('f','outputformat');
  144. ok:=false;
  145. for f in TWebIDLToPasFormat do
  146. begin
  147. if SameText(A,WebIDLToPasFormatNames[f]) then
  148. begin
  149. OutputFormat:=f;
  150. ok:=true;
  151. end;
  152. end;
  153. if not ok then
  154. begin
  155. WriteHelp('unknown outputformat "'+A+'"');
  156. exit;
  157. end;
  158. end;
  159. InitWebIDLToPas;
  160. // then set verbosity
  161. FWebIDLToPas.Verbose:=HasOption('v','verbose');
  162. // read other options
  163. CheckPas2jsOption(p2jcoExternalConst,'c','constexternal');
  164. if CheckBaseOption(coDictionaryAsClass,'d','dicttoclass') then
  165. TWebIDLToPas2js(FWebIDLToPas).DictionaryClassParent:=GetOptionValue('d','dicttoclass');
  166. CheckBaseOption(coExpandUnionTypeArgs,'e','expandunionargs');
  167. CheckBaseOption(coChromeWindow,'r','chrome');
  168. // -f ?
  169. A:=GetOptionValue('g','globals');
  170. if (Copy(A,1,1)='@') then
  171. begin
  172. Delete(A,1,1);
  173. FWebIDLToPas.GlobalVars.LoadFromFile(A);
  174. end
  175. else
  176. FWebIDLToPas.GlobalVars.CommaText:=A;
  177. InputFileName:=GetOptionValue('i','input');
  178. if (InputFileName='') then
  179. begin
  180. WriteHelp('Missing input filename');
  181. Exit();
  182. end;
  183. if HasOption('m','implementation') then
  184. FWebIDLToPas.IncludeImplementationCode.LoadFromFile(GetOptionValue('m','implementation'));
  185. if HasOption('n','include') then
  186. FWebIDLToPas.IncludeInterfaceCode.LoadFromFile(GetOptionValue('n','include'));
  187. OutputFileName:=GetOptionValue('o','output');
  188. CheckBaseOption(coAddOptionsToHeader,'p','optionsinheader');
  189. A:=GetOptionValue('t','typealiases');
  190. if (Copy(A,1,1)='@') then
  191. begin
  192. Delete(A,1,1);
  193. FWebIDLToPas.TypeAliases.LoadFromFile(A);
  194. end
  195. else
  196. FWebIDLToPas.TypeAliases.CommaText:=A;
  197. UnitName:=GetOptionValue('u','unitname');
  198. if UnitName='' then
  199. UnitName:=ChangeFileExt(ExtractFileName(InputFileName),'');
  200. if OutputFileName='' then
  201. begin
  202. if (UnitName<>'') then
  203. OutputFileName:=ExtractFilePath(InputFileName)+UnitName+'.pas';
  204. end;
  205. if HasOption('w','webidlversion') then
  206. begin
  207. A:=GetOptionValue('w','webidlversion');
  208. I:=GetEnumValue(TypeInfo(TWebIDLVersion),A);
  209. if (I<>-1) then
  210. FWebIDLToPas.WebIDLVersion:=TWebIDLVersion(I)
  211. else
  212. begin
  213. WriteHelp('Invalid webidl version: "'+A+'"');
  214. exit;
  215. end;
  216. end;
  217. FWebIDLToPas.ExtraUnits:=GetOptionValue('x','extra');
  218. FWebIDLToPas.Execute;
  219. end;
  220. procedure TWebIDLToPasApplication.InitWebIDLToPas;
  221. begin
  222. case OutputFormat of
  223. wifWasmJob:
  224. FWebIDLToPas:=TWebIDLToPasWasmJob.Create(Self);
  225. wifWasmJobStub:
  226. FWebIDLToPas:=TWebIDLToPasWasmJobStub.Create(Self);
  227. else
  228. FWebIDLToPas:=TWebIDLToPas2js.Create(Self);
  229. end;
  230. FWebIDLToPas.OnLog:=@DoConvertLog;
  231. FWebIDLToPas.ClassPrefix:='TJS';
  232. FWebIDLToPas.ClassSuffix:='';
  233. FWebIDLToPas.KeywordSuffix:='_';
  234. FWebIDLToPas.KeywordPrefix:='';
  235. FWebIDLToPas.DottedUnitsSupport:=dusFull;
  236. end;
  237. constructor TWebIDLToPasApplication.Create(TheOwner: TComponent);
  238. begin
  239. inherited Create(TheOwner);
  240. StopOnException:=True;
  241. ExceptionExitCode:=1;
  242. end;
  243. destructor TWebIDLToPasApplication.Destroy;
  244. begin
  245. FreeAndNil(FWebIDLToPas);
  246. inherited Destroy;
  247. end;
  248. procedure TWebIDLToPasApplication.WriteHelp(const Msg: string);
  249. begin
  250. {AllowWriteln}
  251. if (Msg<>'') then
  252. Writeln(StdErr,'Error : ',Msg);
  253. writeln(StdErr,'Usage: ', ExeName, ' [options]');
  254. Writeln(StdErr,'Where option is one or more of');
  255. Writeln(StdErr,'-h --help this help text');
  256. Writeln(StdErr,'-c --constexternal Write consts as external const (no value)');
  257. Writeln(StdErr,'-d --dicttoclass[=Parent] Write dictionaries as classes');
  258. Writeln(StdErr,'-e --expandunionargs Add overloads for all Union typed function arguments');
  259. Writeln(StdErr,'-f --outputformat=[pas2js|wasmjob] Output format, default ',WebIDLToPasFormatNames[OutputFormat]);
  260. Writeln(StdErr,'-g --globals=list A comma separated list of global vars');
  261. Writeln(StdErr,' use @filename to load the globals from file.');
  262. Writeln(StdErr,' wasmjob: PasVarName=JSClassName,JOBRegisterName');
  263. Writeln(StdErr,'-i --input=FileName input webidl file');
  264. Writeln(StdErr,'-m --implementation=Filename include file as implementation');
  265. Writeln(StdErr,'-n --include=Filename include file at end of interface');
  266. Writeln(StdErr,'-o --output=FileName output file. Defaults to unit name with .pas extension appended.');
  267. Writeln(StdErr,'-p --optionsinheader add options to header of generated file');
  268. Writeln(StdErr,'-s --stub Write a stub implementation for native compilation');
  269. Writeln(StdErr,'-t --typealiases=alias A comma separated list of type aliases in Alias=Name form');
  270. Writeln(StdErr,' use @filename to load the aliases from file.');
  271. Writeln(StdErr,'-u --unitname=Name name for unit. Defaults to input file without extension.');
  272. Writeln(StdErr,'-v --verbose Output some diagnostic information');
  273. Writeln(StdErr,'-w --webidlversion=V Set web IDL version. Allowed values: v1 or v2');
  274. Writeln(StdErr,'-x --extra=units Extra units to put in uses clause (comma separated list)');
  275. ExitCode:=Ord(Msg<>'');
  276. {AllowWriteln-}
  277. end;
  278. var
  279. Application: TWebIDLToPasApplication;
  280. begin
  281. Application:=TWebIDLToPasApplication.Create(nil);
  282. Application.Title:='WebIDL To Pascal converter Application';
  283. Application.Run;
  284. Application.Free;
  285. end.