home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-07-26 | 39.2 KB | 1,310 lines |
- Newsgroups: comp.sources.misc
- subject: v14i025: dmake version 3.5 part 15/21
- From: dvadura@watdragon.waterloo.edu (Dennis Vadura)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 14, Issue 25
- Submitted-by: dvadura@watdragon.waterloo.edu (Dennis Vadura)
- Archive-name: dmake/part15
-
- #!/bin/sh
- # this is part 15 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file make.c continued
- #
- CurArch=15
- if test ! -r s2_seq_.tmp
- then echo "Please unpack part 1 first!"
- exit 1; fi
- ( read Scheck
- if test "$Scheck" != $CurArch
- then echo "Please unpack part $Scheck next!"
- exit 1;
- else exit 0; fi
- ) < s2_seq_.tmp || exit 1
- echo "x - Continuing file make.c"
- sed 's/^X//' << 'SHAR_EOF' >> make.c
- X * that fact for all of the prerequisites that we will be making. */
- X
- X cp->ce_setdir = setdirroot;
- X
- X if( cp->ce_attr & A_SETDIR ) {
- X /* Change directory only if the previous .SETDIR is a different
- X /* directory from the current one. ie. all cells with the same .SETDIR
- X /* attribute are assumed to come from the same directory. */
- X
- X if( (setdirroot == NIL(CELL) || setdirroot->ce_dir != cp->ce_dir) &&
- X (push = Push_dir(cp, (cp->ce_attr | Glob_attr) & A_IGNORE)))
- X setdirroot = cp;
- X }
- X
- X DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
- X if( (how->hw_recipe == NIL(STRING) && !(how->hw_flag & F_INFER)) ) {
- X HOWPTR thp;
- X
- X if( Verbose )
- X printf( "%s: Infering prerequisite(s) and recipe for [%s]\n", Pname,
- X cp->CE_NAME );
- X
- X thp = how->hw_next;
- X (void) Infer_recipe( cp, how, NIL(DFASET), setdirroot );
- X
- X /* If we inferred a new set of prerequisites then make
- X * them before the current list represented by the current how pointer */
- X if( thp != how->hw_next )
- X if( (rval = Make(cp, how->hw_next, cp->ce_setdir)) == -1 ||
- X !(how->hw_next->hw_flag & F_MADE) )
- X goto stop_making_it;
- X }
- X
- X DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
- X /* If we have not yet statted the target then do so. */
- X if( !(cp->ce_flag & F_STAT) ) {
- X time_t itime = cp->ce_time;
- X Stat_target( cp, TRUE );
- X
- X if( cp->ce_time == (time_t)0L ) {
- X if( cp->ce_flag & F_INFER )
- X cp->ce_time = itime;
- X }
- X else
- X cp->ce_attr |= A_PRECIOUS; /* File exists so don't remove it later. */
- X
- X if( Verbose )
- X printf("%s: Time stamp of [%s] is %ld\n",Pname,cp->CE_NAME,
- X cp->ce_time);
- X }
- X
- X DB_PRINT( "make", ("(%s, %ld, 0x%04x, 0x%04x)", cp->CE_NAME,
- X cp->ce_time, cp->ce_attr, cp->ce_flag) );
- X
- X if( !(cp->ce_flag & F_TARGET) && (cp->ce_time == (time_t) 0L) )
- X if( Makemkf )
- X DB_RETURN( -1 );
- X else
- X Fatal( "`%s' not found, and can't be made", cp->CE_NAME );
- X
- X DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
- X
- X /* set value of $* if we have not infered a recipe, in this case $* is
- X * the same as $(@:db), this allows us to be compatible with BSD make */
- X if( how->hw_per == NIL(char) ) how->hw_per = "$(@:db)";
- X
- X for( dp = how->hw_prq; dp != NIL(LINK); dp = dp->cl_next ) {
- X int seq;
- X
- X /* Make the prerequisite, note that if the current target has the
- X * .LIBRARY attribute set we pass on to the prerequisite the .LIBRARYM
- X * attribute and pass on the name of the current target as the library
- X * name, and we take it away when we are done. */
- X
- X tcp = dp->cl_prq;
- X seq = (cp->ce_attr | how->hw_attr | Glob_attr) & A_SEQ;
- X
- X if( (tcp->ce_flag & F_VISITED) && !(tcp->ce_flag & F_MADE) )
- X goto stop_making_it;
- X else if( tcp->ce_flag & F_MADE )
- X continue;
- X
- X if( strchr(tcp->CE_NAME, '$') ) {
- X /* Make this prerequisite link point at the real prerequisite we
- X * are after, ie figure out what the dynamic one is and point at it. */
- X
- X m_at = Def_macro( "@", cp->ce_fname, M_MULTI );
- X name = Expand( tcp->CE_NAME );
- X
- X tcp = dp->cl_prq = Def_cell( name, setdirroot );
- X FREE( name );
- X }
- X
- X if( cp->ce_attr & A_LIBRARY ) {
- X tcp->ce_attr |= A_LIBRARYM;
- X tcp->ce_lib = cp->ce_fname;
- X }
- X
- X if( (tcp->ce_flag & (F_INFER | F_STAT)) == F_INFER )
- X tcp->ce_time = cp->ce_time;
- X
- X /* Propagate parents F_REMOVE and F_INFER attribute to children.
- X * Make certain you do this AFTER propagating the time, since the
- X * time propagation test above uses the F_INFER flag to decide if
- X * it should do so. */
- X tcp->ce_flag |= cp->ce_flag & (F_REMOVE|F_INFER);
- X
- X rval |= Make(tcp, tcp->CE_HOW, setdirroot);
- X
- X if( cp->ce_attr & A_LIBRARY )
- X tcp->ce_attr ^= A_LIBRARYM;
- X
- X if( rval == -1 )
- X goto stop_making_it;
- X else if( seq && (rval == 1) )
- X goto stop_making_it;
- X }
- X
- X /* Do the loop again. We are most definitely going to make the current
- X * how cell now. NOTE: doing this loop here also results in a reduction
- X * in peak memory usage by the algorithm. */
- X
- X for( dp = how->hw_prq; dp != NIL(LINK); dp = dp->cl_next ) {
- X char *dir;
- X int tgflg;
- X tcp = dp->cl_prq;
- X name = tcp->ce_fname;
- X
- X /* make certain that all prerequisites are made prior to advancing. */
- X if( !(tcp->ce_flag & F_MADE) ) goto stop_making_it;
- X
- X /* If the target is a library, then check to make certain that a member
- X * is newer than an object file sitting on disk. If the disk version
- X * is newer then set the time stamps so that the archived member is
- X * replaced. */
- X if( cp->ce_attr & A_LIBRARY )
- X if( tcp->ce_time < cp->ce_time ) {
- X time_t mtime = Do_stat( tcp->ce_fname, tcp->ce_lib, NIL(char *) );
- X if( mtime < tcp->ce_time ) tcp->ce_time = cp->ce_time+1L;
- X }
- X
- X if( tcp->ce_time > otime ) otime = tcp->ce_time;
- X
- X /* Note: If the prerequisite was made using a SETDIR
- X * directory then we will include the directory in the name
- X * of the prerequisite when we build the $?, $&, $^ and $< lists
- X */
- X
- X if( (dir = tcp->ce_dir ) != NIL(char) )
- X name = Build_path( dir, name );
- X
- X all = _strapp( all, name );
- X if( tgflg = (dp->cl_flag & F_TARGET) ) inf = _strapp( inf, name );
- X
- X if((cp->ce_time<tcp->ce_time) || ((tcp->ce_flag & F_TARGET) && Force)) {
- X outall = _strapp( outall, name );
- X if( tgflg ) imm = _strapp( imm, name );
- X }
- X }
- X
- X DB_PRINT( "mem", ("%s:-C mem %ld", cp->CE_NAME, (long) coreleft()) );
- X DB_PRINT( "make", ("I make '%s' if %ld > %ld", cp->CE_NAME, otime,
- X cp->ce_time) );
- X
- X /* mark the how cell as visited since we are making it for certain now. */
- X how->hw_flag |= F_VISITED;
- X if( Verbose ) printf( "%s: >>>> Making [%s]\n", Pname, cp->CE_NAME );
- X
- X if( Check && (cp->ce_time < otime) ) {
- X /* Only checking so stop as soon as we determine we will make something */
- X rval = -1;
- X goto stop_making_it;
- X }
- X
- X if( (cp->ce_time < otime) || ((cp->ce_flag & F_TARGET) && Force) ) {
- X if( Verbose )
- X printf( "%s: Updating [%s], (%ld > %ld)\n", Pname,
- X cp->CE_NAME, otime, cp->ce_time );
- X
- X cp->ce_attr |= A_UPDATED;
- X
- X if( Touch ) {
- X name = cp->ce_fname;
- X lib = cp->ce_lib;
- X
- X if( !(Glob_attr & A_SILENT) || !Trace )
- X if( lib == NIL(char) )
- X printf("touch(%s)", name );
- X else if( cp->ce_attr & A_SYMBOL )
- X printf("touch(%s((%s)))", lib, name );
- X else
- X printf("touch(%s(%s))", lib, name );
- X
- X if( !Trace )
- X if( Do_touch( name, lib,
- X (cp->ce_attr & A_SYMBOL) ? &name : NIL(char *) ) != 0 )
- X printf( " not touched - non-existant" );
- X
- X printf( "\n" );
- X Update_time_stamp( cp, how );
- X }
- X else if( how->hw_recipe != NIL(STRING) ) {
- X HASHPTR m_q, m_b, m_g, m_l, m_bb, m_up;
- X TKSTR tk;
- X
- X m_at = Def_macro( "@", cp->ce_fname,M_MULTI );
- X m_g = Def_macro( ">", cp->ce_lib, M_MULTI );
- X m_q = Def_macro( "?", outall, M_MULTI );
- X m_b = Def_macro( "<", inf, M_MULTI );
- X m_l = Def_macro( "&", all, M_MULTI );
- X m_bb = Def_macro( "*", how->hw_per, M_MULTI );
- X m_up = Def_macro( "^", imm, M_MULTI );
- X
- X _recipes[ RP_RECIPE ] = how->hw_recipe;
- X
- X if( !(how->hw_flag & F_SINGLE) )
- X rval = _exec_commands( cp, how );
- X else {
- X _drop_mac( m_q );
- X SET_TOKEN( &tk, outall );
- X
- X Doing_bang = TRUE;
- X name = Get_token( &tk, "", FALSE );
- X do {
- X m_q->ht_value = name;
- X
- X Wait_for_completion = TRUE; /* Reset in _exec_commands */
- X rval = _exec_commands( cp, how );
- X Unlink_temp_files(how);
- X }
- X while( *(name = Get_token( &tk, "", FALSE )) != '\0' );
- X Doing_bang = FALSE;
- X Update_time_stamp( cp, how );
- X
- X m_q->ht_value = NIL(char);
- X }
- X
- X _drop_mac( m_g );
- X _drop_mac( m_q );
- X _drop_mac( m_b );
- X _drop_mac( m_l );
- X _drop_mac( m_bb );
- X _drop_mac( m_up );
- X }
- X else if( !(cp->ce_flag & F_RULES) &&
- X ((cp != Root) || !(cp->ce_flag & F_EXPLICIT)) )
- X Fatal( "Don't know how to make `%s'",cp->CE_NAME );
- X else {
- X /* Empty recipe, set the how flag as MADE and update the time stamp */
- X Update_time_stamp( cp, how );
- X }
- X }
- X else {
- X /* Make sure everyone gets remade if Force is set */
- X if( !(cp->ce_flag & F_TARGET) && Force ) cp->ce_time = Do_time();
- X
- X /* Set how to MADE since it is done, it was not out of date */
- X how->hw_flag |= F_MADE;
- X if( cp->CE_HOW == how ) {
- X tcp = cp;
- X do {
- X tcp->ce_flag |= F_MADE;
- X tcp = tcp->ce_all;
- X }
- X while( tcp != NIL(CELL) && tcp != cp );
- X }
- X }
- X
- X if( cp->CE_HOW == how ) cp->ce_flag |= F_VISITED;
- X
- Xstop_making_it:
- X if( m_at != NIL(HASH) ) _drop_mac( m_at );
- X
- X if( push ) Pop_dir(FALSE);
- X
- X if( inf != NIL(char) ) FREE( inf );
- X if( all != NIL(char) ) FREE( all );
- X if( imm != NIL(char) ) FREE( imm );
- X if( outall != NIL(char) ) FREE( outall );
- X
- X DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
- X DB_RETURN( rval );
- X}
- X
- X
- X
- Xstatic void
- X_drop_mac( hp )/*
- X================ set a macro value to zero. */
- XHASHPTR hp;
- X{
- X if( hp->ht_value != NIL(char) ) {
- X FREE( hp->ht_value );
- X hp->ht_value = NIL(char);
- X }
- X}
- X
- X
- X
- Xstatic int
- X_exec_commands( cp, how )/*
- X===========================
- X Execute the commands one at a time that are pointed to by the rules pointer
- X of the target cp. If a group is indicated, then the hw_attr determines
- X .IGNORE and .SILENT treatment for the group.
- X
- X The function returns 0, if the command is executed and has successfully
- X returned, and returns 1 if the command is executing but has not yet
- X returned (for parallel makes).
- X
- X The F_MADE bit in the how cell is guaranteed set when the command has
- X successfully completed. */
- XCELLPTR cp;
- XHOWPTR how;
- X{
- X register STRINGPTR rp;
- X char *cmnd;
- X char *groupfile;
- X char *ap;
- X char *hold = NIL(char);
- X FILE *tmpfile;
- X FILE *here_doc = NIL(FILE);
- X int do_it;
- X int attr;
- X int group;
- X int trace;
- X int rval = 0;
- X
- X DB_ENTER( "_exec_commands" );
- X
- X Current_target = how;
- X attr = Glob_attr | cp->ce_attr;
- X trace = Trace || !(attr & A_SILENT);
- X group = how->hw_flag & F_GROUP;
- X
- X if( group ) {
- X attr |= how->hw_attr;
- X trace = Trace || !(attr & A_SILENT);
- X
- X if( !Trace ) tmpfile = Start_temp( Grp_suff, cp, how, &groupfile );
- X if( trace ) fputs( "[\n", stdout );
- X
- X /* Emit group prolog */
- X if( attr & A_PROLOG )
- X _append_file( _recipes[RP_GPPROLOG], tmpfile, cp->CE_NAME, trace );
- X }
- X
- X
- X /* Process commands in recipe. If in group, merely append to file.
- X * Otherwise, run them. If a text diversion indicated, expand
- X * that document as required into a temporary file */
- X
- X for( rp = _recipes[RP_RECIPE]; rp != NIL(STRING); rp=rp->st_next,FREE(cmnd)){
- X char *savecmnd;
- X int done = 0;
- X
- X do_it = !Trace;
- X
- X if( !group && Trace && _strstr(rp->st_string,"$(MAKE)") ) {
- X Wait_for_completion |= Trace;
- X do_it = TRUE;
- X }
- X
- X savecmnd = cmnd = Expand( rp->st_string );
- X
- X/******* TEXT DIVERSION PROCESSING START ********/
- X /* Look for a text diversion surrounded by <+ and +>. Note that the
- X * diversion may be on a single line or span multiple lines. Note that
- X * if a diversion is started with <+ and never finished with +> an error
- X * is issued. */
- X
- X /* Check for the start of a new diversion */
- X do {
- X if( here_doc == NIL(FILE) && (ap = _strstr(cmnd, "<+")) != NIL(char)) {
- X char *t;
- X char *fname;
- X here_doc = Start_temp( "", cp, how, &fname );
- X *ap = '\0';
- X hold = _strjoin( hold, t = _strjoin(cmnd,fname,-1,FALSE),-1,TRUE);
- X FREE(t);
- X cmnd = ap+2;
- X }
- X
- X if( here_doc != NIL(FILE) ) {
- X if( (ap = _strstr(cmnd, "+>")) == NIL(char) ) {
- X _add_here(cmnd, here_doc, TRUE);
- X done = TRUE;
- X }
- X else {
- X *ap = '\0';
- X if( *_strspn(cmnd, " \t") != '\0' )
- X _add_here(cmnd, here_doc, FALSE);
- X
- X cmnd = ap+2;
- X Close_temp( how, here_doc );
- X here_doc = NIL(FILE);
- X }
- X }
- X else if( hold != NIL(char) ) {
- X cmnd = _strjoin( hold, cmnd, -1, TRUE );
- X done = TRUE;
- X hold = NIL(char);
- X FREE( savecmnd );
- X }
- X else
- X done = TRUE;
- X }
- X while( *cmnd && !done );
- X
- X if( here_doc != NIL(FILE) ) continue;
- X if( hold != NIL(char) ) {
- X FREE(savecmnd);
- X cmnd = hold;
- X }
- X/******* TEXT DIVERSION PROCESSING END ********/
- X
- X
- X if( group )
- X _append_line( cmnd, TRUE, tmpfile, cp->CE_NAME, trace );
- X else {
- X if( *_strspn(cmnd, " \t") != '\0' )
- X _print_cmnd(cmnd, !(do_it && ((rp->st_attr | attr) & A_SILENT)), 0);
- X else
- X do_it = FALSE;
- X
- X rval=Do_cmnd(cmnd,FALSE,do_it,cp,how,((attr|rp->st_attr)&A_IGNORE),
- X rp->st_next == NIL(STRING) );
- X }
- X }
- X
- X if( here_doc != NIL(FILE) )
- X Fatal( "Unterminated text diversion while making `%s'", cp->CE_NAME );
- X
- X /* If it is a group then output the EPILOG if required and possibly
- X * execute the command */
- X if( group ) {
- X if( attr & A_EPILOG ) /* emit epilog */
- X _append_file( _recipes[RP_GPEPILOG], tmpfile, cp->CE_NAME, trace );
- X
- X if( trace ) fputs("]\n", stdout);
- X
- X if( do_it = !Trace ) Close_temp( how, tmpfile );
- X rval = Do_cmnd(groupfile, TRUE, do_it, cp, how, attr & A_IGNORE, TRUE);
- X }
- X
- X Wait_for_completion = FALSE;
- X DB_RETURN( rval );
- X}
- X
- X
- X
- Xstatic void
- X_print_cmnd( cmnd, echo, map )/*
- X================================
- X This routine is called to print out the command to stdout. If echo is
- X false the printing to stdout is supressed, but the new lines in the command
- X are still deleted. */
- Xchar *cmnd;
- Xint echo;
- Xint map;
- X{
- X register char *p;
- X register char *n;
- X
- X DB_ENTER( "_print_cmnd" );
- X
- X if( echo ) printf( "%s\n", cmnd );
- X
- X for( p=cmnd; (n = strchr(p, CONTINUATION_CHAR)) != NIL(char); p=n+1 )
- X if(n[1] == '\n') {
- X DB_PRINT( "make", ("fixing [%s]", p) );
- X strcpy( n, n+2 );
- X }
- X else if( map )
- X Map_esc( n );
- X
- X DB_VOID_RETURN;
- X}
- X
- X
- X
- X/* These routines are used to maintain a stack of directories when making
- X * the targets. If a target cd's to the directory then it is assumed that
- X * it will undo it when it is finished making itself. */
- X
- Xstatic STRINGPTR dir_stack = NIL(STRING);
- X
- Xint
- XPush_dir( cp, ignore )/*
- X==========================
- X Change the current working directory to dir and save the current
- X working directory on the stack so that we can come back.
- X
- X If ignore is TRUE then do not complain about _ch_dir if not possible.*/
- XCELLPTR cp;
- Xint ignore;
- X{
- X STRINGPTR new_dir;
- X char *dir;
- X
- X DB_ENTER( "Push_dir" );
- X
- X if( (dir = cp->ce_dir) == NIL(char) ) dir = Pwd;
- X if( *dir == '\'' && dir[strlen(dir)-1] == '\'' ) {
- X dir = _strdup(dir+1);
- X dir[strlen(dir)-1]='\0';
- X }
- X else
- X dir = Expand(dir);
- X
- X if( Set_dir(dir) ) {
- X if( !ignore )
- X Fatal( "Unable to change to directory `%s', target is [%s]",
- X dir, cp->CE_NAME );
- X FREE(dir);
- X DB_RETURN( 0 );
- X }
- X
- X DB_PRINT( "dir", ("Push: [%s]", dir) );
- X if( Verbose ) printf( "%s: Changed to directory [%s]\n", Pname, dir );
- X
- X FREE( dir );
- X TALLOC( new_dir, 1, STRING );
- X new_dir->st_next = dir_stack;
- X dir_stack = new_dir;
- X new_dir->st_string = _strdup( Pwd );
- X
- X Def_macro( "PWD", Get_current_dir(), M_MULTI | M_EXPANDED );
- X _set_tmd();
- X
- X DB_RETURN( 1 );
- X}
- X
- X
- X
- Xvoid
- XPop_dir(ignore)/*
- X=================
- X Change the current working directory to the previous saved dir. */
- Xint ignore;
- X{
- X STRINGPTR old_dir;
- X char *dir;
- X
- X DB_ENTER( "Pop_dir" );
- X
- X if( dir_stack == NIL(STRING) )
- X if( ignore ) {
- X DB_VOID_RETURN;
- X }
- X else
- X Error( "Directory stack empty for return from .SETDIR" );
- X
- X if( Set_dir(dir = dir_stack->st_string) )
- X Fatal( "Could not change to directory `%s'", dir );
- X
- X Def_macro( "PWD", dir, M_MULTI | M_EXPANDED );
- X DB_PRINT( "dir", ("Pop: [%s]", dir) );
- X if( Verbose ) printf( "%s: Changed back to directory [%s]\n", Pname, dir);
- X
- X old_dir = dir_stack;
- X dir_stack = dir_stack->st_next;
- X
- X FREE( old_dir->st_string );
- X FREE( old_dir );
- X _set_tmd();
- X
- X DB_VOID_RETURN;
- X}
- X
- X
- X
- Xstatic void
- X_set_tmd()/*
- X============
- X Set the TWD Macro */
- X{
- X TKSTR md, pd;
- X char *m, *p;
- X char *tmd;
- X int is_sep;
- X int first = 1;
- X
- X SET_TOKEN( &md, Makedir );
- X SET_TOKEN( &pd, Pwd );
- X
- X m = Get_token( &md, DirBrkStr, FALSE );
- X (void) Get_token( &pd, DirBrkStr, FALSE );
- X is_sep = (strchr(DirBrkStr, *m) != NIL(char));
- X tmd = _strdup( "" );
- X
- X do {
- X m = Get_token( &md, DirBrkStr, FALSE );
- X p = Get_token( &pd, DirBrkStr, FALSE );
- X
- X if( !is_sep && strcmp(m, p) ) { /* they differ */
- X char *tmp;
- X if( first ) { /* They differ in the first component */
- X tmd = Makedir; /* In this case use the full path */
- X break;
- X }
- X
- X if( *p ) tmp = Build_path( "..", tmd );
- X if( *m ) tmp = Build_path( tmd, m );
- X FREE( tmd );
- X tmd = _strdup( tmp );
- X }
- X
- X is_sep = 1-is_sep;
- X first = 0;
- X } while (*m || *p);
- X
- X CLEAR_TOKEN( &md );
- X CLEAR_TOKEN( &pd );
- X
- X Def_macro( "TMD", tmd, M_MULTI | M_EXPANDED );
- X if( tmd != Makedir ) FREE( tmd );
- X}
- X
- X
- Xstatic void
- X_set_recipe( target, ind )/*
- X============================
- X Set up the _recipes static variable so that the slot passed in points
- X at the rules corresponding to the target supplied. */
- Xchar *target;
- Xint ind;
- X{
- X CELLPTR cp;
- X HASHPTR hp;
- X
- X if( (hp = Get_name( target, Defs, FALSE, NIL(CELL) )) != NIL(HASH) ) {
- X cp = hp->CP_OWNR;
- X if( cp->CE_HOW != NIL(HOW) ) _recipes[ ind ] = cp->CE_RECIPE;
- X }
- X else
- X _recipes[ ind ] = NIL(STRING);
- X}
- X
- X
- X
- Xstatic void
- X_append_line( cmnd, newline, tmpfile, name, printit )
- Xchar *cmnd;
- Xint newline;
- XFILE *tmpfile;
- Xchar *name;
- Xint printit;
- X{
- X _print_cmnd( cmnd, printit, 0 );
- X
- X if( Trace ) return;
- X
- X fputs(cmnd, tmpfile);
- X if( newline ) fputc('\n', tmpfile);
- X fflush(tmpfile);
- X
- X if( ferror(tmpfile) )
- X Fatal("Write error on temporary group file, for target `%s'", name);
- X}
- X
- X
- X
- Xstatic void
- X_append_file( rp, tmpfile, name, printit )
- Xregister STRINGPTR rp;
- XFILE *tmpfile;
- Xchar *name;
- Xint printit;
- X{
- X char *cmnd;
- X
- X while( rp != NIL(STRING) ) {
- X _append_line(cmnd = Expand(rp->st_string), TRUE, tmpfile, name, printit);
- X FREE(cmnd);
- X rp = rp->st_next;
- X }
- X}
- X
- X
- X
- Xstatic void
- X_add_here( line, file, newline )
- Xchar *line;
- XFILE *file;
- Xint newline;
- X{
- X while( *line == '\t' ) /* skip initial tabs */
- X line++;
- X
- X _print_cmnd( line, FALSE, TRUE );
- X fputs(line, file);
- X if( newline ) fputc('\n', file);
- X fflush(file);
- X
- X if( ferror(file) )
- X Fatal("Write error on temporary file for text diversion");
- X}
- SHAR_EOF
- echo "File make.c is complete"
- chmod 0440 make.c || echo "restore of make.c fails"
- echo "x - extracting make.bat (Text)"
- sed 's/^X//' << 'SHAR_EOF' > make.bat &&
- Xecho off
- Xrem *** This is the make batchfile that is used under MSDOS to make the
- Xrem *** first version of dmake. It isn't pretty but it does work, assuming
- Xrem *** the compilers have been correctly setup. See the warning below
- Xrem *** concerning tlink, if you are making the Turbo C version.
- Xrem
- Xecho Running make.bat script to make a %1 copy of dmake.
- X
- Xif %0%1 == %0 goto error
- Xif %1 == mscdos goto makemsc
- Xif %1 == tccdos goto maketcc
- X
- Xrem label the possible DOS variations for dmake here.
- X:error
- Xecho ERROR: You must specify one of:
- Xecho tccdos - Turbo C 2.0, compile.
- Xecho mscdos - Microsoft C 4.0 or higher, compile.
- Xgoto end
- X
- Xrem This is the script that makes dmake using Microsoft C 4.0 or higher.
- X:makemsc
- Xmsdos\mscdos\make.bat
- Xgoto end
- X
- Xrem This is the script that makes dmake using Turbo C 2.0 or higher.
- X:maketcc
- Xcls
- Xecho WARNING:
- Xecho The default response files msdos\tccdos\tccobj.rsp
- Xecho and msdos\tccdos\tcclib.rsp contain absolute paths to TURBO-C
- Xecho runtime startup objects, and to the standard libraries. You should
- Xecho check that these files point to the right places before proceeding.
- Xecho --
- Xecho Continue if ok, or abort and edit the response files.
- Xpause
- Xmsdos\tccdos\make.bat
- X
- Xrem All done!
- X:end
- SHAR_EOF
- chmod 0440 make.bat || echo "restore of make.bat fails"
- echo "x - extracting macparse.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > macparse.c &&
- X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/macparse.c,v 1.1 90/07/19 13:53:20 dvadura Exp $
- X-- SYNOPSIS -- parse a macro definition
- X--
- X-- DESCRIPTION
- X-- This file contains the code that parses a macro definition
- X-- stored in a buffer. If the string in buffer is not a valid
- X-- macro definition the routie Parse_macro returns 0, otherwise it
- X-- returns 1 to indicate success.
- X--
- X-- AUTHOR
- X-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
- X-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
- X--
- X-- COPYRIGHT
- X-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
- X--
- X-- This program is free software; you can redistribute it and/or
- X-- modify it under the terms of the GNU General Public License
- X-- (version 1), as published by the Free Software Foundation, and
- X-- found in the file 'LICENSE' included with this distribution.
- X--
- X-- This program is distributed in the hope that it will be useful,
- X-- but WITHOUT ANY WARRANTY; without even the implied warrant of
- X-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X-- GNU General Public License for more details.
- X--
- X-- You should have received a copy of the GNU General Public License
- X-- along with this program; if not, write to the Free Software
- X-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X--
- X-- LOG
- X-- $Log: macparse.c,v $
- X * Revision 1.1 90/07/19 13:53:20 dvadura
- X * Initial Revision of Version 3.5
- X *
- X*/
- X
- X#include <ctype.h>
- X#include "extern.h"
- X#include "alloc.h"
- X#include "db.h"
- X
- Xint
- XParse_macro( buffer, flag )/*
- X=============================
- X Parse the string in buffer and define it as a macro if it is a valid macro.
- X Note especially the string .SETDIR= since it is an attribute, but looks a
- X lot like a macro definition. This would not be a problem if make used
- X white space as token separators, since this is not the case we must do
- X something about it. */
- Xchar *buffer;
- Xint flag;
- X{
- X register char *tok1; /* temporary place to keep a token */
- X register char *tok2; /* temporary place to keep a token */
- X char *result; /* temporary pointer for strings */
- X TKSTR input; /* place to scan the buffer from */
- X HASHPTR hv; /* pointer to hash table value */
- X int operator; /* what macro operator do we have */
- X
- X DB_ENTER( "Parse_macro" );
- X
- X SET_TOKEN( &input, buffer );
- X tok1 = Get_token( &input, "=+:", FALSE );
- X
- X if( Macro_op( tok1 ) ) {
- X Error( "No macro name" );
- X CLEAR_TOKEN( &input );
- X DB_RETURN( 1 );
- X }
- X
- X tok1 = _strdup( tok1 );
- X tok2 = Get_token( &input, "=+:", FALSE );
- X if( !(operator = Macro_op( tok2 )) || !strcmp( tok1, ".SETDIR") )
- X {
- X CLEAR_TOKEN( &input );
- X FREE( tok1 );
- X DB_RETURN( 0 );
- X }
- X
- X tok2 = Expand(tok1); FREE(tok1); tok1 = tok2;
- X tok2 = Get_token( &input, NIL( char ), FALSE );
- X
- X switch( operator ) {
- X case M_OP_PLCL:
- X tok2 = Expand( tok2 );
- X
- X case M_OP_PL:
- X /* Add to an existing macro, if it is not defined, though, then
- X * fall through and define a new macro */
- X
- X if( (hv = GET_MACRO(tok1)) != NIL(HASH) ) {
- X if( hv->ht_value != NIL(char) ) {
- X result = _stradd( hv->ht_value, tok2, FALSE );
- X Def_macro( tok1, result, flag );
- X FREE( result );
- X }
- X else
- X Def_macro( tok1, tok2, flag );
- X
- X if( operator == M_OP_PLCL ) FREE(tok2);
- X break;
- X }
- X /*FALLTRHOUGH*/
- X
- X case M_OP_EQ:
- X Def_macro( tok1, tok2, flag );
- X if( operator == M_OP_PLCL ) FREE(tok2);
- X break;
- X
- X case M_OP_CL:
- X /* If the macro we are assigning from is a single control
- X * macro with nothing else, then we propagate the M_MULTI
- X * flag to the macro we are assigning the value to so that
- X * the same macro can be used to do this over and over. */
- X If_multi = 0;
- X tok2 = Expand( tok2 );
- X Def_macro( tok1, tok2, M_EXPANDED | flag | If_multi );
- X FREE( tok2 );
- X break;
- X }
- X
- X FREE( tok1 );
- X
- X DB_RETURN( 1 );
- X}
- X
- X
- X
- Xint
- XMacro_op( op )/*
- X================
- X Check the passed in op string and map it to one of the macro operators */
- Xchar *op;
- X{
- X int ret = 0;
- X
- X DB_ENTER( "macro_op" );
- X
- X switch( *op ) {
- X case '=': ret = M_OP_EQ; break;
- X case ':': ret = M_OP_CL; op++; break;
- X
- X case '+':
- X if( *op == '+' ) { ret = M_OP_PL; op++; }
- X if( *op == ':' ) { ret = M_OP_PLCL; op++; }
- X break;
- X }
- X
- X if( *op++ != '=' )
- X ret = 0;
- X else if( *op != '\0' )
- X ret = 0;
- X
- X DB_RETURN( ret );
- X}
- X
- SHAR_EOF
- chmod 0440 macparse.c || echo "restore of macparse.c fails"
- echo "x - extracting infer.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > infer.c &&
- X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/infer.c,v 1.1 90/07/21 11:06:32 dvadura Exp $
- X-- SYNOPSIS -- infer how to make a target.
- X--
- X-- DESCRIPTION
- X-- This file contains the code to infer a recipe, and possibly some new
- X-- prerequisites for a target which dmake does not know how to make, or
- X-- has no explicit recipe.
- X--
- X-- The inference fails if no path through the inference graph can be
- X-- found by which we can make the target.
- X--
- X-- AUTHOR
- X-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca
- X-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada
- X--
- X-- COPYRIGHT
- X-- Copyright (c) 1990 by Dennis Vadura. All rights reserved.
- X--
- X-- This program is free software; you can redistribute it and/or
- X-- modify it under the terms of the GNU General Public License
- X-- (version 1), as published by the Free Software Foundation, and
- X-- found in the file 'LICENSE' included with this distribution.
- X--
- X-- This program is distributed in the hope that it will be useful,
- X-- but WITHOUT ANY WARRANTY; without even the implied warrant of
- X-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X-- GNU General Public License for more details.
- X--
- X-- You should have received a copy of the GNU General Public License
- X-- along with this program; if not, write to the Free Software
- X-- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X--
- X-- LOG
- X-- $Log: infer.c,v $
- X * Revision 1.1 90/07/21 11:06:32 dvadura
- X * Initial Revision Version 3.5
- X *
- X*/
- X
- X#include "extern.h"
- X#include "alloc.h"
- X#include "db.h"
- X
- X/* attributes that get transfered from the % start cell to the inferred
- X * cells. */
- X
- X#define A_TRANSFER (A_EPILOG | A_PRECIOUS | A_SILENT |\
- X A_LIBRARY | A_IGNORE | A_PROLOG)
- X
- X/* Define local static functions */
- Xstatic DFALINKPTR _dfa_subset ANSI((DFALINKPTR, DFASETPTR));
- Xstatic void _free_dfas ANSI((DFALINKPTR));
- Xstatic int _count_dots ANSI((char *));
- Xstatic char * _build_name ANSI((char *, char *, char *));
- X
- Xstatic int _prep = -1; /* Integer value of Prep variable */
- Xstatic int _dmax;
- X
- XCELLPTR
- XInfer_recipe( cp, how, dfa_stack, setdirroot )/*
- X================================================
- X Infer a set of rules for making a target. We know we have a HOW
- X cell attached, but it's prerequisite list may be NIL as is its
- X recipe! A NIL recipe is a prerequisite for calling this routine. */
- XCELLPTR cp;
- XHOWPTR how;
- XDFASETPTR dfa_stack;
- XCELLPTR setdirroot;
- X{
- X DFALINKPTR pdfa;
- X DFALINKPTR dfas;
- X CELLPTR infcell;
- X CELLPTR meta;
- X DFASET top_dfa_stack;
- X EDGEPTR pedge;
- X
- X DB_ENTER( "Infer_recipe" );
- X DB_PRINT( "inf", (">>> Infer for target [%s]", cp->CE_NAME) );
- X DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long)coreleft()));
- X
- X /* If no further transitive closure on this cell then don't perform
- X * any more inferences */
- X if( cp->ce_attr & A_NOINFER ) DB_RETURN(NIL(CELL));
- X if( _prep == -1 ) _prep = atoi(Prep); /* _dfa_subset needs _prep */
- X
- X if( dfa_stack == NIL(DFASET) )
- X _dmax = _prep + _count_dots(cp->CE_NAME);
- X
- X /* If none of the inference nodes match then forget about the inference.
- X * The user did not tell us how to make such a target. We also stop the
- X * Inference if the new set of DFA's is a proper subset of a previous
- X * subset and it's PREP counts exceed the value of Prep.
- X */
- X dfas = _dfa_subset( Match_dfa(cp->CE_NAME), dfa_stack );
- X
- X#ifdef DBUG
- X { char *tmp;
- X DFASETPTR ds;
- X
- X tmp = _strdup("");
- X for( pdfa = dfas; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next )
- X tmp = _strapp( tmp, pdfa->dl_meta->CE_NAME );
- X
- X DB_PRINT( "inf", ("Working DFA subset [%s]", tmp) );
- X FREE( tmp );
- X
- X tmp = _strdup( "{" );
- X for( ds = dfa_stack; ds != NIL(DFASET); ds = ds->df_next ) {
- X tmp = _strapp( tmp, "[" );
- X for( pdfa = ds->df_set; pdfa != NIL(DFALINK); pdfa = pdfa->dl_next )
- X tmp = _strapp( tmp, pdfa->dl_meta->CE_NAME );
- X tmp = _strapp( tmp, "]" );
- X }
- X tmp = _strapp( tmp, "}" );
- X
- X DB_PRINT( "inf", ("DFA stack: %s", tmp) );
- X FREE(tmp);
- X }
- X#endif
- X
- X if( dfas == NIL(DFALINK) ) {
- X DB_PRINT( "mem", ("%s:<- mem %ld",cp->CE_NAME, (long)coreleft()));
- X DB_PRINT( "inf", ("<<< Exit, no dfas, cp = %04x", NIL(CELL)) );
- X DB_RETURN( NIL(CELL) );
- X }
- X
- X
- X /* We have a set of %-meta's that have not previously been considered, or
- X * whose counts do not violate the Prep count. So we should consider
- X * them, and put them on the top of the stack.
- X */
- X top_dfa_stack.df_set = dfas;
- X top_dfa_stack.df_next = dfa_stack;
- X
- X
- X /* Run through the %-meta cells, build the prerequisite cells. If we are
- X * performing transitive closure, then call Infer_recipe with the new
- X * prerequisite.
- X */
- X for( pdfa = dfas, infcell = NIL(CELL), pedge = NIL(EDGE);
- X pdfa != NIL(DFALINK);
- X pdfa = pdfa->dl_next ) {
- X int push = 0;
- X int _trans = 0;
- X EDGEPTR edge;
- X EDGEPTR edge_noprq; /* No prerequisite for this edge */
- X
- X DB_PRINT( "inf", ("Using dfa: [%s]", pdfa->dl_meta->CE_NAME) );
- X meta = pdfa->dl_meta;
- X
- X
- X /* Change to the required directory prior to checking the prerequisites
- X * Only if the meta has a directory and we haven't changed dir's
- X * for the CELL already.
- X *
- X * Ignore the %-meta if we had to change to a dir, and the dir
- X * did not exist.
- X */
- X if( !(cp->ce_attr & A_SETDIR) && meta->ce_dir != NIL(char) )
- X if( (setdirroot == NIL(CELL) || setdirroot->ce_dir != meta->ce_dir) &&
- X (push = Push_dir(meta, TRUE)) )
- X setdirroot = cp;
- X else {
- X DB_PRINT( "inf", ("Failed PUSH of [%s]", meta->ce_dir) );
- X continue;
- X }
- X
- X
- X /* Now run through the list of prerequisite edge's for the %-meta.
- X * Build each prerequisite in turn, and then see if it needs to be
- X * inferred. We treat the edge that has NO prerequisites last, as
- X * it gives a recipe for making a %-meta from no prerequisites, and
- X * we should really check all NON-NULL prerequisites first.
- X */
- X edge = meta->CE_EDGES;
- X edge_noprq = NIL(EDGE);
- X
- X do {
- X pedge = edge;
- X
- X if( edge->ed_prq == NIL(CELL) )
- X edge_noprq = edge;
- X else {
- X HASHPTR thp; /* temporary hash table pointer */
- X HASH iprqh; /* hash cell for new prerequisite */
- X CELL iprq; /* inferred prerequisite to look for */
- X CELLPTR sdir; /* local setdir root for inference */
- X STRINGPTR sp = NIL(STRING); /* pointer to rcp of inferred target*/
- X int ipush = 0; /* flag for push on inferred prereq */
- X char *name = edge->ed_prq->CE_NAME;
- X int _dmax_fix;
- X
- X DB_PRINT( "inf", ("Trying edge from [%s] to [%s] for [%s]",
- X meta->CE_NAME, name, cp->CE_NAME) );
- X
- X _trans = Transitive &&
- X !((Glob_attr | edge->ed_prq->ce_attr) & A_NOINFER);
- X
- X /* Set the temp CELL used for building prerequisite candidates to
- X * all zero so that we don't have to keep initializing all the
- X * fields. */
- X {
- X register char *s = (char *) &iprq;
- X register int n = sizeof(CELL);
- X while( n ) { *s++ = '\0'; n--; }
- X }
- X
- X
- X /* Build the prerequisite name from the %-meta prerequisite given
- X * for the %-meta rule. */
- X iprqh.ht_name = _build_name( cp->CE_NAME, name, pdfa->dl_per );
- X if( strcmp(cp->CE_NAME, iprqh.ht_name) == 0 )
- X goto try_next_edge;
- X if((_dmax_fix = (_count_dots(name)-_count_dots(meta->CE_NAME))) < 0)
- X _dmax_fix = 0;
- X if( _count_dots(iprqh.ht_name) > _dmax + _dmax_fix )
- X goto try_next_edge;
- X
- X DB_PRINT( "inf", ("Checking prerequisite [%s]", iprqh.ht_name) );
- X
- X if( Verbose )
- X printf( "%s: Trying prerequisite [%s] for [%s]\n", Pname,
- X iprqh.ht_name, cp->CE_NAME );
- X
- X
- X /* See if the prerequisite CELL has been previously defined. If
- X * it has, then make a copy of it into iprq, and use it to try
- X * the inference. We make the copy so that we don't modify the
- X * stat of the inferred cell if the inference fails.
- X */
- X thp = Get_name( iprqh.ht_name, Defs, FALSE, setdirroot );
- X if(thp != NIL(HASH)) {
- X iprq = *thp->CP_OWNR;
- X if( iprq.CE_HOW != NIL(HOW) ) sp = iprq.CE_HOW->hw_recipe;
- X }
- X else
- X iprq.ce_name = &iprqh;
- X
- X
- X /* If the prerequisite has the .SETDIR attr set, then we
- X * should try to CD to the directory, if it is really different
- X * from the one we are currently in. If the CD fails we ignore
- X * the edge and go try another edge.
- X */
- X sdir = setdirroot;
- X if( iprq.ce_dir != NIL(char) )
- X if( sdir==NIL(CELL) || sdir->ce_dir != iprq.ce_dir )
- X if( ipush = Push_dir(&iprq, TRUE) )
- X sdir = &iprq;
- X else
- X goto try_next_edge;
- X
- X
- X /* Stat the inferred prerequisite.
- X */
- X if( !(iprq.ce_flag & F_STAT) ) Stat_target( &iprq, FALSE );
- X
- X
- X /* If the STAT succeeded or if the prerequisite has a recipe for
- X * making it, then infer it. We may later try to perform a
- X * second inference on this prerequisite when we actually go to
- X * make it.
- X */
- X if( (iprq.ce_time != (time_t)0L) || (sp != NIL(STRING)) ) {
- X infcell = Def_cell( iprqh.ht_name, setdirroot );
- X infcell->ce_flag |= F_REMOVE;
- X }
- X else
- X /* The STAT did not succeed, so call Infer_recipe recursively
- X * to see if we know how to make the prerequisite. If it
- X * returns not NULL, then we have an inferred prerequisite
- X * and we should Define it and attach it to the CELL pointed at
- X * by cp. This recursive inference is performed only if
- X * Transitive closure is enabled.
- X */
- X if( _trans ) {
- X int _save = _dmax;
- X if( !_dmax ) _dmax += _dmax_fix;
- X infcell = Infer_recipe( &iprq, iprq.CE_HOW, &top_dfa_stack,
- X sdir);
- X _dmax = _save;
- X
- X if( infcell != NIL(CELL) ) {
- X /* We found we can make the prerequisite, so make it into
- X * a real node. This means, mark it for possible
- X * removal, and when you make it into a node make sure
- X * you don't clobber the Def_cell name.
- X */
- X infcell = Def_cell( iprqh.ht_name, setdirroot );
- X thp = infcell->ce_name;
- X *infcell = iprq;
- X infcell->ce_name = thp;
- X infcell->ce_flag |= F_REMOVE;
- X }
- X }
- X
- X /* If we pushed a directory for the inferred prerequisite then
- X * pop it.
- X */
- X if( ipush ) Pop_dir(FALSE);
- X
- Xtry_next_edge:
- X FREE( iprqh.ht_name );
- X }
- X
- X edge = edge->ed_next;
- X }
- X while( infcell == NIL(CELL) && edge != meta->CE_EDGES );
- X
- X
- X /* If none of the previous edges were any good, and there was an
- X * edge with no prerequsite, then use it.
- X */
- X if( infcell == NIL(CELL) )
- X if( edge_noprq != NIL(EDGE) )
- X pedge = edge_noprq;
- X else
- X pedge = NIL(EDGE);
- X else {
- X /* We have a match, so make the edge's pointer for the corresponding
- X * %-meta target point at the matched prerequisite so that the next
- X * time we perform an inference we will check this edge first.
- X */
- X meta->CE_EDGES = pedge;
- X if( !_trans ) infcell->ce_attr |= A_NOINFER;
- X }
- X
- X
- X /* If we pushed a dir when we treated this %-meta, then
- X * pop it.
- X */
- X if( push ) Pop_dir(FALSE);
- X
- X
- X /* Need this so that pdfa does not get advanced, and remains pointing
- X * to the dfa, that just resulted in a successful match.
- X */
- X if( pedge != NIL(EDGE) ) break;
- X }
- X
- X
- X /* If pedge is not NIL then we have found an edge and possibly inferred
- X * a prerequisite. In any case we should definitely attach the recipe to
- X * the HOW node of the cell pointed at by cp. If the CELL has no HOW node
- X * the we allocate one.
- X */
- X if( pedge != NIL(EDGE) ) {
- X LINKPTR lp;
- X HOWPTR nhow, ihow;
- X
- X DB_PRINT("inf", ("taking edge [%s] to [%s]", pedge->ed_tg->CE_NAME,
- X (pedge->ed_prq == NIL(CELL)) ? "(none)":pedge->ed_prq->CE_NAME));
- X
- X if( Verbose )
- X printf("%s: Inferred recipe using edge from [%s] to [%s]\n",
- X Pname, pedge->ed_tg->CE_NAME,
- X (pedge->ed_prq == NIL(CELL)) ? "(none)":pedge->ed_prq->CE_NAME);
- X
- X if( how == NIL(HOW) ) {
- X /* Get a new HOW node, this should happen only for inferred
- X * cells, as such they have no prior HOW node */
- X TALLOC( how, 1, HOW );
- X cp->CE_HOW = how;
- X }
- X
- X
- X /* Attach the recipe to the HOW node. Note that if the %-meta recipe
- X * is a :: recipe then we will attach all of the HOW cells belonging to
- X * the %-meta :: rule that we matched to the CELL, and we will place
- X * them so that they preceed subsequent HOW cells in the list. Under
- SHAR_EOF
- echo "End of part 15"
- echo "File infer.c is continued in part 16"
- echo "16" > s2_seq_.tmp
- exit 0
-
-