home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 19 Printer / 19-Printer.zip / cpostsrc.zip / CPOSTP1.C < prev    next >
C/C++ Source or Header  |  1993-01-17  |  18KB  |  575 lines

  1. /*------------------------------------------------------------------
  2.  * cpostp1.c : Pass 1 of cPost
  3.  *------------------------------------------------------------------
  4.  * 12-02-91 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. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  17.  
  18. /*------------------------------------------------------------------
  19.  * add bracketing starts in front of braces
  20.  *------------------------------------------------------------------*/
  21. static void AddLBracket(
  22.    File *file,
  23.    char *line,
  24.    char *mask,
  25.    int  *maxMask,
  26.    Tok  *tok
  27.    )
  28.    {
  29.    int  lIndent;
  30.    int  rIndent;
  31.    int  place;
  32.    Tok *sib;
  33.  
  34.    /*---------------------------------------------------------------
  35.     * see if matching bracket is on this line - if so, skip
  36.     *---------------------------------------------------------------*/
  37.    sib = tok->sib;
  38.    if (sib && (sib->tok.line == tok->tok.line))
  39.       return;
  40.  
  41.    /*---------------------------------------------------------------
  42.     * find minimum indent of left and right brace
  43.     *---------------------------------------------------------------*/
  44.    lIndent = strspn(line," ");
  45.    if (!tok->sib)
  46.       place = lIndent;
  47.    else
  48.       {
  49.       rIndent = strspn(file->line[sib->tok.line-1]," ");
  50.       place = min(lIndent,rIndent);
  51.       }
  52.  
  53.    /*---------------------------------------------------------------
  54.     * if no indentation on { or }, don't bracket!
  55.     *---------------------------------------------------------------*/
  56.    if (!place)
  57.       return;
  58.  
  59.    /*---------------------------------------------------------------
  60.     * we'll bracket the column BEFORE this
  61.     *---------------------------------------------------------------*/
  62.    place--;
  63.  
  64.    /*---------------------------------------------------------------
  65.     * set the mask, maxMask, and write bracket to line
  66.     *---------------------------------------------------------------*/
  67.    mask[place]++;
  68.    *maxMask = max(place,*maxMask);
  69.  
  70.    if (' ' == line[place])
  71.       line[place] = '\x01';
  72.    }
  73.  
  74. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  75. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  76.  
  77. /*------------------------------------------------------------------
  78.  * add bracketing ends
  79.  *------------------------------------------------------------------*/
  80. static void AddRBracket(
  81.    File *file,
  82.    char *line,
  83.    char *mask,
  84.    int  *maxMask,
  85.    Tok  *tok
  86.    )
  87.    {
  88.    Tok *sib;
  89.  
  90.    /*---------------------------------------------------------------
  91.     * see if matching bracket is on this line - if so, skip
  92.     *---------------------------------------------------------------*/
  93.    sib = tok->sib;
  94.    if (sib && (sib->tok.line == tok->tok.line))
  95.       return;
  96.  
  97.    /*---------------------------------------------------------------
  98.     * safety valve
  99.     *---------------------------------------------------------------*/
  100.    if (-1 == *maxMask)
  101.       return;
  102.  
  103.    /*---------------------------------------------------------
  104.     * add end bracket to line
  105.     *---------------------------------------------------------*/
  106.    if (' ' == line[*maxMask])
  107.       line[*maxMask] = '\x03';
  108.  
  109.    /*---------------------------------------------------------
  110.     * reset mask and maxMask
  111.     *---------------------------------------------------------*/
  112.    mask[*maxMask]--;
  113.    if (!mask[*maxMask])
  114.       {
  115.       *maxMask -= 1;
  116.       while (-1 != *maxMask)
  117.          if (mask[*maxMask])
  118.             break;
  119.          else
  120.             *maxMask -= 1;
  121.       }
  122.    }
  123.  
  124.  
  125. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  126. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  127.  
  128. /*------------------------------------------------------------------
  129.  * add bracketing chars to line based on mask
  130.  *------------------------------------------------------------------*/
  131. static char *AddMBrackets(
  132.    File *file,
  133.    char *line,
  134.    char *mask,
  135.    int   maxMask
  136.    )
  137.    {
  138.    int   i;
  139.  
  140.    /*------------------------------------------------------------
  141.     * see if we need to make the line longer
  142.     *------------------------------------------------------------*/
  143.    if (maxMask + 1 >= (int) strlen(line))
  144.       {
  145.       char *newLine;
  146.  
  147.       newLine = malloc(maxMask+3);
  148.       if (!newLine)
  149.          cPostError(1,"out of memory!!!");
  150.  
  151.       if ('\n' == line[strlen(line)-1])
  152.          line[strlen(line)-1] = ' ';
  153.  
  154.       memset(newLine,' ',maxMask+1);
  155.       newLine[maxMask+1] = '\n';
  156.       newLine[maxMask+2] = 0;
  157.       memcpy(newLine,line,strlen(line));
  158.  
  159.       free(line);
  160.       line = newLine;
  161.       }
  162.  
  163.    /*---------------------------------------------------------------
  164.     * get number of first non-blank column
  165.     *---------------------------------------------------------------*/
  166.    maxMask = min(maxMask,(int)strspn(line," "));
  167.  
  168.    /*---------------------------------------------------------------
  169.     * for each non-zero entry in mask, write bracket
  170.     *---------------------------------------------------------------*/
  171.    for (i=0; i<=maxMask; i++)
  172.       {
  173.       if (mask[i])
  174.          if (' ' == line[i])
  175.             line[i] = '\02';
  176.       }
  177.  
  178.    return line;
  179.    }
  180.  
  181. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  182. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  183.  
  184. /*------------------------------------------------------------------
  185.  * strip trailing blanks off a line (that has a \n at the end!!)
  186.  *------------------------------------------------------------------*/
  187. static void StripTrailingBlanks(
  188.    char *line
  189.    )
  190.    {
  191.    int slen;
  192.  
  193.    slen = strlen(line);
  194.    if ('\n' != line[slen-1])
  195.       {
  196.       fprintf(stderr,"line found without carriage return!!\n");
  197.       return;
  198.       }
  199.  
  200.    line[slen-1] = ' ';
  201.  
  202.    while (*line && (' ' == line[slen-1]))
  203.       {
  204.       line[slen-1] = '\0';
  205.       slen--;
  206.       }
  207.  
  208.    line[slen] = '\n';
  209.    }
  210.  
  211. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  212. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  213.  
  214. /*------------------------------------------------------------------
  215.  * add function information to trees and lists
  216.  *------------------------------------------------------------------*/
  217. static void AddFunctionPrototype(
  218.    Info          *info,
  219.    File          *file,
  220.    char          *name
  221.    )
  222.    {
  223.    Function *func;
  224.  
  225.    func = GetFunction(info,name);
  226.  
  227.    if (!ListFind(file->funcProList,&func))
  228.       if (!ListAdd(file->funcProList,&func))
  229.          cPostError(1,"error adding function prototype to list");
  230.    }
  231.  
  232. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  233. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  234.  
  235. /*------------------------------------------------------------------
  236.  * add function information to trees and lists
  237.  *------------------------------------------------------------------*/
  238. static void AddFunctionDefinition(
  239.    Info          *info,
  240.    File          *file,
  241.    char          *name,
  242.    unsigned long  lineNo
  243.    )
  244.    {
  245.    Function *func;
  246.  
  247.    func = GetFunction(info,name);
  248.    if (!ListFind(file->funcDefList,&func))
  249.       if (!ListAdd(file->funcDefList,&func))
  250.          cPostError(1,"error adding function definition to list");
  251.  
  252.    func->fileName = file->name;
  253.    func->lineNo   = lineNo;
  254.    }
  255.  
  256. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  257. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  258.  
  259. /*------------------------------------------------------------------
  260.  * add function information to trees and lists
  261.  *------------------------------------------------------------------*/
  262. static void AddFunctionUsage(
  263.    Info          *info,
  264.    char          *calleeName,
  265.    char          *callerName
  266.    )
  267.    {
  268.    Function *caller;
  269.    Function *callee;
  270.  
  271.    callee = GetFunction(info,calleeName);
  272.    caller = GetFunction(info,callerName);
  273.  
  274.    if (!ListFind(caller->callsList,   &callee))
  275.       if (!ListAdd(caller->callsList,   &callee))
  276.          cPostError(1,"error adding function callee to list");
  277.  
  278.    if (!ListFind(callee->calledByList,&caller))
  279.       if (!ListAdd(callee->calledByList,&caller))
  280.          cPostError(1,"error adding function caller to list");
  281.    }
  282.  
  283. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  284. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  285.  
  286. /*------------------------------------------------------------------
  287.  *
  288.  *------------------------------------------------------------------*/
  289. PageEject *addPageEject(
  290.    File      *file,
  291.    Tok       *tok,
  292.    PageEject *pageJ
  293.    )
  294.    {
  295.    PageEject     *new;
  296.    unsigned long  lineNo;
  297.    char          *line;
  298.  
  299.    /*---------------------------------------------------------------
  300.     * get space for new node
  301.     *---------------------------------------------------------------*/
  302.    new = malloc(sizeof(PageEject));
  303.    if (!new)
  304.       cPostError(1,"out of memory!!!");
  305.  
  306.    /*---------------------------------------------------------------
  307.     * link into list
  308.     *---------------------------------------------------------------*/
  309.    if (!pageJ)
  310.       file->breakList = new;
  311.    else
  312.       pageJ->next     = new;
  313.  
  314.    new->next   = NULL;
  315.    new->lineNo = file->lines;
  316.  
  317.    /*---------------------------------------------------------------
  318.     * find first non blank line after token
  319.     *---------------------------------------------------------------*/
  320.    lineNo = tok->tok.line;
  321.    if (lineNo >= file->lines)
  322.       return new;
  323.  
  324.    line = file->line[lineNo];
  325.    while (strspn(line," \n") == strlen(line))
  326.       {
  327.       lineNo++;
  328.       if (lineNo >= file->lines)
  329.          return new;
  330.  
  331.       line = file->line[lineNo];
  332.       }
  333.  
  334.    new->lineNo = lineNo;
  335.    return new;
  336.    }
  337.  
  338. /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  339. /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  340.  
  341. /*------------------------------------------------------------------
  342.  * pass 1 of cPost
  343.  *  - expand tabs, put bracketing around braces, write output files
  344.  *------------------------------------------------------------------*/
  345. int Pass1(
  346.    File     *file,
  347.    Info     *info
  348.    )
  349.    {
  350.    Tok            *next;
  351.    Tok            *def;
  352.    char           *mask;
  353.    char           *this;
  354.    int             lineNo;
  355.    int             i;
  356.    FILE           *tempFile;
  357.    Tok            *stack;
  358.    Tok            *temp;
  359.    int             maxMask;
  360.    int             brackLvl;
  361.    Tok            *lastSemi;
  362.    int             doLastSemi;
  363.    int             inFunc;
  364.    PageEject      *pageJ;
  365.  
  366.    /*---------------------------------------------------------------
  367.     * print status
  368.     *---------------------------------------------------------------*/
  369.    fprintf(stderr,"   Reading file %s\n",file->name);
  370.  
  371.    /*---------------------------------------------------------------
  372.     * parse the file
  373.     *---------------------------------------------------------------*/
  374.    info->indent1 = 1;
  375.  
  376.    cParse(file,info);
  377.  
  378.    info->indent1 = 0;
  379.  
  380.    /*---------------------------------------------------------------
  381.     * go down list, adding function information to function tree,
  382.     * and computing bracket information
  383.     *---------------------------------------------------------------*/
  384.    next       = file->tokList;
  385.    def        = NULL;
  386.    stack      = NULL;
  387.    lastSemi   = NULL;
  388.    pageJ      = NULL;
  389.    brackLvl   = 0;
  390.    inFunc     = 0;
  391.    doLastSemi = 1;
  392.  
  393.    while (next)
  394.       {
  395.       switch(next->extType)
  396.          {
  397.          /*---------------------------------------------------------
  398.           * function stuff
  399.           *---------------------------------------------------------*/
  400.          case TOKEN_FUNPRO:
  401.             AddFunctionPrototype(info,file,next->str);
  402.             break;
  403.  
  404.          case TOKEN_FUNDEF:
  405.             def = next;
  406.             AddFunctionDefinition(info,file,next->str,next->tok.line);
  407.             inFunc = 1;
  408.  
  409.             if (doLastSemi && lastSemi)
  410.                {
  411.                pageJ = addPageEject(file,lastSemi,pageJ);
  412.  
  413.                lastSemi   = NULL;
  414.                doLastSemi = 0;
  415.                }
  416.  
  417.             break;
  418.  
  419.          case TOKEN_FUNUSE:
  420.             AddFunctionUsage(info,next->str,def ? def->str : "");
  421.             break;
  422.  
  423.          /*---------------------------------------------------------
  424.           * semicolons for page breaks
  425.           *---------------------------------------------------------*/
  426.          case TOKEN_SCOLON:
  427.          case TOKEN_PREPROC:
  428.             if (doLastSemi)
  429.                lastSemi = next;
  430.             break;
  431.  
  432.          /*---------------------------------------------------------
  433.           * bracket stuff
  434.           *---------------------------------------------------------*/
  435.          case TOKEN_LBRACE:
  436.             brackLvl++;
  437.             next->sib   = NULL;
  438.             next->flags = 0;
  439.  
  440.             /*---------------------------------------------------
  441.              * put { on the stack
  442.              *---------------------------------------------------*/
  443.             next->sib   = stack;
  444.             stack       = next;
  445.             next->flags = 1;
  446.  
  447.             break;
  448.  
  449.          case TOKEN_RBRACE:
  450.             next->sib   = NULL;
  451.             next->flags = 0;
  452.  
  453.                next->extType = TOKEN_RBRACE;
  454.  
  455.             /*---------------------------------------------------
  456.              * remove { from stack, point { to } and } to {
  457.              *---------------------------------------------------*/
  458.             if (!stack)
  459.                fprintf(stderr,"unmatched } on line %ld\n",next->tok.line);
  460.             else
  461.                {
  462.                temp = stack;
  463.                stack = stack->sib;
  464.  
  465.                temp->sib   = next;
  466.                next->sib   = temp;
  467.                next->flags = 1;
  468.                }
  469.  
  470.             if (brackLvl > 0)
  471.                brackLvl--;
  472.  
  473.             /*------------------------------------------------------
  474.              * add conditional break, if it's time
  475.              *------------------------------------------------------*/
  476.             if (inFunc && !brackLvl)
  477.                {
  478.                pageJ = addPageEject(file,next,pageJ);
  479.  
  480.                doLastSemi = 0;
  481.                }
  482.  
  483.             break;
  484.          }
  485.  
  486.       next = next->next;
  487.       }
  488.  
  489.    /*---------------------------------------------------------------
  490.     * check for extra { on the stack
  491.     *---------------------------------------------------------------*/
  492.    while (stack)
  493.       {
  494.       fprintf(stderr,"unmatched { on line %ld\n",stack->tok.line);
  495.       stack = stack->sib;
  496.       }
  497.  
  498.    /*---------------------------------------------------------------
  499.     * now, let's add the bracketing characters
  500.     *---------------------------------------------------------------*/
  501.  
  502.    /*---------------------------------------------------------------
  503.     * initialize mask
  504.     *---------------------------------------------------------------*/
  505.    mask = malloc(file->maxLineLen+1);
  506.    if (!mask)
  507.       cPostError(1,"out of memory!!!");
  508.  
  509.    memset(mask,0,file->maxLineLen+1);
  510.  
  511.    /*---------------------------------------------------------------
  512.     * process each line
  513.     *---------------------------------------------------------------*/
  514.    next    = file->tokList;
  515.    maxMask = -1;
  516.    for (lineNo=0; lineNo < (int)file->lines; lineNo++)
  517.       {
  518.       this = file->line[lineNo];
  519.  
  520.       /*------------------------------------------------------------
  521.        * go to next token in this line
  522.        *------------------------------------------------------------*/
  523.       while (next && (next->tok.line <  (unsigned long)(lineNo + 1)))
  524.          next = next->next;
  525.  
  526.       /*------------------------------------------------------------
  527.        * add beginning and ending brackets
  528.        *------------------------------------------------------------*/
  529.       if (info->oBrack)
  530.          {
  531.          while (next && (next->tok.line == (unsigned long)(lineNo + 1)))
  532.             {
  533.             if      ((TOKEN_LBRACE == next->extType) && (next->flags))
  534.                AddLBracket(file,this,mask,&maxMask,next);
  535.  
  536.             else if ((TOKEN_RBRACE == next->extType) && (next->flags))
  537.                AddRBracket(file,this,mask,&maxMask,next);
  538.  
  539.             next = next->next;
  540.             }
  541.          }
  542.  
  543.       /*------------------------------------------------------------
  544.        * add middle brackets
  545.        *------------------------------------------------------------*/
  546.       file->line[lineNo] = AddMBrackets(file,this,mask,maxMask);
  547.       }
  548.  
  549.    /*---------------------------------------------------------------
  550.     * generate temp file name
  551.     *---------------------------------------------------------------*/
  552.    file->tempName = TempFileName(&tempFile,info);
  553.  
  554.    /*---------------------------------------------------------------
  555.     * write file to temp file
  556.     *---------------------------------------------------------------*/
  557.    for (i=0; i<(int)file->lines; i++)
  558.       fputs(file->line[i],tempFile);
  559.  
  560.    fclose(tempFile);
  561.  
  562.    /*---------------------------------------------------------------
  563.     * let's clean up all the memory we used
  564.     *---------------------------------------------------------------*/
  565.    free(mask);
  566.  
  567.    /*---------------------------------------------------------------
  568.     * clean out our data structures
  569.     *---------------------------------------------------------------*/
  570.    cParseDone(file,info);
  571.  
  572.    return 0;
  573.    }
  574.  
  575.