v15i074: dmake version 3.6 (part 22/25)
Dennis Vadura
dvadura at watdragon.waterloo.edu
Mon Oct 15 11:44:56 AEST 1990
Posting-number: Volume 15, Issue 74
Submitted-by: Dennis Vadura <dvadura at watdragon.waterloo.edu>
Archive-name: dmake-3.6/part22
#!/bin/sh
# this is part 22 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file dmake.h continued
#
CurArch=22
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.h"
sed 's/^X//' << 'SHAR_EOF' >> dmake.h
X#define ST_IMPORT 9
X
X/* Macro definitions for use inside dmake */
X#define SET_TOKEN(A, B) (A)->tk_str = (B); (A)->tk_cchar = *(B);\
X (A)->tk_quote = 1;
X#define CLEAR_TOKEN(A) *(A)->tk_str = (A)->tk_cchar
X#define GET_MACRO(A) Get_name(A, Macs, FALSE, NIL(CELL))
X#define iswhite(C) ((C == ' ') || (C == '\t'))
X
X#endif
X
SHAR_EOF
echo "File dmake.h is complete"
chmod 0440 dmake.h || echo "restore of dmake.h fails"
echo "x - extracting dmake.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dmake.c &&
X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dmake.c,v 1.1 90/10/06 12:03:35 dvadura Exp $
X-- SYNOPSIS -- The main program.
X--
X-- DESCRIPTION
X--
X-- dmake [-#dbug_string] [ options ]
X-- [ macro definitions ] [ target ... ]
X--
X-- This file contains the main command line parser for the
X-- make utility. The valid flags recognized are as follows:
X--
X-- -f file - use file as the makefile
X-- -#dbug_string - dump out debugging info, see below
X--
X-- options: (can be catenated, ie -irn == -i -r -n)
X--
X-- -A - enable AUGMAKE special target mapping
X-- -i - ignore errors
X-- -n - trace and print, do not execute commands
X-- -t - touch, update dates without executing commands
X-- -T - do not apply transitive closure
X-- -r - don't use internal rules
X-- -s - do your work silently
X-- -S - force Sequential make, overrides -P
X-- -q - check if target is up to date. Does not
X-- do anything. Returns 0 if up to date, -1
X-- otherwise.
X-- -p - print out a version of the makefile
X-- -P# - set value of MAXPROCESS
X-- -e - define environment strings as macros
X-- -E - as -e but done after parsing makefile
X-- -u - force unconditional update of target
X-- -k - make all independent targets even if errors
X-- -V - print out this make version number
X-- -v - verbose, print what we are doing, as we do it.
X-- -M - Microsoft make compatibility, (* disabled *)
X-- -h - print out usage info
X-- -x - export macro defs to environment
X--
X-- NOTE: - #ddbug_string is only availabe for versions of dmake that
X-- have been compiled with -DDBUG switch on. Not the case for
X-- distributed versions. Any such versions must be linked
X-- together with a version of Fred Fish's debug code.
X--
X-- NOTE: - in order to compile the code the include file stddef.h
X-- must be shipped with the bundled code.
X--
X-- AUTHOR
X-- Dennis Vadura, dvadura at 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: dmake.c,v $
X * Revision 1.1 90/10/06 12:03:35 dvadura
X * dmake Release, Version 3.6
X *
X*/
X
X/* Set this flag to one, and the global variables in vextern.h will not
X * be defined as 'extern', instead they will be defined as global vars
X * when this module is compiled. */
X#define _DEFINE_GLOBALS_ 1
X
X#include <ctype.h>
X#include <stdarg.h>
X#include "extern.h"
X#include "alloc.h"
X#include "db.h"
X#include "patchlvl.h"
X#include "version.h"
X
X#ifdef HELP
X#define USAGE \
X"Usage:\n%s [-AeEhiknpqrsStTuvVx] [-P#] [-f file] [macro[*][+][:]=value ...] [target ...]\n"
X#define COPYRIGHT "Copyright (c) 1990 by Dennis Vadura"
X#endif
X
Xstatic char *sccid = COPYRIGHT;
Xstatic char _warn = TRUE; /* warnings on by default */
X
Xstatic void _do_VPATH();
Xstatic void _do_ReadEnvironment();
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X char* fil_name = NIL(char);
X char* cmdmacs;
X char* targets;
X FILE* mkfil;
X int ex_val;
X int m_export;
X HASHPTR hp;
X
X DB_ENTER("main");
X
X /* Initialize Global variables to their default values */
X Prolog(argc, argv);
X Create_macro_vars();
X Catch_signals(Quit);
X
X Def_macro( "MAKECMD", Pname, M_PRECIOUS|M_NOEXPORT );
X Pname = basename(Pname);
X
X DB_PROCESS(Pname);
X (void) setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* stdout line buffered */
X
X Continue = FALSE;
X Get_env = FALSE;
X Force = FALSE;
X Target = FALSE;
X If_expand = FALSE;
X Listing = FALSE;
X Readenv = FALSE;
X Rules = TRUE;
X Trace = FALSE;
X Touch = FALSE;
X Check = FALSE;
X Microsoft = FALSE;
X Verbose = FALSE;
X Makemkf = FALSE;
X m_export = FALSE;
X cmdmacs = NIL(char);
X targets = NIL(char);
X
X Transitive = TRUE;
X Nest_level = 0;
X Line_number = 0;
X
X while( --argc > 0 ) {
X register char *p;
X char *q;
X
X if( *(p = *++argv) == '-' ) {
X if( p[1] == '\0' ) Fatal("Missing option letter");
X
X /* copy options to Buffer for $(MFLAGS), strip 'f' */
X q = strchr(Buffer, 0);
X while (*p != 0)
X if( (*q++ = *p++) == 'f' ) q--;
X
X if( *(q-1) == '-' )
X q--;
X else
X *q++ = ' ';
X
X *q = 0;
X
X for( p = *argv+1; *p; p++) switch (*p) {
X case 'f':
X if( fil_name == NIL(char) ) {
X if( *++argv != NIL(char) ) {
X fil_name = *argv;
X argc--;
X } else
X Fatal("No file name for -f");
X } else
X Fatal("Only one `-f file' allowed");
X break;
X
X case 'k': Continue = TRUE; break;
X case 'p': Listing = TRUE; break;
X case 'r': Rules = FALSE; break;
X case 'n': Trace = TRUE; break;
X case 't': Touch = TRUE; break;
X case 'q': Check = TRUE; break;
X case 'u': Force = TRUE; break;
X case 'v': Verbose = TRUE; break;
X case 'x': m_export = TRUE; break;
X case 'T': Transitive = FALSE; break;
X case 'e': Get_env = 'e'; break;
X case 'E': Get_env = 'E'; break;
X
X case 'V': Version(); Quit(NIL(CELL)); break;
X case 'A': Def_macro("AUGMAKE", "y", M_EXPANDED); break;
X case 'i': Def_macro(".IGNORE", "y", M_EXPANDED); break;
X case 's': Def_macro(".SILENT", "y", M_EXPANDED); break;
X case 'S': Def_macro(".SEQUENTIAL", "y", M_EXPANDED); break;
X
X case 'P':
X if( p[1] ) {
X Def_macro( "MAXPROCESS", p+1, M_MULTI|M_EXPANDED );
X p += strlen(p)-1;
X }
X else
X Fatal( "Missing number for -P flag" );
X break;
X
X#ifdef HELP
X case 'h': Usage(); Quit(NIL(CELL)); break;
X#endif
X#ifdef DBUG
X case '#':
X DB_PUSH(p+1);
X p += strlen(p)-1;
X break;
X#endif
X
X default:
X fprintf(stderr, USAGE, Pname);
X Quit(NIL(CELL));
X break;
X }
X }
X else if( (q = strchr(p, '=')) != NIL(char) ) {
X cmdmacs = _stradd( cmdmacs, _strdup(p), TRUE );
X Parse_macro( p, (strchr(p,'+')==NIL(char))?M_PRECIOUS:M_DEFAULT );
X }
X else {
X register CELLPTR cp;
X targets = _stradd( targets, _strdup(p), TRUE );
X Add_fringe(cp = Def_cell(p, NIL(CELL)));
X cp->ce_flag |= F_TARGET;
X Target = TRUE;
X }
X }
X
X Def_macro( "MAKEMACROS", cmdmacs, M_PRECIOUS|M_NOEXPORT );
X Def_macro( "MAKETARGETS", targets, M_PRECIOUS|M_NOEXPORT );
X if( cmdmacs != NIL(char) ) FREE(cmdmacs);
X if( targets != NIL(char) ) FREE(targets);
X
X Def_macro( "MFLAGS", Buffer, M_PRECIOUS|M_NOEXPORT );
X Def_macro( "%", "$@", M_PRECIOUS|M_NOEXPORT );
X
X if( *Buffer ) Def_macro( "MAKEFLAGS", Buffer+1, M_PRECIOUS|M_NOEXPORT );
X
X _warn = FALSE; /* disable warnings for builtin rules */
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) != 0 );
X Clear_signals();
X Epilog(ex_val); /* Does not return -- EVER */
X}
X
X
Xstatic void
X_do_ReadEnvironment()
X{
X t_attr 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#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
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/10/06 12:03:33 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 at 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/10/06 12:03:33 dvadura
X * dmake Release, Version 3.6
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 t_attr 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 at -+%" );
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 case '+' : flag |= A_SHELL; break;
X case '%' : flag |= A_SWAP; 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/stdmacs.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > common/stdmacs.h &&
X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/common/RCS/stdmacs.h,v 1.1 90/10/06 12:04:47 dvadura Exp $
X-- SYNOPSIS -- general use macros.
X--
X-- DESCRIPTION
X-- ANSI macro relies on the fact that it can be replaced by (), or by
X-- its value, where the value is one value due to the preprocessors
X-- handling of arguments that are surrounded by ()'s as a single
X-- argument.
X--
X-- AUTHOR
X-- Dennis Vadura, dvadura at 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: stdmacs.h,v $
X * Revision 1.1 90/10/06 12:04:47 dvadura
X * dmake Release, Version 3.6
X *
X*/
X
X#ifndef MACROS_h
X#define MACROS_h
X
X#if defined(__STDC__) || defined(__TURBOC__)
X#define ANSI(x) x
X#else
X#define ANSI(x) ()
X#endif
X
X#define NIL(p) ((p*)NULL)
X#define offsetof(type,id) ((size_t)&((type*)NULL)->id)
X
X#define FALSE 0
X#define TRUE 1
X
X#endif
X
SHAR_EOF
chmod 0440 common/stdmacs.h || echo "restore of common/stdmacs.h fails"
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/10/06 12:04:56 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 at 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/10/06 12:04:56 dvadura
X * dmake Release, Version 3.6
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" );
SHAR_EOF
echo "End of part 22"
echo "File common/malloc.c is continued in part 23"
echo "23" > s2_seq_.tmp
exit 0
More information about the Comp.sources.misc
mailing list