webidl2pas.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  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. CheckBaseOption(coPrivateMethods,'a','private');
  125. // -f ?
  126. A:=GetOptionValue('g','globals');
  127. if (Copy(A,1,1)='@') then
  128. begin
  129. Delete(A,1,1);
  130. FWebIDLToPas.GlobalVars.LoadFromFile(A);
  131. end
  132. else
  133. FWebIDLToPas.GlobalVars.CommaText:=A;
  134. if HasOption('l','list') then
  135. begin
  136. L:=TStringList.Create;
  137. try
  138. A:=GetOptionValue('l','list');
  139. if (Copy(A,1,1)='@') then
  140. begin
  141. Delete(A,1,1);
  142. L.LoadFromFile(A);
  143. end
  144. else
  145. L.CommaText:=A;
  146. FWebIDLToPas.SetUsedList(L);
  147. finally
  148. L.free;
  149. end;
  150. end;
  151. InputFileName:=GetOptionValue('i','input');
  152. if (InputFileName='') then
  153. begin
  154. WriteHelp('Missing input filename');
  155. Exit(False);
  156. end;
  157. if HasOption('m','implementation') then
  158. FWebIDLToPas.IncludeImplementationCode.LoadFromFile(GetOptionValue('m','implementation'));
  159. if HasOption('n','include') then
  160. FWebIDLToPas.IncludeInterfaceCode.LoadFromFile(GetOptionValue('n','include'));
  161. OutputFileName:=GetOptionValue('o','output');
  162. CheckBaseOption(coAddOptionsToHeader,'p','optionsinheader');
  163. A:=GetOptionValue('t','typealiases');
  164. if (Copy(A,1,1)='@') then
  165. begin
  166. Delete(A,1,1);
  167. FWebIDLToPas.TypeAliases.LoadFromFile(A);
  168. end
  169. else
  170. FWebIDLToPas.TypeAliases.CommaText:=A;
  171. UnitName:=GetOptionValue('u','unitname');
  172. if UnitName='' then
  173. UnitName:=ChangeFileExt(ExtractFileName(InputFileName),'');
  174. if OutputFileName='' then
  175. begin
  176. if (UnitName<>'') then
  177. OutputFileName:=ExtractFilePath(InputFileName)+UnitName+'.pas';
  178. end;
  179. if HasOption('w','webidlversion') then
  180. begin
  181. A:=GetOptionValue('w','webidlversion');
  182. I:=GetEnumValue(TypeInfo(TWebIDLVersion),A);
  183. if (I<>-1) then
  184. FWebIDLToPas.WebIDLVersion:=TWebIDLVersion(I)
  185. else
  186. begin
  187. WriteHelp('Invalid webidl version: "'+A+'"');
  188. Exit(False);
  189. end;
  190. end;
  191. FWebIDLToPas.ExtraUnits:=GetOptionValue('x','extra');
  192. end;
  193. procedure TWebIDLToPasApplication.DoRun;
  194. const
  195. Short = 'ced::f:g:hi:m:n:o:pt:u:vw:x:rl:a';
  196. Long : Array of string = (
  197. 'help',
  198. 'constexternal',
  199. 'dicttoclass::',
  200. 'expandunionargs',
  201. 'outputformat:',
  202. 'globals:',
  203. 'input:',
  204. 'implementation:',
  205. 'include:',
  206. 'output:',
  207. 'optionsinheader',
  208. 'typealiases:',
  209. 'unitname:',
  210. 'verbose',
  211. 'webidlversion:',
  212. 'extra:',
  213. 'chrome',
  214. 'list:',
  215. 'private'
  216. );
  217. var
  218. A,ErrorMsg: String;
  219. ok: Boolean;
  220. f: TWebIDLToPasFormat;
  221. begin
  222. Terminate;
  223. // quick check parameters
  224. ErrorMsg:=CheckOptions(Short,Long);
  225. if (ErrorMsg<>'') or HasOption('h','help') then
  226. begin
  227. ErrorMsg:='Missing input filename';
  228. WriteHelp(ErrorMsg);
  229. Exit();
  230. end;
  231. // first read outputformat and create FWebIDLToPas
  232. if HasOption('f','outputformat') then
  233. begin
  234. A:=GetOptionValue('f','outputformat');
  235. ok:=false;
  236. for f in TWebIDLToPasFormat do
  237. begin
  238. if SameText(A,WebIDLToPasFormatNames[f]) then
  239. begin
  240. OutputFormat:=f;
  241. ok:=true;
  242. end;
  243. end;
  244. if not ok then
  245. begin
  246. WriteHelp('unknown outputformat "'+A+'"');
  247. exit;
  248. end;
  249. end;
  250. InitWebIDLToPas;
  251. if ConfigWebIDLToPas then
  252. FWebIDLToPas.Execute;
  253. end;
  254. procedure TWebIDLToPasApplication.InitWebIDLToPas;
  255. begin
  256. case OutputFormat of
  257. wifWasmJob:
  258. FWebIDLToPas:=TWebIDLToPasWasmJob.Create(Self);
  259. wifWasmJobStub:
  260. FWebIDLToPas:=TWebIDLToPasWasmJobStub.Create(Self);
  261. else
  262. FWebIDLToPas:=TWebIDLToPas2js.Create(Self);
  263. end;
  264. FWebIDLToPas.OnLog:=@DoConvertLog;
  265. FWebIDLToPas.ClassPrefix:='TJS';
  266. FWebIDLToPas.ClassSuffix:='';
  267. FWebIDLToPas.KeywordSuffix:='_';
  268. FWebIDLToPas.KeywordPrefix:='';
  269. FWebIDLToPas.DottedUnitsSupport:=dusFull;
  270. end;
  271. constructor TWebIDLToPasApplication.Create(TheOwner: TComponent);
  272. begin
  273. inherited Create(TheOwner);
  274. StopOnException:=True;
  275. ExceptionExitCode:=1;
  276. end;
  277. destructor TWebIDLToPasApplication.Destroy;
  278. begin
  279. FreeAndNil(FWebIDLToPas);
  280. inherited Destroy;
  281. end;
  282. procedure TWebIDLToPasApplication.WriteHelp(const Msg: string);
  283. begin
  284. {AllowWriteln}
  285. if (Msg<>'') then
  286. Writeln(StdErr,'Error : ',Msg);
  287. writeln(StdErr,'Usage: ', ExeName, ' [options]');
  288. Writeln(StdErr,'Where option is one or more of');
  289. Writeln(StdErr,'-h --help This help text.');
  290. Writeln(StdErr,'-a --private Write getters/setters as private methods. Default is protected.');
  291. Writeln(StdErr,'-c --constexternal Write consts as external const (no value).');
  292. Writeln(StdErr,'-d --dicttoclass[=Parent] Write dictionaries as classes.');
  293. Writeln(StdErr,'-e --expandunionargs Add overloads for all Union typed function arguments.');
  294. Writeln(StdErr,'-f --outputformat=[pas2js|wasmjob] Output format, default ',WebIDLToPasFormatNames[OutputFormat],'.');
  295. Writeln(StdErr,'-g --globals=list A comma separated list of global vars.');
  296. Writeln(StdErr,' Use @filename to load the globals from file.');
  297. Writeln(StdErr,' wasmjob: PasVarName=JSClassName,JOBRegisterName');
  298. Writeln(StdErr,'-i --input=FileName Input webidl file.');
  299. Writeln(StdErr,'-m --implementation=Filename include file as implementation.');
  300. Writeln(StdErr,'-n --include=Filename Include file at end of interface.');
  301. Writeln(StdErr,'-o --output=FileName Output file. Defaults to unit name with .pas extension appended.');
  302. Writeln(StdErr,'-p --optionsinheader Add options to header of generated file.');
  303. Writeln(StdErr,'-l --used=types A comma separated list of used IDL types. Only these types and necessary dependent types will be converted.');
  304. Writeln(StdErr,' use @filename to load the globals from file.');
  305. Writeln(StdErr,'-t --typealiases=alias A comma separated list of type aliases in Alias=Name form.');
  306. Writeln(StdErr,' use @filename to load the aliases from file.');
  307. Writeln(StdErr,'-u --unitname=Name name for unit. Defaults to input file without extension.');
  308. Writeln(StdErr,'-v --verbose Output some diagnostic information.');
  309. Writeln(StdErr,'-w --webidlversion=V Set web IDL version. Allowed values: v1 or v2.');
  310. Writeln(StdErr,'-x --extra=units Extra units to put in uses clause (comma separated list).');
  311. ExitCode:=Ord(Msg<>'');
  312. {AllowWriteln-}
  313. end;
  314. var
  315. Application: TWebIDLToPasApplication;
  316. begin
  317. Application:=TWebIDLToPasApplication.Create(nil);
  318. Application.Title:='WebIDL To Pascal converter Application';
  319. Application.Run;
  320. Application.Free;
  321. end.