/* ;=======================================================================; ; ; ; ... ... ... ..... ... ... ... ; ; ............. ....... ... ... ... _______________________ ; ; .... ... ... ... ... ... ... ... ; ; ... ... ... ... ... ... ... MORRIS CODE WORKS ; ; ... ... ... ... ... ... ... ; ; ... ... ... ... ... ... ... SYSTEM SOFTWARE FILE ; ; ... ... ... ... ... ... ... ... _______________________ ; ; ... ... ... ....... ........... ; ; ... ... ... ..... .. .. ; ; ; ; ; ;=======================================================================; ; Copyright (c) 1985 by Morris Code Works ; ;=======================================================================; ; ; ; File: MAKEREAD.C ; ; ; ; Description: UNIX like 'make' command ; ; ; ; Create Date: 06 Aug 85 ; ; ; ;=======================================================================; ; ; ; Revision History ; ; ; ; When Who Description ; ; --------- --- ---------------------------------------------- ; ; 06 Aug 85 TGM Module created ; ; 27 Aug 85 TGM Released for use ; ; ; ;=======================================================================; */ #include #include #include "make.h" extern boolean silent; extern struct defnrec *defnlist; extern struct macdef *maclist; /********************************************************/ /* */ /* r e a d t h e m a k e f i l e */ /* */ /********************************************************/ readmakefile( s ) char *s; /* filename to read */ { FILE *fil; /* fp for input file */ boolean def; /* working on definition flag */ struct defs { /* files being defined */ struct defnrec *link; boolean cmdok; boolean spoken; } defp[32]; int defcnt; /* # definitions this line */ int i, j; /* working counters */ struct defnrec *defnp; /* ptr for definitions */ struct deprec *depp; /* ptr for dependencies */ struct howrec *howp; /* ptr for how-to lines */ struct macdef *macp; /* ptr for macros */ char info[INMAX]; /* scratch buffer space */ char *pos, *l; /* ptrs to input line */ char *defs; /* ptr to definitions */ char *deps, *dp; /* ptrs for dependencies */ unsigned long FileTime();/* get last update time of file */ char *ListTime(); /* convert long to ASCII time */ char ws[30]; /* string for date/time */ char *expand(); /* expand macros */ char *readline(); /* read logical line */ char tolower(); /* convert character to lower case */ void chain(); /* chain struct to end */ /* try to open specified file */ if( (fil = fopen( s, "r" )) == 0 ) { fprintf( stderr, "make: unable to open %s.\n", s ); return( FALSE ); } /* process the file */ def = FALSE; while( (l = pos = readline( fil )) != NULL ) { /* check for imbedded commands */ if( !strncmp( pos, ".SILENT", 7 ) ) { silent = TRUE; continue; } /* check for definitions and macros */ switch( linetype( pos, &defs ) ) { case COMMENT: break; /* ignore comments */ case MACRO: def = FALSE; /* a macro definition */ sscanf( pos, "%s", info ); /* strip out macro name */ /* look for pre-existing definitions */ for( macp = maclist; macp; macp = macp->next ) { if( !strcmp( macp->name, info ) ) /* found a match */ break; } /* use NEW definition if not defined */ if( !macp ) { /* add new struct to the end of maclist */ chain( &maclist, macp = (struct macdef *) getmem( sizeof( struct macdef ) ) ); /* initialize it */ strcpy( macp->name = (char *) getmem( strlen( info ) + 1 ), info ); } else /* release OLD text */ free( macp->mactext ); /* copy in macro definition */ for( ++defs; isspace(*defs); ++defs ); /* bypass leading blanks */ strcpy( macp->mactext = (char *) getmem( strlen( defs ) + 1 ), defs ); break; case DEFINE: def = TRUE; /* start of new def */ defcnt = 0; /* no definitions yet */ pos = expand( l, "", "" ); /* expand any definition macros */ strcpy( defs = getmem( strlen( pos ) + 1 ), pos ); (void) linetype( l, &deps ); /* where dependencies start */ for( ; ; ) { /* do while definitions are left */ for( ; ; ) { /* place definition into info */ while( isspace( *defs ) ) ++defs; for( i = 0; !isspace( *defs ); ) info[i++] = tolower( *defs++ ); info[i] = '\0'; break; } if( !strcmp( info, ":" ) ) /* no more definitions */ break; /* look for pre-existing definitions */ for( defnp = defnlist; defnp; defnp = defnp->next ) { if( !strcmp( defnp->name, info ) ) /* found a match */ break; } /* create a NEW definition record */ if( !defnp ) { /* add a new struct to the end of defnlist */ chain( &defnlist, defnp = (struct defnrec *) getmem( sizeof( struct defnrec ) ) ); /* initialize it */ strcpy( defnp->name = (char *) getmem( strlen( info ) + 1 ), info ); defnp->uptodate = FALSE; /* actually unknown */ defnp->modified = FileTime( defnp->name ); } /* keep track of definitions */ if( !defnp->howto ) defp[defcnt].cmdok = TRUE; else defp[defcnt].cmdok = FALSE; defp[defcnt].spoken = FALSE; defp[defcnt++].link = defnp; /* now go thru all of it's dependencies */ for( dp = expand( deps+1, defnp->name, "" ); ; ) { while( isspace( *dp ) ) ++dp; if( *dp == '\0' ) break; for( i = 0; !isspace( *dp ) && (*dp != '\0'); ) info[i++] = tolower( *dp++ ); info[i] = '\0'; /* add new struct to the end of deplist */ chain( &defnp->dependson, depp = (struct deprec *) getmem(sizeof(struct deprec)) ); strcpy( depp->name = (char *) getmem( strlen( info ) + 1 ), info ); } } /* release working strings */ (void) free( defs ); break; case HOWTO: /* a how to line */ if( !def ) { fprintf( stderr, "make: howto line w/o definition.\n" ); fprintf( stderr, "\t%s\n", pos ); break; /* bail out */ } /* now allocate space for the command/args line */ while( isspace( *pos ) ) ++pos; /* if there is something there, allocate mem and copy */ if( strlen( pos ) ) { /* add new struct to the end of howlist */ for( i = 0; i < defcnt; ++i ) { if( !defp[i].cmdok && !defp[i].spoken ) { fprintf( stderr, "too many command lines for %s\n", defp[i].link->name ); defp[i].spoken = TRUE; } else chain( &defp[i].link->howto, howp = (struct howrec *) getmem(sizeof(struct howrec)) ); /* copy command line */ strcpy( howp->howcom = (char *) getmem( strlen( pos ) + 1 ), pos ); } } break; case UNKNOWN: default: /* unrecognized line */ fprintf( stderr, "make: unrecognized line.\n\t%.60s\n", pos ); break; } /* release this line... */ (void) free( l ); } return( TRUE ); } /********************************************************/ /* */ /* e x p a n d m a c r o s o n l i n e */ /* */ /********************************************************/ char *expand( str, name, mod ) char *str; /* string to expand */ char *name; /* name we're making */ char *mod; /* names that caused make */ { static char cmdp[256]; /* expanded command line */ char *c, *c1, *c2; /* working buffer pointers */ char *mp, mac[32]; /* macroo expansion ptr, buffer */ char *index(); /* locate character function */ struct macdef *macp; /* working macro struct ptr */ /* see if any expansion needed */ if( !index( str, '$' ) ) { /* just return the passed string */ strcpy( cmdp, str ); return( cmdp ); } /* let's get the show on the road */ c1 = cmdp; c2 = str; /* while there is any data left... */ while( *c2 ) { if( *c2 != '$' ) *c1++ = *c2++; else { /* assume there is no true macro definition */ mac[0] = NULL; /* decode the character following the '$' */ switch( *++c2 ) { case '$': /* $$ = just a dollar sign */ *c1++ = '$'; break; case '@': /* $@ = copy 'make' name */ for( c = name; *c; ) *c1++ = *c++; break; case '*': /* $* = copy 'make' name prefix */ for( c = name; *c && *c != '.'; ) *c1++ = *c++; break; case '?': /* $? = copy the cause of the make */ for( c = mod; *c; ) *c1++ = *c++; break; case '(': /* $(xx) = a long macro definition */ for( mp = mac; *++c2 != ')'; *mp++ = *c2 ) ; /* copy the macro name (up to ')') */ *mp = NULL; /* terminate macro name */ break; default: /* $ = a short macro definition */ mac[0] = *c2; /* move in the macro definition */ mac[1] = NULL; /* terminate the string */ break; } /* bypass the character which caused the termination */ ++c2; /* expand macro if one has been defined */ if( strlen( mac ) ) { /* look for matching macro definition */ macp = maclist; while( macp ) { /* look for matching string name */ if( !strcmp( macp->name, mac ) ) { mp = macp->mactext; /* copy in macro definition */ while( *mp ) *c1++ = *mp++; break; } macp = macp->next; } } } } /* terminate the EXPANDED string */ *c1 = NULL; return( cmdp ); } /********************************************************/ /* */ /* r e a d l o g i c a l i n p u t l i n e */ /* */ /********************************************************/ char *readline( fp ) FILE *fp; /* input file pointer */ { char *fgets(); /* read input from file */ char *p; /* working string pointer */ char inbuff[INMAX]; /* working input buffer */ boolean readmore; /* continuation char found */ /* initialize buffer ptr */ p = NULL; /* read logical lines */ do { /* get a single physical line */ if( fgets( inbuff, sizeof( inbuff ), fp ) != NULL ) { /* get rid of trailing newline */ inbuff[ strlen( inbuff ) - 1] = NULL; /* see if more data to read */ if( inbuff[ strlen( inbuff ) - 1] != '\\' ) readmore = FALSE; else { inbuff[ strlen( inbuff ) - 1] = NULL; readmore = TRUE; } /* check for first data read */ if( p == NULL ) { /* create NEW string */ p = getmem( strlen( inbuff ) + 1 ); *p = NULL; } else /* create room for combined strings */ if( (p = realloc( p, strlen( p ) + strlen( inbuff ) + 1 )) == NULL ) OutOfMem(); } else /* no more data, return what we have */ return( p ); /* append new data to existing data */ strcat( p, inbuff ); } while( readmore ); /* return pointer to logical input line */ return( p ); } /********************************************************/ /* */ /* r e t u r n t y p e o f i n p u t */ /* */ /********************************************************/ linetype( cp, sep ) char *cp; /* ptr to input buffer */ char **sep; /* location of line sep. */ { char *colon, *equals; /* working ptrs */ char *index(); /* decode buffer type... simple rules */ if( *cp == NULL || *cp == '#' ) return( COMMENT ); else if( *cp == '\t' ) return( HOWTO ); else if( isspace( *cp ) ) return( UNKNOWN ); for( equals = cp; ; ++equals ) { if( equals = index( equals, '=' ) ) { if( (isspace( *(equals+1) ) || *(equals+1) == '\0') && isspace( *(equals-1) ) ) break; } else { equals = cp + strlen( cp ); break; } } for( colon = cp; ; ++colon ) { if( colon = index( colon, ':' ) ) { if( (isspace( *(colon+1) ) || *(colon+1) == '\0') && isspace( *(colon-1) ) ) break; } else { colon = cp + strlen( cp ); break; } } if( colon < equals ) { *sep = colon; return( DEFINE ); } if( equals < colon ) { *sep = equals; return( MACRO ); } return( UNKNOWN ); } /********************************************************/ /* */ /* l o n g c o m p a r i s o n */ /* */ /********************************************************/ unsigned long max( a, b ) unsigned long a, b; { return( a > b ? a : b ); Š}