fpdocxmlopts.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. unit fpdocxmlopts;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpdocproj, dom, fptemplate;
  6. Type
  7. { TXMLFPDocOptions }
  8. TXMLFPDocOptions = Class(TComponent)
  9. private
  10. Protected
  11. Procedure Error(Const Msg : String);
  12. Procedure Error(Const Fmt : String; Args : Array of Const);
  13. Procedure LoadPackage(APackage : TFPDocPackage; E : TDOMElement); virtual;
  14. Procedure LoadPackages(Packages : TFPDocPackages; E : TDOMElement);
  15. Procedure LoadEngineOptions(Options : TEngineOptions; E : TDOMElement); virtual;
  16. Procedure SaveEngineOptions(Options : TEngineOptions; XML : TXMLDocument; AParent : TDOMElement); virtual;
  17. procedure SaveDescription(const ADescription: String; XML: TXMLDocument; AParent: TDOMElement); virtual;
  18. procedure SaveImportFile(const AImportFile: String; XML: TXMLDocument; AParent: TDOMElement);virtual;
  19. procedure SaveInputFile(const AInputFile: String; XML: TXMLDocument; AParent: TDOMElement);virtual;
  20. Procedure SavePackage(APackage : TFPDocPackage; XML : TXMLDocument; AParent : TDOMElement); virtual;
  21. Public
  22. Procedure LoadOptionsFromFile(AProject : TFPDocProject; Const AFileName : String);
  23. Procedure LoadFromXML(AProject : TFPDocProject; XML : TXMLDocument); virtual;
  24. Procedure SaveOptionsToFile(AProject : TFPDocProject; Const AFileName : String);
  25. procedure SaveToXML(AProject : TFPDocProject; ADoc: TXMLDocument); virtual;
  26. end;
  27. EXMLFPdoc = Class(Exception);
  28. Function IndexOfString(S : String; List : Array of string) : Integer;
  29. Const
  30. OptionCount = 11;
  31. OptionNames : Array[0..OptionCount] of string
  32. = ('hide-protected','warn-no-node','show-private',
  33. 'stop-on-parser-error', 'ostarget','cputarget',
  34. 'mo-dir','parse-impl','format', 'language',
  35. 'package','dont-trim');
  36. implementation
  37. Uses XMLRead, XMLWrite;
  38. Resourcestring
  39. SErrInvalidRootNode = 'Invalid options root node: Got "%s", expected "docproject"';
  40. SErrNoPackagesNode = 'No "packages" node found in docproject';
  41. SErrNoInputFile = 'unit tag without file attribute found';
  42. SErrNoDescrFile = 'description tag without file attribute';
  43. SErrNoImportFile = 'Import tag without file attribute';
  44. SErrNoImportPrefix = 'Import tag without prefix attribute';
  45. { TXMLFPDocOptions }
  46. Function IndexOfString(S : String; List : Array of string) : Integer;
  47. begin
  48. S:=UpperCase(S);
  49. Result:=High(List);
  50. While (Result>=0) and (S<>UpperCase(List[Result])) do
  51. Dec(Result);
  52. end;
  53. procedure TXMLFPDocOptions.Error(Const Msg: String);
  54. begin
  55. Raise EXMLFPDoc.Create(Msg);
  56. end;
  57. procedure TXMLFPDocOptions.Error(const Fmt: String; Args: array of const);
  58. begin
  59. Raise EXMLFPDoc.CreateFmt(Fmt,Args);
  60. end;
  61. procedure TXMLFPDocOptions.LoadPackage(APackage: TFPDocPackage; E: TDOMElement);
  62. Function LoadInput(I : TDOMElement) : String;
  63. Var
  64. S : String;
  65. begin
  66. Result:=I['file'];
  67. If (Result='') then
  68. Error(SErrNoInputFile);
  69. S:=I['options'];
  70. if (S<>'') then
  71. Result:=S+' '+Result;
  72. end;
  73. Function LoadDescription(I : TDOMElement) : String;
  74. begin
  75. Result:=I['file'];
  76. If (Result='') then
  77. Error(SErrNoDescrFile);
  78. end;
  79. Function LoadImport(I : TDOMElement) : String;
  80. Var
  81. S : String;
  82. begin
  83. Result:=I['file'];
  84. If (Result='') then
  85. Error(SErrNoImportFile);
  86. S:=I['prefix'];
  87. If (S='') then
  88. Error(SErrNoImportPrefix);
  89. Result:=Result+','+S;
  90. end;
  91. Var
  92. N,S : TDOMNode;
  93. O : TDomElement;
  94. begin
  95. APackage.Name:=E['name'];
  96. APackage.output:=E['output'];
  97. APackage.ContentFile:=E['content'];
  98. N:=E.FirstChild;
  99. While (N<>Nil) do
  100. begin
  101. If (N.NodeType=ELEMENT_NODE) then
  102. begin
  103. O:=N as TDOMElement;
  104. If (O.NodeName='units') then
  105. begin
  106. S:=O.FirstChild;
  107. While (S<>Nil) do
  108. begin
  109. If (S.NodeType=Element_Node) and (S.NodeName='unit') then
  110. APackage.Inputs.add(LoadInput(S as TDomElement));
  111. S:=S.NextSibling;
  112. end;
  113. end
  114. else If (O.NodeName='descriptions') then
  115. begin
  116. S:=O.FirstChild;
  117. While (S<>Nil) do
  118. begin
  119. If (S.NodeType=Element_Node) and (S.NodeName='description') then
  120. APackage.Descriptions.add(LoadDescription(S as TDomElement));
  121. S:=S.NextSibling;
  122. end;
  123. end
  124. else If (O.NodeName='imports') then
  125. begin
  126. S:=O.FirstChild;
  127. While (S<>Nil) do
  128. begin
  129. If (S.NodeType=Element_Node) and (S.NodeName='import') then
  130. APackage.Imports.add(LoadImport(S as TDomElement));
  131. S:=S.NextSibling;
  132. end;
  133. end
  134. end;
  135. N:=N.NextSibling;
  136. end;
  137. end;
  138. procedure TXMLFPDocOptions.LoadPackages(Packages: TFPDocPackages; E: TDOMElement
  139. );
  140. Var
  141. N : TDOMNode;
  142. begin
  143. N:=E.FirstChild;
  144. While (N<>Nil) do
  145. begin
  146. If (N.NodeName='package') and (N.NodeType=ELEMENT_NODE) then
  147. LoadPackage(Packages.Add as TFPDocPackage, N as TDOMElement);
  148. N:=N.NextSibling;
  149. end;
  150. end;
  151. procedure TXMLFPDocOptions.LoadEngineOptions(Options: TEngineOptions;
  152. E: TDOMElement);
  153. Function TrueValue(V : String) : Boolean;
  154. begin
  155. V:=LowerCase(V);
  156. Result:=(v='true') or (v='1') or (v='yes');
  157. end;
  158. Var
  159. O : TDOMnode;
  160. N,V : String;
  161. begin
  162. O:=E.FirstChild;
  163. While (O<>Nil) do
  164. begin
  165. If (O.NodeType=Element_NODE) and (O.NodeName='option') then
  166. begin
  167. N:=LowerCase(TDOMElement(o)['name']);
  168. V:=TDOMElement(o)['value'];
  169. Case IndexOfString(N,OptionNames) of
  170. 0 : Options.HideProtected:=TrueValue(v);
  171. 1 : Options.WarnNoNode:=TrueValue(v);
  172. 2 : Options.ShowPrivate:=TrueValue(v);
  173. 3 : Options.StopOnParseError:=TrueValue(v);
  174. 4 : Options.ostarget:=v;
  175. 5 : Options.cputarget:=v;
  176. 6 : Options.MoDir:=V;
  177. 7 : Options.InterfaceOnly:=Not TrueValue(V);
  178. 8 : Options.Backend:=V;
  179. 9 : Options.Language:=v;
  180. 10 : Options.DefaultPackageName:=V;
  181. 11 : Options.DontTrim:=TrueValue(V);
  182. else
  183. Options.BackendOptions.add('--'+n);
  184. Options.BackendOptions.add(v);
  185. end;
  186. end;
  187. O:=O.NextSibling
  188. end;
  189. end;
  190. procedure TXMLFPDocOptions.SaveToXML(AProject: TFPDocProject; ADoc: TXMLDocument);
  191. var
  192. i: integer;
  193. E,PE: TDOMElement;
  194. begin
  195. E:=ADoc.CreateElement('docproject');
  196. ADoc.AppendChild(E);
  197. E:=ADoc.CreateElement('options');
  198. ADoc.DocumentElement.AppendChild(E);
  199. SaveEngineOptions(AProject.Options,ADoc,E);
  200. E:=ADoc.CreateElement('packages');
  201. ADoc.DocumentElement.AppendChild(E);
  202. for i := 0 to AProject.Packages.Count - 1 do
  203. begin
  204. PE:=ADoc.CreateElement('package');
  205. E.AppendChild(PE);
  206. SavePackage(AProject.Packages[i],ADoc,PE);
  207. end;
  208. end;
  209. Procedure TXMLFPDocOptions.SaveEngineOptions(Options : TEngineOptions; XML : TXMLDocument; AParent : TDOMElement);
  210. procedure AddStr(const n, v: string);
  211. var
  212. E : TDOMElement;
  213. begin
  214. if (v='') then
  215. Exit;
  216. E:=XML.CreateElement('option');
  217. AParent.AppendChild(E);
  218. E['name'] := n;
  219. E['value'] := v;
  220. end;
  221. procedure AddBool(const AName: string; B: Boolean);
  222. begin
  223. if B then
  224. AddStr(Aname,'true')
  225. else
  226. AddStr(Aname,'false');
  227. end;
  228. begin
  229. AddStr('ostarget', Options.OSTarget);
  230. AddStr('cputarget', Options.CPUTarget);
  231. AddStr('mo-dir', Options.MoDir);
  232. AddStr('format', Options.Backend);
  233. AddStr('language', Options.Language);
  234. AddStr('package', Options.DefaultPackageName);
  235. AddBool('hide-protected', Options.HideProtected);
  236. AddBool('warn-no-node', Options.WarnNoNode);
  237. AddBool('show-private', Options.ShowPrivate);
  238. AddBool('stop-on-parser-error', Options.StopOnParseError);
  239. AddBool('parse-impl', Options.InterfaceOnly);
  240. AddBool('dont-trim', Options.DontTrim);
  241. end;
  242. Procedure TXMLFPDocOptions.SaveInputFile(Const AInputFile : String; XML : TXMLDocument; AParent: TDOMElement);
  243. Function GetNextWord(Var s : string) : String;
  244. Const
  245. WhiteSpace = [' ',#9,#10,#13];
  246. var
  247. i,j: integer;
  248. begin
  249. I:=1;
  250. While (I<=Length(S)) and (S[i] in WhiteSpace) do
  251. Inc(I);
  252. J:=I;
  253. While (J<=Length(S)) and (not (S[J] in WhiteSpace)) do
  254. Inc(J);
  255. if (I<=Length(S)) then
  256. Result:=Copy(S,I,J-I);
  257. Delete(S,1,J);
  258. end;
  259. Var
  260. S,W,F,O : String;
  261. begin
  262. S:=AInputFile;
  263. O:='';
  264. F:='';
  265. While (S<>'') do
  266. begin
  267. W:=GetNextWord(S);
  268. If (W<>'') then
  269. begin
  270. if W[1]='-' then
  271. begin
  272. if (O<>'') then
  273. O:=O+' ';
  274. o:=O+W;
  275. end
  276. else
  277. F:=W;
  278. end;
  279. end;
  280. AParent['file']:=F;
  281. AParent['options']:=O;
  282. end;
  283. Procedure TXMLFPDocOptions.SaveDescription(Const ADescription : String; XML : TXMLDocument; AParent: TDOMElement);
  284. begin
  285. AParent['file']:=ADescription;
  286. end;
  287. procedure TXMLFPDocOptions.SaveImportFile(const AImportFile: String;
  288. XML: TXMLDocument; AParent: TDOMElement);
  289. Var
  290. I : integer;
  291. begin
  292. I:=Pos(',',AImportFile);
  293. AParent['file']:=Copy(AImportFile,1,I-1);
  294. AParent['prefix']:=Copy(AImportFile,i+1,Length(AImportFile));
  295. end;
  296. Procedure TXMLFPDocOptions.SavePackage(APackage: TFPDocPackage; XML : TXMLDocument; AParent: TDOMElement);
  297. var
  298. i: integer;
  299. E,PE : TDomElement;
  300. begin
  301. AParent['name']:=APackage.Name;
  302. AParent['output']:=APackage.Output;
  303. AParent['content']:=APackage.ContentFile;
  304. // Units
  305. PE:=XML.CreateElement('units');
  306. AParent.AppendChild(PE);
  307. for i:=0 to APackage.Inputs.Count-1 do
  308. begin
  309. E:=XML.CreateElement('unit');
  310. PE.AppendChild(E);
  311. SaveInputFile(APackage.Inputs[i],XML,E);
  312. end;
  313. // Descriptions
  314. PE:=XML.CreateElement('descriptions');
  315. AParent.AppendChild(PE);
  316. for i:=0 to APackage.Descriptions.Count-1 do
  317. begin
  318. E:=XML.CreateElement('description');
  319. PE.AppendChild(E);
  320. SaveDescription(APackage.Descriptions[i],XML,E);
  321. end;
  322. // Imports
  323. PE:=XML.CreateElement('imports');
  324. AParent.AppendChild(PE);
  325. for i:=0 to APackage.Imports.Count-1 do
  326. begin
  327. E:=XML.CreateElement('import');
  328. PE.AppendChild(E);
  329. SaveImportFile(APackage.Imports[i],XML,E);
  330. end;
  331. end;
  332. procedure TXMLFPDocOptions.LoadOptionsFromFile(AProject: TFPDocProject; const AFileName: String);
  333. Var
  334. XML : TXMLDocument;
  335. begin
  336. ReadXMLFile(XML,AFileName);
  337. try
  338. LoadFromXML(AProject,XML);
  339. finally
  340. FreeAndNil(XML);
  341. end;
  342. end;
  343. procedure TXMLFPDocOptions.LoadFromXML(AProject: TFPDocProject;
  344. XML: TXMLDocument);
  345. Var
  346. E : TDOMElement;
  347. N : TDomNode;
  348. begin
  349. E:=XML.DocumentElement;
  350. if (E.NodeName<>'docproject') then
  351. Error(SErrInvalidRootNode,[E.NodeName]);
  352. N:=E.FindNode('packages');
  353. If (N=Nil) or (N.NodeType<>ELEMENT_NODE) then
  354. Error(SErrNoPackagesNode);
  355. LoadPackages(AProject.Packages,N as TDomElement);
  356. N:=E.FindNode('options');
  357. If (N<>Nil) and (N.NodeType=ELEMENT_NODE) then
  358. LoadEngineOptions(AProject.Options,N as TDOMElement);
  359. end;
  360. Procedure TXMLFPDocOptions.SaveOptionsToFile(AProject: TFPDocProject; const AFileName: String);
  361. Var
  362. XML : TXMLDocument;
  363. begin
  364. XML:=TXMLDocument.Create;
  365. try
  366. SaveToXML(AProject,XML);
  367. WriteXMLFile(XML, AFileName);
  368. finally
  369. XML.Free;
  370. end;
  371. end;
  372. end.