home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / dosdisas.zip / parsehdr.zip / PARSEHDR.C < prev    next >
C/C++ Source or Header  |  1994-03-31  |  30KB  |  1,539 lines

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