dvadura@watdragon.waterloo.edu (Dennis Vadura) (07/27/90)
Posting-number: Volume 14, Issue 28 Submitted-by: dvadura@watdragon.waterloo.edu (Dennis Vadura) Archive-name: dmake/part18 #!/bin/sh # this is part 18 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file dmake.c continued # CurArch=18 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 dmake.c" sed 's/^X//' << 'SHAR_EOF' >> dmake.c X ex_val = Target; /* make sure we don't mark any */ X Target = TRUE; /* of the default rules as */ X Make_rules(); /* potential targets */ X _warn = TRUE; X X if( Rules ) { X /* order of precedence is: X * X * MAKESTARTUP from command line (precious is marked) X * MAKESTARTUP from environment X * MAKESTARTUP from builtin rules (not precious) X */ X char *fname; X X if( ((hp = GET_MACRO("MAKESTARTUP")) != NIL(HASH)) && X (hp->ht_flag & M_PRECIOUS) && X (mkfil=Openfile(fname=hp->ht_value, FALSE)) != NIL(FILE) || X (mkfil=Openfile(fname=Read_env_string("MAKESTARTUP"), FALSE)) != NIL(FILE) || X hp != NIL(HASH) && X (mkfil=Openfile(fname=hp->ht_value, FALSE)) != NIL(FILE) ) X { X Parse(mkfil); X mkfil = NIL(FILE); X } X else X Fatal( "configuration file `%s' not found", fname ); X } X X Target = ex_val; X X if( Get_env == 'e' ) _do_ReadEnvironment(); X X if( fil_name != NIL(char) ) X mkfil = Openfile( fil_name, TRUE ); X else { X /* Search .MAKEFILES dependent list looking for a makefile. X */ X register CELLPTR cp; X register LINKPTR lp; X X cp = Def_cell( ".MAKEFILES", NIL(CELL) ); X X if( (lp = cp->CE_PRQ) != NIL(LINK) ) { X int s_n, s_t, s_q; X X s_n = Trace; X s_t = Touch; X s_q = Check; X X Trace = Touch = Check = FALSE; X Makemkf = Wait_for_completion = TRUE; X mkfil = NIL(FILE); X X for(; lp != NIL(LINK) && mkfil == NIL(FILE); lp=lp->cl_next) { X mkfil = Openfile( lp->cl_prq->CE_NAME, FALSE ); X X if( mkfil == NIL(FILE) && X Make(lp->cl_prq, lp->cl_prq->CE_HOW, NIL(CELL)) != -1 ) X mkfil = Openfile( lp->cl_prq->CE_NAME, FALSE ); X } X X Trace = s_n; X Touch = s_t; X Check = s_q; X Makemkf = Wait_for_completion = FALSE; X } X } X X if( mkfil != NIL(FILE) ) { X char *f = Filename(); X char *p; X X if( strcmp(f, "stdin") == 0 ) f = "-"; X p = _stradd( "-f", f, FALSE ); X Def_macro( "MAKEFILE", p, M_PRECIOUS|M_NOEXPORT ); X Parse( mkfil ); X } X else if( !Rules ) X Fatal( "No `makefile' present" ); X X if( Nest_level ) Fatal( "Missing .END for .IF" ); X if( Get_env == 'E' ) _do_ReadEnvironment(); X X _do_VPATH(); /* kludge it up with .SOURCE */ X X if( Listing ) Dump(); /* print out the structures */ X if( Trace ) Glob_attr &= ~A_SILENT; /* make sure we see the trace */ X X if( !Target ) X Fatal( "No target" ); X else { X Check_circle( Fringe_hd ); X Check_circle_dfa(); X } X X TALLOC( Start_dir.ce_name, 1, HASH ); X Start_dir.CE_NAME = ".SETDIR"; X Push_dir( &Start_dir, Glob_attr & A_IGNORE ); X X if( m_export ) { X int i; X X for( i=0; i<HASH_TABLE_SIZE; ++i ) { X char *tmpstr = hp->ht_value; X X if( tmpstr == NIL(char) ) tmpstr = ""; X if( !(hp->ht_flag & M_NOEXPORT) && X Write_env_string(hp->ht_name, tmpstr) != 0 ) X Warning( "Could not export %s", hp->ht_name ); X } X } X X if( Buffer != NIL(char) ) FREE( Buffer ); X if( Trace ) Def_macro(".SEQUENTIAL", "y", M_EXPANDED); X if( Glob_attr & A_SEQ ) Def_macro( "MAXPROCESS", "1", M_EXPANDED|M_FORCE ); X X ex_val = Make_targets(); X X Pop_dir( Glob_attr & A_IGNORE ); X Clear_signals(); X Epilog(ex_val); /* Does not return -- EVER */ X} X X Xstatic void X_do_ReadEnvironment() X{ X int saveattr = Glob_attr; X X Glob_attr |= A_SILENT; X ReadEnvironment(); X Glob_attr = saveattr; X} X X Xstatic void X_do_VPATH() X{ X HASHPTR hp; X char *_rl[2]; X extern char **Rule_tab; X X hp = GET_MACRO("VPATH"); X if( hp == NIL(HASH) ) return; X X _rl[0] = ".SOURCE :^ $(VPATH:s/:/ /)"; X _rl[1] = NIL(char); X X Rule_tab = _rl; X Parse( NIL(FILE) ); X} X X X/* The file table and pointer to the next FREE slot for use by both X Openfile and Closefile. Each open stacks the new file onto the open X file stack, and a corresponding close will close the passed file, and X return the next file on the stack. The maximum number of nested X include files is limited by the value of MAX_INC_DEPTH */ X Xstatic struct { X FILE *file; /* file pointer */ X char *name; /* name of file */ X int numb; /* line number */ X} ftab[ MAX_INC_DEPTH ]; X Xstatic int next_file_slot = 0; X X/* Set the proper macro value to reflect the depth of the .INCLUDE directives. X */ Xstatic void X_set_inc_depth() X{ X char buf[10]; X sprintf( buf, "%d", next_file_slot-1 ); X Def_macro( "INCDEPTH", buf, M_MULTI|M_NOEXPORT ); X} X X XFILE * XOpenfile(name, err)/* X===================== X This routine opens a file for input. X If the file name is `-' then it returns standard input. X The file is pushed onto the open file stack. */ Xchar *name; Xint err; X{ X FILE *fil; X X DB_ENTER("Openfile"); X X if( name == NIL(char) || !*name ) X if( !err ) X DB_RETURN(NIL(FILE)); X else X Fatal( "Openfile: NIL filename" ); X X if( next_file_slot == MAX_INC_DEPTH ) X Fatal( "Too many open files. Max nesting level is %d.", MAX_INC_DEPTH); X X DB_PRINT( "io", ("Opening file [%s], in slot %d", name, next_file_slot) ); X X if( strcmp("-", name) == 0 ) { X name = "stdin"; X fil = stdin; X } X else X fil = fopen( name, "r" ); X X if( fil == NIL(FILE) ) { X if( err ) X Fatal( "File %s not found", name ); X } X else { X ftab[next_file_slot].file = fil; X ftab[next_file_slot].numb = Line_number; X ftab[next_file_slot++].name = _strdup(name); X Line_number = 0; X _set_inc_depth(); X } X X DB_RETURN(fil); X} X XFILE * XClosefile()/* X============= X This routine is used to close the last file opened. This forces make X to open files in a last open first close fashion. It returns the X file pointer to the next file on the stack, and NULL if the stack is empty.*/ X{ X DB_ENTER("Closefile"); X X if( !next_file_slot ) X DB_RETURN( NIL(FILE) ); X X if( ftab[--next_file_slot].file != stdin ) { X DB_PRINT( "io", ("Closing file in slot %d", next_file_slot) ); X fclose( ftab[next_file_slot].file ); X FREE( ftab[next_file_slot].name ); X _set_inc_depth(); X } X X if( next_file_slot > 0 ) { X Line_number = ftab[next_file_slot].numb; X DB_RETURN( ftab[next_file_slot-1].file ); X } X else X Line_number = 0; X X DB_RETURN( NIL(FILE) ); X} X X Xchar * XFilename()/* X============ X Return name of file on top of stack */ X{ X return( next_file_slot==0 ? NIL(char) : ftab[next_file_slot-1].name ); X} X X/* X** print error message from variable arg list X*/ X Xstatic int errflg = TRUE; Xstatic int warnflg = FALSE; X Xstatic void Xerrargs(fmt, args) Xchar *fmt; Xva_list args; X{ X int warn = _warn && warnflg && !(Glob_attr & A_SILENT); X X if( errflg || warn ) { X char *f = Filename(); X X fprintf( stderr, "%s: ", Pname ); X if( f != NIL(char) ) fprintf(stderr, "%s: line %d: ", f, Line_number); X X if( errflg ) X fprintf(stderr, "Error -- "); X else if( warn ) X fprintf(stderr, "Warning -- "); X X vfprintf( stderr, fmt, args ); X putc( '\n', stderr ); X if( errflg && !Continue ) Quit( NIL(CELL) ); X } X} X X/* X** Print error message and abort X*/ Xint XFatal(fmt, va_alist) Xchar *fmt; Xva_dcl; X{ X va_list args; X X va_start(args, fmt); X Continue = FALSE; X errargs(fmt, args); X va_end(args); X} X X/* X** error message and exit (unless -k) X*/ Xint XError(fmt, va_alist) Xchar* fmt; Xva_dcl; X{ X va_list args; X X va_start(args, fmt); X errargs(fmt, args); X va_end(args); X} X X X/* X** non-fatal message X*/ Xint XWarning(fmt, va_alist) Xchar *fmt; Xva_dcl; X{ X va_list args; X X va_start(args, fmt); X warnflg = TRUE; X errflg = FALSE; X errargs(fmt, args); X errflg = TRUE; X warnflg = FALSE; X va_end(args); X} X X Xvoid XNo_ram() X{ X Fatal( "No more memory" ); X} X X X#ifdef HELP XUsage() X{ X printf(USAGE, Pname); X puts(" -P# - set max number of child processes for parallel make"); X puts(" -f file - use file as the makefile\n"); X X puts("OPTIONS: (can be catenated, ie -irn == -i -r -n)"); X puts(" -A - enable AUGMAKE special target mapping"); X puts(" -e - define environment strings as macros"); X puts(" -E - same as -e but done after parsing makefile"); X puts(" -h - print out usage info"); X puts(" -i - ignore errors"); X puts(" -k - make independent targets, even if errors"); X puts(" -n - trace and print, do not execute commands"); X puts(" -p - print out a version of the makefile"); X puts(" -q - check if target is up to date. Does not do"); X puts(" anything. Returns 0 if up to date, 1 otherwise"); X puts(" -r - don't use internal rules"); X puts(" -s - do your work silently"); X puts(" -S - disable parallel (force sequential) make, overrides -P"); X puts(" -t - touch, update time stamps without executing commands"); X puts(" -T - do not apply transitive closure"); X puts(" -u - force unconditional update of target"); X puts(" -v - verbose, print out what we are doing"); X puts(" -V - print out version number"); X puts(" -x - export macro values to environment"); X X /*** The feature below is disabled for now */ X /*puts(" -M - Microsoft MAKE compatibility");*/ X} X#endif X X XVersion() X{ X extern char **Rule_tab; X char **p; X X printf("%s - %s, ", Pname, COPYRIGHT); X printf("Version %s, Patch Level %d\n\n", VERSION, PATCHLEVEL); X X puts("Default Configuration:"); X for (p=Rule_tab; *p != NIL(char); p++) X printf("\t%s\n", *p); X} SHAR_EOF echo "File dmake.c is complete" chmod 0440 dmake.c || echo "restore of dmake.c fails" echo "x - extracting dag.c (Text)" sed 's/^X//' << 'SHAR_EOF' > dag.c && X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dag.c,v 1.1 90/07/19 13:53:02 dvadura Exp $ X-- SYNOPSIS -- Routines to construct the internal dag. X-- X-- DESCRIPTION X-- This file contains all the routines that are responsible for X-- defining and manipulating all objects used by the make facility. 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: dag.c,v $ X * Revision 1.1 90/07/19 13:53:02 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 X XHASHPTR XGet_name( name, tab, define, dir )/* X==================================== X Look to see if the name is defined, if it is then return X a pointer to its node, if not return NIL(HASH). X If define is TRUE and the name is not found it will be added. */ X Xchar *name; /* name we are looking for */ XHASHPTR *tab; /* the hash table to look in */ Xint define; /* TRUE => add to table */ XCELLPTR dir; X{ X register HASHPTR hp; X register char *p; X uint16 hv; X uint32 hash_key; X X DB_ENTER( "Get_name" ); X DB_PRINT( "name", ("Looking for %s", name) ); X X hv = Hash( name, &hash_key ); X X for( hp = tab[ hv ]; hp != NIL(HASH); hp = hp->ht_next ) X if( hp->ht_hash == hash_key && X (tab != Defs || ((tab == Defs) && (hp->CP_ROOT == dir))) && X !strcmp(hp->ht_name, name) ) X break; X X if( hp == NIL(HASH) && define ) { X /* Check to make sure that CELL name contains only printable chars */ X for( p=name; *p; p++ ) X if( !isprint(*p) ) X Fatal( "Name contains non-printable character [0x%02x]", *p ); X X TALLOC( hp, 1, HASH ); /* allocate a cell and add it in */ X X if( tab == Defs ) hp->CP_ROOT = dir; X hp->ht_name = _strdup( name ); X hp->ht_hash = hash_key; X hp->ht_next = tab[ hv ]; X tab[ hv ] = hp; X X DB_PRINT( "name", ("Adding %s", name) ); X } X X DB_PRINT( "name",("Returning: [%s,%lu]", X (hp == NIL(HASH)) ? "":hp->ht_name, hv) ); X DB_RETURN( hp ); X} X X X XHASHPTR XDef_macro( name, value, flags )/* X================================= X This routine is used to define a macro, and it's value. X The flags indicates if it is a permanent macro or if it's value X can be redefined. A flags of M_PRECIOUS means it is a precious X macro and cannot be further redefined. If the flags flag also X contains the M_MULTI bit it means that the macro can be redefined X multiple times and no warning of the redefinitions should be issued. X Once a macro's VAR flags are set they are preserved through all future X macro definitions. X X Macro definitions that have one of the variable bits set are treated X specially. In each case the hash table entry var field points at the X global variable that can be set by assigning to the macro. X X bit valued global vars must be computed when the macro value is changed. X char valued global vars must have the first char of ht_value copied to X them. string valued global vars have the same value as ht_value and should X just have the new value of ht_value copied to them. */ X Xchar *name; /* macro name to define */ Xchar *value; /* macro value to set */ Xint flags; /* initial ht_flags */ X{ X register HASHPTR hp; X register char *p, *q; X X DB_ENTER( "Def_macro" ); X DB_PRINT( "mac", ("Defining macro %s = %s, %x", name, value, flags) ); X X /* check to see if name is in the table, if so then just overwrite X the previous definition. Otherwise allocate a new node, and X stuff it in the hash table, at the front of any linked list */ X X if( Readenv ) flags |= M_LITERAL; X X hp = Get_name( name, Macs, TRUE, NIL(CELL) ); X X if( (hp->ht_flag & M_PRECIOUS) && !(flags & M_FORCE) ) { X Warning( "Macro `%s' cannot be redefined", name ); X DB_RETURN( hp ); X } X X if( hp->ht_value != NIL(char) ) FREE( hp->ht_value ); X X if( (hp->ht_flag & M_USED) && !((flags | hp->ht_flag) & M_MULTI) ) X Warning( "Macro `%s' redefined after use", name ); X X if( (value != NIL(char)) && (*value) ) { X /* strip out any \<nl> combinations where \ is the current CONTINUATION X * char */ X X for( p = value; (p = strchr(p, CONTINUATION_CHAR)) != NIL(char); ) X if( p[1] == '\n' ) X strcpy( p, p+2 ); X else X p++; X X if( !(flags & M_LITERAL) ) { X p = _strdup( _strspn( value, " \t" ) ); /* strip white space before */ X /* ... and after value */ X if( *p ) { X for(q=p+strlen(p)-1; ((*q == ' ')||(*q == '\t')); q--); X *++q = '\0'; X } X flags &= ~M_LITERAL; X } X else X p = _strdup( value ); /* take string literally */ X X if( !*p ) { /* check if result is "" */ X FREE( p ); X p = NIL(char); X flags |= M_EXPANDED; X } X else if( *_strpbrk( p, "${}" ) == '\0' ) X flags |= M_EXPANDED; X X hp->ht_value = p; X } X else X hp->ht_value = NIL(char); X X /* Assign the hash table flag less the M_MULTI flag, it is used only X * to silence the warning. But carry it over if it was previously X * defined in ht_flag, as this is a permanent M_MULTI variable. */ X X hp->ht_flag = (flags & ~(M_MULTI|M_FORCE)) | X (hp->ht_flag & (M_VAR_MASK | M_MULTI)); X X /* Check for macro variables and make the necessary adjustment in the X * corresponding global variables */ X X if( hp->ht_flag & M_VAR_MASK ) X if( !(flags & M_EXPANDED) ) X Error( "Macro variables must be assigned with :=" ); X else switch( hp->ht_flag & M_VAR_MASK ) /* only one var type per var */ X { X case M_VAR_STRING: X *hp->MV_SVAR = hp->ht_value; X break; X X case M_VAR_CHAR: X *hp->MV_CVAR = (hp->ht_value == NIL(char)) ? '\0':*hp->ht_value; X break; X X case M_VAR_INT: { X int tvalue; X if( hp->MV_IVAR == NIL(int) ) break; /* first time */ X X tvalue = atoi(hp->ht_value); X if( hp->MV_IVAR == &Buffer_size ) { X /* If Buffer_size is modified then make sure you change the X * size of the real buffer as well. */ X tvalue = (tvalue < (BUFSIZ-2)) ? BUFSIZ : tvalue+2; X if( Buffer_size == tvalue ) break; X if( Buffer ) FREE(Buffer); X if((Buffer=MALLOC(tvalue, char)) == NIL(char)) No_ram(); X *Buffer = '\0'; X } X *hp->MV_IVAR = tvalue; X X if( hp->MV_IVAR == &Max_proc || hp->MV_IVAR == &Max_proclmt ) { X if( tvalue < 1 ) X Fatal( "Process limit value must be > 1" ); X X if( Max_proc > Max_proclmt ) X Fatal( "Specified # of processes exceeds limit of [%d]", X Max_proclmt ); X } X } break; X X case M_VAR_BIT: X /* Bit variables are set to 1 if ht_value is not NULL and 0 X * otherwise */ X X if( hp->ht_value == NIL(char) ) X *hp->MV_BVAR &= ~hp->MV_MASK; X else X *hp->MV_BVAR |= hp->MV_MASK; X break; X } X X DB_RETURN( hp ); X} X X X XCELLPTR XDef_cell( name, dir )/* X======================= X Take a string passed in and define it as a cell X If the cell exists then return a pointer to it. */ Xchar *name; XCELLPTR dir; X{ X register HASHPTR hp; X register CELLPTR cp; X register CELLPTR lib; X char *member; X char *end; X X DB_ENTER( "Def_cell" ); X X /* Check to see if the cell is a member of the form lib(member) or X * lib((symbol)) and handle the cases appropriately. X * What we do is we look at the target, if it is of the above two X * forms we get the lib, and add the member/symbol to the list of X * prerequisites for the library. If this is a symbol name def'n X * we additionally add the attribute A_SYMBOL, so that stat can X * try to do the right thing. */ X X if( ((member = strchr(name, '(')) != NIL(char)) && X ((end = strrchr(member, ')')) != NIL(char)) && X (member > name) && (member[-1] != '$') && X (end > member+1) && (end[1] == '\0') ) X { X *member++ = *end = '\0'; X X if( (*member == '(') && (member[strlen(member)-1] == ')') ) { X member[ strlen(member)-1 ] = '\0'; X cp = Def_cell( member+1, dir ); X cp->ce_attr |= A_SYMBOL; X } X else X cp = Def_cell( member, dir ); X X lib = Def_cell( name, dir ); X X if( lib->CE_HOW == NIL(HOW) ) TALLOC( lib->CE_HOW, 1, HOW ); X X Add_prerequisite( lib->CE_HOW, cp, FALSE ); X lib->ce_attr |= A_LIBRARY | A_COMPOSITE; X X if( !Def_targets ) cp = lib; X } X else { X hp = Get_name( name, Defs, TRUE, dir );/* get the name from hash table */ X X if( hp->CP_OWNR == NIL(CELL) ) /* was it previously defined */ X { /* NO, so define a new cell */ X DB_PRINT( "cell", ("Defining cell [%s]", name) ); X X TALLOC( cp, 1, CELL ); X hp->CP_OWNR = cp; X cp->ce_name = hp; X } X else /* YES, so return the old cell */ X { X DB_PRINT( "cell", ("Getting cell [%s]", hp->ht_name) ); X cp = hp->CP_OWNR; X } X } X X DB_RETURN( cp ); X} X X X X XLINKPTR XAdd_prerequisite( how, cell, head )/* X===================================== X Add a dependency node to the dag. It adds it to the prerequisites, X if any, of the cell and makes certain they are in linear order. X If head == 1, then add to head of the prerequisite list, else X add to tail. */ X XHOWPTR how; XCELLPTR cell; Xint head; X{ X register LINKPTR lp, tlp; X X DB_ENTER( "Add_prerequisite" ); X DB_PRINT( "cell", ("Defining prerequisite %s", cell->CE_NAME) ); X X if( (cell->ce_flag & (F_MAGIC | F_PERCENT)) ) X Fatal( "Special target [%s] cannot be a prerequisite", X cell->CE_NAME ); X X if( how->hw_prq == NIL(LINK) ) { /* it's the first one */ X TALLOC( lp, 1, LINK ); X lp->cl_prq = cell; X how->hw_prq = lp; X } X else { /* search the list, checking for duplicates */ X for( lp = how->hw_prq; X (lp->cl_next != NIL(LINK)) && (lp->cl_prq != cell); X lp = lp->cl_next ); X X /* If the cell is not found and we are at the last cell in the list, X * allocate a new cell and place it into the list, insert it at the X * head if head == 1, else we add it to the end. */ X X if( (lp->cl_prq != cell) ) { X TALLOC( tlp, 1, LINK ); X tlp->cl_prq = cell; X X if( head ) { X tlp->cl_next = how->hw_prq; X how->hw_prq = tlp; X } X else X lp->cl_next = tlp; X X lp = tlp; X } X } X X DB_RETURN( lp ); X} X X X Xvoid XClear_prerequisites( how )/* X============================ X Clear out the list of prerequisites, freeing all of the LINK nodes, X and setting the list to NULL */ XHOWPTR how; X{ X LINKPTR lp, tlp; X X DB_ENTER( "Clear_prerequisites" ); X DB_PRINT( "cell", ("Nuking prerequisites") ); X X if( how == NIL(HOW) ) { DB_VOID_RETURN; } X X for( lp=how->hw_prq; lp != NIL(LINK); lp=tlp ) { X tlp=lp->cl_next; X FREE( lp ); X } X X how->hw_prq = NIL(LINK); X X DB_VOID_RETURN; X} X X X Xvoid XAdd_fringe( cp )/* X================== Take the cell pointed to by cp and put it at the end X of the fringe of targets */ XCELLPTR cp; X{ X DB_ENTER( "Add_fringe" ); X X if( !(cp->ce_attr & A_FRINGE) ) { X DB_PRINT( "cell", ("Adding to fringe %s", cp->ce_name->ht_name) ); X X if( Fringe_hd == NIL(LINK) ) { X TALLOC( Fringe_hd, 1, LINK ); X Fringe_tl = Fringe_hd; X } X else if( Fringe_tl != NIL(LINK) ) { X TALLOC( Fringe_tl->cl_next, 1, LINK ); X Fringe_tl = Fringe_tl->cl_next; X } X X Fringe_tl->cl_prq = cp; X cp->ce_attr |= A_FRINGE; X } X X DB_VOID_RETURN; X} X X X X Xvoid XCheck_circle( lp )/* X==================== X Check for circular definitions in the make graph */ XLINKPTR lp; X{ X for( ; lp != NIL(LINK); lp = lp->cl_next ) X if( Test_circle( lp->cl_prq, FALSE ) ) X Fatal( "Detected circular dependency in graph at [%s]", X lp->cl_prq->CE_NAME ); X} X X X X Xint XTest_circle( cp, meta )/* X========================= X Actually run through the graph */ XCELLPTR cp; Xint meta; X{ X int res = 0; X DB_ENTER( "Test_circle" ); X DB_PRINT( "tc", ("checking [%s]", cp->CE_NAME) ); X X if( cp->ce_flag & F_MARK ) X DB_RETURN( (cp->ce_attr & A_LIBRARY) ? 0 : 1 ); X X cp->ce_flag |= F_MARK; X X if( meta ) { X register EDGEPTR ep; X X if( cp->CE_EDGES != NIL(EDGE) ) { X EDGEPTR es; X X ep = es = cp->CE_EDGES; X do { X if( ep->ed_prq != NIL(CELL) && ep->ed_prq->ce_flag & F_DFA ) X res = Test_circle( ep->ed_prq, TRUE ); X ep = ep->ed_next; X } X while( ep != es && !res ); X } X } X else { X register LINKPTR tcp; X X if( cp->CE_HOW != NIL(HOW) ) X for( tcp = cp->CE_HOW->hw_prq; !res && tcp != NIL(LINK); X tcp = tcp->cl_next ) X if( tcp->cl_prq != cp ) res = Test_circle( tcp->cl_prq, FALSE ); X } X X cp->ce_flag ^= F_MARK; X DB_RETURN( res ); X} X X X X XSTRINGPTR XDef_recipe( rcp, sp, white_too, no_check )/* X============================================= X Take the recipe and add it to the list of recipes X pointed to by sp. sp points to the last element. X return a pointer to the new recipe. If white_too == TRUE add the X recipe even if it contains only white space. X If no_check is true then don't look for -@ at the start of the X recipe line. */ Xchar *rcp; XSTRINGPTR sp; Xint white_too; Xint no_check; X{ X register STRINGPTR nsp; X register char *rp; X int flag; X int done; X X DB_ENTER( "Def_recipe" ); X DB_PRINT( "rul", ("Defining recipe %s", rcp) ); X X if( !white_too ) rcp = _strspn( rcp, " \t" ); X if( (rcp == NIL(char)) || (*rcp == 0 && !white_too) ) X DB_RETURN( sp ); /* return last recipe when new recipe not added */ X X rp = no_check ? rcp : _strspn( rcp, " \t@-" ); X X TALLOC( nsp, 1, STRING ); X nsp->st_string = _strdup( rp ); X X if( sp != NIL(STRING) ) sp->st_next = nsp; X nsp->st_next = NIL(STRING); X X if( no_check ) DB_RETURN( nsp ); X X for( flag = A_DEFAULT, rp = rcp, done = FALSE; !done; ) X switch( *rp++ ) X { X case '@' : flag |= A_SILENT; break; X case '-' : flag |= A_IGNORE; break; X X case ' ' : X case '\t': break; X X default: done = TRUE; break; X } X X nsp->st_attr |= flag; X X DB_RETURN( nsp ); X} SHAR_EOF chmod 0440 dag.c || echo "restore of dag.c fails" echo mkdir - common mkdir common echo "x - extracting common/print.mk (Text)" sed 's/^X//' << 'SHAR_EOF' > common/print.mk && X# Make a listing of either everything so far, or just the stuff that has X# been updated since the last time a printout was made. X# The targets are: X# print - to print only updated files. X# printall - to print entire tree. X# X# MACROS are: X# PRINTER - printer name on which to put output, output X# goes to a file if no printer name is given. X# PRINTFLAGS - flags to pass to the printer. X# PRINTEXCLUDE - substrings in file names not to include in output. X XGROUPFLAGS := XSEDLIST = _sed_e_flag_'/{ $(PRINTEXCLUDE) }/d' XFILIST = $(TMPDIR)/pr$$$$ XOFILE = $(TMPDIR)/pr$$$$.out X X.IF $(PRINTEXCLUDE) X SEDARGS = $(SEDLIST:s/_sed_e_flag_/-e /) X.END X Xprintall : print_remove_ctl print; Xprint_remove_ctl:;@-$(RM) control/print X Xprint: X@[ X if [ -f control/print ]; then X find . -type f -newer control/print -print |\ X sort -t. +2 +1 -2 |\ X sed $(SEDARGS) >$(FILIST); X if [ -s $(FILIST) ]; then X find . -type f -print | sort -t. +2 +1 -2 |\ X sed $(SEDARGS) >$(FILIST).full; X cpr -c -T control/title -N -C `cat $(FILIST).full` >$(OFILE); X cpr -c -N `cat $(FILIST)` >> $(OFILE); X $(RM) $(FILIST).full; X else X echo "No modified files since last printing"; X fi X else X find . -type f -print | sort -t. +2 +1 -2 |\ X sed $(SEDARGS) >$(FILIST); X if [ -s $(FILIST) ]; then X cpr -c -T control/title -N `cat $(FILIST)` >$(OFILE); X fi X fi X X if [ -s $(OFILE) ]; then X.IF $(PRINTER) X $(PRINT) $(PRINTFLAGS) $(OFILE); X echo "Listing printed on $(PRINTER)"; X.IF $(PRINTKEEPTMP) == $(NULL) X $(RM) $(OFILE); X.END X.ELSE X echo "Listing can be temporarily found in $(OFILE)"; X.END X fi X.IF $(PRINTKEEPTMP) == $(NULL) X $(RM) $(FILIST) X.END X touch control/print; X exit 0 X] SHAR_EOF chmod 0662 common/print.mk || echo "restore of common/print.mk fails" echo "x - extracting common/malloc.c (Text)" sed 's/^X//' << 'SHAR_EOF' > common/malloc.c && X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/common/RCS/malloc.c,v 1.1 90/07/19 13:31:06 dvadura Exp $ X-- SYNOPSIS -- debugging version of malloc X-- X-- DESCRIPTION X-- malloc for debugging -- allocates via sbrk and tracks stuff, does diag X-- dump if things appear to be screwed up. This code is taken from a X-- malloc package off the net. By the time I got it the original authors X-- name had disappeared. This file can be used by anyone for any X-- purpose, since it is originally from usenet, hence the missing X-- copyright notice. X-- X-- AUTHOR X-- Dennis Vadura, dvadura@watdragon.uwaterloo.ca X-- CS DEPT, University of Waterloo, Waterloo, Ont., Canada X-- X-- LOG X-- $Log: malloc.c,v $ X * Revision 1.1 90/07/19 13:31:06 dvadura X * Initial Revision of Version 3.5 X * X*/ X X#ifdef DBUG X X#include <signal.h> X#include "extern.h" X#include "alloc.h" X#include "db.h" X Xextern char *sbrk(); Xextern char etext[]; Xextern char edata[]; Xextern char end[]; X Xvoid XMy_free( ptr, fil, line )/* X=========================== X A routine that check the freeing of NULL pointers. */ Xchar *ptr; Xchar *fil; Xint line; X{ X#ifdef DB_MALLOC X _malldstr( "free: file:" ); X _malldstr( fil ); X _malldstr( " line: " ); X _dbdumpint( line ); X _malldstr( " :: " ); X#endif X X if( ptr == NIL( char ) ) X Fatal( "Freeing NIL pointer" ); X X free( ptr ); X} X X Xchar * XMy_malloc( n, fil, line )/* X=========================== X A routine that check alloc */ Xunsigned int n; Xchar *fil; Xint line; X{ X#ifdef DB_MALLOC X _malldstr( "alloc: file:" ); X _malldstr( fil ); X _malldstr( " line: " ); X _dbdumpint( line ); X _malldstr( " :: " ); X#endif X X return( malloc( n )); X} X X X Xchar * XMy_calloc( n, size, fil, line )/* X================================= X A routine that check alloc */ Xunsigned int n; Xunsigned int size; Xchar *fil; Xint line; X{ X#ifdef DB_MALLOC X _malldstr( "alloc: file:" ); X _malldstr( fil ); X _malldstr( " line: " ); X _dbdumpint( line ); X _malldstr( " :: " ); X#endif X X return( calloc( n, size )); X} X X X X#ifdef DB_MALLOC X Xstruct _Dmi { X struct _Dmi *m_next; X struct _Dmi *m_prev; X long m_size; X char m_blk[1]; X}; X Xstatic struct _Dmi *_fab = (struct _Dmi *) 0; Xstatic struct _Dmi *_ffb = (struct _Dmi *) 0; Xstatic char *_xbrk = 0; Xstatic int _in_malloc = 0; Xstatic int _st_malloc = 0; Xint _mall_opt = 1; X X/* X * initialize stuff, we want to _malldmp() on a bus/seg error X */ X Xstatic _mall_sig(sig) { X if (sig == SIGSEGV) X _malldstr("\nsegmentation violation\n\n"); X else if (sig == SIGBUS) X _malldstr("\nbus error\n\n"); X else if (sig == SIGSYS) X _malldstr("\ninvalid syscall arg\n\n"); X else { X _malldstr("\nsignal "); X _malldptr(sig); X _malldstr("\n\n"); X } X _malldmp(); X kill(getpid(), sig); X} X Xstatic _mall_init() { X if (_st_malloc) X return; X signal(SIGSEGV, _mall_sig); X signal(SIGBUS, _mall_sig); X _st_malloc = 1; X} X X/* X * figure out which allocation block this pointer came from X * return NULL if none X */ X Xstatic struct _Dmi *_mallgb(s) Xchar *s; { X register struct _Dmi *blk; X X for (blk = _fab; blk != (struct _Dmi *) 0; blk = blk->m_next) X if (blk->m_blk == s) X break; X return blk; X} X X X/* X * internal: write a pointer in hex without using stdio X */ X Xstatic _malldptr(x) Xregister long x; { X char buf[20]; X static char hex[] = "0123456789abcdef"; X register long dx; X register char *p; X X if (x == 0) X return _malldstr("0x0(0)"); X _malldstr("0x"); X p = buf; X dx = x; X while (x > 0) X *p++ = hex[x % 16], x = x / 16; X while (p != buf) X write(2, --p, 1); X _malldstr("("); X p = buf; X x = dx; X while (x > 0) X *p++ = hex[x % 10], x /= 10; X while (p != buf) X write(2, --p, 1); X _malldstr(")"); X} X X/* X * internal: dump a string X */ X Xstatic _malldstr(s) Xregister char *s; { X register int len; X X for (len = 0; s[len] != '\0'; len++) X ; X write(2, s, len); X} X X Xstatic _dbdumpint(x) Xregister int x; { X char buf[20]; X static char hex[] = "0123456789abcdef"; X register long dx; X register char *p; X X if (x == 0) return _malldstr("0"); X p = buf; X while (x > 0) X *p++ = hex[x % 10], x /= 10; X while (p != buf) X write(2, --p, 1); X} X X X/* X * dump arena; can be called externally, and is non-destructive X */ X X_malldmp() { X register struct _Dmi *blk; X int oldf; X X oldf = _in_malloc; X _in_malloc = 0; X _malldstr("brk = "); X _malldptr(sbrk(0)); X _malldstr(" xbrk = "); X _malldptr(_xbrk); X _malldstr("\n_fab = "); X _malldptr(_fab); X _malldstr(" _ffb = "); X _malldptr(_ffb); X _malldstr(" blksiz = "); X _malldptr(sizeof (struct _Dmi)); X _malldstr("\netext = "); X _malldptr(etext); X _malldstr(" edata = "); X _malldptr(edata); X _malldstr(" end = "); X _malldptr(end); X _malldstr("\n\nallocated blocks\n\n"); X if (_fab == (struct _Dmi *) 0) X _malldstr("(none)\n"); X else { X for (blk = _fab; blk != (struct _Dmi *) 0 && (char *) blk >= _xbrk && (char *) blk < sbrk(0); blk = blk->m_next) { X _malldstr("("); X _malldptr(blk); X _malldstr(") "); X _malldptr(blk->m_prev); X _malldstr("< "); X _malldptr(blk->m_size); X _malldstr(" >"); X _malldptr(blk->m_next); X _malldstr("\n"); X } X if (blk != (struct _Dmi *) 0) X _malldstr("(subsequent block pointers corrupted)\n"); X } X _malldstr("\nfree blocks\n\n"); X if (_ffb == (struct _Dmi *) 0) X _malldstr("(none)\n"); X else { X for (blk = _ffb; blk != (struct _Dmi *) 0 && (char *) blk >= _xbrk && (char *) blk < sbrk(0); blk = blk->m_next) { X _malldstr("("); X _malldptr(blk); X _malldstr(") "); X _malldptr(blk->m_prev); X _malldstr("< "); X _malldptr(blk->m_size); X _malldstr(" >"); X _malldptr(blk->m_next); X _malldstr("\n"); X } X if (blk != (struct _Dmi *) 0) X _malldstr("(subsequent block pointers corrupted)\n"); X } X _in_malloc = oldf; X} X X/* X * internal error routine: print error message (without using stdio) and X * drop core X */ X Xstatic _mallerr(fn, s, ptr) Xchar *fn, *s; Xlong ptr; { X _malldstr(fn); X _malldstr(": "); X _malldstr(s); X _malldptr(ptr); X _malldstr("\n"); X _malldmp(); X signal(SIGQUIT, SIG_DFL); X kill(getpid(), SIGQUIT); X} X Xchar *malloc(n ) Xregister unsigned n; X{ X register struct _Dmi *blk; X X _in_malloc = 1; X _mall_init(); X if (_mall_opt) X { X _malldstr("malloc: size: " ); X _malldptr(n); X _malldstr("\n"); X } X _mallchk("malloc"); X if (n == 0) { X _malldstr("malloc(0) is illegal!\n"); X _mall_sig(SIGSYS); X } X for (blk = _ffb; blk != (struct _Dmi *) 0; blk = blk->m_next) X if (blk->m_size >= n) { X if (blk->m_next != (struct _Dmi *) 0) X blk->m_next->m_prev = blk->m_prev; X if (blk->m_prev != (struct _Dmi *) 0) X blk->m_prev->m_next = blk->m_next; X if (blk == _ffb) X _ffb = blk->m_next; X blk->m_next = _fab; X blk->m_prev = (struct _Dmi *) 0; X if (_fab != (struct _Dmi *) 0) X _fab->m_prev = blk; X _fab = blk; X _in_malloc = 0; X return blk->m_blk; X } X if ((blk = (struct _Dmi *) sbrk(sizeof (struct _Dmi) + n - 1)) == (struct _Dmi *) -1) { X _in_malloc = 0; X return (char *) 0; /* no space */ X } X if (_xbrk == (char *) 0) X _xbrk = (char *) blk; X blk->m_next = _fab; X blk->m_prev = (struct _Dmi *) 0; X if (_fab != (struct _Dmi *) 0) X _fab->m_prev = blk; X _fab = blk; X blk->m_size = n; X _in_malloc = 0; X return blk->m_blk; X} X X/* The free-block list is sorted in size order */ X Xfree(s) Xregister char *s; X{ X register struct _Dmi *blk, *fblk; X int didit; X X _in_malloc = 1; X _mall_init(); X if (_mall_opt) X { X _malldstr("free: ptr: "); X _malldptr(s); X _malldstr("\n"); X } X _mallchk("free"); X if (s == (char *) 0) { X _malldstr("free((char *) 0) is illegal!\n"); X _mall_sig(SIGSYS); X } X if ((blk = _mallgb(s)) == (struct _Dmi *) 0) X _mallerr("non-allocated pointer passed to free(): ", s); X if (blk->m_prev != (struct _Dmi *) 0) X blk->m_prev->m_next = blk->m_next; X if (blk->m_next != (struct _Dmi *) 0) X blk->m_next->m_prev = blk->m_prev; X if (blk == _fab) X _fab = blk->m_next; X if (_ffb == (struct _Dmi *) 0) { X _ffb = blk; X blk->m_next = (struct _Dmi *) 0; X blk->m_prev = (struct _Dmi *) 0; X goto crunch; X } X for (fblk = _ffb; fblk->m_next != (struct _Dmi *) 0; fblk = fblk->m_next) X if (fblk->m_next->m_size >= blk->m_size) X break; X blk->m_next = fblk->m_next; X if (fblk->m_next != (struct _Dmi *) 0) X fblk->m_next->m_prev = blk; X blk->m_prev = fblk; X fblk->m_next = blk; X X/* X * crunch the free list by dropping consecutive end-of-brk until we hit xbrk X * or a "hole" (i.e. allocated block). coalescing is possible but not supp- X * orted in malloc, so we don't bother here. X */ X Xcrunch: X didit = 1; X while (_ffb != (struct _Dmi *) 0 && didit) { X didit = 0; X for (fblk = _ffb; fblk != (struct _Dmi *) 0; fblk = fblk->m_next) X if ((char *) fblk + sizeof *fblk + fblk->m_size - 1 == sbrk(0)) { X didit = 1; X if (fblk->m_next != (struct _Dmi *) 0) X fblk->m_next->m_prev = fblk->m_prev; X if (fblk->m_prev != (struct _Dmi *) 0) X fblk->m_prev->m_next = fblk->m_next; X if (fblk == _ffb) X _ffb = fblk->m_next; X sbrk(- fblk->m_size); X break; X } X } X _in_malloc = 0; X} X Xchar *realloc(s, n) Xregister char *s; Xregister unsigned n; { X register char *s1, *d, *d1; X register struct _Dmi *blk; X X if (_mall_opt) X _malldstr("called realloc("), _malldptr(s), _malldstr(", "), _malldptr(n), _malldstr(")\n"); X _mallchk("realloc"); X if (s == (char *) 0) { X _malldstr("realloc((char *) 0, size) is illegal!\n"); X _mall_sig(SIGSYS); X } X if (n == 0) { X _malldstr("realloc(ptr, 0) is illegal!\n"); X _mall_sig(SIGSYS); X } X if ((blk = _mallgb(s)) == (struct _Dmi *) 0) X _mallerr("non-allocated pointer passed to realloc(): ", s); X if ((s1 = malloc(n)) == (char *) 0) X return (char *) 0; X if (blk->m_size < n) X n = blk->m_size; X d1 = s1; X d = s; X while (n-- != 0) X *d1++ = *d++; X free(s); X return s1; X} X X/* X * _mallchk() is global, so external routines can do discreet checks on the X * arena. If the arena is detectibly corrupted, it will abort(). X */ X X_mallchk(fn) Xchar *fn; { X register struct _Dmi *blk, *cblk; X register char *send; X register int cnt; X X send = sbrk(0); X cblk = (struct _Dmi *) 0; X for (blk = _fab; blk != (struct _Dmi *) 0; cblk = blk, blk = blk->m_next) { X if ((char *) blk < _xbrk || (char *) blk >= send) X _mallerr(fn, "allocated block list corrupted: blkptr = ", blk); X if (blk->m_prev != cblk) X _mallerr(fn, "allocated block list corrupted: back pointer incorrect blk ", blk); X if (blk->m_size < 0) X _mallerr(fn, "allocated block list corrupted: blk->m_size = ", blk->m_size); X } X cblk = (struct _Dmi *) 0; X for (blk = _ffb; blk != (struct _Dmi *) 0; cblk = blk, blk = blk->m_next) { X if ((char *) blk < _xbrk || (char *) blk >= sbrk(0)) X _mallerr(fn, "free block list corrupted: blkptr = ", blk); X if (blk->m_prev != cblk) X _mallerr(fn, "free block list corrupted: back pointer incorrect blk ", blk); X if (blk->m_size < 0) X _mallerr(fn, "free block list corrupted: blk->m_size = ", blk->m_size); SHAR_EOF echo "End of part 18" echo "File common/malloc.c is continued in part 19" echo "19" > s2_seq_.tmp exit 0