home *** CD-ROM | disk | FTP | other *** search
- /* read the makefile, and generate the linked lists */
- #include <stdio.h>
- #include "make.h"
-
- #if MSC
- #include <ctype.h>
- #endif
-
- #define DONE 1
- #define ADEFN 2
- #define ARULE 3
- #define AMACRO 4
-
- #if LC
- extern int _stack;
- #endif
-
- /* externals, all defined in make.c */
- extern struct macrec *maclist;
- extern struct defnrec *defnlist;
- extern struct llist *dolist;
- extern struct rulerec *rulelist;
- extern int no_file,linecont;
- long getmodified();
- char *get_mem(),*mov_in();
-
-
-
- /* local variables */
- FILE *fil;
- char *fword,*restline,line[INMAX],backup[INMAX];
- char *frule;
- struct llist *fhowto,*howp3;
- struct llist *fdeps,*deprec3;
- struct macrec *macp,*macp2;
- struct rulerec *rulep,*rulep2;
- struct defnrec *defnp;
- int sending,def_ready,gdone,rule_send,rule_ready;
- struct llist *targ,*q_how,*q_dep,*targ2;
-
- readmakefile(s)
- char *s;
- {
- int i,k;
-
- /* open the file */
- if ( strcmp(s,"-") == 0 ) fil = stdin;
- else if ( (fil = fopen(s,"r")) == NULL) {
- error("couldn't open '%s'.",s);
- return;
- }
-
- /* initialise getnxt() */
- sending = def_ready = gdone = rule_send = rule_ready = FALSE;
- targ = q_how = q_dep = NULL;
- if (getline(fil, backup) == FALSE)
- panic("Empty Makefile");
-
-
- /* getnxt() parses the next line, and returns the parts */
- while (TRUE) switch( getnxt() ){
-
- case DONE: return;
-
- case AMACRO: /* add a macro to the list */
-
- /** get space */
- macp = (struct macrec *)get_mem((unsigned) sizeof(struct macrec));
- if (maclist == NULL)
- maclist = macp;
- else {
- macp2 = maclist;
- while (macp2->nextmac != NULL)
- macp2 = macp2->nextmac;
- macp2->nextmac = macp;
- }
- uppercase(fword);
- macp->name = mov_in(fword);
- macp->mexpand = mov_in(restline);
- macp->nextmac = NULL;
- break;
-
- case ARULE: /* add a rule to the list */
-
- rulep = (struct rulerec *)get_mem(sizeof(struct rulerec));
- if (rulelist == NULL)
- rulelist = rulep;
- else{
- rulep2 = rulelist;
- while (rulep2->nextrule != NULL)
- rulep2 = rulep2->nextrule;
- rulep2->nextrule = rulep;
- }
- /*fword[0] is defined to be a period*/
- for (i=1; notnull(fword[i]) ;i++)
- if ( fword[i] == '.' ) break;
- if ( i == strlen(fword) ) panic("Bad rule '%s'",fword);
- fword[i] = NUL;
- rulep->dep = mov_in(fword + 1); /*don't save the preceding '.' */
- /* be sure object extension has no spaces */
- for ( k = i+1 ; notnull(fword[k]) && !isspace(fword[k]) ; k++ )
- ;/*NOP*/
- if ( isspace(fword[k]) ) fword[k] = NUL;
- rulep->targ = mov_in(fword + i + 1);
- rulep->rule = fhowto;
- rulep->nextrule = NULL;
- break;
-
- case ADEFN: /* add a definition */
-
- if (no_file) { /*if no target specified on command line... */
- add_do(fword); /*push this target on to do list */
- no_file = FALSE;
- }
- /* getnxt() returns target ( fword ) , pointer to expanded howto
- list ( fhowto ) and pointer to expanded depends ( fdeps )
- */
- if ( defnlist == NULL ) {
- add_defn(); /* add the current definition to the end */
- }
- else {
- defnp = defnlist;
- while ( defnp != NULL ) {
- if (strcmp(defnp->name,fword) == 0) break;
- else defnp = defnp->nextdefn;
- }
- if ( defnp == NULL ) {
- /* target not currently in list */
- add_defn();
- }
- else {
- /* target is on list, add new depends and howtos */
- if (defnp->dependson == NULL)
- defnp->dependson = fdeps;
- else {
- deprec3 = defnp->dependson;
- while (deprec3->next != NULL)
- deprec3 = deprec3->next;
- deprec3->next = fdeps;
- }
- /* add new howtos */
- if (defnp->howto == NULL)
- defnp->howto = fhowto;
- else {
- howp3 = defnp->howto;
- while ( howp3->next != NULL)
- howp3 = howp3->next;
- howp3->next = fhowto;
- }
- }
- }
- break;
- }
- }
-
- add_defn() /* add a new definition */
- {
- struct defnrec *ptr,*ptr2;
- ptr = (struct defnrec *)get_mem(sizeof(struct defnrec));
- ptr->name = fword;
- ptr->uptodate = FALSE;
- ptr->modified = getmodified(fword,DEPENDANT);
- ptr->dependson = fdeps;
- ptr->howto = fhowto;
- ptr->nextdefn = NULL;
- if ( defnlist == NULL ) {
- defnlist = ptr;
- return;
- }
- else {
- ptr2 = defnlist;
- while ( ptr2->nextdefn != NULL )
- ptr2 = ptr2->nextdefn;
- ptr2->nextdefn = ptr;
- }
- }
-
- getnxt()
- {
- int pos,mark,parsed;
- char exp_line[INMAX];
- struct llist *mkllist(),*mkexphow(),*mkexpdep(),*q_how2,*q_how3;
-
- while ( TRUE ) {
-
- /* if we are currently sending targets */
- if ( sending ) {
- if ( targ2->next == NULL) {
- sending = def_ready = FALSE;
- }
- fword = mov_in(targ2->name);
- fhowto = mkexphow(q_how,targ2->name,REPT_ERR);
- fdeps = mkexpdep(q_dep,targ2->name);
- targ2 = targ2->next;
- return ( ADEFN );
- }
-
- /* are we sending a rule? */
- if ( rule_send ) {
- fword = frule;
- fhowto = mkexphow(q_how,(char *)NULL,IGN_ERR); /* target == NULL -> don't expand */
- rule_send = rule_ready = FALSE;
- return( ARULE );
- }
-
- if ( gdone ) return ( DONE );
- /* if we are not currently sending... */
-
- /* load the next line into 'line' ( which may be backed-up ) */
- if ( backup[0] != NUL ) {
- strcpy(line,backup);
- backup[0] = NUL;
- }
- else {
- if ( getline(fil,line) == FALSE ) {
- if ( def_ready ) sending = TRUE;
- if ( rule_ready ) rule_send = TRUE;
- gdone = TRUE;
- continue; /* break the loop, and flush any definitions */
- }
- }
- parsed = FALSE;
-
- /* check for rule, and begin loading it if there */
- if (line[0] == '.'){
- /* found a rule */
- for (pos = 0 ; line[pos] != ':' && notnull(line[pos]) ; pos++)
- if (isspace(line[pos])) continue;
- if (isnull(line[pos]))
- error("rule needs colon separator '%s'",line);
- mark = pos;
- for (pos++ ; line[pos] != ';' && notnull(line[pos]) ; pos++) ;
- if (isnull(line[pos]))
- error("rule needs ';' after ':'-- '%s'",line);
- parsed = TRUE;
- if ( rule_ready || def_ready ) {
- if ( def_ready ) sending = TRUE;
- else rule_send = TRUE;
- strcpy(backup,line); /* push this line, and send what we already have */
- }
- else {
- rule_ready = TRUE;
- line[mark] = NUL;
- frule = mov_in(line);
- free_list(q_how);
- q_how = MkListMem();
- q_how->name = mov_in(line + pos + 1 );
- q_how->next = NULL;
- }
- }
-
- /* check for macro, and return it if there */
- if ( !parsed ) {
- pos = 0;
- while ( line[pos] != '=' &&
- line[pos] != ':' &&
- !isspace(line[pos]) &&
- notnull(line[pos])) pos++;
- mark = pos;
- if (notnull(line[pos]) && line[pos] != ':'){
- /* found a macro */
- if (isspace(line[pos]))
- while (isspace(line[pos]) && notnull(line[pos])) pos++;
- if (isnull(line[pos]))
- panic("bad macro or definition '%s'",line);
- if ( line[pos] == '=' ) {
- /* found a macro */
- line[mark] = NUL;
- fword = line;
- mark = pos + 1;
- while ( isspace(line[mark]) ) mark++; /* skip spaces before macro starts */
- restline = line + mark;
- return ( AMACRO );
- }
- }
- }
-
-
-
- /* check for and add howto line */
- if ( isspace(line[0]) ) {
- if (!def_ready && !rule_ready)
- error("how-to line without preceeding definition or rule\n'%s'",line);
- for ( pos = 0 ; isspace(line[pos]) ; pos++ ) ;
- q_how2 = MkListMem();
- if ( q_how == NULL ) {
- q_how = q_how2;
- }
- else {
- q_how3 = q_how;
- while ( q_how3->next != NULL )
- q_how3 = q_how3->next;
- q_how3->next = q_how2;
- }
- q_how2->name = mov_in(line);
- q_how2->next = NULL;
- parsed = TRUE;
- }
-
-
- /* check for definition */
- if (!parsed) {
- pos = 0;
- while ( notnull(line[pos]) && line[pos] != ':') pos++;
- if (line[pos] == ':') {
- /* found a definition */
- parsed = TRUE;
- if (def_ready || rule_ready) {
- if ( def_ready ) sending = TRUE;
- else rule_send = TRUE;
- strcpy(backup,line);
- }
- else {
- /* free up the space used by the previous lists */
- free_list(targ);targ = NULL;
- free_list(q_how);q_how = NULL;
- free_list(q_dep);q_dep = NULL;
- line[pos] = NUL;
- expand(line,exp_line,"",NO_TARG);
- targ2 = targ = mkllist(exp_line);
- q_dep = mkllist(line + pos + 1);
- def_ready = TRUE;
- }
- }
- }
- if (!parsed)
- panic("unable to parse line '%s'",line);
- }
- }
-
-
-
- /*
- load the next line from 'stream' to 'where' allowing for comment char
- and line continuations
- */
- getline(stream,where)
- char *where;
- FILE *stream;
- {
- int i,x;
-
- while (fgets(where,INMAX,stream) != NULL) {
- i = strlen(where);
- where[--i] = NUL; /* null terminate the string ( drop \n ) */
-
- /* terminate stdin input with a '.' */
- if ( (stream == stdin) && (strcmp(where,".") == 0) ) return( FALSE );
-
- /* if line is blank, or begins with # , skip it */
- if (isnull(where[0]) || where[0] == '#') continue;
-
- /* if the line is only ws, skip it */
- for ( x = 0; isspace(where[x]) && notnull(where[x]) ; x++) ;
- if (isnull(where[x])) continue;
-
- while (where[i-1] == linecont ){
- /*continue reading line if line continuation character*/
- if (fgets(where + i - 1,INMAX,stream) == NULL)
- error("end of file before end of line");
- if ( (stream == stdin) && (strcmp(where + i - 1,".\n") == 0) )
- error("end of file before end of line");
- i = strlen(where);
- where[--i] = NUL;
- }
- if ( i >= INMAX ) {
- where[INMAX] = NUL;
- panic("line too long\n'%s'",where);
- }
- return ( TRUE );
- }
- return ( FALSE );
- }
-
-
-
- struct llist *mkllist( s ) /* make a linked list */
- char *s;
- {
- int i,pos;
- char lname[INMAX];
- struct llist *ptr,*ptr2,*retval;
-
-
- i = pos = 0;
- retval = NULL;
- while ( TRUE ) {
- while ( notnull(s[pos]) && isspace(s[pos]) ) pos++;
-
- if ( isnull(s[pos]) ) return( retval );
-
- while ( !isspace(s[pos]) && notnull(s[pos]) ) lname[i++] = s[pos++];
-
- /* found something to add */
- ptr = MkListMem();
- if ( retval == NULL ) {
- retval = ptr;
- }
- else {
- ptr2 = retval;
- while ( ptr2->next != NULL )
- ptr2 = ptr2->next;
- ptr2->next = ptr;
- }
- lname[i] = NUL;
- ptr->name = mov_in(lname);
- ptr->next = NULL;
- i = 0;
- }
- }
-
-
- struct llist *mkexphow(head,target,eflag) /* make an expanded linked list for how */
- struct llist *head;
- char *target;
- int eflag;
- {
- struct llist *p,*p2,*retval;
- char temp[INMAX];
-
- if ( head == NULL ) {
- return ( NULL );
- }
-
- retval = NULL;
- while ( head != NULL ) {
-
- if ( target != NULL ) expand(head->name,temp,target,eflag);
- else strcpy(temp,head->name);
- p = MkListMem();
- p->name = mov_in(temp);
- p->next = NULL;
-
- if ( retval == NULL ) retval = p;
- else {
- p2 = retval;
- while ( p2->next != NULL )
- p2 = p2->next;
- p2->next = p;
- }
- head = head->next;
- }
- return( retval );
- }
-
- struct llist *mkexpdep(head,target) /* make an expanded linked list for dep*/
- struct llist *head;
- char *target;
- {
- struct llist *p,*p2,*p3,*retval;
- char temp[INMAX];
-
- if ( head == NULL ) {
- return ( NULL );
- }
-
- retval = NULL;
- while ( head != NULL ) {
-
- expand(head->name,temp,target,REPT_ERR);
- p3 = mkllist(temp);
- while ( p3 != NULL ) {
- p = MkListMem();
- p->name = mov_in(p3->name);
- p->next = NULL;
-
- if ( retval == NULL ) retval = p;
- else {
- p2 = retval;
- while ( p2->next != NULL )
- p2 = p2->next;
- p2->next = p;
- }
- p3 = p3->next;
- }
- free_list(p3);
- head = head->next;
- }
- return( retval );
- }
-
-
- free_list(ptr) /* kill a linked list */
- struct llist *ptr;
- {
- if ( ptr == NULL ) return;
- else if ( ptr->next == NULL ) free(ptr);
- else free_list(ptr->next);
- }
-