v15i058: dmake version 3.6 (part 06/25)

Dennis Vadura dvadura at watdragon.waterloo.edu
Mon Oct 15 11:38:27 AEST 1990


Posting-number: Volume 15, Issue 58
Submitted-by: Dennis Vadura <dvadura at watdragon.waterloo.edu>
Archive-name: dmake-3.6/part06

#!/bin/sh
# this is part 6 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file rulparse.c continued
#
CurArch=6
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 rulparse.c"
sed 's/^X//' << 'SHAR_EOF' >> rulparse.c
X	  * get marked as having rules and being a target if appropriate. */
X	 do {
X	    tcp->ce_flag |= tg->ce_flag & (F_RULES|F_TARGET);
X	    tcp = tcp->ce_all;
X	 }
X	 while( tcp != tg );
X	 break;
X      }
X   }
X
X   if( tflag ) Target = TRUE;
X   _sv_rules   = NIL(STRING);
X   _sv_crule   = NIL(STRING);
X   _sv_targets = NIL(CELL);
X   _sv_glb_prq = NIL(LINK);
X   _sv_edgel   = NIL(EDGE);
X   _sp_target  = FALSE;
X   _sv_globprq_only = 0;
X
X   DB_VOID_RETURN;
X}
X
X
X
Xint
XSet_group_attributes( list )/*
X==============================
X	Scan list looking for the standard @ and - (as in recipe line defs)
X	and set the flags accordingly so that they apply when we bind the
X	rules to the appropriate targets. */
Xchar *list;
X{
X   t_attr attr = 0;
X   int done = FALSE;
X   int res  = FALSE;
X
X   DB_ENTER( "Set_group_attributes" );
X
X   while( !done )
X      switch( *list++ ) {
X	 case '@' : attr |= A_SILENT; ;break;
X	 case '-' : attr |= A_IGNORE; ;break;
X	 case '%' : attr |= A_SWAP;   ;break;
X
X         case ' ' :
X	 case '+' :
X	 case '\t': break;
X
X	 case '\0': done = TRUE; break;
X	 case '[' : res = TRUE; break;
X
X	 default  : done = TRUE; res = FALSE; break;
X      }
X
X   if( res ) _sv_attr |= attr;
X   DB_RETURN( res );
X}
X
X
X
Xstatic void
X_do_special( special, op, attr, set_dir, target, prereq, state )/*
X==================================================================
X   Process a special target.  So far the only special targets we have
X   are those recognized by the _is_special function.
X
X   target is always only a single special target.
X   
X   NOTE:  For the cases of .IMPORT, and .INCLUDE, the cells created by the
X   	  parser are never freed.  This is due to the fact that it is too much
X	  trouble to get them out of the hash table once they are defined, and
X	  if they are per chance used again it will be ok, anyway, since the
X	  cell is not really used by the code below.  */
X
Xint	special;
Xint	op;
Xt_attr	attr;
Xchar	*set_dir;
XCELLPTR target;
XCELLPTR prereq;
Xint     *state;
X{
X   HASHPTR	hp;		/* pointer to macro def cell		*/
X   CELLPTR	cp;		/* temporary pointer into cells list	*/
X   CELLPTR 	dp;		/* pointer to directory dir cell	*/
X   LINKPTR 	lp;		/* pointer at prerequisite list 	*/
X   char    	*dir;		/* current dir to prepend		*/
X   char    	*path;		/* resulting path to try to read	*/
X   char 	*name;		/* File name for processing a .INCLUDE	*/
X   char		*tmp;		/* temporary string pointer		*/
X   FILE 	*fil;		/* File descriptor returned by Openfile	*/
X
X   DB_ENTER( "_do_special" );
X
X   target->ce_flag = F_SPECIAL;	/* mark the target as special */
X
X   switch( special ) {
X      case ST_EXPORT:
X	 for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) {
X	    DB_PRINT( "par", ("Exporting [%s]", prereq->CE_NAME) );
X	    hp = GET_MACRO( prereq->CE_NAME );
X
X	    if( hp != NIL(HASH) ) {
X	       char *tmpstr = hp->ht_value;
X
X	       if( tmpstr == NIL(char) ) tmpstr = "";
X
X	       if( Write_env_string( prereq->CE_NAME, tmpstr ) != 0 )
X		  Warning( "Could not export %s", prereq->CE_NAME );
X	    }
X	 }
X	 break;
X
X      case ST_IMPORT:
X	 if( prereq != NIL(CELL) && prereq->ce_link == NIL(CELL) &&
X	     strcmp(prereq->CE_NAME, ".EVERYTHING") == 0 )
X	 {
X	    ReadEnvironment();
X	 }
X	 else {
X	    char *tmpstr;
X
X	    for( ; prereq != NIL(CELL); prereq = prereq->ce_link ) {
X	       DB_PRINT( "par", ("Importing [%s]", prereq->CE_NAME) );
X
X	       tmpstr = Read_env_string( prereq->CE_NAME );
X
X	       if( tmpstr != NIL(char) )
X		  Def_macro( prereq->CE_NAME, tmpstr, M_EXPANDED | M_LITERAL );
X	       else
X	          if( !((Glob_attr | attr) & A_IGNORE) )
X		     Fatal( "Imported macro `%s' not found", prereq->CE_NAME );
X	    }
X
X	    attr &= ~A_IGNORE;
X	 }
X	 break;
X
X      case ST_INCLUDE:
X      {
X	 int ignore = (((Glob_attr | attr) & A_IGNORE) != 0);
X	 int pushed = FALSE;
X	 CELL inc;
X	 HASH hcell;
X
X	 if( prereq == NIL(CELL) )  Fatal( "No .INCLUDE file(s) specified" );
X
X	 dp = Def_cell( ".INCLUDEDIRS", NIL(CELL) );
X
X	 if( (attr & A_SETDIR) && *(dir = strchr(set_dir, '=')+1) ) {
X	    hcell.ht_name = ".INCLUDE";
X	    inc.ce_name   = &hcell;
X	    inc.ce_dir    = dir;
X	    pushed = Push_dir( &inc, ignore );
X	 }
X
X	 for( cp=prereq; cp != NIL(CELL); cp = cp->ce_link ) {
X	    name = cp->CE_NAME;
X	    
X	    if( *name == '<' ) {
X	       /* We have a file name enclosed in <....>
X	        * so get rid of the <> arround the file name */
X
X	       name++;
X	       if( (tmp = strrchr( name, '>' )) != NIL( char ) )
X		  *tmp = 0;
X
X	       if( If_root_path( name ) )
X	          fil = Openfile( name, FALSE );
X	       else
X		  fil = NIL(FILE);
X	    }
X	    else
X	       fil = Openfile( name, FALSE );
X	       
X	    if( fil == NIL(FILE) ) {	/*if true ==> not found in current dir*/
X	       /* Now we must scan the list of prerequisites for .INCLUDEDIRS
X	        * looking for the file in each of the specified directories.
X		* if we don't find it then we issue an error.  The error
X		* message is suppressed if the .IGNORE attribute of attr is
X		* set.  If a file is found we call Parse on the file to
X		* perform the parse and then continue on from where we left
X		* off.  */
X
X	       if( (dp->CE_HOW != NIL(HOW)) &&
X		   ((lp = dp->CE_HOW->hw_prq) != NIL(LINK)) )
X		  for(; lp != NIL(LINK) && fil == NIL(FILE); lp=lp->cl_next) {
X		     dir  = lp->cl_prq->CE_NAME;
X		     if( strchr(dir, '$') ) dir = Expand(dir);
X		     path = Build_path( dir, name );
X
X		     DB_PRINT( "par", ("Trying to include [%s]", path) );
X
X		     fil = Openfile( path, FALSE );
X		     if( dir != lp->cl_prq->CE_NAME ) FREE(dir);
X		  }
X	    }
X
X	    if( fil != NIL(FILE) )
X	       Parse( fil );
X	    else if( !((Glob_attr | attr) & A_IGNORE) )
X	       Fatal( "Include file %s, not found", name );
X	 }
X
X	 if( pushed ) Pop_dir(FALSE);
X	 attr &= ~(A_IGNORE|A_SETDIR);
X      }
X      break;
X	 
X      case ST_SOURCE:
X      /* case ST_SUFFIXES: */
X      	 if( prereq != NIL(CELL) )
X	    _do_targets( op & (R_OP_CL | R_OP_MI | R_OP_UP), attr, set_dir,
X			 target, prereq );
X	 else {
X	    /* The old semantics of .SOURCE were that an empty list of
X	     * prerequisites clears the .SOURCE list.  So we must implement
X	     * that here as a clearout prerequisite operation.  Since this is
X	     * a standard operation with the :- opcode we can simply call the
X	     * proper routine with the target cell and it should do the trick
X	     */
X
X	    if( op == R_OP_CL || (op & R_OP_MI) )
X	       Clear_prerequisites( target->CE_HOW );
X	 }
X
X	 op &= ~(R_OP_MI | R_OP_UP);
X	 break;
X
X      case ST_REST:
X         /* The rest of the special targets can all take rules, as such they
X	  * must be able to affect the state of the parser. */
X
X	 {
X	    int s_targ = Target;
X
X	    Target     = TRUE;
X	    _sp_target = TRUE;
X	    *state     = _do_targets( op, attr, set_dir, target, prereq );
X	    Target     = s_targ;
X
X	    set_dir = NIL( char );
X	    attr    = A_DEFAULT;
X	    op      = R_OP_CL;
X	 }
X	 break;
X
X      default:break;
X   }
X      
X   if( set_dir != NIL(char) ) FREE( set_dir );
X   if( op   != R_OP_CL   ) Warning( "Modifier(s) for operator ignored" );
X   if( attr != A_DEFAULT ) Warning( "Extra attributes ignored" );
X
X   DB_VOID_RETURN;
X}
X
X
X
Xstatic int
X_do_targets( op, attr, set_dir, targets, prereq )/*
X================================================= */
Xint	op;
Xt_attr	attr;
Xchar	*set_dir;
XCELLPTR targets;
XCELLPTR prereq;
X{
X   CELLPTR	tg1;		/* temporary target pointer		*/
X   CELLPTR	tp1;		/* temporary prerequisite pointer	*/
X   char		*p;		/* temporary char pointer		*/
X   CELLPTR      prev_cell;	/* pointer for .UPDATEALL processing	*/
X   int		update;		/* A_UPDATEALL attribute flag		*/
X   int		smagic = 0;	/* collective amount of magic :-)	*/
X
X   DB_ENTER( "_do_targets" );
X
X   if( update = ((attr & A_UPDATEALL) != 0) )
X      if( targets == NIL(CELL) )
X	    Fatal( ".UPDATEALL attribute requires non-empty list of targets" );
X
X   prev_cell = NIL(CELL);
X   for( tg1 = targets; tg1 != NIL(CELL); tg1 = tg1->ce_link ) {
X      /* Check each target.  Check for inconsistencies between :: and : rule
X       * sets.  :: may follow either : or :: but not the reverse.  We allocate
X       * a HOW cell for each target that we see, if it already does not have
X       * one.  If it has a HOW cell then we use it, unless the current
X       * operator is ::, in which case we must allocate a new one. */
X
X      int magic  = (tg1->ce_flag & F_PERCENT) && !(tg1->ce_flag & F_MAGIC);
X      smagic |= magic;
X
X      if( !(op & R_OP_DCL ) && (tg1->ce_flag & F_MULTI) && !magic )
X	 Fatal( "Inconsistency in inference rules for %s", tg1->CE_NAME );
X
X      if( magic )
X         do {
X	    _build_graph( op, tg1, prereq );
X	    if( prereq != NIL(CELL) ) prereq = prereq->ce_link;
X	 } while( prereq != NIL(CELL) );
X      else if( !(tg1->ce_flag & F_SPECIAL) && 
X		(p = _is_magic( tg1->CE_NAME )) != NIL(char) )
X         smagic |= _do_magic( op, p, tg1, prereq, attr, set_dir );
X      else if( op & R_OP_DCL ) {
X	 HOWPTR hp;
X
X	 TALLOC( hp, 1, HOW );
X
X	 hp->hw_next   = tg1->CE_HOW;
X	 tg1->CE_HOW   = hp;
X	 tg1->ce_flag |= F_MULTI;
X      }
X      else if( tg1->CE_HOW == NIL(HOW) )
X	 TALLOC( tg1->CE_HOW, 1, HOW );
X
X      if( !magic ) _set_attributes( attr, set_dir, tg1 );
X
X      if( update ) {
X	 if( smagic ) Fatal( ".UPDATEALL attribute not legal in meta rule" );
X
X	 /* Check this as it would break another cirlcular .UPATEALL list if
X	  * we blindly assign it and it is part of another list already. */
X	 if( tg1->ce_all != NIL(CELL) )
X	    Fatal( "Target [%s] appears on multiple .UPDATEALL lists" );
X
X	 tg1->ce_all = prev_cell;
X	 prev_cell = tg1;
X      }
X
X      /* Build the proper prerequisite list of the target.  If the `-',
X       * modifier was used clear the prerequisite list before adding any
X       * new prerequisites.  Else add them to the head/tail as appropriate.
X       *
X       * If the target has F_PERCENT set then no prerequisites are used. */
X
X      if( !(tg1->ce_flag & F_PERCENT) )
X	 if( tg1 == targets || !update ) {
X	    register HOWPTR  how  = tg1->CE_HOW;
X
X	    if( op & R_OP_MI ) Clear_prerequisites( how );
X
X	    if( (op & R_OP_UP) && (how->hw_prq != NIL(LINK)) )
X	       _stick_at_head( how, prereq );
X	    else
X	       for( tp1=prereq; tp1 != NIL(CELL); tp1 = tp1->ce_link )
X		  Add_prerequisite( how, tp1, FALSE );
X	 }
X      else
X         if( op & (R_OP_MI | R_OP_UP) )
X	    Warning( "Modifier(s) `^!' for ':' operator ignored" );
X   }
X
X   if( targets != NIL(CELL) ) targets->ce_all = prev_cell;
X
X
X   /* Check to see if we have NO targets but some attributes.  IF so then
X    * apply all of the attributes to the complete list of prerequisites.
X    * Cannot happen for F_PERCENT targets. (ie. in that case targets is always
X    * not NIL) */
X
X   if( (targets == NIL(CELL)) && attr )
X      if( prereq != NIL(CELL) )
X	 for( tp1=prereq; tp1 != NIL(CELL); tp1 = tp1->ce_link ) {
X	    if( tp1->CE_HOW == NIL(HOW) ) TALLOC( tp1->CE_HOW, 1, HOW );
X	    _set_attributes( attr, set_dir, tp1 );
X	 }
X      else
X	 _set_global_attr( attr, set_dir );
X
X   /* Fix up the HOW pointers for the A_UPDATEALL case, they should all point
X    * to the same cell (targets->CE_HOW), if the .UPDATEALL attribute is given
X    */
X   if( update && targets != NIL(CELL) )
X      for( tg1=targets->ce_link; tg1 != NIL(CELL); tg1 = tg1->ce_link ) {
X	 FREE(tg1->CE_HOW);
X	 tg1->CE_HOW = targets->CE_HOW;
X      }
X
X   /* Now that we have built the lists of targets, the parser must parse the
X    * rules if there are any.  However we must start the rule list with the
X    * rule specified as via the ; kludge, if there is one */
X
X   _sv_targets = targets;
X   _sv_attr    = _sv_attro = attr;
X   _sv_flag    = ((op & R_OP_BG) ? F_SINGLE : F_DEFAULT);
X      
X   DB_RETURN( RULE_SCAN );
X}
X
X
Xstatic int
X_do_magic( op, dot, target, prereq, attr, set_dir )/*
X=====================================================
X   This function takes a magic target of the form .<chars>.<chars> or
X   .<chars> and builds the appropriate % rules for that target.
X   
X   The function builds the % rule, `%.o : %.c'  from .c.o, and
X   `%.a :' from .a */
X
Xint	op;
Xchar    *dot;
XCELLPTR target;
XCELLPTR prereq;
Xt_attr  attr;
Xchar    *set_dir;
X{
X   CELLPTR tg;
X   CELLPTR prq;
X   char    *tmp, *tmp2;
X
X   DB_ENTER( "_do_magic" );
X
X   if( prereq != NIL(CELL) )
X      Warning( "Ignoring prerequisites of old style meta-target" );
X
X   op &= (R_OP_CL | R_OP_DCL);
X
X   if( dot == target->CE_NAME )	{		/* its of the form .a	*/
X      tg  = Def_cell( "%", NIL(CELL) );		/* ==> no prerequisite  */
X      tmp = _build_meta( target->CE_NAME );
X      prq = Def_cell( tmp, NIL(CELL) );
X      FREE( tmp );
X
X      _build_graph( op, tg, prq );
X   }
X   else {
X      tmp = _build_meta( dot );
X      tg  = Def_cell( tmp, NIL(CELL) );
X      FREE( tmp );
X
X      tmp = _build_meta( tmp2 = _substr( target->CE_NAME, dot ) );
X      prq = Def_cell( tmp, NIL(CELL) );
X      FREE( tmp  );
X      FREE( tmp2 );
X
X      _build_graph( op, tg, prq );
X   }
X
X   tg->ce_flag      |= F_PERCENT;
X   target->ce_flag  |= (tg->ce_flag & (F_MULTI | F_PERCENT)) | F_MAGIC;
X   target->CE_EDGES  = tg->CE_EDGES;
X
X   _set_attributes( attr, set_dir, tg );
X
X   DB_RETURN(1);
X}
X
X
X
Xstatic char *
X_build_meta( name )/*
X=====================
X   Check to see if the name is of the form .c~ if so and if Augmake
X   translation is enabled then return s.%.c, else return %.suff, where if the
X   suffix ends in '~' then leave it be.*/
Xchar *name;
X{
X   char *tmp;
X   int  test = Augmake ? name[strlen(name)-1] == '~' : 0;
X
X   tmp = _strjoin( test ? "s.%" : "%", name, -1, FALSE);
X   if( test ) tmp[ strlen(tmp)-1 ] = '\0';
X
X   return(tmp);
X}
X
X
X
Xstatic void
X_build_graph( op, target, prereq )/*
X====================================
X   This function is called to build the graph for the % rule given by
X   target : prereq cell combination.  This function assumes that target
X   is a % target and that prereq is a single % prerequisite.  op can be
X   either R_OP_CL or R_OP_DCL, all other operations are ignored.
X   
X   It also assumes that target cell has F_PERCENT set already. */
Xint op;
XCELLPTR target;
XCELLPTR prereq;
X{
X   int      match;
X   EDGEPTR  edge;
X
X   DB_ENTER( "_build_graph" );
X   DB_PRINT( "%", ("Building graph for [%s : %s]", target->CE_NAME,
X   	     (prereq == NIL(CELL)) ? "" : prereq->CE_NAME) );
X
X   if( prereq != NIL(CELL) ) {
X      char *name = prereq->CE_NAME;
X      int   len  = strlen(name);
X
X      if( *name == '\'' && name[len-1]=='\'' ){
X	 _add_global_prereq( prereq );
X	 name[len-1] = '\0';
X	 strcpy(name, name+1);
X	 DB_VOID_RETURN;
X      }
X   }
X
X   /* The list of edges is kept as a circular list.  Thus we must find the
X    * last edge if we are to add a new edge.  Also we must check the list to
X    * find out if a new edge needs to be added. */
X
X   match = FALSE;
X   if( (edge = target->CE_EDGES) != NIL(EDGE) ) {
X      EDGEPTR start;
X
X      start = edge;
X      do {
X	 DB_PRINT( "%", ("Trying to match [%s]", edge->ed_prq->CE_NAME) );
X
X         if( edge->ed_prq == prereq )
X	    match = TRUE;
X	 else
X	    edge  = edge->ed_next;
X      }
X      while ( !match && start != edge );
X   }
X
X   if( match ) {
X      /* match is TRUE hence, we found an edge joining the target and the
X       * prerequisite so set the current target's CE_EDGES pointer to point
X       * at the edge we found and make sure the new edge has a valid HOW
X       * pointer. */
X
X      DB_PRINT( "%", ("It's an old edge") );
X
X      target->CE_EDGES = edge;
X
X      if( op & R_OP_DCL ) {
X         HOWPTR hp;
X
X	 TALLOC( hp, 1, HOW );
X
X	 hp->hw_next   = edge->ed_how;
X	 edge->ed_how  = hp;
X      }
X      else {
X	 HOWPTR hp = edge->ed_how;
X
X	 hp->hw_flag = F_DEFAULT;
X	 hp->hw_attr = A_DEFAULT;
X	 target->ce_dir    = NIL(char);
X	 target->ce_flag  &= (F_PERCENT|F_MAGIC);
X	 target->ce_attr  &= A_NOINFER;
X      }
X	
X   }
X   else {
X      EDGEPTR tedge;
X
X      TALLOC( tedge, 1, EDGE );
X
X      if( edge == NIL(EDGE) ) {
X	 DB_PRINT( "%", ("It's a new edge") );
X	 edge = tedge;
X	 target->CE_EDGES = edge->ed_next = edge;
X      }
X      else {
X	 DB_PRINT( "%", ("It's a new edge (non-empty edge list)") );
X	 tedge->ed_next   = edge->ed_next;
X	 edge->ed_next    = tedge;
X	 target->CE_EDGES = edge = tedge;
X      }
X
X      /* This was a new edge so we must point it's prerequisite pointer at the
X       * prerequisite, and add the first HOW cell.
X       * Since this is also the first time we have seen the % target we
X       * add it to the NFA we are building of % rule targets. */
X
X      TALLOC( edge->ed_how, 1, HOW );
X
X      edge->ed_prq = prereq;
X      edge->ed_tg  = target;
X
X      if( !(target->ce_flag & F_DFA) ) {
X	 Add_nfa( target->CE_NAME );
X	 target->ce_flag |= F_DFA;
X      }
X
X      if( op & R_OP_DCL ) target->ce_flag |= F_MULTI;
X   }
X
X   edge->ed_link = _sv_edgel;
X   _sv_edgel = edge;
X   _sv_globprq_only = 0;
X
X   DB_VOID_RETURN;
X}
X
X
X
Xstatic void
X_add_global_prereq( pq )/*
X==========================
X	Prerequisite is a non-% prerequisite for a %-rule target, add it to
X	the target's list of global prerequsites to add on match */
XCELLPTR pq;
X{
X   register LINKPTR ln;
X
X   TALLOC( ln, 1, LINK );
X   ln->cl_next = _sv_glb_prq;
X   ln->cl_prq  = pq;
X   _sv_glb_prq = ln;
X}
X
X
X
Xstatic void
X_set_attributes( attr, set_dir, cell )/*
X=============================================
X	Set the appropriate attributes for a cell */
Xt_attr	attr;
Xchar	*set_dir;
XCELLPTR cell;
X{
X   char   *dir;
X
X   DB_ENTER( "_set_attributes" );
X
X   /* If .SETDIR attribute is set then we have at least .SETDIR= in the
X    * set_dir string.  So go and fishout what is at the end of the =.
X    * If not set and not NULL then propagate it to the target cell. */
X
X   if( attr & A_SETDIR ) {
X      dir = strchr( set_dir, '=' ) + 1;
X
X      if( cell->ce_attr & A_SETDIR )
X	 Warning( "Multiple .SETDIR for %s ignored", cell->CE_NAME );
X      else
X	 if( *dir ) cell->ce_dir = dir;
X   }
X   cell->ce_attr |= attr;		/* set rest of attributes for target */
X
X   DB_VOID_RETURN;
X}
X
X
X
Xstatic void
X_set_global_attr( attr, dir )/*
X===============================
X	Handle the setting of the global attribute functions based on
X	The attribute flags set in attr.  Note we set the dir path name
X	to be the value of Start_dir.  If Start_dir is initially set
X	Make will CD to that directory before making any targets. */
Xt_attr attr;
Xchar   *dir;
X{
X   int flag;
X
X   /* Some compilers can't handle a switch on a long, and t_attr is now a long
X    * integer on some systems.  foey! */
X   for( flag = MAX_ATTR; flag; flag >>= 1 )
X      if( flag & attr )
X	 if( flag == A_PRECIOUS)      Def_macro(".PRECIOUS",  "y", M_EXPANDED);
X	 else if( flag == A_SILENT)   Def_macro(".SILENT",    "y", M_EXPANDED);
X	 else if( flag == A_IGNORE )  Def_macro(".IGNORE",    "y", M_EXPANDED);
X	 else if( flag == A_EPILOG )  Def_macro(".EPILOG",    "y", M_EXPANDED);
X	 else if( flag == A_PROLOG )  Def_macro(".PROLOG",    "y", M_EXPANDED);
X	 else if( flag == A_NOINFER ) Def_macro(".NOINFER",   "y", M_EXPANDED);
X	 else if( flag == A_SEQ )     Def_macro(".SEQUENTIAL","y", M_EXPANDED);
X	 else if( flag == A_SHELL )   Def_macro(".USESHELL",  "y", M_EXPANDED);
X	 else if( flag == A_MKSARGS ) Def_macro(".MKSARGS",   "y", M_EXPANDED);
X	 else if( flag == A_SWAP )    Def_macro(".SWAP",      "y", M_EXPANDED);
X	 else if( flag == A_SETDIR ) {
X	    dir = strchr( dir, '=' ) + 1;
X	    if( *dir ) Start_dir.ce_dir = dir;
X	 }
X   
X   attr &= ~A_GLOB;
X   if( attr ) Warning( "Non global attribute(s) ignored" );
X}
X
X
X
Xstatic void
X_stick_at_head( how, pq )/*
X===========================
X	Add the prerequisite list to the head of the existing prerequisite
X	list */
X
XHOWPTR  how;		/* HOW cell for target node	*/
XCELLPTR pq;		/* list of prerequisites to add */
X{
X   DB_ENTER( "_stick_at_head" );
X
X   if( pq->ce_link != NIL(CELL) ) _stick_at_head( how, pq->ce_link );
X   Add_prerequisite( how, pq, TRUE );
X
X   DB_VOID_RETURN;
X}
X
X
X
Xstatic t_attr
X_is_attribute( name )/*
X=======================
X   Check the passed name against the list of valid attributes and return the
X   attribute index if it is, else return 0, indicating the name is not a valid
X   attribute.  The present attributes are defined in dmake.h as A_xxx #defines,
X   with the corresponding makefile specification:  (note they must be named
X   exactly as defined below)
X   
X   Valid attributes are:  .IGNORE, .SETDIR=, .SILENT, .PRECIOUS, .LIBRARY,
X                          .EPILOG, .PROLOG,  .LIBRARYM, .SYMBOL, .UPDATEALL,
X			  .USESHELL, .NOINFER
X
X   NOTE:  The strcmp's are OK since at most three are ever executed for any
X          one attribute check, and that happens only when we can be fairly
X          certain we have an attribute.  */
Xchar *name;
X{
X   t_attr attr = 0;
X   
X   DB_ENTER( "_is_attribute" );
X   
X   if( *name++ == '.' )
X      switch( *name )
X      {
X         case 'E': attr = (strcmp(name, "EPILOG"))   ? 0 : A_EPILOG;  break;
X         case 'I': attr = (strcmp(name, "IGNORE"))   ? 0 : A_IGNORE;  break;
X         case 'L': attr = (strcmp(name, "LIBRARY"))  ? 0 : A_LIBRARY; break;
X         case 'M': attr = (strcmp(name, "MKSARGS"))  ? 0 : A_MKSARGS; break;
X         case 'N': attr = (strcmp(name, "NOINFER"))  ? 0 : A_NOINFER; break;
X
X         case 'U':
X	    if( !strcmp(name, "UPDATEALL") )    attr = A_UPDATEALL;
X	    else if( !strcmp(name, "USESHELL")) attr = A_SHELL;
X	    else attr = 0;
X	    break;
X
X         case 'P':
X            if( !strcmp(name, "PRECIOUS") )     attr = A_PRECIOUS;
X            else if( !strcmp(name, "PROLOG") )  attr = A_PROLOG;
X            else attr = 0;
X            break;
X
X         case 'S':
X            if( !strncmp(name, "SETDIR=", 7) )    attr = A_SETDIR;
X            else if( !strcmp(name, "SILENT") )    attr = A_SILENT;
X            else if( !strcmp(name, "SYMBOL") )    attr = A_SYMBOL;
X            else if( !strcmp(name, "SEQUENTIAL")) attr = A_SEQ;
X            else if( !strcmp(name, "SWAP"))       attr = A_SWAP;
X            else attr = 0;
X            break;
X      }
X
X   DB_RETURN( attr );
X}
X
X
X
Xstatic int
X_is_special( tg )/*
X===================
X   This function returns TRUE if the name passed in represents a special
X   target, otherwise it returns false.  A special target is one that has
X   a special meaning to dmake, and may require processing at the time that
X   it is parsed.
X   
X   Current Special targets are:
X	.GROUPPROLOG	.GROUPEPILOG	.INCLUDE	.IMPORT
X	.EXPORT		.SOURCE 	.SUFFIXES	.ERROR
X	.INCLUDEDIRS	.MAKEFILES	.REMOVE
X*/
Xchar *tg;
X{
X   DB_ENTER( "_is_special" );
X   
X   if( *tg++ != '.' ) DB_RETURN( 0 );
X   
X   switch( *tg )
X   {
X      case 'I':
X         if( !strcmp( tg, "IMPORT" ) )		DB_RETURN( ST_IMPORT   );
X         else if( !strcmp( tg, "INCLUDE" ) )	DB_RETURN( ST_INCLUDE  );
X	 else if( !strcmp( tg, "INCLUDEDIRS" )) DB_RETURN( ST_REST     );
X	 break;
X      
X      case 'M':
X         if( !strcmp( tg, "MAKEFILES" ) )	DB_RETURN( ST_REST     );
X	 break;
X
X      case 'E':
X         if( !strcmp( tg, "ERROR" ) )		DB_RETURN( ST_REST     );
X         else if( !strcmp( tg, "EXPORT" ) )	DB_RETURN( ST_EXPORT   );
X	 break;
X
X      case 'G':
X	 if( !strcmp( tg, "GROUPPROLOG" ))      DB_RETURN( ST_REST     );
X	 else if( !strcmp( tg, "GROUPEPILOG" )) DB_RETURN( ST_REST     );
X	 break;
X
X      case 'R':
X         if( !strcmp( tg, "REMOVE" ) )		DB_RETURN( ST_REST     );
X	 break;
X
X      case 'S':
X         if( !strncmp( tg, "SOURCE", 6 ) )	DB_RETURN( ST_SOURCE   );
X         else if( !strncmp(tg, "SUFFIXES", 8 )) DB_RETURN( ST_SOURCE   );
X	 break;
X   }
X   
X   DB_RETURN( 0 );
X}
X
X
X
Xstatic int
X_is_percent( np )/*
X===================
X	return TRUE if np points at a string containing a % sign */
Xchar *np;
X{
X   return( (strchr(np,'%') && (*np != '\'' && np[strlen(np)-1] != '\'')) ?
X	   TRUE : FALSE );
X}
X
X
Xstatic char *
X_is_magic( np )/*
X=================
X	return TRUE if np points at a string of the form
X	      .<chars>.<chars>  or  .<chars>
X	where chars are only alpha characters.
X
X        NOTE:  reject target if it begins with ./ or ../ */
Xchar *np;
X{
X   register char *n;
X
X   n = np;
X   if( *n != '.' ) return( NIL(char) );
X   if (strchr(DirBrkStr, *(n+1))!=NULL || *(n+1) == '.' )
X      return (NIL(char));
X
X   for( n++; isgraph(*n) && (*n != '.'); n++ );
X
X   if( *n != '\0' ) {
X      if( *n != '.' )  return( NIL(char) );
X      for( np = n++; isgraph( *n ) && (*n != '.'); n++ );
X      if( *n != '\0' ) return( NIL(char) );
X   }
X   else if( !Augmake )
X      return( NIL(char) );
X
X   /* np points at the second . of .<chars>.<chars> string.
X    * if the special target is of the form .<chars> then np points at the
X    * first . in the token. */
X
X   return( np );
X}
X
SHAR_EOF
echo "File rulparse.c is complete"
chmod 0440 rulparse.c || echo "restore of rulparse.c fails"
echo mkdir - readme
mkdir readme
echo "x - extracting readme/release (Text)"
sed 's/^X//' << 'SHAR_EOF' > readme/release &&
Xdmake Version 3.6
X=================
X
XMANDATORY REPLACEMENT FOR VERSION 3.5 PATCH LEVEL 1 and PATCH LEVEL 2
X
XNature:   This version of dmake MUST replace all versions of dmake 3.5 patch
X-------   levels 1 and 2, and all versions of dmake 3.5 patch level 1 and 2
X	  must then be DELETED.  This release addresses several issues.
X
X		1. Copyright infringement claim made by MKS, of Waterloo.
X		2. Modifications to text diversion processing.
X		3. Support for DOS Swapping, and MKS argument passing.
X		4. Other minor nits and tweaks.
X
X	  This distribution advances dmake to Version 3.6, patch level 1.  This
X	  version is certified free of MKS copyrighted code.  See below for
X	  details.
X          
XAvailability:
X-------------
X	  dmake is available via anonymous ftp from watmsg.uwaterloo.edu
X	  (129.97.129.9) as:
X
X	     pub/src/dmake-3.6.tar.Z
X	     pub/src/dmake-3.6.zoo 
X
X	  and comes in either a compressed tar or zoo archive take your pick.
X
XAcknowledgements:
X-----------------
X	  Thanks to all who submitted code for new features, suggestions for
X	  improvements, and bug fixes.  Special thanks to those who helped
X	  test this version of dmake on the many platforms that the
X	  distribution now supports.  I have tried to make sure no gotchas
X	  remain, if you encounter problems installing or running dmake please
X	  let me know.  As always, I am always happy to receive e-mail.
X
X
XDETAILS OF CHANGES:
X===================
X
XMKS Copyright Infringement:
X---------------------------
X   Due to a misunderstanding over past contractual obligations between
X   myself and Mortice Kern Systems of Waterloo, Ontario, Canada (MKS),
X   the original posting of dmake unitentionally contains some code
X   derived from MKS proprietary code.
X
X   This version rectifies that situation and MUST replace all versions
X   of DMAKE and DMAKE patches that have been previously distributed.
X   Please delete from any archive site versions of DMAKE source code
X   labeled 3.5 patch level 1 or patch level 2 and dmake 3.5 patch 1.
X
X   Version 3.6 of the dmake source replaces *ALL* MKS proprietary code.
X   In particular, putenv.c in the bsd43 and sysvr1 directories is new.
X   Three routines in percent.c;  Add_dfa, Construct_dfa, and Advance_dfa
X   have been replaced.  Lastly, TEXT DIVERSION processing has been removed
X   from make.c and <+...+> constructions are replaced by the $(mktmp ...)
X   construct (see below for more details).  The changes relating to the
X   above mentioned modifications have been reviewed by MKS and certified by
X   MKS to be free of MKS proprietary code.  The note below is from MKS
X   and releases dmake version 3.6 patch level 1 from any MKS copyright
X   infringement claims.
X
X	"MKS has reviewed the latest sources, as of 90.09.20,
X	 for the files make.c, putenv.c, and percent.c, which
X	 are part of the program dmake version 3.6, and found
X	 these files to be free of MKS proprietary source code."
X
X   No functionality is lost as a result of these changes, however
X   certain constructs may have to be expressed using a new syntax.  See
X   the documentation and the comments below for details.
X
X
XText Diversion Processing:
X--------------------------
X   As alluded to above, the <+...+> text diversion facility has been
X   officially replaced by a new facility of the form $(mktmp ...) details of
X   which may be found in the TEXT DIVERSION section of the documentation.
X   Briefly, the construct:
X
X        exe:; link @<+$(OBJFILES:t"+\n")+>
X
X   is replaced by:
X
X        exe:; link @$(mktmp $(OBJFILES:t"+\n"))
X
X   similarly the construct:
X
X        all :
X                echo hi <+
X                line1
X                line2 +>
X
X   is replaced by:
X
X        all :
X                echo hi $(mktmp\
X                line1\n\
X                line2)
X
X   where the \n\ is added to the end of each line within the data portion of
X   the $(mktmp ...) construction.  For a number of reasons it is my belief
X   that this new construct is a better implementation of text diversions than
X   the previous <+...+> as it can be used in macro expressions that appear
X   anywhere in the makefile.
X
X   Compatibility is retained for previous versions of dmake that utilize
X   a simple form of the <+...+> construct.  If your <+...+> constructs do not
X   span multiple lines (cf second example above), then the new version of
X   dmke will recognize these and will map them to the appropriate
X   $(mktmp ...) construct.  Thus, If you use <+...+> and you do not allow the
X   interior data to span multiple lines and both <+ and +> appear as clear
X   text in the same recipe line or macro value, then dmake will process these
X   correctly and the output is 100% compatible to version 3.5 patch level 2.
X   Any other use of <+...+> must be converted to the new $(mktmp ...) form.
X
X   The new form also provides for massaging the name of the temporary file
X   which replaces the text in the recipe.  See the documentation regarding
X   the special macros USESHELL, TMPFILE, and DIVSHELL.  This is of most use
X   in an MSDOS environment.
X
X
XDOS Swapping, and MKS argument passing:
X---------------------------------------
X   dmake now supports swapping the executable image to secondary storage when
X   it executes a child.  Swapping is enabled by setting the new attribute
X   .SWAP to on, either for a target or globally, or by specifying the '%'
X   modifier to a recipe line.  So for example:
X
X	xx .SWAP :; recipe
X
X   and
X
X	xx :;% recipe
X
X   are equivalent.
X
X   The MKS DOS argument passing conventions are now supported, and dmake is
X   able to communicate with programs that understand those conventions.  The
X   global variable .MKSARGS is used to enable/disable this facility.  With
X   these modifications, dmake now supports long command lines for running
X   commands that understand the MKS argument passing convention, and it does
X   not run into memory limitations when executing child processes in most
X   situations.
X
X   Both .SWAP and .MKSARGS are ignored by non-MSDOS versions of dmake.
X   See the manual page for further details.
X
X
XOther tweaks modifications and BUG FIXES:
X-----------------------------------------
X-- Slight modifications to msdos/startup.mk files.  Set DIRSEPSTR to \
X   if using command.com as the shell, otherwise set internaly to /.
X   Removed -o $@ from MSC startup.mk, and added $(ASFLAGS) to %$O : %$S
X   rule, in all default DOS startup.mk files.
X
X-- Added POSIX '+' character to start of recipe lines.  You can use this
X   to force the recipe line to be executed by a shell, in addition to the
X   test used for .SHELLMETAS.
X
X   To make the '+' fit into the dmake mold, a new attribute has been created.
X   the .USESHELL attribute forces the use of a shell for the target or
X   recipe group for which it is specified.  If it is specified as a global
X   attribute then all recipes executed will use a shell.  The macro variable
X   .USESHELL corresponds to the special target '.USESHELL :' in the same way
X   that .IGNORE corresponds to '.IGNORE :'.
X
X-- Added *= and *:= macro assignmen operator, patches from 
X   Piercarlo Grandi <pcg at compsci.aberystwyth.ac.uk>, see the documentation
X   for more details.
X
X-- Changed makefile.mk to force use of a shell (via '+') to make OBJDIR,
X   doesn't break on baren DOS systems that way :-).  Many other small changes
X   to msdos and unix versions of various config.mk files.
X
X-- Added two new macros related to diversion file processing.
X   See the TEXT DIVERSIONS section of the man page for an explanation of this
X   functionality.
X
X        TMPFILE - is set to the name of the temporary file whenever
X                  a temporary file is opened by dmake.
X        USESHELL- It's value is 'no' if the current recipe line is not forced
X		  to use a shell via a '+' or .USESHELL directive.  It's
X		  value is 'yes' if such a directive is given.
X	DIVFILE - is defined in startup.mk and gives a macro to use to set
X		  name of the diversion file, (under UNIX, DIVFILE defaults to
X		  $(TMPFILE), under MSDOS it is the value of $(TMPFILE) with
X		  any / replaced by the appropriate number of \ depending, on
X		  if a shell is used or not).
X
X-- \\ appearing at the end of a line does not cause a continuation to the next
X   line.
X
X-- Modified the definition of macro supplied from the command line to allow
X   macros defined using += or +:= to be modified further from within the
X   makefile.
X
X-- Added MAKETARGETS macro which contains the name of the target(s), if any,
X   specified on the command line.
X
X-- Modified Pack_argv in sysintf.c to use dynamic memory allocation rather
X   than limit it to a fixed number of arguments.
X
X-- BIG BUG FIX:
X   This one is cute.  It turns out that all individual recipe line
X   attributes supplied via '@', '-', and now '+' and '%' characters were
X   getting or'ed together and applied to ALL recipe lines of the recipe, yulk!
X
X-- BUG FIX:
X   Fixed off by one error in make.c:_print_cmnd when remapping \n after
X   printing the text.
X
X-- BUG FIX:  Bug reported by holos0!lbr at gatech.edu
X   Inferred prerequisites were not getting made when a target was found to
X   be out of date relative to a non-inferred prerequisite, and the inferred
X   prerequisite did not exist but the file it could be made from did and was
X   not out of date relative to the target.  This was a problem with the
X   following setup.
X
X        file.o : header.h
X
X   File system contains file.o, header.h and RCS/file.c,v, If file.o is newer
X   than RCS/file.c,v and older than header.h, then dmake didn't check out
X   file.c prior to doing the compile.
X
X-- BUG FIX: Applied patch from UUCP: twc at legal or ...sun!ys2!legal!twc
X   to msdos/_chdir.c to fix changing of directory in OS/2 protected mode
X
X-- BUG FIX: Applied patch from UUCP: twc at legal or ...sun!ys2!legal!twc
X   to msdos/switchar.c to read environment variable SWITCHAR instead of using
X   unsupported call in DOS.  OS/2 doesn't have _get_switchar call!  (It damn
X   well should though!  Microsoft is really dumb in this respect!)
X
X   Extended this patch to use SWITCHAR environment variable in all DOS
X   versions.  This ensures that DOS 4.0 can selectively change SWITCHAR by
X   using the environment variable.
X
X   Dmake now first gets SWITCHAR from the environment and if that fails it
X   tries the unsupported MSDOS call.  Under UNIX getswitchar returns '-'
X   as before.
X
X-- BUG FIX: Changed the line _ar.ar_size = atol(arhdr.ar_size) found in
X   ar_scan() in arlib.c to not use atol() if ASCARCH is FALSE.  I forget who
X   reported this one :-)
SHAR_EOF
chmod 0640 readme/release || echo "restore of readme/release fails"
echo "x - extracting readme/os2 (Text)"
sed 's/^X//' << 'SHAR_EOF' > readme/os2 &&
XAs shipped the DOS versions of dmake will run under OS/2 protected mode.
XI have a port that works in real mode but it was based on the DOS version.
XI would like to produce an independent OS/2 directory (cf unix) that contains
Xall necessary files to make an OS/2 version, and to boot strap it with a
Xcommand shell.  If anyone is willing to do this I will send them the OS/2
Xmods that need to be made.
SHAR_EOF
chmod 0640 readme/os2 || echo "restore of readme/os2 fails"
echo "x - extracting readme/msdos (Text)"
sed 's/^X//' << 'SHAR_EOF' > readme/msdos &&
XSome notes on the MSDOS implementation of dmake.
X
XMaking the binary:
X------------------
X
X   Turbo-C:  By default the turbo-C (make tcc) script will make a version
X	     of the binary that is compiled for an 8088 and up cpu.  Once made
X	     you can make a version for a 186 or 286 by modifying
X	     msdos/tccdos/config.mk and setting CFLAGS to contain the right
X	     flags, comments are supplied in the makefile to do so.
X
X	     The contents of the default response files
X	     (named in msdos/tccdos/mk*.bat) assume specific locations for
X	     your turbo-C libraries, you may need to edit these before actually
X	     getting a successful binary linked.
X
X   Microsoft-C 4.0 to 5.1:
X	     Is straight forward, just type 'make msc' and the compile will
X	     chunk along.
X
X   Microsoft-C 6.0:
X	     Is equally easy, just type 'make msc60' and the compile will
X	     chunk along.  Once made, if you want to use dmake to compile
X	     itself then set the environment variable MSC_VER=6.0, otherwise
X	     the compile flags will not be correct.  You may also supply this
X	     as an option on the dmake command line.
X
X   Memory Requirements and Swapping:
X	     dmake requires quite a bit of memory to run.  As a result
X	     a swapping version of dmake is made if you issue the command
X	     'make tccswp', 'make mscswp' or 'make msc60swp'.  If you leave
X	     the 'swp' off then corresponding (as described above) non-swapping
X	     versions are made.
X
X	     The swapping code currently only swaps to DISK, I have left hooks
X	     in to accomodate XMS and EMS, I have some code that performs the
X	     necessary XMS/EMS accesses but have not incorporated it in yet.
X	     It appears that a ramdisk seems to work just fine.  If anyone
X	     wishes to fill in the hooks please do and I'll be happy to include
X	     them in future distributions.
X
X   dmake 'makefile.mk' control variables:
X	     Initially dmake is compiled for the compact memory model.
X	     Setting MODEL={s,c,m,l} on the command line will select a different
X	     memory model.  Setting NOSWAP:=1 on the command line
X	     will disable the compile and linking of the swap code.
X	     A summary of the available configuration variables follows:
X
X	          MODEL={s,c,m,l}  - Select {small, compact, medium, large}
X		  		     memory model respectively.
X		  NOSWAP:=y	   - If set, do not compile the dmake
X		  		     swapping version of spawnvpe.
X		  MSC_VER:=6.0	   - Must be set if using MSC 6.0 and dmake
X		  		     is used to make a new version of dmake.
X
X   ^C and stopping a make:
X	     Handling of ^C in the swapping version seems to be somewhat
SHAR_EOF
echo "End of part 6"
echo "File readme/msdos is continued in part 7"
echo "7" > s2_seq_.tmp
exit 0



More information about the Comp.sources.misc mailing list