home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 19 Printer / 19-Printer.zip / cpostsrc.zip / CPOSTPAR.C < prev    next >
C/C++ Source or Header  |  1992-12-04  |  14KB  |  429 lines

  1. /*------------------------------------------------------------------
  2.  * cPostPar.c : higher level parser for cPost
  3.  *------------------------------------------------------------------
  4.  * 03-19-92 originally by Patrick J. Mueller
  5.  * 12-03-92 converted from cBook to cPost
  6.  *------------------------------------------------------------------*/
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11.  
  12. #include "ctok.h"
  13. #include "cpost.h"
  14.  
  15. /*------------------------------------------------------------------
  16.  * is string a C keyword
  17.  *------------------------------------------------------------------*/
  18. static int IsKeyword(
  19.    Info *info,
  20.    char *str
  21.    )
  22.    {
  23.    if (HashFind(info->reservedHash,&str))
  24.       return 1;
  25.    else
  26.       return 0;
  27.    }
  28.  
  29. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  30. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  31.  
  32. /*------------------------------------------------------------------
  33.  * add function information to tokens in list
  34.  *------------------------------------------------------------------*/
  35. static void AddFunctionInfoToTokens(
  36.    File *file
  37.    )
  38.    {
  39.    Tok *next;
  40.    Tok *func;
  41.  
  42.    /*---------------------------------------------------------------
  43.     * loop through the file
  44.     *---------------------------------------------------------------*/
  45.    next = file->tokList;
  46.    while (NULL != next)
  47.       {
  48.       /*------------------------------------------------------------
  49.        * continue reading till we have an identifier
  50.        *------------------------------------------------------------*/
  51.       if (TOKEN_IDENT != next->extType)
  52.          {
  53.          next = next->next;
  54.          continue;
  55.          }
  56.  
  57.       /*---------------------------------------------------------
  58.        * if next token is (, this is a function name!
  59.        *---------------------------------------------------------*/
  60.       func = next;
  61.       next = next->next;
  62.       if (NULL == next)
  63.          return;
  64.  
  65.       while ((TOKEN_COMMENT == next->extType) ||
  66.              (TOKEN_PREPROC == next->extType))
  67.          {
  68.          next = next->next;
  69.  
  70.          if (NULL == next)
  71.             return;
  72.          }
  73.  
  74.       if (TOKEN_LPAREN == next->extType)
  75.          {
  76.  
  77.          /*------------------------------------------------------
  78.           * if we're in braces, it's usage
  79.           *------------------------------------------------------*/
  80.          if (next->nestBrace > 0)
  81.             func->extType = TOKEN_FUNUSE;
  82.  
  83.          /*------------------------------------------------------
  84.           * otherwise it's a prototype or definition
  85.           *------------------------------------------------------*/
  86.          else
  87.             {
  88.             /*---------------------------------------------------
  89.              * get to the top level parenthesis
  90.              *---------------------------------------------------*/
  91.             while (next->nestParen > 0)
  92.                {
  93.                next = next->next;
  94.                if (NULL == next)
  95.                   return;
  96.                }
  97.  
  98.             /*---------------------------------------------------
  99.              * if next token is ;, it's a prototype, otherwise
  100.              * it's a definition - we'll assume it's a prototype
  101.              * though
  102.              *---------------------------------------------------*/
  103.             func->extType = TOKEN_FUNPRO;
  104.  
  105.             next = next->next;
  106.             if (NULL == next)
  107.                return;
  108.  
  109.             while ((TOKEN_COMMENT == next->extType) ||
  110.                    (TOKEN_PREPROC == next->extType))
  111.                {
  112.                next = next->next;
  113.  
  114.                if (NULL == next)
  115.                   return;
  116.                }
  117.  
  118.             if      (TOKEN_SCOLON == next->extType)
  119.                func->extType = TOKEN_FUNPRO;
  120.             else if (TOKEN_COMMA  == next->extType)
  121.                func->extType = TOKEN_FUNPRO;
  122.             else
  123.                func->extType = TOKEN_FUNDEF;
  124.             }
  125.          }
  126.       }
  127.    }
  128.  
  129. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  130. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  131.  
  132. /*------------------------------------------------------------------
  133.  * function that walks over hash table - for each thing in hash
  134.  * table, see if it's a function - if not, release the strings
  135.  * storage - otherwise add to the info hash table
  136.  *------------------------------------------------------------------*/
  137. static int CleanUpHashTableWalker(
  138.    char **ident,
  139.    Info  *info
  140.    )
  141.    {
  142.    Function  func;
  143.    Function *found;
  144.  
  145.    func.name = *ident;
  146.  
  147.    /*---------------------------------------------------------------
  148.     * see if it's a function
  149.     *---------------------------------------------------------------*/
  150.    found = ListFind(info->funcTree,&func);
  151.  
  152.    /*---------------------------------------------------------------
  153.     * if not found, release string storage
  154.     *---------------------------------------------------------------*/
  155.    if (!found)
  156.       {
  157.       free(*ident);
  158.       return 0;
  159.       }
  160.  
  161.    /*---------------------------------------------------------------
  162.     * see if it's already in the info hash table
  163.     *---------------------------------------------------------------*/
  164.    if (HashFind(info->identHash,ident))
  165.       {
  166.       free(*ident);
  167.       return 0;
  168.       }
  169.  
  170.    /*---------------------------------------------------------------
  171.     * if not, add it
  172.     *---------------------------------------------------------------*/
  173.    if (!HashAdd(info->identHash,ident))
  174.       cPostError(1,"error adding identifier to global hash table");
  175.  
  176.    return 0;
  177.    }
  178.  
  179. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  180. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  181.  
  182. /*------------------------------------------------------------------
  183.  * parse the file for functions
  184.  *------------------------------------------------------------------*/
  185. void cParse(
  186.    File     *file,
  187.    Info     *info
  188.    )
  189.    {
  190.    void          *hTokenizer;
  191.    Tok           *next;
  192.    Tok           *prev;
  193.    Tok           *fnc;
  194.    static char    tmpIdent [MAX_IDENT_LEN + 1];
  195.    char          *ptmpIdent  =   tmpIdent;
  196.    char         **pptmpIdent = &ptmpIdent;
  197.    char         **tempStr;
  198.  
  199.    /*---------------------------------------------------------------
  200.     * read the file
  201.     *---------------------------------------------------------------*/
  202.    if (NULL == FileReadLines(info,file))
  203.       cPostError(1,"unable to read file");
  204.  
  205.    file->identHash = HashCreate(sizeof(char *),
  206.                                 1000,
  207.                                 (HashFunc *)IdentHash,
  208.                                 (ListCompareFunc *)IdentCompare,
  209.                                 cPostNoMem);
  210.    if (!file->identHash)
  211.       cPostError(1,"error creating hash table");
  212.  
  213.    /*------------------------------------------------------------
  214.     * initialize tokenization
  215.     *------------------------------------------------------------*/
  216.    hTokenizer      = CTokInit(GetBlockOfFile,file);
  217.    if (!hTokenizer)
  218.       cPostError(1,"error initializing tokenization");
  219.  
  220.    file->tokList   = NULL;
  221.    next            = malloc(sizeof(Tok));
  222.    if (!next)
  223.       cPostError(1,"out of memory!!!");
  224.  
  225.    next->next      = NULL;
  226.    next->nestParen = 0;
  227.    next->nestBrace = 0;
  228.    next->str       = NULL;
  229.  
  230.    prev = NULL;
  231.  
  232.    fnc = NULL;
  233.  
  234.    /*------------------------------------------------------------
  235.     * build list of tokens
  236.     *------------------------------------------------------------*/
  237.    CTokGet(hTokenizer,&(next->tok));
  238.    while (TOKEN_EOF != next->tok.type)
  239.       {
  240.  
  241.       /*------------------------------------------------------------
  242.        * get a little more info
  243.        *------------------------------------------------------------*/
  244.       next->extType = next->tok.type;
  245.  
  246.       if (TOKEN_OPER == next->extType)
  247.          {
  248.          switch(next->tok.ident[0])
  249.             {
  250.             case '{':
  251.                next->extType = TOKEN_LBRACE;
  252.                next->nestBrace++;
  253.  
  254.                if (next->nestParen)
  255.                   {
  256.                   fprintf(stderr,"unmatched ( on or before "
  257.                                  "line %ld\n",next->tok.line);
  258.                   next->nestParen = 0;
  259.                   }
  260.                break;
  261.  
  262.             case '}':
  263.                next->extType = TOKEN_RBRACE;
  264.                next->nestBrace--;
  265.  
  266.                if (next->nestParen)
  267.                   {
  268.                   fprintf(stderr,"unmatched ( on or before "
  269.                                  "line %ld\n",next->tok.line);
  270.                   next->nestParen = 0;
  271.                   }
  272.                break;
  273.  
  274.             case '(':
  275.                next->extType = TOKEN_LPAREN;
  276.                next->nestParen++;
  277.  
  278.                /*---------------------------------------------------
  279.                 * add the identifier before this, if there was one
  280.                 *---------------------------------------------------*/
  281.                if (!fnc)
  282.                   break;
  283.  
  284.                /*------------------------------------------------------
  285.                 * get string from hash or add it
  286.                 *------------------------------------------------------*/
  287.                tempStr = HashFind(file->identHash,pptmpIdent);
  288.                if (tempStr)
  289.                   fnc->str = *tempStr;
  290.                else
  291.                   {
  292.                   fnc->str = malloc(1+strlen(tmpIdent));
  293.                   if (!fnc->str)
  294.                      cPostError(1,"out of memory!!!");
  295.  
  296.                   strcpy(fnc->str,tmpIdent);
  297.                   if (!HashAdd(file->identHash,&(fnc->str)))
  298.                      cPostError(1,"error adding identifier to file hash table");
  299.                   }
  300.  
  301.                fnc = NULL;
  302.                break;
  303.  
  304.             case ')':
  305.                next->extType = TOKEN_RPAREN;
  306.  
  307.                if (next->nestParen)
  308.                   next->nestParen--;
  309.                else
  310.                   {
  311.                   fprintf(stderr,"unnested ) on "
  312.                                  "line %ld\n",next->tok.line);
  313.                   next->nestParen = 0;
  314.                   }
  315.  
  316.                break;
  317.  
  318.             case ';':
  319.                next->extType = TOKEN_SCOLON;
  320.                break;
  321.  
  322.             case ',':
  323.                next->extType = TOKEN_COMMA;
  324.                break;
  325.             }
  326.          }
  327.  
  328.       else if (TOKEN_IDENT == next->extType)
  329.          {
  330.  
  331.          if (IsKeyword(info,next->tok.ident))
  332.             next->extType = TOKEN_RESER;
  333.          else
  334.             {
  335.             strcpy(tmpIdent,next->tok.ident);
  336.             fnc = next;
  337.             }
  338.          }
  339.  
  340.       /*------------------------------------------------------------
  341.        * link into list
  342.        *------------------------------------------------------------*/
  343.       if (NULL == file->tokList)
  344.          file->tokList = next;
  345.       else
  346.          prev->next = next;
  347.  
  348.       /*------------------------------------------------------------
  349.        * get next token
  350.        *------------------------------------------------------------*/
  351.       prev            = next;
  352.       next            = malloc(sizeof(Tok));
  353.       if (!next)
  354.          cPostError(1,"out of memory!!!");
  355.  
  356.       next->next      = NULL;
  357.       next->nestParen = prev->nestParen;
  358.       next->nestBrace = prev->nestBrace;
  359.       next->str       = NULL;
  360.  
  361.       CTokGet(hTokenizer,&(next->tok));
  362.       }
  363.  
  364.    /*---------------------------------------------------------------
  365.     * free the last hanging token
  366.     *---------------------------------------------------------------*/
  367.    free(next);
  368.  
  369.    /*------------------------------------------------------------
  370.     * terminate tokenization
  371.     *------------------------------------------------------------*/
  372.    CTokTerm(hTokenizer);
  373.  
  374.    /*---------------------------------------------------------------
  375.     * analyze the tokens
  376.     *---------------------------------------------------------------*/
  377.    AddFunctionInfoToTokens(file);
  378.    }
  379.  
  380. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  381. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  382.  
  383. /*------------------------------------------------------------------
  384.  * clean up after parsing file for functions
  385.  *------------------------------------------------------------------*/
  386. void cParseDone(
  387.    File     *file,
  388.    Info     *info
  389.    )
  390.    {
  391.    Tok *tok;
  392.    Tok *next;
  393.    int  i;
  394.  
  395.    /*---------------------------------------------------------------
  396.     * walk over old hash table, adding functions to info hash table
  397.     * and freeing non-function strings
  398.     *---------------------------------------------------------------*/
  399.    HashIterate(file->identHash,(ListIterateFunc *)CleanUpHashTableWalker,info);
  400.  
  401.    /*---------------------------------------------------------------
  402.     * destroy the file hash table
  403.     *---------------------------------------------------------------*/
  404.    HashDestroy(file->identHash);
  405.  
  406.    /*---------------------------------------------------------------
  407.     * now clean up token list
  408.     *---------------------------------------------------------------*/
  409.    tok = file->tokList;
  410.  
  411.    /*---------------------------------------------------------------
  412.     * loop through tokens and free 'um
  413.     *---------------------------------------------------------------*/
  414.    while (tok)
  415.       {
  416.       next = tok->next;
  417.       free(tok);
  418.       tok = next;
  419.       }
  420.  
  421.    /*---------------------------------------------------------------
  422.     * release file storage
  423.     *---------------------------------------------------------------*/
  424.    for (i=0; i<(int)file->lines; i++)
  425.       free(file->line[i]);
  426.  
  427.    free(file->line);
  428.    }
  429.