home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 216.lha / PdMake / input.c < prev    next >
C/C++ Source or Header  |  1996-02-15  |  7KB  |  332 lines

  1. /*
  2.  *     Parse a makefile
  3.  */
  4.  
  5.  
  6. #include <stdio.h>
  7. #include    <ctype.h>
  8. #include "h.h"
  9.  
  10.  
  11. struct name            namehead;            /* head of name list */
  12. struct name            *firstname;
  13.  
  14. char                str1[LZ];            /*  General store  */
  15. char                str2[LZ];
  16.  
  17.  
  18. /* create a symbol table for a name, if one does not already exist */
  19.  
  20. /*
  21.  *     Intern a name.  Return a pointer to the name struct
  22.  */
  23. struct name *newname(name) char *name;
  24. {
  25.     register struct name        *rp;
  26.     register struct name        *rrp;
  27.     register char                *cp;
  28.     extern TimeStamp time_zero;                        /* a null timestamp */
  29.  
  30.     for
  31.     (    rp = namehead.n_next, rrp = &namehead;        /* for each name */
  32.         rp;
  33.         rp = rp->n_next, rrp = rrp->n_next
  34.     )
  35.         if (strcmp(name, rp->n_name) == 0)            /* if name found, return it */
  36.             return rp;
  37.  
  38.         /* else make a new name, and link it in */
  39.  
  40.     if ((rp = (struct name *)malloc(sizeof (struct name)))
  41.                 == (struct name *)0)
  42.         fatal("No memory for name");
  43.     rrp->n_next = rp;
  44.     rp->n_next = (struct name *)0;
  45.     if ((cp = malloc(strlen(name)+1)) == (char *)0)
  46.         fatal("No memory for name");
  47.     strcpy(cp, name);
  48.  
  49.     /* initialize name structure */
  50.  
  51.     rp->n_name = cp;
  52.     rp->n_line = NULL;
  53.     rp->n_time = time_zero;
  54.     rp->n_flag = 0;
  55.  
  56.     /* return pointer to new name */
  57.  
  58.     return rp;
  59. }
  60.  
  61.  
  62. /*
  63.  *     Add a dependant to the end of the supplied list of dependants.
  64.  *     Return the new head pointer for that list.
  65.  */
  66. struct depend *
  67. newdep(np, dp)
  68. struct name *        np;
  69. struct depend *         dp;
  70. {
  71.     register struct depend *     rp;
  72.     register struct depend *     rrp;
  73.  
  74.  
  75.     if ((rp = (struct depend *)malloc(sizeof (struct depend)))
  76.                 == (struct depend *)0)
  77.         fatal("No memory for dependant");
  78.     rp->d_next = (struct depend *)0;
  79.     rp->d_name = np;
  80.  
  81.     if (dp == (struct depend *)0)
  82.         return rp;
  83.  
  84.     for (rrp = dp; rrp->d_next; rrp = rrp->d_next)
  85.         ;
  86.  
  87.     rrp->d_next = rp;
  88.  
  89.     return dp;
  90. }
  91.  
  92.  
  93. /*
  94.  *     Add a command to the end of the supplied list of commands.
  95.  *     Return the new head pointer for that list.
  96.  */
  97. struct cmd *
  98. newcmd(str, cp)
  99. char *            str;
  100. struct cmd *        cp;
  101. {
  102.     register struct cmd *   rp;
  103.     register struct cmd *   rrp;
  104.     register char *        rcp;
  105.  
  106.  
  107.     if (rcp = rindex(str, '\n'))
  108.         *rcp = '\0';         /*  Loose newline  */
  109.  
  110.     while (isspace(*str))
  111.         str++;
  112.  
  113.     if (*str == '\0')         /*  If nothing left, the exit  */
  114.         return;
  115.  
  116.     if ((rp = (struct cmd *)malloc(sizeof (struct cmd)))
  117.                 == (struct cmd *)0)
  118.         fatal("No memory for command");
  119.     rp->c_next = (struct cmd *)0;
  120.     if ((rcp = malloc(strlen(str)+1)) == (char *)0)
  121.         fatal("No memory for command");
  122.     strcpy(rcp, str);
  123.     rp->c_cmd = rcp;
  124.  
  125.     if (cp == (struct cmd *)0)
  126.         return rp;
  127.  
  128.     for (rrp = cp; rrp->c_next; rrp = rrp->c_next)
  129.         ;
  130.  
  131.     rrp->c_next = rp;
  132.  
  133.     return cp;
  134. }
  135.  
  136.  
  137. /*
  138.  *     Add a new 'line' of stuff to a target.  This check to see
  139.  *     if commands already exist for the target.  If flag is set,
  140.  *     the line is a double colon target.
  141.  *
  142.  *     Kludges:
  143.  *     i)  If the new name begins with a '.', and there are no dependents,
  144.  *       then the target must cease to be a target.  This is for .SUFFIXES.
  145.  *     ii) If the new name begins with a '.', with no dependents and has
  146.  *       commands, then replace the current commands.  This is for
  147.  *       redefining commands for a default rule.
  148.  *     Neither of these free the space used by dependents or commands,
  149.  *     since they could be used by another target.
  150.  */
  151. void
  152. newline(np, dp, cp, flag)
  153. struct name *        np;
  154. struct depend *         dp;
  155. struct cmd *        cp;
  156. {
  157.     bool            hascmds = FALSE;  /*  Target has commands  */
  158.     register struct line *  rp;
  159.     register struct line *  rrp;
  160.  
  161.  
  162.     /* Handle the .SUFFIXES case */
  163.     if (np->n_name[0] == '.' && !dp && !cp)
  164.     {
  165.         for (rp = np->n_line; rp; rp = rrp)
  166.         {
  167.             rrp = rp->l_next;
  168.             free(rp);
  169.         }
  170.         np->n_line = (struct line *)0;
  171.         np->n_flag &= ~N_TARG;
  172.         return;
  173.     }
  174.  
  175.     /* This loop must happen since rrp is used later. */
  176.     for
  177.     (
  178.         rp = np->n_line, rrp = (struct line *)0;
  179.         rp;
  180.         rrp = rp, rp = rp->l_next
  181.     )
  182.         if (rp->l_cmd)
  183.             hascmds = TRUE;
  184.  
  185.     if (hascmds && cp && !(np->n_flag & N_DOUBLE))
  186.         /* Handle the implicit rules redefinition case */
  187.         if (np->n_name[0] == '.' && dp == (struct depend *)0)
  188.         {
  189.             np->n_line->l_cmd = cp;
  190.             return;
  191.         }
  192.         else
  193.             error("Commands defined twice for target %s", np->n_name);
  194.     if (np->n_flag & N_TARG)
  195.         if (!(np->n_flag & N_DOUBLE) != !flag)        /* like xor */
  196.             error("Inconsistent rules for target %s", np->n_name);
  197.  
  198.     if ((rp = (struct line *)malloc(sizeof (struct line)))
  199.                 == (struct line *)0)
  200.         fatal("No memory for line");
  201.     rp->l_next = (struct line *)0;
  202.     rp->l_dep = dp;
  203.     rp->l_cmd = cp;
  204.  
  205.     if (rrp)
  206.         rrp->l_next = rp;
  207.     else
  208.         np->n_line = rp;
  209.  
  210.     np->n_flag |= N_TARG;
  211.     if (flag)
  212.         np->n_flag |= N_DOUBLE;
  213. }
  214.  
  215.  
  216. /*
  217.  *     Parse input from the makefile, and construct a tree structure
  218.  *     of it.
  219.  */
  220. void input()
  221. {
  222.     char                *p;        /*  General  */
  223.     char                 *q;
  224.     struct name            *np;
  225.     struct depend        *dp;
  226.     struct cmd            *cp;
  227.     bool                dbl;
  228.  
  229.     if (getline(str1)) return;  /*  Read the first line    */
  230.  
  231.     for(;;)
  232.     {    if (*str1 == '\t')      /*  Rules without targets  */
  233.             error("Command found with no target/dependancy line");
  234.  
  235.         p = str1;
  236.  
  237.         while (isspace(*p))     /*  Find first target  */
  238.             p++;
  239.  
  240.         while (((q = index(p, '=')) != (char *)0) &&
  241.            (p != q) && (q[-1] == '\\'))     /*  Find value */
  242.         {
  243.             register char *        a;
  244.  
  245.             a = q - 1;      /*  Del \ chr; move rest back  */
  246.             p = q;
  247.             while(*a++ = *q++)
  248.                 ;
  249.         }
  250.  
  251.         if (q != (char *)0)
  252.         {
  253.             register char *        a;
  254.             *q++ = '\0';         /*  Separate name and val  */
  255.             while (isspace(*q))
  256.                 q++;
  257.             if (p = rindex(q, '\n'))
  258.                 *p = '\0';
  259.  
  260.             p = str1;
  261.             if ((a = gettok(&p)) == (char *)0)
  262.                 error("No macro name");
  263.  
  264.             setmacro(a, q);
  265.  
  266.             if (getline(str1)) return;
  267.             continue;
  268.         }
  269.  
  270.         expand(str1);
  271.         p = str1;
  272.  
  273.         while (((q = index(p, ':')) != (char *)0) &&
  274.            (p != q) && (q[-1] == '\\'))     /*  Find dependents  */
  275.         {
  276.             register char *        a;
  277.  
  278.             a = q - 1;      /*  Del \ chr; move rest back  */
  279.             p = q;
  280.             while(*a++ = *q++)
  281.                 ;
  282.         }
  283.  
  284.         if (q == (char *)0)
  285.             error("No targets provided");
  286.  
  287.         *q++ = '\0';    /*  Separate targets and dependents  */
  288.  
  289.         if (*q == ':')       /* Double colon */
  290.         {
  291.             dbl = 1;
  292.             q++;
  293.         }
  294.         else
  295.             dbl = 0;
  296.  
  297.         for (dp = (struct depend *)0; ((p = gettok(&q)) != (char *)0);)
  298.                     /*  get list of dep's */
  299.         {
  300.             np = newname(p);         /*  Intern name    */
  301.             dp = newdep(np, dp);        /*  Add to dep list */
  302.         }
  303.  
  304.         *((q = str1) + strlen(str1) + 1) = '\0';
  305.             /*  Need two nulls for gettok (Remember separation)  */
  306.  
  307.         cp = (struct cmd *)0;
  308.         if (getline(str2) == FALSE)        /*  Get commands  */
  309.         {
  310.             while (*str2 == '\t')
  311.             {
  312.                 cp = newcmd(&str2[0], cp);
  313.                 if (getline(str2))
  314.                     break;
  315.             }
  316.         }
  317.  
  318.         while ((p = gettok(&q)) != (char *)0)   /* Get list of targ's */
  319.         {
  320.             np = newname(p);         /*  Intern name    */
  321.             newline(np, dp, cp, dbl);
  322.             if (!firstname && p[0] != '.')
  323.                 firstname = np;
  324.         }
  325.  
  326.         if (nestlvl < 0)            /*  EOF?  */
  327.             return;
  328.  
  329.         strcpy(str1, str2);
  330.     }
  331. }
  332.