home *** CD-ROM | disk | FTP | other *** search
- /*
- (c) 1990 S.Hawtin.
- Permission is granted to copy this file provided that:
- 1) It is not used for commercial gain
- 2) This notice is included in all copies
- 3) Altered copies are marked as such.
-
- No liability is accepted for the contents of the file.
-
- reader.c within WBmake
-
- */
-
- /* Read the makefile into the data structures */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- #include "make.h"
-
- extern FileInfo *find_file();
- extern Variable *find_var();
- extern ConsCell *cons();
-
- /************************************************************/
- /* Defaults for default list */
-
- typedef struct
- {char *name;
- char *string[4];
- } DefaultInfo;
-
- DefaultInfo def_defaults[] =
- {{".c.o",{"NorthC -Ot:$*.s $*.c",
- "A68K -q -g -O$*.o t:$*.s","delete t:$*.s",NULL}},
- {".asm.o",{"A68K $*.asm",NULL}},
- {".s.o",{"A68K $*.s",NULL}},
- {".c.s",{"NorthC -O$*.s $*.c",NULL}},
- {NULL}};
-
- /************************************************************/
-
- FileInfo *first_file = NULL;
- ConsCell *defaults = NULL;
-
- lowerstr(str)
- char *str;
- {/* Convert a string to lower case */
-
- for(;*str;str++)
- *str = tolower(*str);
- }
-
- append(list,new_cons)
- ConsCell *list;
- ConsCell *new_cons;
- {/* Add a cons cell to the end of the list */
- while(list->cdr)
- list = list->cdr;
- list->cdr = new_cons;
- }
-
- static int line_no;
- static int last_ungot;
- FILE *inputs[4];
- int input_level=0;
- int input_feof = 0;
- char *push_str = "";
- static char last_ch;
-
- char
- make_getc()
- {/* Get a character from the Makefile */
- char temp_str[128];
- int count;
- char next;
-
- again:
- if(input_feof)
- return('\n');
- else if(*push_str)
- next = *push_str++;
- else if(last_ungot)
- {next = last_ch;
- last_ungot = 0;
- }
- else
- next = fgetc(inputs[input_level]);
- switch(next)
- {case '\n':
- line_no++;
- default:
- break;
- case '#':
- /* Skip comments */
- next = fgetc(inputs[input_level]);
- while(next!='\n' && !feof(inputs[input_level]))
- next = fgetc(inputs[input_level]);
- break;
- case '$':
- next = fgetc(inputs[input_level]);
- switch(next)
- {case '*':
- /* Pass $* to gomake file */
- push_str = "*";
- next = '$';
- goto out;
- case '<':
- /* Read file name and add to file stack */
- temp_str[0] = fgetc(inputs[input_level]);
- for(count=1;temp_str[count-1]!='>' && count<32;count++)
- temp_str[count] = fgetc(inputs[input_level]);
- temp_str[count-1] = '\0';
- /* Attempt to open the file */
- if(input_level>=3)
- {printf("Too many file levels $<%s>\n",temp_str);
- goto again;
- }
- inputs[input_level+1]=fopen(temp_str,"r");
- if(inputs[input_level+1])
- {input_level++;
- }
- else
- printf("Cannot open %s\n",temp_str);
- goto again;
- default:
- printf("Cannot cope with $%c\n",next);
- }
- break;
- }
- if(feof(inputs[input_level]))
- {fclose(inputs[input_level]);
- input_level--;
- if(input_level<0)
- input_feof = -1;
- next = '\n';
- }
- out:
- last_ch = next;
- return(next);
- }
-
- make_ungetc(ch)
- char ch;
- {/* Unget a single character */
- last_ungot = -1;
- }
-
- int
- skip_space()
- {/* Move past the space characters */
- char next;
-
- next = make_getc();
- while(isspace(next))
- {/* After a '#' read to next '\n' */
- if(input_feof)
- return(0);
- next = make_getc();
- }
- make_ungetc(next);
- return(-1);
- }
-
- next_tok(str)
- char *str;
- {/* Read the next token into the buffer */
- char *full_str;
-
- full_str = str;
- if(!skip_space())
- {*str='\0';
- return;
- }
- *str = make_getc();
- if(*str=='$')
- {/* The next character tells us what to do */
- str++;
- *str = make_getc();
- switch(*str)
- {case '*':
- default:
- /* read to next whitespace */
- goto normal_tok;
- case '(':
- /* Read a variable name and substitute it */
- str = full_str;
- *str = make_getc();
- while(*str!=')')
- {str++;
- *str = make_getc();
- }
- *(++str) = '\0';
- printf("Variable value %s\n",full_str);
- }
- }
- else
- {/* Normal token */
- normal_tok:
- while(isalnum(*str) || *str=='.' || *str=='_' || *str=='/')
- {str++;
- *str = make_getc();
- }
- make_ungetc(*str);
- *str = '\0';
- }
- }
-
- char
- next_oper()
- {/* Get the next operator */
- if(skip_space())
- return(make_getc());
- else
- return('\0');
- }
-
- String *
- make_str(str)
- char *str;
- {/* Create a string object */
- String *temp;
-
- temp = (String *)calloc(strlen(str)+sizeof(String),1);
- if(str)
- strcpy(temp->contents,str);
- return(temp);
- }
-
- String *
- read_string(multi)
- int multi;
- {/* Read a string, either a variable value or how to make
- something */
- String *first;
- String *last;
- char curr_line[128];
- int index;
- int done;
-
- first = NULL;
- last = NULL;
-
- for(;;)
- {/* Keep reading lines until we fulfill the end condition */
- index = 0;
- done = -1;
- curr_line[index++] = make_getc();
- while((curr_line[0]==' ' || curr_line[0]=='\t') && !input_feof)
- curr_line[0] = make_getc();
-
- while(!input_feof && curr_line[index-1]!='\n' && index<127)
- {
- curr_line[index++] = make_getc();
- }
-
- if(index==1)
- return(first);
-
- curr_line[index-1] ='\0';
-
- if(!multi && curr_line[index-2]=='\\')
- {curr_line[index-2] = '\0';
- done = 0;
- }
- if(first==NULL)
- {first = make_str(curr_line);
- last = first;
- }
- else
- {last->next = make_str(curr_line);
- last = last->next;
- }
- last->next = 0;
- if(!multi && done)
- return(first);
- }
- }
-
- add_defs(file)
- FileInfo *file;
- {if(defaults==NULL)
- {defaults = cons(file,NULL);
- }
- else
- {append(defaults,cons(file,NULL));
- }
- }
-
- next_clause()
- {/* Read the next clause from the file */
- Variable *var;
- String *string;
- FileInfo *file;
- char tok[32];
- char oper;
-
- next_tok(tok);
- oper = next_oper();
- if(oper=='\0')
- return;
- switch(oper)
- {case '=':
- /* Set variable value */
- var = find_var(tok);
- var->val = read_string(0);
- break;
- case ':':
- lowerstr(tok);
- file = find_file(tok,-1);
- if(first_file==NULL)
- first_file = file;
- if(*tok=='.')
- add_defs(file);
- do {
- /* Read the dependancies, add them to the file */
- do {/* Skip initial spaces */
- oper = make_getc();
- if(oper == '\\')
- {oper = make_getc();
- if(oper=='\n')
- oper = ' ';
- }
- } while (oper==' ' || oper=='\t');
- if(!isspace(oper))
- {make_ungetc(oper);
- next_tok(tok);
- /* Insert on dependancies */
- lowerstr(tok);
- file->depends = cons(find_file(tok,-1),
- file->depends);
- }
- } while (!isspace(oper));
- string = read_string(-1);
- if(string)
- {
- if(file->create && string)
- printf("Overwriting old create for %s\n",file->name);
- file->create = string;
- }
- break;
- default:
- printf("Failed to parse %c line %d\n",oper,line_no);
- exit(10);
- }
- }
-
- FileInfo *
- read_makefile(makefile,target)
- char *makefile;
- char *target;
- {/* Scan the makefile */
- int i;
-
- inputs[0] = fopen(makefile,"r");
- input_level = 0;
- input_feof = 0;
-
- if(inputs[0]==NULL)
- {printf("Cannot open \"%s\" for input\n",makefile);
- return(NULL);
- }
- line_no = 0;
-
- /* Set up the predefined variables */
-
- while(!input_feof)
- {/* Main loop of reader, read next item */
- next_clause();
- }
-
- /* Add the implied tokens if they have not been defined */
- for(i=0;def_defaults[i].name!=NULL;i++)
- {
- FileInfo *file;
- String *string;
- int j;
-
- if(find_file(def_defaults[i].name,0)==NULL)
- {/* Default has not been created, we better do it */
- file = find_file(def_defaults[i].name,-1);
- add_defs(file);
- string = NULL;
- for(j=3;j>=0;j--)
- if(def_defaults[i].string[j])
- {file->create = make_str(def_defaults[i].string[j]);
- file->create->next = string;
- string = file->create;
- }
- }
- }
- if(*target)
- {lowerstr(target);
- return(find_file(target,0));
- }
- else
- return(first_file);
- }
-