home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff384.lzh / NorthC / Example2.LZH / make / reader.c < prev    next >
C/C++ Source or Header  |  1990-08-30  |  10KB  |  400 lines

  1. /*
  2.   (c) 1990 S.Hawtin.
  3.   Permission is granted to copy this file provided that:
  4.    1) It is not used for commercial gain
  5.    2) This notice is included in all copies
  6.    3) Altered copies are marked as such.
  7.  
  8.   No liability is accepted for the contents of the file.
  9.  
  10.   reader.c    within        WBmake
  11.  
  12. */
  13.  
  14. /* Read the makefile into the data structures */
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <ctype.h>
  19. #include <string.h>
  20. #include "make.h"
  21.  
  22. extern FileInfo *find_file();
  23. extern Variable *find_var();
  24. extern ConsCell *cons();
  25.  
  26. /************************************************************/
  27. /* Defaults for default list */
  28.  
  29. typedef struct
  30.    {char  *name;
  31.     char  *string[4];
  32.     } DefaultInfo;
  33.  
  34. DefaultInfo def_defaults[] =
  35.    {{".c.o",{"NorthC -Ot:$*.s $*.c",
  36.              "A68K -q -g -O$*.o t:$*.s","delete t:$*.s",NULL}},
  37.     {".asm.o",{"A68K $*.asm",NULL}},
  38.     {".s.o",{"A68K $*.s",NULL}},
  39.     {".c.s",{"NorthC -O$*.s $*.c",NULL}},
  40.     {NULL}};
  41.  
  42. /************************************************************/
  43.  
  44. FileInfo *first_file = NULL;
  45. ConsCell *defaults = NULL;
  46.  
  47. lowerstr(str)
  48.     char *str;
  49.    {/* Convert a string to lower case */
  50.  
  51.     for(;*str;str++)
  52.         *str = tolower(*str);
  53.     }
  54.  
  55. append(list,new_cons)
  56.     ConsCell *list;
  57.     ConsCell *new_cons;
  58.    {/* Add a cons cell to the end of the list */
  59.     while(list->cdr)
  60.         list = list->cdr;
  61.     list->cdr = new_cons;
  62.     }
  63.  
  64. static int line_no;
  65. static int  last_ungot;
  66. FILE *inputs[4];
  67. int  input_level=0;
  68. int  input_feof = 0;
  69. char *push_str = "";
  70. static char last_ch;
  71.  
  72. char
  73. make_getc()
  74.    {/* Get a character from the Makefile */
  75.     char temp_str[128];
  76.     int  count;
  77.     char next;
  78.  
  79. again:
  80.     if(input_feof)
  81.         return('\n');
  82.       else if(*push_str)
  83.         next = *push_str++;
  84.       else if(last_ungot)
  85.        {next = last_ch;
  86.         last_ungot = 0;
  87.         }
  88.       else
  89.         next = fgetc(inputs[input_level]);
  90.     switch(next)
  91.        {case '\n':
  92.             line_no++;
  93.         default:
  94.             break;
  95.         case '#':
  96.             /* Skip comments */
  97.             next = fgetc(inputs[input_level]);
  98.             while(next!='\n' && !feof(inputs[input_level]))
  99.                 next = fgetc(inputs[input_level]);
  100.             break;
  101.         case '$':
  102.             next = fgetc(inputs[input_level]);
  103.             switch(next)
  104.                {case '*':
  105.             /* Pass $* to gomake file */
  106.                     push_str = "*";
  107.                     next = '$';
  108.                     goto out;
  109.         case '<':
  110.             /* Read file name and add to file stack */
  111.             temp_str[0] = fgetc(inputs[input_level]);
  112.             for(count=1;temp_str[count-1]!='>' && count<32;count++)
  113.                 temp_str[count] = fgetc(inputs[input_level]);
  114.             temp_str[count-1] = '\0';
  115.             /* Attempt to open the file */
  116.                     if(input_level>=3)
  117.                {printf("Too many file levels $<%s>\n",temp_str);
  118.                         goto again;
  119.                         }
  120.             inputs[input_level+1]=fopen(temp_str,"r");
  121.             if(inputs[input_level+1])
  122.                {input_level++;
  123.             }
  124.               else
  125.                 printf("Cannot open %s\n",temp_str);
  126.             goto again;
  127.                 default:
  128.                     printf("Cannot cope with $%c\n",next);
  129.                 }
  130.             break;
  131.         }
  132.     if(feof(inputs[input_level]))
  133.        {fclose(inputs[input_level]);
  134.         input_level--;
  135.         if(input_level<0)
  136.             input_feof = -1;
  137.         next = '\n';
  138.         }
  139. out:
  140.     last_ch = next;
  141.     return(next);
  142.     }
  143.  
  144. make_ungetc(ch)
  145.     char ch;
  146.    {/* Unget a single character */
  147.     last_ungot = -1;
  148.     }
  149.  
  150. int
  151. skip_space()
  152.    {/* Move past the space characters */
  153.     char next;
  154.  
  155.     next = make_getc();
  156.     while(isspace(next))
  157.        {/* After a '#' read to next '\n' */
  158.         if(input_feof)
  159.             return(0);
  160.         next = make_getc();
  161.         }
  162.     make_ungetc(next);
  163.     return(-1);
  164.     }
  165.  
  166. next_tok(str)
  167.     char *str;
  168.    {/* Read the next token into the buffer */
  169.     char *full_str;
  170.  
  171.     full_str = str;
  172.     if(!skip_space())
  173.        {*str='\0';
  174.         return;
  175.         }
  176.     *str = make_getc();
  177.     if(*str=='$')
  178.        {/* The next character tells us what to do */
  179.         str++;
  180.         *str = make_getc();
  181.         switch(*str)
  182.            {case '*':
  183.             default:
  184.                 /* read to next whitespace */
  185.                 goto normal_tok;
  186.             case '(':
  187.                 /* Read a variable name and substitute it */
  188.                 str = full_str;
  189.                 *str = make_getc();
  190.                 while(*str!=')')
  191.                    {str++;
  192.                     *str = make_getc();
  193.                     }
  194.                 *(++str) = '\0';
  195.                 printf("Variable value %s\n",full_str);
  196.             }
  197.         }
  198.       else
  199.        {/* Normal token */
  200. normal_tok:
  201.         while(isalnum(*str) || *str=='.' || *str=='_' || *str=='/')
  202.            {str++;
  203.             *str = make_getc();
  204.             }
  205.         make_ungetc(*str);
  206.         *str = '\0';
  207.         }
  208.     }
  209.  
  210. char
  211. next_oper()
  212.    {/* Get the next operator */
  213.     if(skip_space())
  214.         return(make_getc());
  215.       else
  216.         return('\0');
  217.     }
  218.  
  219. String *
  220. make_str(str)
  221.     char *str;
  222.    {/* Create a string object */
  223.     String *temp;
  224.  
  225.     temp = (String *)calloc(strlen(str)+sizeof(String),1);
  226.     if(str)
  227.         strcpy(temp->contents,str);
  228.     return(temp);
  229.     }
  230.  
  231. String *
  232. read_string(multi)
  233.     int multi;
  234.    {/* Read a string, either a variable value or how to make
  235.        something */
  236.     String *first;
  237.     String *last;
  238.     char   curr_line[128];
  239.     int    index;
  240.     int    done;
  241.  
  242.     first = NULL;
  243.     last = NULL;
  244.  
  245.     for(;;)
  246.        {/* Keep reading lines until we fulfill the end condition */
  247.         index = 0;
  248.         done = -1;
  249.         curr_line[index++] = make_getc();
  250.         while((curr_line[0]==' ' || curr_line[0]=='\t') && !input_feof)
  251.             curr_line[0] = make_getc();
  252.  
  253.         while(!input_feof && curr_line[index-1]!='\n' && index<127)
  254.            {
  255.             curr_line[index++] = make_getc();
  256.             }
  257.  
  258.         if(index==1)
  259.             return(first);
  260.  
  261.         curr_line[index-1] ='\0';
  262.  
  263.         if(!multi && curr_line[index-2]=='\\')
  264.            {curr_line[index-2] = '\0';
  265.             done = 0;
  266.             }
  267.         if(first==NULL)
  268.            {first = make_str(curr_line);
  269.             last  = first;
  270.             }
  271.           else
  272.            {last->next = make_str(curr_line);
  273.             last = last->next;
  274.             }
  275.         last->next = 0;
  276.         if(!multi && done)
  277.             return(first);
  278.         }
  279.     }
  280.  
  281. add_defs(file)
  282.     FileInfo *file;
  283.    {if(defaults==NULL)
  284.        {defaults = cons(file,NULL);
  285.         }
  286.       else
  287.        {append(defaults,cons(file,NULL));
  288.         }
  289.     }
  290.  
  291. next_clause()
  292.    {/* Read the next clause from the file */
  293.     Variable *var;
  294.     String   *string;
  295.     FileInfo *file;
  296.     char tok[32];
  297.     char oper;
  298.  
  299.     next_tok(tok);
  300.     oper = next_oper();
  301.     if(oper=='\0')
  302.         return;
  303.     switch(oper)
  304.        {case '=':
  305.             /* Set variable value */
  306.             var = find_var(tok);
  307.             var->val = read_string(0);
  308.             break;
  309.         case ':':
  310.             lowerstr(tok);
  311.             file = find_file(tok,-1);
  312.             if(first_file==NULL)
  313.                 first_file = file;
  314.             if(*tok=='.')
  315.                 add_defs(file);
  316.             do {
  317.                 /* Read the dependancies, add them to the file */
  318.                 do {/* Skip initial spaces */
  319.                     oper = make_getc();
  320.                     if(oper == '\\')
  321.                        {oper = make_getc();
  322.                         if(oper=='\n')
  323.                             oper = ' ';
  324.                         }
  325.                     } while (oper==' ' || oper=='\t');
  326.                 if(!isspace(oper))
  327.                    {make_ungetc(oper);
  328.                     next_tok(tok);
  329.                     /* Insert on dependancies */
  330.                     lowerstr(tok);
  331.                     file->depends = cons(find_file(tok,-1),
  332.                                          file->depends);
  333.                     }
  334.                 } while (!isspace(oper));
  335.             string = read_string(-1);
  336.             if(string)
  337.                {
  338.                 if(file->create && string)
  339.                     printf("Overwriting old create for %s\n",file->name);
  340.                 file->create = string;
  341.                 }
  342.             break;
  343.         default:
  344.             printf("Failed to parse %c line %d\n",oper,line_no);
  345.             exit(10);
  346.         }
  347.     }
  348.  
  349. FileInfo *
  350. read_makefile(makefile,target)
  351.     char *makefile;
  352.     char *target;
  353.    {/* Scan the makefile */
  354.     int i;
  355.  
  356.     inputs[0] = fopen(makefile,"r");
  357.     input_level = 0;
  358.     input_feof = 0;
  359.  
  360.     if(inputs[0]==NULL)
  361.        {printf("Cannot open \"%s\" for input\n",makefile);
  362.         return(NULL);
  363.         }
  364.     line_no = 0;
  365.  
  366.     /* Set up the predefined variables */
  367.  
  368.     while(!input_feof)
  369.        {/* Main loop of reader, read next item */
  370.         next_clause();
  371.         }
  372.  
  373.     /* Add the implied tokens if they have not been defined */
  374.     for(i=0;def_defaults[i].name!=NULL;i++)
  375.        {
  376.         FileInfo *file;
  377.         String   *string;
  378.         int j;
  379.  
  380.         if(find_file(def_defaults[i].name,0)==NULL)
  381.            {/* Default has not been created, we better do it */
  382.             file = find_file(def_defaults[i].name,-1);
  383.             add_defs(file);
  384.             string = NULL;
  385.             for(j=3;j>=0;j--)
  386.                 if(def_defaults[i].string[j])
  387.                    {file->create = make_str(def_defaults[i].string[j]);
  388.                     file->create->next = string;
  389.                     string = file->create;
  390.                     }
  391.             }
  392.         }
  393.     if(*target)
  394.        {lowerstr(target);
  395.         return(find_file(target,0));
  396.         }
  397.       else
  398.         return(first_file);
  399.     }
  400.