webidl2pas.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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. function ConfigWebIDLToPas: Boolean;
  39. procedure DoConvertLog(Sender: TObject; {%H-}LogType: TCodegenLogType; const Msg: String);
  40. function GetInputFileName: String;
  41. function GetOutputFileName: String;
  42. function GetUnitName: String;
  43. procedure SetinputFileName(AValue: String);
  44. procedure SetOutputFileName(AValue: String);
  45. procedure SetunitName(AValue: String);
  46. protected
  47. procedure DoRun; override;
  48. procedure InitWebIDLToPas; virtual;
  49. Protected
  50. Property WebIDLToPas : TBaseWebIDLToPas Read FWebIDLToPas;
  51. public
  52. constructor Create(TheOwner: TComponent); override;
  53. destructor Destroy; override;
  54. procedure WriteHelp(Const Msg : string); virtual;
  55. Property UnitName : String Read GetUnitName Write SetunitName;
  56. property InputFileName : String Read GetInputFileName Write SetinputFileName;
  57. property OutputFileName : String Read GetOutputFileName Write SetOutputFileName;
  58. property OutputFormat: TWebIDLToPasFormat read FOutputFormat write FOutputFormat;
  59. end;
  60. { TWebIDLToPasApplication }
  61. function TWebIDLToPasApplication.GetInputFileName: String;
  62. begin
  63. Result:=FWebIDLToPas.InputFileName;
  64. end;
  65. procedure TWebIDLToPasApplication.DoConvertLog(Sender: TObject;
  66. LogType: TCodegenLogType; const Msg: String);
  67. begin
  68. {AllowWriteln}
  69. Writeln(Msg);
  70. {AllowWriteln-}
  71. end;
  72. function TWebIDLToPasApplication.GetOutputFileName: String;
  73. begin
  74. Result:=FWebIDLToPas.OutputFileName
  75. end;
  76. function TWebIDLToPasApplication.GetUnitName: String;
  77. begin
  78. Result:=FWebIDLToPas.OutputUnitName;
  79. end;
  80. procedure TWebIDLToPasApplication.SetinputFileName(AValue: String);
  81. begin
  82. FWebIDLToPas.InputFileName:=aValue;
  83. end;
  84. procedure TWebIDLToPasApplication.SetOutputFileName(AValue: String);
  85. begin
  86. FWebIDLToPas.OutputFileName:=aValue;
  87. end;
  88. procedure TWebIDLToPasApplication.SetunitName(AValue: String);
  89. begin
  90. FWebIDLToPas.OutputUnitName:=aValue;
  91. end;
  92. function TWebIDLToPasApplication.CheckBaseOption(C: TBaseConversionOption;
  93. const AShort: Char; const aLong: String): Boolean;
  94. begin
  95. Result:=HasOption(aShort,ALong);
  96. if Result then
  97. FWebIDLToPas.BaseOptions:=FWebIDLToPas.BaseOptions+[C];
  98. end;
  99. function TWebIDLToPasApplication.CheckPas2jsOption(C: TPas2jsConversionOption;
  100. const AShort: Char; const aLong: String): Boolean;
  101. begin
  102. if not (FWebIDLToPas is TWebIDLToPas2js) then exit;
  103. Result:=HasOption(aShort,ALong);
  104. if Result then
  105. TWebIDLToPas2js(FWebIDLToPas).Pas2jsOptions:=TWebIDLToPas2js(FWebIDLToPas).Pas2jsOptions+[C];
  106. end;
  107. // Return true if the configuration was OK.
  108. function TWebIDLToPasApplication.ConfigWebIDLToPas : Boolean;
  109. var
  110. A,ErrorMsg: String;
  111. I : Integer;
  112. ok: Boolean;
  113. L : TStrings;
  114. begin
  115. Result:=True;
  116. // set verbosity
  117. FWebIDLToPas.Verbose:=HasOption('v','verbose');
  118. // read other options
  119. CheckPas2jsOption(p2jcoExternalConst,'c','constexternal');
  120. if CheckBaseOption(coDictionaryAsClass,'d','dicttoclass') then
  121. TWebIDLToPas2js(FWebIDLToPas).DictionaryClassParent:=GetOptionValue('d','dicttoclass');
  122. CheckBaseOption(coExpandUnionTypeArgs,'e','expandunionargs');
  123. CheckBaseOption(coChromeWindow,'r','chrome');
  124. // -f ?
  125. A:=GetOptionValue('g','globals');
  126. if (Copy(A,1,1)='@') then
  127. begin
  128. Delete(A,1,1);
  129. FWebIDLToPas.GlobalVars.LoadFromFile(A);
  130. end
  131. else
  132. FWebIDLToPas.GlobalVars.CommaText:=A;
  133. if HasOption('l','list') then
  134. begin
  135. L:=TStringList.Create;
  136. try
  137. A:=GetOptionValue('l','list');
  138. if (Copy(A,1,1)='@') then
  139. begin
  140. Delete(A,1,1);
  141. L.LoadFromFile(A);
  142. end
  143. else
  144. L.CommaText:=A;
  145. FWebIDLToPas.SetUsedList(L);
  146. finally
  147. L.free;
  148. end;
  149. end;
  150. InputFileName:=GetOptionValue('i','input');
  151. if (InputFileName='') then
  152. begin
  153. WriteHelp('Missing input filename');
  154. Exit(False);
  155. end;
  156. if HasOption('m','implementation') then
  157. FWebIDLToPas.IncludeImplementationCode.LoadFromFile(GetOptionValue('m','implementation'));
  158. if HasOption('n','include') then
  159. FWebIDLToPas.IncludeInterfaceCode.LoadFromFile(GetOptionValue('n','include'));
  160. OutputFileName:=GetOptionValue('o','output');
  161. CheckBaseOption(coAddOptionsToHeader,'p','optionsinheader');
  162. A:=GetOptionValue('t','typealiases');
  163. if (Copy(A,1,1)='@') then
  164. begin
  165. Delete(A,1,1);
  166. FWebIDLToPas.TypeAliases.LoadFromFile(A);
  167. end
  168. else
  169. FWebIDLToPas.TypeAliases.CommaText:=A;
  170. UnitName:=GetOptionValue('u','unitname');
  171. if UnitName='' then
  172. UnitName:=ChangeFileExt(ExtractFileName(InputFileName),'');
  173. if OutputFileName='' then
  174. begin
  175. if (UnitName<>'') then
  176. OutputFileName:=ExtractFilePath(InputFileName)+UnitName+'.pas';
  177. end;
  178. if HasOption('w','webidlversion') then
  179. begin
  180. A:=GetOptionValue('w','webidlversion');
  181. I:=GetEnumValue(TypeInfo(TWebIDLVersion),A);
  182. if (I<>-1) then
  183. FWebIDLToPas.WebIDLVersion:=TWebIDLVersion(I)
  184. else
  185. begin
  186. WriteHelp('Invalid webidl version: "'+A+'"');
  187. Exit(False);
  188. end;
  189. end;
  190. FWebIDLToPas.ExtraUnits:=GetOptionValue('x','extra');
  191. end;
  192. procedure TWebIDLToPasApplication.DoRun;
  193. const
  194. Short = 'ced::f:g:hi:m:n:o:pt:u:vw:x:rl:';
  195. Long : Array of string = (
  196. 'help',
  197. 'constexternal',
  198. 'dicttoclass::',
  199. 'expandunionargs',
  200. 'outputformat:',
  201. 'globals:',
  202. 'input:',
  203. 'implementation:',
  204. 'include:',
  205. 'output:',
  206. 'optionsinheader',
  207. 'typealiases:',
  208. 'unitname:',
  209. 'verbose',
  210. 'webidlversion:',
  211. 'extra:',
  212. 'chrome',
  213. 'list:'
  214. );
  215. var
  216. A,ErrorMsg: String;
  217. ok: Boolean;
  218. f: TWebIDLToPasFormat;
  219. begin
  220. Terminate;
  221. // quick check parameters
  222. ErrorMsg:=CheckOptions(Short,Long);
  223. if (ErrorMsg<>'') or HasOption('h','help') then
  224. begin
  225. ErrorMsg:='Missing input filename';
  226. WriteHelp(ErrorMsg);
  227. Exit();
  228. end;
  229. // first read outputformat and create FWebIDLToPas
  230. if HasOption('f','outputformat') then
  231. begin
  232. A:=GetOptionValue('f','outputformat');
  233. ok:=false;
  234. for f in TWebIDLToPasFormat do
  235. begin
  236. if SameText(A,WebIDLToPasFormatNames[f]) then
  237. begin
  238. OutputFormat:=f;
  239. ok:=true;
  240. end;
  241. end;
  242. if not ok then
  243. begin
  244. WriteHelp('unknown outputformat "'+A+'"');
  245. exit;
  246. end;
  247. end;
  248. InitWebIDLToPas;
  249. if ConfigWebIDLToPas then
  250. FWebIDLToPas.Execute;
  251. end;
  252. procedure TWebIDLToPasApplication.InitWebIDLToPas;
  253. begin
  254. case OutputFormat of
  255. wifWasmJob:
  256. FWebIDLToPas:=TWebIDLToPasWasmJob.Create(Self);
  257. wifWasmJobStub:
  258. FWebIDLToPas:=TWebIDLToPasWasmJobStub.Create(Self);
  259. else
  260. FWebIDLToPas:=TWebIDLToPas2js.Create(Self);
  261. end;
  262. FWebIDLToPas.OnLog:=@DoConvertLog;
  263. FWebIDLToPas.ClassPrefix:='TJS';
  264. FWebIDLToPas.ClassSuffix:='';
  265. FWebIDLToPas.KeywordSuffix:='_';
  266. FWebIDLToPas.KeywordPrefix:='';
  267. FWebIDLToPas.DottedUnitsSupport:=dusFull;
  268. end;
  269. constructor TWebIDLToPasApplication.Create(TheOwner: TComponent);
  270. begin
  271. inherited Create(TheOwner);
  272. StopOnException:=True;
  273. ExceptionExitCode:=1;
  274. end;
  275. destructor TWebIDLToPasApplication.Destroy;
  276. begin
  277. FreeAndNil(FWebIDLToPas);
  278. inherited Destroy;
  279. end;
  280. procedure TWebIDLToPasApplication.WriteHelp(const Msg: string);
  281. begin
  282. {AllowWriteln}
  283. if (Msg<>'') then
  284. Writeln(StdErr,'Error : ',Msg);
  285. writeln(StdErr,'Usage: ', ExeName, ' [options]');
  286. Writeln(StdErr,'Where option is one or more of');
  287. Writeln(StdErr,'-h --help This help text.');
  288. Writeln(StdErr,'-c --constexternal Write consts as external const (no value).');
  289. Writeln(StdErr,'-d --dicttoclass[=Parent] Write dictionaries as classes.');
  290. Writeln(StdErr,'-e --expandunionargs Add overloads for all Union typed function arguments.');
  291. Writeln(StdErr,'-f --outputformat=[pas2js|wasmjob] Output format, default ',WebIDLToPasFormatNames[OutputFormat],'.');
  292. Writeln(StdErr,'-g --globals=list A comma separated list of global vars.');
  293. Writeln(StdErr,' Use @filename to load the globals from file.');
  294. Writeln(StdErr,' wasmjob: PasVarName=JSClassName,JOBRegisterName');
  295. Writeln(StdErr,'-i --input=FileName Input webidl file.');
  296. Writeln(StdErr,'-m --implementation=Filename include file as implementation.');
  297. Writeln(StdErr,'-n --include=Filename Include file at end of interface.');
  298. Writeln(StdErr,'-o --output=FileName Output file. Defaults to unit name with .pas extension appended.');
  299. Writeln(StdErr,'-p --optionsinheader Add options to header of generated file.');
  300. Writeln(StdErr,'-l --used=types A comma separated list of used IDL types. Only these types and necessary dependent types will be converted.');
  301. Writeln(StdErr,' use @filename to load the globals from file.');
  302. Writeln(StdErr,'-t --typealiases=alias A comma separated list of type aliases in Alias=Name form.');
  303. Writeln(StdErr,' use @filename to load the aliases from file.');
  304. Writeln(StdErr,'-u --unitname=Name name for unit. Defaults to input file without extension.');
  305. Writeln(StdErr,'-v --verbose Output some diagnostic information.');
  306. Writeln(StdErr,'-w --webidlversion=V Set web IDL version. Allowed values: v1 or v2.');
  307. Writeln(StdErr,'-x --extra=units Extra units to put in uses clause (comma separated list).');
  308. ExitCode:=Ord(Msg<>'');
  309. {AllowWriteln-}
  310. end;
  311. var
  312. Application: TWebIDLToPasApplication;
  313. begin
  314. Application:=TWebIDLToPasApplication.Create(nil);
  315. Application.Title:='WebIDL To Pascal converter Application';
  316. Application.Run;
  317. Application.Free;
  318. end.