webidl2pas.pp 9.5 KB

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