parsehdr.cpp 28 KB

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