parsehdr.cpp 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274
  1. /*
  2. *$Log: parsehdr.c,v $
  3. */
  4. /* Code to parse a header (.h) file */
  5. /* Descended from xansi; thanks Geoff! thanks Glenn! */
  6. #include "parsehdr.h"
  7. #include <malloc.h> /* For debugging */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <algorithm>
  12. dword userval;
  13. /* the IGNORE byte */
  14. byte slosh;
  15. byte last_slosh;
  16. byte quote1;
  17. byte quote2;
  18. byte comment;
  19. byte hash;
  20. byte ignore1; /* Special: ignore egactly 1 char */
  21. byte double_slash;
  22. byte spare;
  23. int buff_idx;
  24. char buffer[BUFF_SIZE];
  25. byte start; /* Started recording to the buffer */
  26. byte func; /* Function header detected */
  27. byte hash_ext;
  28. int curly; /* Level inside curly brackets */
  29. int xtern; /* Level inside a extern "C" {} situation */
  30. int round1; /* Level inside () */
  31. int line, col;
  32. dword chars;
  33. char lastch;
  34. #define NIL -1 /* Used as an illegal index */
  35. FILE *datFile; /* Stream of the data (output) file */
  36. char fileName[81]; /* Name of current header file */
  37. PH_FUNC_STRUCT *pFunc; /* Pointer to the functions array */
  38. int numFunc; /* How many elements saved so far */
  39. int allocFunc; /* How many elements allocated so far */
  40. int headFunc; /* Head of the function name linked list */
  41. PH_ARG_STRUCT *pArg; /* Pointer to the arguements array */
  42. int numArg; /* How many elements saved so far */
  43. int allocArg; /* How many elements allocated so far */
  44. int headArg; /* Head of the arguements linked list */
  45. // DO Callback
  46. boolT phDoCB(int id, char *data) {
  47. /* return callback(hDCX, id, data, userval);*/
  48. return true;
  49. }
  50. void phError(char *errmsg) {
  51. char msg[200];
  52. sprintf(msg, "PH *ERROR*\nFile: %s L=%d C=%d O=%lu\n%s", fileName, line, col,
  53. chars, errmsg);
  54. printf(msg);
  55. }
  56. void phWarning(char *errmsg) {
  57. char msg[200];
  58. sprintf(msg, "PH -warning-\nFile: %s L=%d C=%d O=%lu\n%s\n", fileName, line,
  59. col, chars, errmsg);
  60. printf(msg);
  61. }
  62. int IsIgnore() {
  63. return (comment || quote1 || quote2 || slosh || hash || ignore1 ||
  64. double_slash);
  65. }
  66. boolT isAlphaNum(char ch) {
  67. return (((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z')) ||
  68. ((ch >= '0') && (ch <= '9')) || (ch == '_'));
  69. }
  70. boolT AddToBuffer(char ch) {
  71. if (buff_idx >= BUFF_SIZE) {
  72. ERR("function buffer overflow (function unterminated?)\n");
  73. return false;
  74. } else {
  75. buffer[buff_idx++] = ch;
  76. return true;
  77. }
  78. }
  79. boolT remFromBuffer() {
  80. if (buff_idx == 0) {
  81. ERR("function buffer underflow (internal error?)\n");
  82. return false;
  83. } else {
  84. buff_idx--;
  85. return true;
  86. }
  87. }
  88. /*----------------------------------------------*/
  89. /* This is a function declaration, typedef, etc.*/
  90. /* Do something with it. */
  91. /*----------------------------------------------*/
  92. void ProcessBuffer(int id) {
  93. if (buff_idx > 0) {
  94. buffer[buff_idx] = '\0';
  95. // CALL CALL BACK FUNTION WITH APPRORIATE CODE!
  96. switch (id) {
  97. case PH_FUNCTION:
  98. // eek, but...
  99. case PH_PROTO:
  100. // sort out into params etc
  101. phBuffToFunc(buffer);
  102. break;
  103. case PH_TYPEDEF:
  104. case PH_DEFINE:
  105. // sort out into defs
  106. phBuffToDef(buffer);
  107. break;
  108. case PH_MPROTO:
  109. // eek!
  110. case PH_VAR:
  111. // eek!
  112. case PH_JUNK:
  113. default:
  114. phDoCB(id, buffer);
  115. break;
  116. }
  117. start = false;
  118. func = false;
  119. buff_idx = 0;
  120. }
  121. }
  122. void phInit(char *filename) // filename is for reference only!!!
  123. {
  124. slosh = last_slosh = start = func = comment = double_slash = hash = ignore1 =
  125. quote1 = quote2 = hash_ext = false;
  126. buff_idx = curly = xtern = col = round1 = 0;
  127. line = 1;
  128. chars = 0L;
  129. lastch = 0;
  130. }
  131. boolT phFree(void) {
  132. // remove atoms etc, free buffers
  133. return true;
  134. }
  135. void phChar(char ch) {
  136. col++;
  137. chars++;
  138. // printf("%d%% done\r", chars*100/filelen);
  139. if (slosh != last_slosh) {
  140. DBG("[SLOSH OFF]");
  141. }
  142. switch (ch) {
  143. case ',':
  144. if (!IsIgnore() && (curly == xtern) && (start) && (func))
  145. /* must be multi proto */
  146. {
  147. if (lastch == ')') /* eg int foo(), bar(); */
  148. {
  149. ProcessBuffer(PH_MPROTO);
  150. DBG("[END OF MULTIPROTOTYPE]")
  151. }
  152. }
  153. break;
  154. case ';':
  155. if (!IsIgnore() && (curly == xtern) && (start)) {
  156. if (func) {
  157. if (lastch == ')') {
  158. ProcessBuffer(PH_PROTO);
  159. DBG("[END OF PROTOTYPE]")
  160. }
  161. } else {
  162. ProcessBuffer(PH_VAR);
  163. DBG("[END OF VARIABLE]")
  164. }
  165. }
  166. break;
  167. case 10: /* end of line */
  168. line++;
  169. /* chars++; */ /* must have been a CR before it
  170. methinks */
  171. col = 0;
  172. if (double_slash) {
  173. double_slash = false;
  174. DBG("[DOUBLE_SLASH_COMMENT OFF]")
  175. } else if (hash) {
  176. if (hash_ext) {
  177. hash_ext = false;
  178. } else {
  179. hash = false;
  180. DBG("[HASH OFF]")
  181. }
  182. }
  183. if (xtern && (strncmp(buffer, "extern", 6) == 0)) {
  184. start = false; /* Not the start of anything */
  185. buff_idx = 0; /* Kill the buffer */
  186. }
  187. break;
  188. case '#': /* start of # something at beginning of line */
  189. if ((!IsIgnore()) && (curly == xtern)) {
  190. hash = true;
  191. DBG("[HASH ON]")
  192. }
  193. break;
  194. case '{':
  195. if (!IsIgnore()) {
  196. char st[80];
  197. if ((curly == xtern) && (start) && (func)) {
  198. ProcessBuffer(PH_FUNCTION);
  199. DBG("[FUNCTION DECLARED]")
  200. }
  201. curly++;
  202. sprintf(st, "[CURLY++ %d]", curly);
  203. DBG(st)
  204. }
  205. break;
  206. case '}':
  207. if (!IsIgnore()) {
  208. char st[80];
  209. if (curly > 0) {
  210. if (xtern && (xtern == curly)) {
  211. xtern = 0;
  212. DBG("[EXTERN OFF]");
  213. }
  214. curly--;
  215. sprintf(st, "[CURLY-- %d]", curly);
  216. DBG(st)
  217. } else {
  218. /* match the {s */
  219. ERR("too many \"}\"\n");
  220. }
  221. }
  222. break;
  223. case '(':
  224. if (!IsIgnore()) {
  225. char st[80];
  226. if ((curly == xtern) && (round1 == 0) && (start)) {
  227. func = true;
  228. DBG("[FUNCTION]")
  229. }
  230. round1++;
  231. sprintf(st, "[ROUND++ %d]", round1);
  232. DBG(st)
  233. }
  234. break;
  235. case ')':
  236. if (!IsIgnore()) {
  237. char st[80];
  238. if (round1 > 0) {
  239. round1--;
  240. sprintf(st, "[ROUND-- %d]", round1);
  241. DBG(st)
  242. } else {
  243. ERR("too many \")\"\n");
  244. }
  245. }
  246. break;
  247. case '\\':
  248. if (!slosh && (quote1 || quote2)) {
  249. last_slosh = true;
  250. DBG("[SLOSH ON]")
  251. } else if (hash) {
  252. hash_ext = true;
  253. }
  254. break;
  255. case '*':
  256. if (lastch == '/') /* allow nested comments ! */
  257. {
  258. char st[80];
  259. comment++;
  260. if (start) {
  261. remFromBuffer();
  262. }
  263. sprintf(st, "[COMMENT++ %d]", comment);
  264. DBG(st)
  265. }
  266. break;
  267. case '/':
  268. if ((lastch == '*') && (!quote1) && (!quote2)) {
  269. if (comment > 0) {
  270. char st[80];
  271. comment--;
  272. /* Don't want the closing slash in the buffer */
  273. ignore1 = true;
  274. sprintf(st, "[COMMENT-- %d]", comment);
  275. DBG(st)
  276. } else {
  277. ERR("too many \"*/\"\n");
  278. }
  279. } else if (lastch == '/') {
  280. /* Double slash to end of line is a comment. */
  281. double_slash = true;
  282. if (start) {
  283. remFromBuffer();
  284. }
  285. DBG("[DOUBLE_SLASH_COMMENT ON]")
  286. }
  287. break;
  288. case '\"':
  289. if ((!comment) && (!quote1) && (!slosh)) {
  290. quote2 = (byte)(!quote2);
  291. if (quote2)
  292. DBG("[QUOTE2ON]")
  293. if (!quote2)
  294. DBG("[QUOTE2OFF]")
  295. /* We want to catch the extern "C" {} thing... */
  296. if (!quote2 && start && (lastch == 'C')) {
  297. if (strcmp(buffer, "extern ") == 0) {
  298. char st[80];
  299. xtern = curly + 1; /* The level inside the extern {} */
  300. sprintf(st, "[EXTERN ON %d]", xtern);
  301. DBG(st)
  302. }
  303. }
  304. }
  305. break;
  306. case '\'':
  307. if ((!comment) && (!quote2) && (!slosh)) {
  308. {
  309. quote1 = (byte)(!quote1);
  310. if (quote1)
  311. DBG("[QUOTE1ON]")
  312. if (!quote1)
  313. DBG("[QUOTE1OFF]")
  314. }
  315. }
  316. break;
  317. case '\t':
  318. ch = ' ';
  319. break;
  320. default:
  321. if ((ch != -1) && !IsIgnore() && (curly == xtern) && (!start) &&
  322. (ch != ' ')) {
  323. start = true;
  324. DBG("[START OF SOMETHING]")
  325. }
  326. break;
  327. }
  328. if (ch != -1) {
  329. if (start && !IsIgnore()) {
  330. AddToBuffer(ch);
  331. }
  332. }
  333. lastch = ch;
  334. slosh = last_slosh;
  335. last_slosh = 0;
  336. ignore1 = false;
  337. } /* of phChar */
  338. /* Take a lump of data from a header file, and churn the state machine
  339. through each char */
  340. boolT phData(char *buff, int ndata) {
  341. int i, j;
  342. #ifdef DEBUG
  343. char cLine[81];
  344. char cfLine[90];
  345. #endif
  346. if (ndata < 1) {
  347. ndata = strlen(buff);
  348. }
  349. j = 0;
  350. for (i = 0; i < ndata; i++) {
  351. phChar(buff[i]);
  352. #ifdef DEBUG
  353. if (j < 80)
  354. cLine[j++] = buff[i];
  355. if (buff[i] == '\n') {
  356. cLine[j] = '\0';
  357. sprintf(cfLine, "\n***%03d %s\n", line, cLine);
  358. DBG(cfLine);
  359. j = 0;
  360. }
  361. #endif
  362. }
  363. return true;
  364. }
  365. boolT phPost(void) {
  366. boolT err = true;
  367. char msg[80];
  368. if (quote1) {
  369. WARN("EOF: \' not closed");
  370. err = false;
  371. }
  372. if (quote2) {
  373. WARN("EOF: \" not closed");
  374. err = false;
  375. }
  376. if (comment) {
  377. WARN("EOF: comment not closed");
  378. err = false;
  379. }
  380. if (slosh) {
  381. WARN("EOF: internal slosh set error");
  382. err = false;
  383. }
  384. if (curly > 0) {
  385. sprintf(msg, "EOF: { level = %d", curly);
  386. WARN(msg);
  387. err = false;
  388. }
  389. if (round1 > 0) {
  390. sprintf(msg, "EOF: ( level = %d", round1);
  391. WARN(msg);
  392. err = false;
  393. }
  394. if (hash) {
  395. WARN("warning hash is set on last line ???");
  396. err = false;
  397. }
  398. return err;
  399. }
  400. #if 0
  401. enum FUNC_E { NORM , LEFT , RIGHT, NEXT };
  402. void
  403. NamesToLabel(LPPH_FUNC lpF)
  404. {
  405. int i, j;
  406. for (i=0; i < lpF->num_params; i++)
  407. {
  408. while (isspace(types[i][0]))
  409. {
  410. lstrcdel(types[i], 0);
  411. }
  412. j = 0;
  413. while(names[i][j] != '\0')
  414. {
  415. if ((names[i][j] != '*') &&
  416. (names[i][j] != '[') &&
  417. (names[i][j] != ']'))
  418. {
  419. lstrccat(label[i], names[i][j]);
  420. }
  421. j++ ;
  422. }
  423. }
  424. }
  425. boolT
  426. MoveLastWord(char *src, char *dest) /* take arg name from type */
  427. {
  428. int i, l;
  429. LPSTR s2;
  430. if (s2 = strchr(src, '*')) /* if there is a * use it as starting point */
  431. {
  432. lstrcpy(dest, s2);
  433. *s2 = '\0'; /* terminate */
  434. }
  435. else
  436. {
  437. l = strlen(src);
  438. i = l-1;
  439. while ((i > 0) && ((isspace(src[i])) || (src[i] == '[') || (src[i] == ']')))
  440. /* find last non space or non [] */
  441. {
  442. if (isspace(src[i]))
  443. {
  444. lstrcdel(src, i);
  445. } /* remove trailing spaces */
  446. i--;
  447. }
  448. while ((i > 0) && (!isspace(src[i]))) /* find the previous space */
  449. {
  450. i--;
  451. }
  452. if (i)
  453. {
  454. i++;
  455. lstrcpy(dest, &src[i]);
  456. src[i] = '\0'; /* terminate */
  457. }
  458. else
  459. {
  460. /* no type !!! */
  461. // if ((mode == TOANSI) ||
  462. // ((mode == FROMANSI) && (strstr(src, "...") == NULL))
  463. // )
  464. if (strstr(src, "...") == NULL) // not a var arg perhaps?
  465. {
  466. char msg[80];
  467. // sprintf(msg,"no type for arg # %d, \"%s\"\n",lpF->num_params, (LPSTR) src);
  468. // ERR(msg);
  469. return false;
  470. }
  471. else // d'oh!
  472. {
  473. WARN("looks like a vararg to me!");
  474. /* maybe it is a ... !!!!!! */
  475. }
  476. }
  477. }
  478. i = strlen(src) - 1;
  479. while ((isspace(src[i])) && (i >= 0))
  480. {
  481. src[i--] = '\0';
  482. }
  483. i = 0;
  484. while (dest[i] != '\0')
  485. {
  486. if (isspace(dest[i]))
  487. {
  488. lstrcdel(dest, i);
  489. }
  490. i++ ;
  491. }
  492. while ((isspace(src[0])) && (src[0] != '\0'))
  493. {
  494. lstrcdel(src, 0);
  495. }
  496. return true;
  497. }
  498. int
  499. Lookup(char *aname) /* lookup var name in labels and return arg number */
  500. {
  501. int i, p;
  502. char tname[NAMES_L];
  503. int bstate = false;
  504. /* eg: lookup *fred[] for match to fred */
  505. tname[0] = '\0';
  506. p = -1; /* default return for no match */
  507. /* tname is aname without puncs etc */
  508. i = 0;
  509. while(aname[i] != '\0')
  510. {
  511. if (aname[i] == '[')
  512. {
  513. bstate = true;
  514. }
  515. else
  516. if (aname[i] == ']')
  517. {
  518. bstate = false;
  519. }
  520. if ((isalnum(aname[i]) || aname[i] == '-' || aname[i] == '_') && (!bstate))
  521. {
  522. lstrccat(tname, aname[i]);
  523. }
  524. i++;
  525. }
  526. /* lookup tname in the labels and find out which arg it is */
  527. for (i=0; i < num_params; i++)
  528. {
  529. if (lstrcmp(tname, label[i]) == 0)
  530. {
  531. p = i; /* this one ! */
  532. break;
  533. }
  534. }
  535. return p;
  536. }
  537. /* put the name and type at correct arg number */
  538. boolT
  539. Plop(char *atype, char *aname, int FAR *num_params, int FAR *num_found)
  540. {
  541. char msg[80];
  542. int t;
  543. if (num_found >= num_params)
  544. {
  545. sprintf(msg,"extra argument \"%s\" in func \"%s\"\n", (LPSTR) aname, (LPSTR) func_name);
  546. ERR(msg);
  547. return false;
  548. }
  549. t = Lookup(aname); /* arg number */
  550. if (t == -1) /* couldn't find it */
  551. {
  552. sprintf(msg,"bad argument \"%s\" in func \"%s\"\n", (LPSTR) aname, (LPSTR) func_name);
  553. ERR(msg);
  554. return false;
  555. }
  556. if ((strlen(types[t]) > 0) || (strlen(names[t]) > 0)) /* in use ? */
  557. {
  558. sprintf(msg,"argument \"%s\" already used in \"%s\"\n", (LPSTR) aname, (LPSTR) func_name);
  559. ERR(msg);
  560. return false;
  561. }
  562. lstrcpy(types[t], atype);
  563. lstrcpy(names[t], aname);
  564. num_found++; /* got another! */
  565. return true;
  566. }
  567. #define IGN \
  568. ((*chp == '(') || (*chp == ')') || (*chp == ',') || (*chp == ';') || \
  569. (isspace(*chp)))
  570. #define IGNP \
  571. ((*chp == '(') || (*chp == ')') || (*chp == ',') || (*chp == ';') || \
  572. (*chp == '\n'))
  573. #endif
  574. char token[40]; /* Strings that might be types, nodifiers or idents */
  575. char ident[40]; /* Names of functions or protos go here */
  576. char lastChar;
  577. char *p;
  578. int indirect;
  579. boolT isLong, isShort, isUnsigned;
  580. int lastTokPos; /* For "^" in error messages */
  581. char *buffP;
  582. int tok; /* Current token */
  583. baseType bt; /* Type of current param (or return type) */
  584. int argNum; /* Arg number (in case no name: arg1, arg2...) */
  585. void initType(void) {
  586. indirect = 0;
  587. isLong = isShort = isUnsigned = false;
  588. bt = BT_INT;
  589. }
  590. void errorParse(char *msg) {
  591. printf("%s: got ", msg);
  592. if (tok == TOK_NAME)
  593. printf("<%s>", token);
  594. else if (tok == TOK_DOTS)
  595. printf("...");
  596. else
  597. printf("%c (%X)", tok, tok);
  598. printf("\n%s\n", buffP);
  599. printf("%*c\n", lastTokPos + 1, '^');
  600. }
  601. /* Get a token from pointer p */
  602. int getToken(void) {
  603. char ch;
  604. memset(token, 0, sizeof(token));
  605. while (*p && ((*p == ' ') || (*p == '\n')))
  606. p++;
  607. lastTokPos = p - buffP; /* For error messages */
  608. if (lastChar) {
  609. ch = lastChar;
  610. lastChar = '\0';
  611. return ch;
  612. }
  613. while (ch = *p++) {
  614. switch (ch) {
  615. case '*':
  616. case '[':
  617. case ']':
  618. case '(':
  619. case ')':
  620. case ',':
  621. case ';':
  622. case ' ':
  623. case '\n':
  624. if (strlen(token)) {
  625. if ((ch != ' ') && (ch != '\n'))
  626. lastChar = ch;
  627. return TOK_NAME;
  628. } else if ((ch == ' ') || (ch == '\n'))
  629. break;
  630. else
  631. return ch;
  632. case '.':
  633. if ((*p == '.') && (p[1] == '.')) {
  634. p += 2;
  635. return TOK_DOTS;
  636. }
  637. default:
  638. token[strlen(token)] = ch;
  639. }
  640. }
  641. return TOK_EOL;
  642. }
  643. boolT isBaseType(void) {
  644. if (tok != TOK_NAME)
  645. return false;
  646. if (strcmp(token, "int") == 0) {
  647. bt = BT_INT;
  648. } else if (strcmp(token, "char") == 0) {
  649. bt = BT_CHAR;
  650. } else if (strcmp(token, "void") == 0) {
  651. bt = BT_VOID;
  652. } else if (strcmp(token, "float") == 0) {
  653. bt = BT_FLOAT;
  654. } else if (strcmp(token, "double") == 0) {
  655. bt = BT_DOUBLE;
  656. } else if (strcmp(token, "struct") == 0) {
  657. bt = BT_STRUCT;
  658. tok = getToken(); /* The name of the struct */
  659. /* Do something with the struct name */
  660. } else if (strcmp(token, "union") == 0) {
  661. bt = BT_STRUCT; /* Well its still a struct */
  662. tok = getToken(); /* The name of the union */
  663. /* Do something with the union name */
  664. } else if (strcmp(token, "FILE") == 0) {
  665. bt = BT_STRUCT;
  666. } else if (strcmp(token, "size_t") == 0) {
  667. bt = BT_INT;
  668. isUnsigned = true;
  669. } else if (strcmp(token, "va_list") == 0) {
  670. bt = BT_VOID;
  671. indirect = 1; /* va_list is a void* */
  672. } else
  673. return false;
  674. return true;
  675. }
  676. boolT isModifier(void) {
  677. if (tok != TOK_NAME)
  678. return false;
  679. if (strcmp(token, "long") == 0) {
  680. isLong = true;
  681. } else if (strcmp(token, "unsigned") == 0) {
  682. isUnsigned = true;
  683. } else if (strcmp(token, "short") == 0) {
  684. isShort = true;
  685. } else if (strcmp(token, "const") == 0) {
  686. } else if (strcmp(token, "_far") == 0) {
  687. } else
  688. return false;
  689. return true;
  690. }
  691. boolT isAttrib(void) {
  692. if (tok != TOK_NAME)
  693. return false;
  694. if (strcmp(token, "far") == 0) {
  695. /* Not implemented yet */
  696. } else if (strcmp(token, "__far") == 0) {
  697. /* Not implemented yet */
  698. } else if (strcmp(token, "__interrupt") == 0) {
  699. /* Not implemented yet */
  700. } else
  701. return false;
  702. return true;
  703. }
  704. boolT isCdecl(void) {
  705. return ((strcmp(token, "__cdecl") == 0) || (strcmp(token, "_Cdecl") == 0) ||
  706. (strcmp(token, "cdecl") == 0));
  707. }
  708. void getTypeAndIdent(void) {
  709. /* Get a type and ident pair. Complicated by the fact that types are
  710. actually optional modifiers followed by types, and the identifier
  711. is also optional. For example:
  712. myfunc(unsigned footype *foovar);
  713. declares an arg named foovar, of type unsigned pointer to footype.
  714. But we don't exand typedefs and #defines, so the footype may not
  715. be recognised as a type. Then it is not possible to know whether
  716. footype is an identifier or an unknown type until the next token is
  717. read (in this case, the star). If it is a comma or paren, then footype
  718. is actually an identifier. (This function gets called for the function
  719. return type and name as well, so "(" is possible as well as ")" and
  720. ",").
  721. The identifier is copied to ident.
  722. */
  723. boolT im = false, ib;
  724. while (isModifier()) {
  725. tok = getToken();
  726. im = true;
  727. }
  728. if (!im && (tok != TOK_NAME)) {
  729. errorParse("Expected type");
  730. }
  731. ib = isBaseType();
  732. if (ib)
  733. tok = getToken();
  734. /* Could be modifiers like "far", "interrupt" etc */
  735. while (isAttrib()) {
  736. tok = getToken();
  737. }
  738. while (tok == '*') {
  739. indirect++;
  740. tok = getToken();
  741. }
  742. /* Ignore the cdecl's */
  743. while (isCdecl())
  744. tok = getToken();
  745. if (tok == TOK_NAME) {
  746. /* This could be an ident or an unknown type */
  747. strcpy(ident, token);
  748. tok = getToken();
  749. }
  750. if (!ib && (tok != ',') && (tok != '(') && (tok != ')')) {
  751. /* That was (probably) not an ident! Assume it was an unknown type */
  752. printf("Unknown type %s\n", ident);
  753. ident[0] = '\0';
  754. bt = BT_UNKWN;
  755. while (tok == '*') {
  756. indirect++;
  757. tok = getToken();
  758. }
  759. /* Ignore the cdecl's */
  760. while (isCdecl())
  761. tok = getToken();
  762. }
  763. if (tok == TOK_NAME) {
  764. /* This has to be the ident */
  765. strcpy(ident, token);
  766. tok = getToken();
  767. }
  768. while (tok == '[') {
  769. indirect++; /* Treat x[] like *x */
  770. do {
  771. tok = getToken(); /* Ignore stuff between the '[' and ']' */
  772. } while (tok != ']');
  773. tok = getToken();
  774. }
  775. }
  776. hlType convType(void) {
  777. /* Convert from base type and signed/unsigned flags, etc, to a htType
  778. as Cristina currently uses */
  779. if (indirect >= 1) {
  780. if (bt == BT_CHAR)
  781. return TYPE_STR; /* Assume char* is ptr */
  782. /* Pointer to anything else (even unknown) is type pointer */
  783. else
  784. return TYPE_PTR;
  785. }
  786. switch (bt) {
  787. case BT_INT:
  788. if (isLong) {
  789. if (isUnsigned)
  790. return TYPE_LONG_UNSIGN;
  791. else
  792. return TYPE_LONG_SIGN;
  793. } else {
  794. if (isUnsigned)
  795. return TYPE_WORD_UNSIGN;
  796. else
  797. return TYPE_WORD_SIGN;
  798. }
  799. case BT_CHAR:
  800. if (isUnsigned)
  801. return TYPE_BYTE_UNSIGN;
  802. else
  803. return TYPE_BYTE_SIGN;
  804. case BT_FLOAT:
  805. return TYPE_FLOAT;
  806. case BT_DOUBLE:
  807. return TYPE_DOUBLE;
  808. case BT_STRUCT:
  809. return TYPE_RECORD;
  810. case BT_VOID:
  811. default:
  812. return TYPE_UNKNOWN;
  813. }
  814. }
  815. /* Add a new function to the array of function name and return types. The
  816. array is logically sorted by a linked list. Note that numArg is filled
  817. in later */
  818. boolT addNewFunc(char *name, hlType typ) {
  819. int i, prev, res;
  820. /* First see if the name already exists */
  821. prev = NIL;
  822. for (i = headFunc; i != NIL; i = pFunc[i].next) {
  823. res = strcmp(pFunc[i].name, name);
  824. if (res > 0) {
  825. break; /* Exit this loop when just past insert point */
  826. }
  827. if (res == 0) {
  828. /* Already have this function name */
  829. return true;
  830. }
  831. prev = i;
  832. }
  833. if (numFunc >= allocFunc) {
  834. allocFunc += DELTA_FUNC;
  835. pFunc = (PH_FUNC_STRUCT *)realloc(pFunc, allocFunc * sizeof(PH_FUNC_STRUCT));
  836. if (pFunc == NULL) {
  837. fprintf(stderr, "Could not allocate %ud bytes for function array\n",
  838. allocFunc * sizeof(PH_FUNC_STRUCT));
  839. exit(1);
  840. }
  841. memset(&pFunc[allocFunc - DELTA_FUNC], 0,
  842. DELTA_FUNC * sizeof(PH_FUNC_STRUCT));
  843. }
  844. name[SYMLEN - 1] = '\0';
  845. strcpy(pFunc[numFunc].name, name);
  846. pFunc[numFunc].typ = typ;
  847. pFunc[numFunc].firstArg = numArg;
  848. if (prev == NIL) {
  849. pFunc[numFunc].next = headFunc;
  850. headFunc = numFunc;
  851. } else {
  852. pFunc[numFunc].next = pFunc[prev].next;
  853. pFunc[prev].next = numFunc;
  854. }
  855. numFunc++;
  856. return false;
  857. }
  858. /* Add a new arguement to the array of arguement name and types. The
  859. array is logically sorted by a linked list */
  860. void addNewArg(char *name, hlType typ) {
  861. if (numArg >= allocArg) {
  862. allocArg += DELTA_FUNC;
  863. pArg = (PH_ARG_STRUCT *)realloc(pArg, allocArg * sizeof(PH_ARG_STRUCT));
  864. if (pArg == NULL) {
  865. fprintf(stderr, "Could not allocate %ud bytes for arguement array\n",
  866. allocArg * sizeof(PH_ARG_STRUCT));
  867. exit(1);
  868. }
  869. memset(&pArg[allocArg - DELTA_FUNC], 0, DELTA_FUNC * sizeof(PH_ARG_STRUCT));
  870. }
  871. name[SYMLEN - 1] = '\0';
  872. strcpy(pArg[numArg].name, name);
  873. pArg[numArg].typ = typ;
  874. numArg++;
  875. }
  876. void parseParam(void) {
  877. initType();
  878. if (tok == TOK_DOTS) {
  879. tok = getToken();
  880. pFunc[numFunc - 1].bVararg = true;
  881. return;
  882. }
  883. getTypeAndIdent();
  884. if ((bt == BT_VOID) && (indirect == 0)) {
  885. /* Just a void arg list. Ignore and pFunc[].numArgs will be set to zero */
  886. return;
  887. }
  888. argNum++;
  889. if (ident[0]) {
  890. addNewArg(ident, convType());
  891. } else {
  892. sprintf(ident, "arg%d", argNum);
  893. addNewArg(ident, convType());
  894. }
  895. }
  896. /* Parse the prototype as follows:
  897. <type> [<cdecl>] ["*"]... <funcName>"("<paramDef> [","<paramDef>]...")"
  898. where <type> is
  899. ["const"] [<modifier>] [<basetype>] modifier could be short, long, far
  900. and where paramdef is
  901. ["const"] <type> ["*"]... [<paramName>] or "..."
  902. Note that the closing semicolon is not seen.
  903. */
  904. void phBuffToFunc(char *buff) {
  905. initType();
  906. p = buffP = buff;
  907. tok = getToken();
  908. /* Ignore typedefs, for now */
  909. if ((tok == TOK_NAME) && (strcmp(token, "typedef") == 0))
  910. return;
  911. getTypeAndIdent();
  912. if (ident[0] == '\0') {
  913. errorParse("Expected function name");
  914. return;
  915. }
  916. if (addNewFunc(ident, convType())) {
  917. /* Already have this prototype, so ignore it */
  918. return;
  919. }
  920. if (tok != '(') {
  921. errorParse("Expected '('");
  922. return;
  923. }
  924. tok = getToken();
  925. argNum = 0;
  926. while (tok != TOK_EOL) {
  927. parseParam();
  928. if ((tok != ',') && (tok != ')')) {
  929. errorParse("Expected ',' between parameter defs");
  930. return;
  931. }
  932. tok = getToken();
  933. }
  934. pFunc[numFunc - 1].numArg = argNum; /* Number of args this func */
  935. }
  936. void phBuffToDef(char *buff) {}
  937. void writeFile(char *buffer, int len) {
  938. if ((int)fwrite(buffer, 1, len, datFile) != len) {
  939. printf("Could not write to file\n");
  940. exit(1);
  941. }
  942. }
  943. void writeFileShort(word w) {
  944. byte b;
  945. b = (byte)(w & 0xFF);
  946. writeFile((char *)&b, 1); /* Write a short little endian */
  947. b = (byte)(w >> 8);
  948. writeFile((char *)&b, 1);
  949. }
  950. void saveFile(void) {
  951. int i;
  952. fprintf(datFile, "dccp"); /* Signature */
  953. fprintf(datFile, "FN"); /* Function name tag */
  954. writeFileShort(numFunc); /* Number of func name records */
  955. for (i = headFunc; i != NIL; i = pFunc[i].next) {
  956. writeFile(pFunc[i].name, SYMLEN);
  957. writeFileShort((word)pFunc[i].typ);
  958. writeFileShort((word)pFunc[i].numArg);
  959. writeFileShort((word)pFunc[i].firstArg);
  960. writeFile((char *)&pFunc[i].bVararg, 1);
  961. }
  962. fprintf(datFile, "PM"); /* Parameter Name tag */
  963. writeFileShort(numArg); /* Number of args */
  964. for (i = 0; i < numArg; i++) {
  965. // writeFile(pArg[i].name, SYMLEN); // Don't want names yet
  966. writeFileShort((word)pArg[i].typ);
  967. }
  968. }
  969. int main(int argc, char *argv[]) {
  970. char *buf;
  971. long fSize;
  972. int ndata;
  973. FILE *f, *fl;
  974. int i;
  975. char *p;
  976. if (argc != 2) {
  977. printf("Usage: parsehdr <listfile>\n"
  978. "where <listfile> is a file of header file names to parse.\n"
  979. "The file dcclibs.dat will be written\n");
  980. exit(1);
  981. }
  982. fl = fopen(argv[1], "rt");
  983. if (fl == NULL) {
  984. printf("Could not open file list file %s\n", argv[1]);
  985. exit(1);
  986. }
  987. datFile = fopen("dcclibs.dat", "wb");
  988. if (datFile == NULL) {
  989. printf("Could not open output file dcclibs.dat\n");
  990. exit(2);
  991. }
  992. /* Allocate the arrys for function and proto names and types */
  993. pFunc = (PH_FUNC_STRUCT *)malloc(DELTA_FUNC * sizeof(PH_FUNC_STRUCT));
  994. if (pFunc == 0) {
  995. fprintf(stderr, "Could not malloc %ud bytes for function name array\n",
  996. DELTA_FUNC * sizeof(PH_FUNC_STRUCT));
  997. exit(1);
  998. }
  999. memset(pFunc, 0, DELTA_FUNC * sizeof(PH_FUNC_STRUCT));
  1000. allocFunc = DELTA_FUNC;
  1001. numFunc = 0;
  1002. pArg = (PH_ARG_STRUCT *)malloc(DELTA_FUNC * sizeof(PH_ARG_STRUCT));
  1003. if (pArg == 0) {
  1004. fprintf(stderr, "Could not malloc %ud bytes for arguement array\n",
  1005. DELTA_FUNC * sizeof(PH_ARG_STRUCT));
  1006. exit(1);
  1007. }
  1008. memset(pArg, 0, DELTA_FUNC * sizeof(PH_ARG_STRUCT));
  1009. allocArg = DELTA_FUNC;
  1010. numArg = 0;
  1011. headFunc = headArg = NIL;
  1012. buf = NULL;
  1013. while (!feof(fl)) {
  1014. /* Get another filename from the file list */
  1015. p = fgets(fileName, 80, fl);
  1016. if (p == NULL)
  1017. break; /* Otherwise read last filename twice */
  1018. i = strlen(fileName) - 1;
  1019. if (fileName[i] == '\n')
  1020. fileName[i] = '\0';
  1021. f = fopen(fileName, "rt");
  1022. if (f == NULL) {
  1023. printf("Could not open header file %s\n", fileName);
  1024. exit(1);
  1025. }
  1026. printf("Processing %s...\n", fileName);
  1027. fseek(f, 0, SEEK_END);
  1028. fSize = ftell(f);
  1029. fseek(f, 0, SEEK_SET);
  1030. ndata = std::min<int>(fSize, FBUF_SIZE);
  1031. if (buf)
  1032. free(buf);
  1033. buf = (char *)malloc(ndata);
  1034. if (buf == 0) {
  1035. printf("Could not malloc input file buffer of %d bytes\n", ndata);
  1036. exit(1);
  1037. }
  1038. while (!feof(f)) {
  1039. ndata = fread(buf, 1, ndata, f);
  1040. phData(buf, ndata);
  1041. }
  1042. phPost();
  1043. fclose(f);
  1044. }
  1045. saveFile();
  1046. fclose(datFile);
  1047. fclose(fl);
  1048. free(buf);
  1049. free(pFunc);
  1050. free(pArg);
  1051. }
  1052. #if CHECK_HEAP
  1053. void checkHeap(char *msg)
  1054. /* HEAPCHK.C: This program checks the heap for
  1055. * consistency and prints an appropriate message.
  1056. */
  1057. {
  1058. int heapstatus;
  1059. printf("%s\n", msg);
  1060. /* Check heap status */
  1061. heapstatus = _heapchk();
  1062. switch (heapstatus) {
  1063. case _HEAPOK:
  1064. printf(" OK - heap is fine\n");
  1065. break;
  1066. case _HEAPEMPTY:
  1067. printf(" OK - heap is empty\n");
  1068. break;
  1069. case _HEAPBADBEGIN:
  1070. printf("ERROR - bad start of heap\n");
  1071. break;
  1072. case _HEAPBADNODE:
  1073. printf("ERROR - bad node in heap\n");
  1074. break;
  1075. }
  1076. }
  1077. #endif