c_gen.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. {
  2. unit generation tool
  3. (C) 2000 Alexander Stohr, [email protected]
  4. based upon the linux dynamic tool from Sebastian Guenther
  5. with latest version "1.1 1999/12/23 13:51:50 peter"
  6. }
  7. {$MODE objfpc}
  8. {$H-} { use normal strings }
  9. (* do not enable! fpc bug with H+ *)
  10. program c_gen;
  11. uses
  12. SysUtils,
  13. Classes,
  14. buildgl;
  15. // =====================================================================
  16. type
  17. ptDefFile = ^tDefFile;
  18. tDefFile = record
  19. Name : String;
  20. DefFile : TDefReader;
  21. pNext : ptDefFile;
  22. end;
  23. ptSectionKey = ^tSectionKey;
  24. tSectionKey = record
  25. Keyword : String;
  26. Rule : DWord;
  27. pDefFile : ptDefFile;
  28. Option2 : String;
  29. pNext : ptSectionKey;
  30. end;
  31. // =====================================================================
  32. const
  33. verbose = 0; // change this for debugging
  34. const
  35. ST_NONE = 0;
  36. ST_COMMON = 1;
  37. ST_FILE = 2;
  38. RULE_IG = 0;
  39. RULE_TX = 1;
  40. RULE_IF = 2;
  41. RULE_PD = 3;
  42. RULE_PL = 4;
  43. RULE_PS = 5;
  44. // =====================================================================
  45. // global vars
  46. var
  47. ReturnVal : Word;
  48. pSectionKey : ptSectionKey;
  49. pAllDefFile : ptDefFile;
  50. ToolName : String;
  51. TargetText : String;
  52. TargetDir : String;
  53. SectionType : DWord;
  54. SectionName : String;
  55. TemplateName : String;
  56. // =====================================================================
  57. procedure StripSpaces(var s : String);
  58. var
  59. L : Byte;
  60. begin
  61. // strip leading spaces
  62. while (Pos(' ',s)=1) or (Pos(#8,s)=1) do
  63. Delete(s,1,1);
  64. // strip trailing spaces
  65. L := Length(s);
  66. while L<>0 do
  67. begin
  68. if (s[L]=' ') or (s[L]=#8) then
  69. begin
  70. Delete(s,L,1);
  71. Dec(L);
  72. end
  73. else
  74. L := 0;
  75. end;
  76. end;
  77. function GetName(var s : String) : String;
  78. var
  79. Name : String;
  80. P : Byte;
  81. begin
  82. Name := s;
  83. P := Pos(',',s);
  84. if p>0 then
  85. begin
  86. Delete(s,1,P);
  87. Delete(Name,P,255);
  88. end
  89. else
  90. s := '';
  91. StripSpaces(Name);
  92. { WriteLn('GetName, reminder = ',Name,',',s); }
  93. GetName := Name;
  94. end;
  95. function Name2Rule(Name : String) : DWord;
  96. begin
  97. if Name='IG'
  98. then Name2Rule := RULE_IG
  99. else
  100. if Name='TX'
  101. then Name2Rule := RULE_TX
  102. else
  103. if Name='IF'
  104. then Name2Rule := RULE_IF
  105. else
  106. if Name='PD'
  107. then Name2Rule := RULE_PD
  108. else
  109. if Name='PL'
  110. then Name2Rule := RULE_PL
  111. else
  112. if Name='PS'
  113. then Name2Rule := RULE_PS
  114. else
  115. begin
  116. Name2Rule := RULE_IG;
  117. WriteLn('error - unknown rule: ',Name);
  118. ReturnVal := 1;
  119. end;
  120. end;
  121. function AddDefFile(Name : String) : ptDefFile;
  122. var
  123. pDefFile : ptDefFile;
  124. pSearch : ptDefFile;
  125. begin
  126. pDefFile := NIL;
  127. // search if file is already loaded
  128. if pAllDefFile<>NIL then
  129. begin
  130. pSearch := pAllDefFile;
  131. while pSearch<>NIL do
  132. begin
  133. if pSearch^.Name = Name then
  134. begin
  135. pDefFile := pSearch;
  136. pSearch := NIL;
  137. end
  138. else
  139. pSearch := pSearch^.pNext;
  140. end;
  141. end;
  142. // create new file if its not loaded
  143. if pDefFile = NIL then
  144. begin
  145. New(pDefFile);
  146. pDefFile^.Name := Name;
  147. pDefFile^.DefFile := TDefReader.Create(Name);
  148. pDefFile^.pNext := pAllDefFile; // chain in as first member
  149. pAllDefFile := pDefFile;
  150. end;
  151. AddDefFile := pDefFile;
  152. end;
  153. procedure AddSectionKey(s : string);
  154. var
  155. pKey : ptSectionKey;
  156. t : string;
  157. begin
  158. New(pKey);
  159. pKey^.Keyword := GetName(s);
  160. pKey^.Rule := Name2Rule(GetName(s));
  161. pKey^.pDefFile := AddDefFile(GetName(s));
  162. t := GetName(s);
  163. pKey^.Option2 := t;
  164. pKey^.pNext := pSectionKey; // chain in as first member
  165. pSectionKey := pKey;
  166. end;
  167. function GetSectionKey(s : string) : ptSectionKey;
  168. var
  169. pSearch : ptSectionKey;
  170. begin
  171. GetSectionKey := NIL;
  172. pSearch := pSectionKey;
  173. while pSearch<>NIL do
  174. begin
  175. if pSearch^.Keyword = s then
  176. begin
  177. GetSectionKey := pSearch;
  178. pSearch := NIL;
  179. end
  180. else pSearch := pSearch^.pNext;
  181. end;
  182. end;
  183. procedure FreeSectionKeys;
  184. var
  185. pSearch, pNext : ptSectionKey;
  186. begin
  187. pSearch := pSectionKey;
  188. while pSearch<>NIL do
  189. begin
  190. pNext := pSearch^.pNext;
  191. Dispose(pSearch);
  192. pSearch := pNext;
  193. end;
  194. pSectionKey := pSearch;
  195. end;
  196. // =====================================================================
  197. procedure ResetCommonSecData;
  198. begin
  199. ToolName := 'BuildTool';
  200. TargetText := 'unknown';
  201. TargetDir := '.\';
  202. end;
  203. procedure ResetFileSecData;
  204. begin
  205. FreeSectionKeys;
  206. TemplateName := '';
  207. end;
  208. procedure InitGlobals;
  209. begin
  210. ReturnVal := 0;
  211. SectionType := ST_NONE;
  212. pSectionKey := NIL;
  213. pAllDefFile := NIL;
  214. ResetCommonSecData;
  215. ResetFileSecData;
  216. end;
  217. // =====================================================================
  218. procedure PrintInterface(var dest: Text; lines: TStringList);
  219. var
  220. i: Integer;
  221. begin
  222. for i := 0 to lines.Count - 1 do
  223. WriteLn(dest, lines.Strings[i]);
  224. end;
  225. procedure PrintProcDecls(var dest: Text; procs: TStringList; const Modifier : String);
  226. var
  227. i, j: Integer;
  228. s: String;
  229. begin
  230. for i := 0 to procs.Count - 1 do
  231. begin
  232. s := procs.Strings[i];
  233. j := Pos('//', s);
  234. if (Length(s) = 0)
  235. then
  236. WriteLn(dest)
  237. else
  238. if (Pos('{', s) = 1)
  239. then
  240. WriteLn(dest,procs.Strings[i])
  241. else
  242. if ((j > 0) and (Trim(s)[1] = '/')) then
  243. WriteLn(dest, s)
  244. else if j = 0 then
  245. WriteLn(dest, s, ' ',Modifier)
  246. else
  247. WriteLn(dest, TrimRight(Copy(s, 1, j-1)),
  248. ' ',Modifier,' ', Copy(s, j, Length(s)) );
  249. end;
  250. end;
  251. procedure PrintProcLoaders(var dest: Text; procs: TStringList; const libname: String);
  252. var
  253. i, j: Integer;
  254. s: String;
  255. begin
  256. for i := 0 to procs.Count - 1 do
  257. begin
  258. s := Trim(procs.Strings[i]);
  259. if (Pos('//', s) > 0)
  260. or (Pos('{', s) = 1)
  261. then
  262. WriteLn(dest,procs.Strings[i])
  263. else
  264. begin
  265. j := Pos(':', s);
  266. s := Trim(Copy(s, 1, j - 1));
  267. if (Length(s) = 0)
  268. then
  269. continue
  270. else
  271. WriteLn(dest, ' ', s, ' := GetProc(', libname, ', ''', s, ''');');
  272. end;
  273. end;
  274. end;
  275. procedure PrintProcStatic(var dest: Text; procs: TStringList; const Modifier: String);
  276. var
  277. i, j, k: Integer;
  278. s: String;
  279. t: String;
  280. begin
  281. for i := 0 to procs.Count - 1 do
  282. begin
  283. s := procs.Strings[i];
  284. j := Pos('//', s);
  285. if (Length(s) = 0) or ((j > 0) and (Trim(s)[1] = '/')) then
  286. WriteLn(dest, s)
  287. else
  288. begin
  289. // swap order of leading symbols and remove ':'
  290. t := Trim(procs.Strings[i]);
  291. j := Pos(':', t);
  292. t := Trim(Copy(t, 1, j - 1));
  293. j := Pos(':', s);
  294. Delete(s,1,j);
  295. s := Trim(s);
  296. j := Pos(';', s);
  297. k := Pos('(', s);
  298. if k>0 then if j>k then j := k;
  299. k := Pos(':', s);
  300. if k>0 then if j>k then j := k;
  301. Insert(t,s,j);
  302. Insert(' ',s,j);
  303. j := Pos('//', s);
  304. if j = 0 then
  305. WriteLn(dest, s, ' ',Modifier)
  306. else
  307. WriteLn(dest, TrimRight(Copy(s, 1, j-1)),
  308. ' ',Modifier,' ', Copy(s, j, Length(s)) );
  309. end;
  310. end;
  311. end;
  312. procedure PrintCVSLogSection(var dest: Text);
  313. begin
  314. WriteLn(dest);
  315. WriteLn(dest);
  316. WriteLn(dest, '{');
  317. WriteLn(dest, ' $', 'Log:$'); // needed because _this_ file might be in CVS, too
  318. WriteLn(dest, '}');
  319. end;
  320. // =====================================================================
  321. procedure ProcessFileSection;
  322. var
  323. f : Text;
  324. tpl : Text;
  325. s : String;
  326. { j : Integer; }
  327. tmp : String;
  328. pKey : ptSectionKey;
  329. begin
  330. WriteLn('Generating "',TargetDir+SectionName,'" ...');
  331. Assign(f, TargetDir+SectionName);
  332. Rewrite(f);
  333. Assign(tpl, TemplateName);
  334. Reset(tpl);
  335. while not EOF(tpl) do
  336. begin
  337. ReadLn(tpl, s);
  338. if Copy(s, 1, 1) = '%' then
  339. begin
  340. tmp := Copy(s,2,255);
  341. StripSpaces(tmp);
  342. pKey := GetSectionKey(tmp);
  343. if pKey=NIL then
  344. begin
  345. WriteLn(f, '// ### ',ToolName,': Don''t know what to insert here!: ', s);
  346. WriteLn('error - unknown keyword: ',tmp);
  347. ReturnVal := 1;
  348. end
  349. else
  350. begin
  351. case pKey^.Rule of
  352. RULE_IG : { ignore };
  353. RULE_TX : { todo };
  354. RULE_IF : PrintInterface(f, pKey^.pDefFile^.DefFile.InterfaceBlock);
  355. RULE_PD : PrintProcDecls(f, pKey^.pDefFile^.DefFile.Procs,
  356. pKey^.Option2);
  357. RULE_PL : PrintProcLoaders(f, pKey^.pDefFile^.DefFile.Procs,
  358. pKey^.Option2);
  359. RULE_PS : PrintProcStatic(f, pKey^.pDefFile^.DefFile.Procs,
  360. pKey^.Option2);
  361. end;
  362. end;
  363. end
  364. else
  365. begin
  366. if Copy(s, 1, 1) <> '#'
  367. then WriteLn(f, s);
  368. end;
  369. end;
  370. PrintCVSLogSection(f);
  371. Close(f);
  372. (*
  373. if Copy(s, 1, 1) <> '#' then
  374. begin
  375. j := Pos('#extdecl', s);
  376. if j = 0 then
  377. WriteLn(f, s)
  378. else
  379. WriteLn(f, Copy(s, 1, j - 1), 'cdecl', Copy(s, j + 8, Length(s)));
  380. end;
  381. *)
  382. end;
  383. procedure ProcessCommonSection;
  384. begin
  385. if verbose>0 then
  386. begin
  387. WriteLn('common section:');
  388. WriteLn(' ToolName = ',ToolName);
  389. WriteLn(' TargetText = ',TargetText);
  390. WriteLn(' TargetDir = ',TargetDir);
  391. end;
  392. end;
  393. // =====================================================================
  394. procedure SectionComplete;
  395. begin
  396. if ReturnVal=0 then { if we are error free }
  397. case SectionType of
  398. ST_NONE :
  399. begin
  400. // ignore
  401. end;
  402. ST_COMMON :
  403. begin
  404. ProcessCommonSection;
  405. end;
  406. ST_FILE :
  407. begin
  408. ProcessFileSection();
  409. end;
  410. end;
  411. end;
  412. var
  413. hFGen : Text;
  414. Line : String;
  415. KeyName : String;
  416. KeyValue : String;
  417. begin
  418. InitGlobals;
  419. WriteLn('File Generator Tool for OpenGL related Units');
  420. if ParamCount<>1 then
  421. begin
  422. WriteLn('specify a generator file as parameter 1');
  423. Halt(1);
  424. end;
  425. // Open Generation File
  426. Assign(hFGen,ParamStr(1));
  427. Reset(hFGen);
  428. while Not(EOF(hFGen)) do
  429. begin
  430. ReadLn(hFGen,Line);
  431. if Length(Line)>0 then
  432. begin
  433. if Line[1]='[' then
  434. begin
  435. // its a new section
  436. SectionComplete; // close previous section
  437. Delete(Line,Pos(']',Line),255);
  438. SectionName := Copy(Line,2,255);
  439. if verbose>0 then
  440. WriteLn('SectionName = ',SectionName);
  441. if SectionName='common' then
  442. begin
  443. SectionType := ST_COMMON;
  444. ResetCommonSecData;
  445. end
  446. else
  447. begin
  448. SectionType := ST_FILE;
  449. ResetFileSecData;
  450. end;
  451. end
  452. else
  453. if Pos(Line[1],'#*;''')<>0 then
  454. begin
  455. // just a comment - ignore
  456. end
  457. else
  458. begin
  459. // its a key in the section
  460. KeyName := Line;
  461. KeyValue := Line;
  462. Delete(KeyName,Pos('=',KeyName),255);
  463. Delete(KeyValue,1,Pos('=',KeyValue));
  464. StripSpaces(KeyName);
  465. StripSpaces(KeyValue);
  466. // WriteLn('KeyName = ',KeyName);
  467. // WriteLn('KeyValue = ',KeyValue);
  468. case SectionType of
  469. ST_COMMON :
  470. begin
  471. if KeyName='TOOL_NAME'
  472. then ToolName := KeyValue
  473. else
  474. if KeyName='TARGET_TEXT'
  475. then TargetText := KeyValue
  476. else
  477. if KeyName='TARGET_DIR'
  478. then
  479. begin
  480. TargetDir := KeyValue;
  481. end
  482. else
  483. begin
  484. WriteLn('error in script file - inside common section');
  485. WriteLn('key line: ',Line);
  486. ReturnVal := 1;
  487. end;
  488. end;
  489. ST_FILE :
  490. begin
  491. if KeyName='TEMPLATE'
  492. then TemplateName := KeyValue
  493. else
  494. if KeyName='KEY'
  495. then AddSectionKey(KeyValue)
  496. else
  497. begin
  498. WriteLn('error in script file - inside file section');
  499. WriteLn('key line: ',Line);
  500. ReturnVal := 1;
  501. end;
  502. end;
  503. ELSE
  504. begin
  505. WriteLn('error in script file - not in a section');
  506. WriteLn('key line: ',Line);
  507. ReturnVal := 1;
  508. end;
  509. end;
  510. end
  511. end;
  512. end;
  513. SectionComplete; // close last section
  514. Close(hFGen);
  515. WriteLn('Done...');
  516. Halt(ReturnVal);
  517. end.