webidl2pas.pp 9.0 KB

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