fpdocxmlopts.pas 9.7 KB

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