dvadura@watdragon.waterloo.edu (Dennis Vadura) (07/27/90)
Posting-number: Volume 14, Issue 26 Submitted-by: dvadura@watdragon.waterloo.edu (Dennis Vadura) Archive-name: dmake/part16 #!/bin/sh # this is part 16 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file infer.c continued # CurArch=16 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 infer.c" sed 's/^X//' << 'SHAR_EOF' >> infer.c X * these circumstances the CELL is marked as a MULTI cell. X */ X nhow = how->hw_next; X for( ihow=meta->CE_EDGES->ed_how; ihow != NIL(HOW); ihow=ihow->hw_next ) { X how->hw_per = pdfa->dl_per; X how->hw_flag |= (ihow->hw_flag & (F_SINGLE | F_GROUP)) | F_INFER; X how->hw_attr |= ihow->hw_attr & (A_SILENT | A_IGNORE); X how->hw_recipe = ihow->hw_recipe; X X /* If infcell is not NIL then we have inferred a prerequisite, so X * add it to the first HOW cell as well. X */ X if( infcell != NIL(CELL) ) { X (Add_prerequisite( how, infcell, TRUE))->cl_flag |= F_TARGET; X X if( Verbose ) X printf( "%s: Inferred prerequisite [%s]\n", X Pname, infcell->CE_NAME ); X } X X /* Add global prerequisites to the first HOW cell X */ X for( lp=ihow->hw_indprq; lp != NIL(LINK); lp=lp->cl_next ) { X char *name = lp->cl_prq->CE_NAME; X CELLPTR tcp; X X name = _build_name( cp->CE_NAME, name, pdfa->dl_per ); X tcp = Def_cell( name, setdirroot ); X tcp->ce_flag |= F_REMOVE; X Add_prerequisite( how, tcp, FALSE ); X X if( Verbose ) X printf( "%s: Inferred indirect prerequisite [%s]\n", X Pname, name ); X FREE(name); X } X X /* If the recipe is a :: recipe then Insert a new HOW node after X * the inferred recipe HOW node and prior to any previous X * :: nodes. X */ X if( ihow->hw_next != NIL(HOW) ) { X cp->ce_flag |= F_MULTI; X TALLOC( how->hw_next, 1, HOW ); X how = how->hw_next; X } X } X how->hw_next = nhow; X pdfa->dl_per = NIL(char); /* We used it, so don't FREE it */ X X /* Make sure to set the FLAGS, and ATTRIBUTES of the CELL so that it X * gets made correctly. X */ X cp->ce_flag |= F_RULES | F_TARGET | F_INFER; X X if( !(cp->ce_attr & A_SETDIR) ) { X cp->ce_attr |= (meta->ce_attr & A_SETDIR); X cp->ce_dir = meta->ce_dir; X } X } X else X cp = NIL(CELL); X X _free_dfas( dfas ); X X DB_PRINT( "mem", ("%s:-< mem %ld", (cp!=NIL(CELL)) ? cp->CE_NAME : "(none)", X (long)coreleft())); X DB_PRINT( "inf", ("<<< Exit, cp = %04x", cp) ); X DB_RETURN( cp ); X} X X Xstatic char * X_build_name( tg, meta, per ) Xchar *tg; Xchar *meta; Xchar *per; X{ X char *name; X X name = Apply_edit( meta, "%", per, FALSE, FALSE ); X if( strchr(name, '$') ) { X HASHPTR m_at; X char *tmp; X X m_at = Def_macro( "@", tg, M_MULTI ); X tmp = Expand( name ); X X if( m_at->ht_value != NIL(char) ) { X FREE( m_at->ht_value ); X m_at->ht_value = NIL(char); X } X X if( name != meta ) FREE( name ); X name = tmp; X } X else if( name == meta ) X name = _strdup( name ); X X return(name); X} X X Xstatic DFALINKPTR X_dfa_subset( pdfa, stack )/* X============================ X This is the valid DFA subset computation. Whenever a CELL has a Match_dfa X subset computed this algorithm is run to see if any of the previously X computed sets on the DFA stack are proper subsets of the new set. If they X are, then any elements of the matching subset whose Prep counts exceed X the allowed maximum given by Prep are removed from the computed DFA set, X and hence from consideration, thereby cutting off the cycle in the X inference graph. */ XDFALINKPTR pdfa; Xregister DFASETPTR stack; X{ X register DFALINKPTR element; X DFALINKPTR nelement; X X DB_ENTER( "_dfa_subset" ); X X for(; pdfa != NIL(DFALINK) && stack != NIL(DFASET); stack = stack->df_next) { X int subset = TRUE; X X for( element=stack->df_set; subset && element != NIL(DFALINK); X element=element->dl_next ) { X register DFALINKPTR subel; X X for( subel = pdfa; X subel != NIL(DFALINK) && (subel->dl_meta != element->dl_meta); X subel = subel->dl_next ); X X if( subset = (subel != NIL(DFALINK)) ) element->dl_member = subel; X } X X if( subset ) X for( element=stack->df_set; element != NIL(DFALINK); X element=element->dl_next ) { X DFALINKPTR mem = element->dl_member; X int npr = element->dl_prep + 1; X X if( npr > _prep ) X mem->dl_delete++; X else X mem->dl_prep = npr; X } X } X X for( element = pdfa; element != NIL(DFALINK); element = nelement ) { X nelement = element->dl_next; X X if( element->dl_delete ) { X /* A member of the subset has a PREP count equal to PREP, so X * it should not be considered further in the inference, hence X * we remove it from the doubly linked set list */ X if( element == pdfa ) X pdfa = element->dl_next; X else X element->dl_prev->dl_next = element->dl_next; X X if( element->dl_next != NIL(DFALINK) ) X element->dl_next->dl_prev = element->dl_prev; X X DB_PRINT("inf", ("deleting dfa [%s]", element->dl_meta->CE_NAME)); X FREE( element->dl_per ); X FREE( element ); X } X } X X DB_RETURN( pdfa ); X} X X X Xstatic void X_free_dfas( chain )/* X===================== X Free the list of DFA's constructed by Match_dfa, and linked together by X LINK cells. FREE the % value as well, as long as it isn't NIL. */ XDFALINKPTR chain; X{ X register DFALINKPTR tl; X X DB_ENTER( "_free_dfas" ); X X for( tl=chain; tl != NIL(DFALINK); chain = tl ) { X tl = tl->dl_next; X X DB_PRINT( "inf", ("Freeing DFA [%s], %% = [%s]", chain->dl_meta->CE_NAME, X chain->dl_per) ); X X if( chain->dl_per != NIL(char) ) FREE( chain->dl_per ); X FREE( chain ); X } X X DB_VOID_RETURN; X} X X Xstatic int X_count_dots( name )/* X=====================*/ Xchar *name; X{ X register char *p; X register int i = 0; X X for( p = name; *p; p++ ) if(*p == '.') i++; X X return( i ); X} SHAR_EOF echo "File infer.c is complete" chmod 0440 infer.c || echo "restore of infer.c fails" echo "x - extracting imacs.c (Text)" sed 's/^X//' << 'SHAR_EOF' > imacs.c && X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/imacs.c,v 1.1 90/07/19 13:53:17 dvadura Exp $ X-- SYNOPSIS -- define default internal macros. X-- X-- DESCRIPTION X-- This file adds to the internal macro tables the set of default X-- internal macros, and for those that are accessible internally via X-- variables creates these variables, and initializes them to point X-- at the default values of these macros. 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: imacs.c,v $ X * Revision 1.1 90/07/19 13:53:17 dvadura X * Initial Revision of Version 3.5 X * X*/ X X#include "extern.h" X Xstatic void _set_int_var ANSI((char *, char *, int, int *)); Xstatic void _set_string_var ANSI((char *, char *, int, char **)); Xstatic void _set_bit_var ANSI((char *, char *, int)); X X/* X** Arrange to parse the strings stored in Rules[] X*/ Xvoid XMake_rules() X{ X Parse(NIL(FILE)); X} X X X#define M_FLAG M_DEFAULT | M_EXPANDED X X/* X** Add to the macro table all of the internal macro variables plus X** create secondary variables which will give access to their values X** easily, both when needed and when the macro value is modified. X** The latter is accomplished by providing a flag in the macro and a field X** which gives a pointer to the value if it is a char or string macro value X** and a mask representing the bit of the global flag register that is affected X** by this macro's value. X*/ Xvoid XCreate_macro_vars() X{ X static char* switChar; X char swchar[2]; X X swchar[0] = Get_switch_char(), swchar[1] = '\0'; X _set_string_var("SWITCHAR", swchar, M_PRECIOUS, &switChar); X _set_string_var("DIRSEPSTR", "/", M_PRECIOUS, &DirSepStr); X _set_string_var("DIRBRKSTR", DirBrkStr, M_PRECIOUS, &DirBrkStr); X X _set_bit_var(".SILENT", "", A_SILENT ); X _set_bit_var(".IGNORE", "", A_IGNORE ); X _set_bit_var(".PRECIOUS", "", A_PRECIOUS); X _set_bit_var(".EPILOG", "", A_EPILOG ); X _set_bit_var(".PROLOG", "", A_PROLOG ); X _set_bit_var(".NOINFER", "", A_NOINFER ); X _set_bit_var(".SEQUENTIAL","",A_SEQ ); X X Glob_attr = A_DEFAULT; /* set all flags to NULL */ X X _set_string_var("SHELL", "", M_DEFAULT, &Shell ); X _set_string_var("SHELLFLAGS", " ", M_DEFAULT, &Shell_flags ); X _set_string_var("GROUPSHELL", "", M_DEFAULT, &GShell ); X _set_string_var("GROUPFLAGS", " ", M_DEFAULT, &GShell_flags); X _set_string_var("SHELLMETAS", "", M_DEFAULT, &Shell_metas ); X _set_string_var("GROUPSUFFIX", "", M_DEFAULT, &Grp_suff ); X _set_string_var("PREP", "0", M_DEFAULT, &Prep ); X _set_string_var("AUGMAKE", NIL(char), M_DEFAULT, &Augmake ); X X _set_string_var("MAKEDIR", Get_current_dir(), M_PRECIOUS|M_NOEXPORT, X &Makedir); X _set_string_var("PWD", Makedir, M_DEFAULT|M_NOEXPORT, &Pwd); X X Def_macro("NULL", "", M_PRECIOUS|M_NOEXPORT|M_FLAG); X X _set_int_var( "MAXLINELENGTH", "0", M_DEFAULT|M_NOEXPORT, &Buffer_size ); X (void) Def_macro("MAXLINELENGTH", "0", M_FLAG | M_DEFAULT); X X /* set MAXPROCESSLIMIT high initially so that it allows MAXPROCESS to X * change from command line. */ X _set_int_var( "MAXPROCESSLIMIT", "100", M_DEFAULT|M_NOEXPORT, &Max_proclmt ); X _set_int_var( "MAXPROCESS", "1", M_DEFAULT|M_NOEXPORT, &Max_proc ); X} X X/* X** Define a string variable value, and set up the macro. X*/ Xstatic void X_set_int_var(name, val, flag, var) Xchar *name; Xchar *val; Xint flag; Xint *var; X{ X HASHPTR hp; X X hp = Def_macro(name, val, M_FLAG | flag); X hp->ht_flag |= M_VAR_INT | M_MULTI; X hp->MV_IVAR = var; X *var = atoi(val); X} X X/* X** Define a string variables value, and set up the macro. X*/ Xstatic void X_set_string_var(name, val, flag, var) Xchar *name; Xchar *val; Xint flag; Xchar **var; X{ X HASHPTR hp; X X hp = Def_macro(name, val, M_FLAG | flag); X hp->ht_flag |= M_VAR_STRING | M_MULTI; X hp->MV_SVAR = var; X *var = hp->ht_value; X} X X/* X** Define a string variables value, and set up the macro. X*/ Xstatic void X_set_bit_var(name, val, mask) Xchar *name; Xchar *val; Xint mask; X{ X HASHPTR hp; X X hp = Def_macro(name, val, M_FLAG); X hp->ht_flag |= M_VAR_BIT | M_MULTI; X hp->MV_MASK = mask; X hp->MV_BVAR = &Glob_attr; X} X SHAR_EOF chmod 0440 imacs.c || echo "restore of imacs.c fails" echo "x - extracting hash.c (Text)" sed 's/^X//' << 'SHAR_EOF' > hash.c && X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/hash.c,v 1.1 90/07/19 13:53:14 dvadura Exp $ X-- SYNOPSIS -- hashing function for hash tables. X-- X-- DESCRIPTION X-- Hash an identifier. The hashing function works by computing the sum X-- of each char and the previous hash value multiplied by 129. Finally the X-- length of the identifier is added in. This way the hash depends on the X-- chars as well as the length, and appears to be sufficiently unique, X-- and is FAST to COMPUTE, unlike the previous hash function... 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: hash.c,v $ X * Revision 1.1 90/07/19 13:53:14 dvadura X * Initial Revision of Version 3.5 X * X*/ X X#include "extern.h" X Xuint16 XHash( id, phv )/* X================= X This function computes the identifier's hash value and returns the hash X value modulo the key size as well as the full hash value. The reason X for returning both is so that hash table searches can be sped up. You X compare hash keys instead and compare strings only for those whose 32-bit X hash keys match. (not many) */ X Xchar *id; Xuint32 *phv; X{ X register char *p = id; X register uint32 hash = (uint32) 0; X X while( *p ) hash = (hash << 7) + hash + (uint32) (*p++); X *phv = hash = hash + (uint32) (p-id); X X return( (uint16) (hash % HASH_TABLE_SIZE) ); X} X SHAR_EOF chmod 0440 hash.c || echo "restore of hash.c fails" echo "x - extracting getinp.c (Text)" sed 's/^X//' << 'SHAR_EOF' > getinp.c && X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/getinp.c,v 1.1 90/07/19 13:53:12 dvadura Exp $ X-- SYNOPSIS -- handle reading of input. X-- X-- DESCRIPTION X-- The code in this file reads the input from the specified stream X-- into the provided buffer of size Buffer_size. In doing so it deletes X-- comments. Comments are delimited by the #, and X-- <nl> character sequences. An exception is \# which X-- is replaced by # in the input. Line continuations are signalled X-- at the end of a line and are recognized inside comments. X-- The line continuation is always <\><nl>. X-- X-- If the file to read is NIL(FILE) then the Get_line routine returns the X-- next rule from the builtin rule table if there is one. 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: getinp.c,v $ X * Revision 1.1 90/07/19 13:53:12 dvadura X * Initial Revision of Version 3.5 X * X*/ X X#include "extern.h" X#include "alloc.h" X#include "db.h" X X#define IS_WHITE(A) ((A == ' ') || (A == '\t') || (A == '\n')) X#define SCAN_WHITE(A) \ X while( IS_WHITE(*A) ) A++; X Xstatic int _is_conditional ANSI((char*)); Xstatic int _handle_conditional ANSI((int, TKSTRPTR)); X Xstatic int rule_ind = 0; /* index of rule when reading Rule_tab */ Xstatic int skip = FALSE; /* if true the skip input */ X X Xint XGet_line( buf, fil )/* X====================== X Read a line of input from the file stripping X off comments. The routine returns TRUE if EOF */ Xchar *buf; XFILE *fil; X{ X extern char **Rule_tab; X register char *p; X register char *q; X register char *c; X char *buf_org; X static int ignore = FALSE; X int cont = FALSE; X int pos = 0; X int res; X X DB_ENTER( "Get_line" ); X X if( fil == NIL(FILE) ) { X /* Reading the internal rule table. Set the rule_index to zero. X * This way ReadEnvironment works as expected every time. */ X X while( (p = Rule_tab[ rule_ind++ ]) != NIL(char) ) X /* The last test in this if '*p != '~', handles the environment X * passing conventions used by MKS to pass arguments. We want to X * skip those environment entries. */ X if( !Readenv || (Readenv && (strchr(p,'=') != NIL(char)) && *p!='~')){ X strcpy( buf, p ); X X DB_PRINT( "io", ("Returning [%s]", buf) ); X DB_RETURN( FALSE ); X } X X rule_ind = 0; X X DB_PRINT( "io", ("Done Ruletab") ); X DB_RETURN( TRUE ); X } X X buf_org = buf; X Xdo_again: X do { X p = buf+pos; X if(feof( fil ) || (fgets( p, Buffer_size-pos, fil ) == NIL(char))) X DB_RETURN( TRUE ); X X Line_number++; X X /* ignore input if ignore flag set and line ends in a continuation X character. */ X X q = p+strlen(p)-2; X if( ignore ) { X if( q[0] != CONTINUATION_CHAR || q[1] != '\n' ) ignore = FALSE; X *p = '\0'; X continue; X } X X /* Search the input string looking for comment chars. If it contains X * comment chars then NUKE the remainder of the line, if the comment X * char is preceeded by \ then shift the remainder of the line left X * by one char. */ X X c = p; X X while( (c = strchr(c, COMMENT_CHAR)) != NIL(char) ) { X if( c != p && c[-1] == ESCAPE_CHAR ) { X strcpy( c-1, c ); /* copy it left, due to \# */ X q--; /* shift tail pointer left */ X } X else { X *c = '\0'; /* a true comment so break */ X break; X } X } X X /* Does the end of the line end in a continuation sequence? */ X X if( (q[0] == CONTINUATION_CHAR) && (q[1] == '\n')) { X /* If the continuation was at the end of a comment then ignore the X next input line, (or lines until we get one ending in just <nl>) X else it's a continuation, so build the input line from several X text lines on input. The maximum size of this is governened by X Buffer_size */ X X if( c != NIL(char) ) X ignore = TRUE; X else X cont = TRUE; X } X else { X cont = FALSE; X } X X q = ( c == NIL(char) ) ? q+2 : c; X pos += q-p; X } X while( (cont || !*buf) && (pos <= Buffer_size) ); X X if( buf[ pos-1 ] == '\n' ) X buf[ --pos ] = '\0'; X else X if( pos == Buffer_size-1 ) X Fatal( "Input line too long, increase MAXLINELENGTH" ); X X X /* Now that we have the next line of input to make, we should check to X * see if it is a conditional expression. If it is then process it, X * otherwise pass it on to the parser. */ X X if( *(p = _strspn(buf, " \t")) == CONDSTART ) { X TKSTR token; X X SET_TOKEN( &token, p ); X X p = Get_token( &token, "", FALSE ); X X if( (res = _is_conditional( p )) ) /* ignore non control special */ X { /* targets */ X res = _handle_conditional( res, &token ); X skip = TRUE; X } X else { X CLEAR_TOKEN( &token ); X res = TRUE; X } X } X X if( skip ) { X buf = buf_org; /* ignore line just read in */ X pos = 0; X skip = res; X goto do_again; X } X X DB_PRINT( "io", ("Returning [%s]", buf) ); X DB_RETURN( FALSE ); X} X X X Xchar * XGet_token( string, brk, anchor )/* X================================== X Return the next token in string. X Returns empty string when no more tokens in string. X brk is a list of chars that also cause breaks in addition to space and X tab, but are themselves returned as tokens. if brk is NULL then the X remainder of the line is returned as a single token. X X anchor if TRUE, says break on chars in the brk list, but only if X the entire token begins with the first char of the brk list, if X FALSE then any char of brk will cause a break to occurr. */ X XTKSTRPTR string; Xchar *brk; Xint anchor; X{ X register char *s; X register char *curp; X register char *t; X int done = FALSE; X char space[10]; X X DB_ENTER( "Get_token" ); X X s = string->tk_str; /* Get string parameters */ X *s = string->tk_cchar; /* ... and strip leading w/s */ X X SCAN_WHITE( s ); X X DB_PRINT( "tok", ("What's left [%s]", s) ); X X if( !*s ) { X DB_PRINT( "tok", ("Returning NULL token") ); X DB_RETURN( "" ); X } X X X /* Build the space list. space contains all those chars that may possibly X * cause breaks. This includes the brk list as well as white space. */ X X if( brk != NIL(char) ) { X strcpy( space, " \t\n" ); X strcat( space, brk ); X } X else { X space[0] = 0xff; /* a char we know will not show up */ X space[1] = 0; X } X X X /* Handle processing of quoted tokens. Note that this is disabled if X * brk is equal to NIL */ X X while( *s == '\"' && ((brk != NIL(char)) || !string->tk_quote) ) { X s++; X if( string->tk_quote ) { X curp = s-1; X do { curp = strchr( curp+1, '\"' ); } X while( (curp != NIL(char)) && (*(curp+1) == '\"')); X X if( curp == NIL(char) ) Fatal( "Unmatched quote in token" ); X string->tk_quote = !string->tk_quote; X X /* Check for "" case, and if found ignore it */ X if( curp == s ) continue; X goto found_token; X } X else X SCAN_WHITE( s ); X X string->tk_quote = !string->tk_quote; X } X X X /* Check for a token break character at the beginning of the token. X * If found return the next set of break chars as a token. */ X X if( (brk != NIL(char)) && (strchr( brk, *s ) != NIL(char)) ) { X curp = _strspn( s, brk ); X done = anchor ? (*s == *brk) : TRUE; X } X X X /* Scan for the next token in the list and return it less the break char X * that was used to terminate the token. It will possibly be returned in X * the next call to Get_token */ X X if( !done ) { X SCAN_WHITE( s ); X X t = s; X do { X done = TRUE; X curp = _strpbrk( t, space); X X if( anchor && *curp && !IS_WHITE( *curp ) ) X if( *curp != *brk ) { X t++; X done = FALSE; X } X } X while( !done ); X X if( (curp == s) && (strchr(brk, *curp) != NIL(char)) ) curp++; X } X Xfound_token: X string->tk_str = curp; X string->tk_cchar = *curp; X *curp = '\0'; X X DB_PRINT( "tok", ("Returning [%s]", s) ); X DB_RETURN( s ); X} X X X Xstatic int X_is_conditional( tg )/* X======================= X Look at tg and return it's value if it is a conditional identifier X otherwise return 0. */ Xchar *tg; X{ X DB_ENTER( "_is_conditional" ); X X tg++; X switch( *tg ) { X case 'I': if( !strcmp( tg, "IF" )) DB_RETURN( ST_IF ); break; X X case 'E': X if( !strcmp( tg, "END" )) DB_RETURN( ST_END ); X else if( !strcmp( tg, "ELSE" )) DB_RETURN( ST_ELSE ); X break; X } X X DB_RETURN( 0 ); X} X X X Xstatic int X_handle_conditional( opcode, tg )/* X=================================== X Perform the necessary processing for .IF conditinal targets. X Someday this should be modified to do bracketted expressions ala X CPP... sigh */ Xint opcode; XTKSTRPTR tg; X{ X static short action[MAX_COND_DEPTH]; X char *tok, *lhs, *rhs, *op, *expr; X int result; X X DB_ENTER( "_handle_conditional" ); X X switch( opcode ) { X case ST_IF: X if( Nest_level+1 == MAX_COND_DEPTH ) X Fatal( ".IF .ELSE ... .END nesting too deep" ); X X If_expand = TRUE; X expr = Expand( Get_token( tg, NIL(char), FALSE )); X If_expand = FALSE; X lhs = _strspn( expr, " \t" ); X if( !*lhs ) lhs = NIL(char); X X if( (op = _strstr( lhs, "==" )) == NIL(char) ) X op = _strstr( lhs, "!=" ); X X if( op == NIL(char) ) X result = (lhs != NIL(char)); X else { X op[1] = op[0]; X if( lhs != op ) { X for( tok = op-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t')); X tok-- ); X tok[1] = '\0'; X } X else X lhs = NIL(char); X X op++; X rhs = _strspn( op+1, " \t" ); X if( !*rhs ) rhs = NIL(char); X X if( (rhs == NIL(char)) || (lhs == NIL(char)) ) X result = (rhs == lhs) ? TRUE : FALSE; X else { X tok = rhs + strlen( rhs ); X for( tok=tok-1; (tok != lhs) && ((*tok == ' ')||(*tok == '\t')); X tok--); X tok[1] = '\0'; X X result = (strcmp( lhs, rhs ) == 0) ? TRUE : FALSE; X } X X if( *op == '!' ) result = !result; X } X X if( expr != NIL(char) ) FREE( expr ); X Nest_level++; X X if( result ) X action[ Nest_level ] = action[ Nest_level-1 ]; X else X action[ Nest_level ] = 1; X break; X X case ST_ELSE: X if( Nest_level <= 0 ) Fatal( ".ELSE without .IF" ); X if( action[ Nest_level-1 ] != 1 ) X action[ Nest_level ] ^= 0x1; /* flip between 0 and 1 */ X break; X X case ST_END: X Nest_level--; X if( Nest_level < 0 ) Fatal( "Unmatched .END" ); X break; X } X X DB_RETURN( action[ Nest_level ] ); X} X SHAR_EOF chmod 0440 getinp.c || echo "restore of getinp.c fails" echo "x - extracting extern.h (Text)" sed 's/^X//' << 'SHAR_EOF' > extern.h && X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/extern.h,v 1.1 90/07/19 13:55:31 dvadura Exp $ X-- SYNOPSIS -- external declarations for dmake functions. X-- X-- DESCRIPTION X-- ANSI is a macro that allows the proper handling of ANSI style X-- function declarations. 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: extern.h,v $ X * Revision 1.1 90/07/19 13:55:31 dvadura X * Initial Revision of Version 3.5 X * X*/ X X#ifndef EXTERN_h X#define EXTERN_h X X#include "vextern.h" X#include "config.h" X#include <stdlib.h> X#include <string.h> X Xextern void Add_dfa ANSI((char *)); Xextern void Add_fringe ANSI((CELLPTR)); Xextern void Add_recipe_to_list ANSI((char *, int, int)); Xextern LINKPTR Add_prerequisite ANSI((HOWPTR, CELLPTR, int)); Xextern char* Apply_edit ANSI((char *, char *, char *, int, int)); Xextern char* basename ANSI((char*)); Xextern void Bind_rules_to_targets ANSI((int)); Xextern char* Build_path ANSI((char *, char *)); Xextern void Catch_signals ANSI((void (*)())); Xextern void Check_circle ANSI((LINKPTR)); Xextern void Check_circle_dfa ANSI(()); Xextern void Clear_prerequisites ANSI((HOWPTR)); Xextern void Clear_signals ANSI(()); Xextern void Clean_up_processes ANSI(()); Xextern FILE* Closefile ANSI(()); Xextern void Close_temp ANSI((HOWPTR, FILE *)); Xextern void Create_macro_vars ANSI(()); Xextern DFAPTR Construct_dfa ANSI((char *)); Xextern CELLPTR Def_cell ANSI((char *, CELLPTR)); Xextern HASHPTR Def_macro ANSI((char *, char *, int)); Xextern STRINGPTR Def_recipe ANSI((char *, STRINGPTR, int, int)); Xextern int Do_cmnd ANSI((char *, int, int, CELLPTR, HOWPTR, int, int)); Xextern time_t Do_stat ANSI((char *, char *, char **)); Xextern time_t Do_time ANSI(()); Xextern int Do_touch ANSI((char *, char *, char **)); Xextern void Dump ANSI(()); Xextern void Dump_recipe ANSI((STRINGPTR)); Xextern void Epilog ANSI((int)); Xextern char* Expand ANSI((char *)); Xextern CELLPTR Explode_cell ANSI((CELLPTR, CELLPTR)); Xextern HOWPTR Explode_how ANSI((HOWPTR, CELLPTR, int)); Xextern LINKPTR Explode_prq ANSI((LINKPTR, CELLPTR, int)); Xextern char* Filename ANSI(()); Xextern char* Get_current_dir ANSI(()); Xextern int Get_line ANSI((char *, FILE *)); Xextern HASHPTR Get_name ANSI((char *, HASHPTR *, int, CELLPTR)); Xextern char* Get_suffix ANSI((char *)); Xextern char Get_switch_char ANSI(()); Xextern char* Get_token ANSI((TKSTRPTR, char *, int)); Xextern uint16 Hash ANSI((char *,uint32 *)); Xextern void Handle_result ANSI((int, int, int, CELLPTR)); Xextern int If_root_path ANSI((char *)); Xextern CELLPTR Infer_recipe ANSI((CELLPTR, HOWPTR, DFASETPTR, CELLPTR)); Xextern int Macro_op ANSI((char *)); Xextern int Make ANSI((CELLPTR, HOWPTR, CELLPTR)); Xextern void Make_rules ANSI(()); Xextern void Map_esc ANSI((char *)); Xextern DFALINKPTR Match_dfa ANSI((char *)); Xextern char* My_malloc ANSI((unsigned int, char *, int)); Xextern char* My_calloc ANSI((unsigned int, unsigned int, char *, int)); Xextern void My_free ANSI((char *, char *, int)); Xextern void No_ram ANSI(()); Xextern FILE* Open_temp ANSI((char **, char *)); Xextern FILE* Openfile ANSI((char *, int)); Xextern void Pack_argv ANSI((char **, int, int, char *)); Xextern void Parse ANSI((FILE *)); Xextern int Parse_macro ANSI((char *, int)); Xextern int Parse_rule_def ANSI((int *)); Xextern void Pop_dir ANSI((int)); Xextern void Prolog ANSI((int, char **)); Xextern int Push_dir ANSI((CELLPTR, int)); Xextern void Quit ANSI(()); Xextern char* Read_env_string ANSI((char *)); Xextern void ReadEnvironment ANSI(()); Xextern void Remove_prq ANSI((CELLPTR)); Xextern int Rule_op ANSI((char *)); Xextern int runargv ANSI((CELLPTR, HOWPTR, int, int, int, char *)); Xextern time_t seek_arch ANSI((char*, char*)); Xextern int Set_dir ANSI((char *)); Xextern int Set_group_attributes ANSI((char *)); Xextern void Stat_target ANSI((CELLPTR, int)); Xextern FILE* Start_temp ANSI((char *, CELLPTR, HOWPTR, char **)); Xextern int Test_circle ANSI((CELLPTR, int)); Xextern int touch_arch ANSI((char*, char*)); Xextern void Unlink_temp_files ANSI((HOWPTR)); Xextern void Update_time_stamp ANSI((CELLPTR, HOWPTR)); Xextern void Void_lib_cache ANSI((char *, char *)); Xextern int Wait_for_child ANSI((int, int)); Xextern int Write_env_string ANSI((char *, char *)); X Xextern char* _stradd ANSI((char *,char *, int)); Xextern char* _strapp ANSI((char *,char *)); Xextern char* _strjoin ANSI((char *,char *,int, int)); Xextern char* _strdup ANSI((char *)); Xextern char* _strpbrk ANSI((char *,char *)); Xextern char* _strspn ANSI((char *,char *)); Xextern char* _strstr ANSI((char *,char *)); Xextern char* _substr ANSI((char *,char *)); X X#endif X SHAR_EOF chmod 0440 extern.h || echo "restore of extern.h fails" echo "x - extracting expand.c (Text)" sed 's/^X//' << 'SHAR_EOF' > expand.c && X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/expand.c,v 1.1 90/07/19 13:53:10 dvadura Exp $ X-- SYNOPSIS -- macro expansion code. X-- X-- DESCRIPTION X-- X-- This routine handles all the necessary junk that deals with macro X-- expansion. It understands the following syntax. If a macro is X-- not defined it expands to NULL, and {} are synonyms for (). X-- X-- $$ - expands to $ X-- {{ - expands to { X-- }} - expands to } X-- $A - expands to whatever the macro A is defined as X-- $(AA) - expands to whatever the macro AA is defined as X-- $($(A)) - represents macro indirection X-- X-- following macro is recognized X-- X-- string1{ token_list }string2 X-- X-- and expands to string1 prepended to each element of token_list and X-- string2 appended to each of the resulting tokens from the first X-- operation. If string2 is of the form above then the result is X-- the cross product of the specified (possibly modified) token_lists. X-- X-- The folowing macro modifiers are defined and expanded: X-- X-- $(macro:modifier_list:modifier_list:...) X-- X-- where modifier_list a combination of: X-- X-- D or d - Directory portion of token including separator X-- F or f - File portion of token including suffix X-- B or b - basename portion of token not including suffix X-- T or t - for tokenization X-- X-- or a single X-- S or s - pattern substitution (simple) X-- X-- NOTE: Modifiers are applied once the macro value has been found. X-- Thus the construct $($(test):s/joe/mary/) is defined and X-- modifies the value of $($(test)) X-- X-- Also the construct $(m:d:f) is not the same as $(m:df) X-- the first applies d to the value of $(m) and then X-- applies f to the value of that whereas the second form X-- applies df to the value of $(m). 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: expand.c,v $ X * Revision 1.1 90/07/19 13:53:10 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 Xstatic char* _scan_token ANSI((char*, char**)); Xstatic char* _scan_macro ANSI((char*, char**)); Xstatic char* _scan_brace ANSI((char*, char**, int*)); Xstatic char* _cross_prod ANSI((char*, char*)); Xstatic char* _apply_modifiers ANSI((int, char*)); Xstatic char* _tokenize ANSI((char*, char*)); X X#define SUFFIX_FLAG 1 /* defines for macro modifier code */ X#define DIRECTORY_FLAG 2 X#define FILE_FLAG 4 X X Xchar * XExpand( src )/* X=============== X This is the driver routine for the expansion, it identifies non-white X space tokens and gets the _scan_token routine to figure out if they should X be treated in a special way. */ X Xchar *src; /* pointer to source string */ X{ X char *tmp; /* pointer to temporary str */ X char *res; /* pointer to result string */ X char *start; /* pointer to start of token */ X X DB_ENTER( "Expand" ); X DB_PRINT( "exp", ("Expanding [%s]", src) ); X X res = _strdup( "" ); X if( src == NIL(char) ) DB_RETURN( res ); X X while( *src ) { X /* Here we find the next non white space token in the string X * and find it's end, with respect to non-significant white space. */ X X start = _strspn( src, " \t\n" ); X res = _strjoin( res, src, start-src, TRUE ); X if( !(*start) ) break; X res = _strjoin( res, tmp = _scan_token( start, &src ), -1, TRUE ); X FREE( tmp ); X } X X DB_PRINT( "exp", ("Returning [%s]", res) ); X DB_RETURN( res ); X} X X X Xchar * XApply_edit( src, pat, subst, fr, anchor )/* X=========================================== X Take the src string and apply the pattern substitution. ie. look for X occurrences of pat in src and replace each occurrence with subst. This is X NOT a regular expressions pattern substitution, it's just not worth it. X X if anchor == TRUE then the src pattern match must be at the end of a token. X ie. this is for SYSV compatibility and is only used for substitutions of X the caused by $(macro:pat=sub). So if src = "fre.o.k june.o" then X $(src:.o=.a) results in "fre.o.k june.a", and $(src:s/.o/.a) results in X "fre.a.k june.a" */ X Xchar *src; /* the source string */ Xchar *pat; /* pattern to find */ Xchar *subst; /* substitute string */ Xint fr; /* if TRUE free src */ Xint anchor; /* if TRUE anchor */ X{ X char *res; X char *p; X char *s; X int l; X X DB_ENTER( "Apply_edit" ); X X if( !*pat ) DB_RETURN( src ); /* do nothing if pat is NULL */ X X DB_PRINT( "mod", ("Source str: [%s]", src) ); X DB_PRINT( "mod", ("Replacing [%s], with [%s]", pat, subst) ); X X s = src; X l = strlen( pat ); X if( (p = _strstr( s, pat )) != NIL(char) ) { X res = _strdup( "" ); X do { X if( anchor ) X if( !*(p+l) || (strchr(" \t", *(p+l)) != NIL(char)) ) X res = _strjoin( _strjoin( res, s, p-s, TRUE ), subst, -1, TRUE ); X else X res = _strjoin( res, s, p+l-s, TRUE ); X else X res = _strjoin( _strjoin( res, s, p-s, TRUE ), subst, -1, TRUE ); X X s = p + l; X } X while( (p = _strstr( s, pat )) != NIL(char) ); X X res = _strjoin( res, s, -1, TRUE ); X if( fr ) FREE( src ); X } X else X res = src; X X X DB_PRINT( "mod", ("Result [%s]", res) ); X DB_RETURN( res ); X} X X X Xvoid XMap_esc( tok )/* X================ X Map an escape sequence and replace it by it's corresponding character X value. It is assumed that tok points at the initial \, the esc X sequence in the original string is replaced and the value of tok X is not modified. */ Xchar *tok; X{ X if( strchr( "\"\\vantbrf01234567", tok[1] ) ) { X switch( tok[1] ) { X case 'a' : *tok = 0x07; break; X case 'b' : *tok = '\b'; break; X case 'f' : *tok = '\f'; break; X case 'n' : *tok = '\n'; break; X case 'r' : *tok = '\r'; break; X case 't' : *tok = '\t'; break; X case 'v' : *tok = 0x0b; break; X case '\\': *tok = '\\'; break; X case '\"': *tok = '\"'; break; X X default: { X register int i = 0; X register int j = 0; X for( ; i<2 && isdigit(tok[2]); i++ ) { X j = (j << 3) + (tok[1] - '0'); X strcpy( tok+1, tok+2 ); X } X j = (j << 3) + (tok[1] - '0'); X *tok = j; X } X } X strcpy( tok+1, tok+2 ); SHAR_EOF echo "End of part 16" echo "File expand.c is continued in part 17" echo "17" > s2_seq_.tmp exit 0