dvadura@watdragon.waterloo.edu (Dennis Vadura) (10/15/90)
Posting-number: Volume 15, Issue 72 Submitted-by: Dennis Vadura <dvadura@watdragon.waterloo.edu> Archive-name: dmake-3.6/part20 #!/bin/sh # this is part 20 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file infer.c continued # CurArch=20 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 * 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 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_TRANSFER); X how->hw_recipe = ihow->hw_recipe; 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 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, FALSE))->cl_flag |= F_TARGET; X X if( Verbose ) X printf( "%s: Inferred prerequisite [%s]\n", X Pname, infcell->CE_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/10/06 12:03:48 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/10/06 12:03:48 dvadura X * dmake Release, Version 3.6 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 _set_bit_var(".USESHELL", "", A_SHELL ); X _set_bit_var(".SWAP", "", A_SWAP ); X _set_bit_var(".MKSARGS", "", A_MKSARGS ); 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} 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/10/06 12:03:45 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/10/06 12:03:45 dvadura X * dmake Release, Version 3.6 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/10/06 12:03:43 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/10/06 12:03:43 dvadura X * dmake Release, Version 3.6 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 if( q != p && q[-1] == CONTINUATION_CHAR ) { X strcpy( q, q+1 ); X q--; X cont = FALSE; X } X else 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 == 0) ? TRUE : X ((anchor == 1)?(*s == *brk) : (*brk == curp[-1])); 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( ((anchor == 1)?*curp:_strspn(curp,brk)[-1]) != *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 function.c (Text)" sed 's/^X//' << 'SHAR_EOF' > function.c && X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/function.c,v 1.1 90/10/06 12:04:36 dvadura Exp $ X-- SYNOPSIS -- GNU style functions for dmake. X-- X-- DESCRIPTION X-- All GNU stule functions understood by dmake are implemented in this X-- file. Currently the only such function is $(mktmp ...) which is X-- not part of GNU-make is an extension provided by dmake. 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: function.c,v $ X * Revision 1.1 90/10/06 12:04:36 dvadura X * dmake Release, Version 3.6 X * X*/ X X#include "extern.h" X#include "alloc.h" X Xstatic char *_exec_mktmp ANSI((char *, char *)); X X Xchar * XExec_function(buf)/* X==================== X Execute the function given by the value of args. X X So far mktmp is the only valid function, anything else elicits and error X message. It is my hope to support the GNU style functions in this portion X of the code at some time in the future. */ Xchar *buf; X{ X char *fname; X char *args = NIL(char); X char *mod = NIL(char); X char *res = NIL(char); X X /* This must succeed since the presence of ' ', \t or \n is what X * determines if this functions is called in the first place. */ X fname = _substr(buf, args=_strpbrk(buf," \t\n")); X X if( (mod = strchr(fname,',')) != NIL(char) ){ X *mod = '\0'; X mod++; X } X X switch( *fname ) { X case 'm': X if( strncmp(fname,"mktmp", 5) == 0 ) res = _exec_mktmp(mod, args); X break; X } X X if( res == NIL(char) ) { X Warning( "Function '%s' not implemented at this time", fname ); X res = _strdup(""); X } X X return(res); X} X X Xstatic char * X_exec_mktmp( mod, data ) Xchar *mod; Xchar *data; X{ X register char *p; X char *tmpname; X FILE *tmpfile; X char *name; X X tmpfile = Start_temp( "", Recipe_cell, Recipe_how, &tmpname ); X data = Expand(_strspn(data, " \t\n")); X name = Recipe_cell ? Recipe_cell->CE_NAME:"makefile text"; X X for(p=strchr(data,'\n'); p; p=strchr(p,'\n')) { X char *q = _strspn(++p," \t"); X strcpy(p,q); X } X X Append_line( data, FALSE, tmpfile, name, FALSE, TRUE ); X Close_temp( Recipe_how, tmpfile ); X FREE(data); X X return( (mod != NIL(char) && *mod) ? Expand(mod) : _strdup(tmpname) ); X} SHAR_EOF chmod 0440 function.c || echo "restore of function.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/10/06 12:04:24 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/10/06 12:04:24 dvadura X * dmake Release, Version 3.6 X * X*/ X X#ifndef EXTERN_h X#define EXTERN_h X X#include "vextern.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 void Append_line ANSI((char*, int, FILE*, 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,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* Exec_function ANSI((char *)); 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 char** Pack_argv ANSI((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, 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/* Include this last as it invalidates some functions that are defined X * externally above and turns them into no-ops. Have to do this after X * the extern declarations however. */ X#include "config.h" 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/10/06 12:03:40 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 SHAR_EOF echo "End of part 20" echo "File expand.c is continued in part 21" echo "21" > s2_seq_.tmp exit 0