fpdocxmlopts.pas 9.6 KB

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