webidl2pas.pp 9.6 KB

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