webidl2pas.pp 9.5 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. procedure E(const Msg: string);
  106. begin
  107. {AllowWriteln}
  108. writeln('Error: ',Msg);
  109. {AllowWriteln-}
  110. Halt(1);
  111. end;
  112. var
  113. A,ErrorMsg: String;
  114. I : Integer;
  115. ok: Boolean;
  116. f: TWebIDLToPasFormat;
  117. begin
  118. Terminate;
  119. // quick check parameters
  120. ErrorMsg:=CheckOptions('ced::f:g:hi:m:n:o:pt:u:vw:x:', [
  121. 'help',
  122. 'constexternal',
  123. 'dicttoclass::',
  124. 'expandunionargs',
  125. 'outputformat:',
  126. 'globals:',
  127. 'input:',
  128. 'implementation:',
  129. 'include:',
  130. 'output:',
  131. 'optionsinheader',
  132. 'typealiases:',
  133. 'unitname:',
  134. 'verbose',
  135. 'webidlversion:',
  136. 'extra:'
  137. ]);
  138. if (ErrorMsg<>'') or HasOption('h','help') then
  139. begin
  140. WriteHelp(ErrorMsg);
  141. if ErrorMsg<>'' then
  142. Halt(1)
  143. else
  144. Exit;
  145. end;
  146. // first read outputformat and create FWebIDLToPas
  147. if HasOption('f','outputformat') then
  148. begin
  149. A:=GetOptionValue('f','outputformat');
  150. ok:=false;
  151. for f in TWebIDLToPasFormat do
  152. begin
  153. if SameText(A,WebIDLToPasFormatNames[f]) then
  154. begin
  155. OutputFormat:=f;
  156. ok:=true;
  157. end;
  158. end;
  159. if not ok then
  160. E('unknown outputformat "'+A+'"');
  161. end;
  162. InitWebIDLToPas;
  163. // then set verbosity
  164. FWebIDLToPas.Verbose:=HasOption('v','verbose');
  165. // read other options
  166. CheckPas2jsOption(p2jcoExternalConst,'c','constexternal');
  167. if CheckBaseOption(coDictionaryAsClass,'d','dicttoclass') then
  168. TWebIDLToPas2js(FWebIDLToPas).DictionaryClassParent:=GetOptionValue('d','dicttoclass');
  169. CheckBaseOption(coExpandUnionTypeArgs,'e','expandunionargs');
  170. // -f ?
  171. A:=GetOptionValue('g','globals');
  172. if (Copy(A,1,1)='@') then
  173. begin
  174. Delete(A,1,1);
  175. FWebIDLToPas.GlobalVars.LoadFromFile(A);
  176. end
  177. else
  178. FWebIDLToPas.GlobalVars.CommaText:=A;
  179. InputFileName:=GetOptionValue('i','input');
  180. if HasOption('m','implementation') then
  181. FWebIDLToPas.IncludeImplementationCode.LoadFromFile(GetOptionValue('m','implementation'));
  182. if HasOption('n','include') then
  183. FWebIDLToPas.IncludeInterfaceCode.LoadFromFile(GetOptionValue('n','include'));
  184. OutputFileName:=GetOptionValue('o','output');
  185. CheckBaseOption(coAddOptionsToHeader,'p','optionsinheader');
  186. A:=GetOptionValue('t','typealiases');
  187. if (Copy(A,1,1)='@') then
  188. begin
  189. Delete(A,1,1);
  190. FWebIDLToPas.TypeAliases.LoadFromFile(A);
  191. end
  192. else
  193. FWebIDLToPas.TypeAliases.CommaText:=A;
  194. UnitName:=GetOptionValue('u','unitname');
  195. if UnitName='' then
  196. UnitName:=ChangeFileExt(ExtractFileName(InputFileName),'');
  197. if OutputFileName='' then
  198. begin
  199. if (UnitName<>'') then
  200. OutputFileName:=ExtractFilePath(InputFileName)+UnitName+'.pas';
  201. end;
  202. if HasOption('w','webidlversion') then
  203. begin
  204. A:=GetOptionValue('w','webidlversion');
  205. I:=GetEnumValue(TypeInfo(TWebIDLVersion),A);
  206. if (I<>-1) then
  207. FWebIDLToPas.WebIDLVersion:=TWebIDLVersion(I)
  208. else
  209. E('Invalid webidl version: "'+A+'"');
  210. end;
  211. FWebIDLToPas.ExtraUnits:=GetOptionValue('x','extra');
  212. FWebIDLToPas.Execute;
  213. // stop program loop
  214. Terminate;
  215. end;
  216. procedure TWebIDLToPasApplication.InitWebIDLToPas;
  217. begin
  218. case OutputFormat of
  219. wifWasmJob:
  220. FWebIDLToPas:=TWebIDLToPasWasmJob.Create(Self);
  221. else
  222. FWebIDLToPas:=TWebIDLToPas2js.Create(Self);
  223. end;
  224. FWebIDLToPas.OnLog:=@DoConvertLog;
  225. FWebIDLToPas.ClassPrefix:='TJS';
  226. FWebIDLToPas.ClassSuffix:='';
  227. FWebIDLToPas.KeywordSuffix:='_';
  228. FWebIDLToPas.KeywordPrefix:='';
  229. end;
  230. constructor TWebIDLToPasApplication.Create(TheOwner: TComponent);
  231. begin
  232. inherited Create(TheOwner);
  233. StopOnException:=True;
  234. ExceptionExitCode:=1;
  235. end;
  236. destructor TWebIDLToPasApplication.Destroy;
  237. begin
  238. FreeAndNil(FWebIDLToPas);
  239. inherited Destroy;
  240. end;
  241. procedure TWebIDLToPasApplication.WriteHelp(const Msg: string);
  242. begin
  243. {AllowWriteln}
  244. if (Msg<>'') then
  245. Writeln(StdErr,'Error : ',Msg);
  246. writeln(StdErr,'Usage: ', ExeName, ' [options]');
  247. Writeln(StdErr,'Where option is one or more of');
  248. Writeln(StdErr,'-h --help this help text');
  249. Writeln(StdErr,'-c --constexternal Write consts as external const (no value)');
  250. Writeln(StdErr,'-d --dicttoclass[=Parent] Write dictionaries as classes');
  251. Writeln(StdErr,'-e --expandunionargs Add overloads for all Union typed function arguments');
  252. Writeln(StdErr,'-f --outputformat=[pas2js|wasmjob] Output format, default ',WebIDLToPasFormatNames[OutputFormat]);
  253. Writeln(StdErr,'-g --globals=list A comma separated list of global vars');
  254. Writeln(StdErr,' use @filename to load the globals from file.');
  255. Writeln(StdErr,' wasmjob: PasVarName=JSClassName,JOBRegisterName');
  256. Writeln(StdErr,'-i --input=FileName input webidl file');
  257. Writeln(StdErr,'-m --implementation=Filename include file as implementation');
  258. Writeln(StdErr,'-n --include=Filename include file at end of interface');
  259. Writeln(StdErr,'-o --output=FileName output file. Defaults to unit name with .pas extension appended.');
  260. Writeln(StdErr,'-p --optionsinheader add options to header of generated file');
  261. Writeln(StdErr,'-t --typealiases=alias A comma separated list of type aliases in Alias=Name form');
  262. Writeln(StdErr,' use @filename to load the aliases from file.');
  263. Writeln(StdErr,'-u --unitname=Name name for unit. Defaults to input file without extension.');
  264. Writeln(StdErr,'-v --verbose Output some diagnostic information');
  265. Writeln(StdErr,'-w --webidlversion=V Set web IDL version. Allowed values: v1 or v2');
  266. Writeln(StdErr,'-x --extra=units Extra units to put in uses clause (comma separated list)');
  267. ExitCode:=Ord(Msg<>'');
  268. {AllowWriteln-}
  269. end;
  270. var
  271. Application: TWebIDLToPasApplication;
  272. begin
  273. Application:=TWebIDLToPasApplication.Create(nil);
  274. Application.Title:='WebIDL To Pascal converter Application';
  275. Application.Run;
  276. Application.Free;
  277. end.