home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-07-26 | 39.4 KB | 1,370 lines |
- Newsgroups: comp.sources.misc
- subject: v14i015: dmake version 3.5 part 5/21
- From: dvadura@watdragon.waterloo.edu (Dennis Vadura)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 14, Issue 15
- Submitted-by: dvadura@watdragon.waterloo.edu (Dennis Vadura)
- Archive-name: dmake/part05
-
- #!/bin/sh
- # this is part 5 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file rulparse.c continued
- #
- CurArch=5
- 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 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;
- Xint 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) )
- 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;
- Xint 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_dfa( 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 */
- Xint 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. */
- Xint attr;
- Xchar *dir;
- X{
- X int flag;
- X
- X for( flag = MAX_ATTR; flag; flag >>= 1 )
- X switch( flag & attr )
- X {
- X case A_PRECIOUS: Def_macro(".PRECIOUS", "y", M_EXPANDED); break;
- X case A_SILENT: Def_macro(".SILENT", "y", M_EXPANDED); break;
- X case A_IGNORE: Def_macro(".IGNORE", "y", M_EXPANDED); break;
- X case A_EPILOG: Def_macro(".EPILOG", "y", M_EXPANDED); break;
- X case A_PROLOG: Def_macro(".PROLOG", "y", M_EXPANDED); break;
- X case A_NOINFER: Def_macro(".NOINFER", "y", M_EXPANDED); break;
- X case A_SEQ: Def_macro(".SEQUENTIAL","y",M_EXPANDED); break;
- X
- X case A_SETDIR:
- X dir = strchr( dir, '=' ) + 1;
- X if( *dir ) Start_dir.ce_dir = dir;
- X break;
- X }
- X
- X attr &= ~(A_PRECIOUS | A_SETDIR | A_SILENT | A_IGNORE |
- X A_EPILOG | A_PROLOG | A_NOINFER | A_SEQ);
- X
- X if( attr )
- X 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 int
- 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 .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 int 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 'N': attr = (strcmp(name, "NOINFER")) ? 0 : A_NOINFER; break;
- X case 'U': attr = (strcmp(name, "UPDATEALL"))? 0 : A_UPDATEALL;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 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 "x - extracting quit.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > quit.c &&
- X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/quit.c,v 1.1 90/07/19 13:53:29 dvadura Exp $
- X-- SYNOPSIS -- end the dmake session.
- X--
- X-- DESCRIPTION
- X-- Handles dmake termination.
- 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: quit.c,v $
- X * Revision 1.1 90/07/19 13:53:29 dvadura
- X * Initial Revision of Version 3.5
- X *
- X*/
- X
- X#include "extern.h"
- X
- Xstatic void _handle_quit ANSI((char*));
- Xstatic int _dont_quit = 0;
- X
- X
- Xvoid
- XQuit()/*
- X======== Error or quit */
- X{
- X if( _dont_quit ) return;
- X
- X while( Closefile() != NIL( FILE ) );
- X Clean_up_processes();
- X
- X if( Current_target != NIL(HOW) )
- X Unlink_temp_files(Current_target);
- X
- X if( _dont_quit == 0 ) _handle_quit( ".ERROR" );
- X
- X Set_dir( Makedir ); /* No Error message if we can't do it */
- X Epilog( ERROR_EXIT_VALUE );
- X}
- X
- X
- Xstatic void
- X_handle_quit( err_target )/*
- X============================
- X Called by quit and the others to handle the execution of termination code
- X from within make */
- Xchar *err_target;
- X{
- X HASHPTR hp;
- X CELLPTR cp;
- X
- X if( (hp = Get_name(err_target, Defs, FALSE, NIL(CELL))) != NIL(HASH) ) {
- X cp = hp->CP_OWNR;
- X Glob_attr |= A_IGNORE;
- X
- X _dont_quit = 1;
- X cp->ce_flag |= F_TARGET;
- X Make( cp, cp->CE_HOW, NIL(CELL) );
- X }
- X}
- SHAR_EOF
- chmod 0440 quit.c || echo "restore of quit.c fails"
- echo "x - extracting percent.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > percent.c &&
- X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/percent.c,v 1.1 90/07/19 13:53:25 dvadura Exp $
- X-- SYNOPSIS -- handle building or %-rule meta-target nfa.
- X--
- X-- DESCRIPTION
- X-- Builds the NFA used by dmake to match targets against %-meta
- X-- rule constructs. The NFA is built as a set of DFA's.
- 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: percent.c,v $
- X * Revision 1.1 90/07/19 13:53:25 dvadura
- X * Initial Revision of Version 3.5
- X *
- X*/
- X
- X#include "extern.h"
- X#include "alloc.h"
- X#include "db.h"
- X
- X#define NO_ACTION 0
- X#define START_PERCENT 1
- X#define END_PERCENT 2
- X#define ACCEPT 4
- X#define EPSILON 8
- X#define FAIL -1
- X
- Xstatic NFAPTR _nfa = NIL( NFA );
- X
- X
- XDFALINKPTR
- XMatch_dfa( buf )/*
- X==================
- X This routines runs all DFA's in parrallel and selects the one that best
- X matches the string. If no match then it returns NIL( DFA ) */
- Xchar *buf;
- X{
- X register NFAPTR nfa;
- X int adv;
- X DFALINKPTR dfa_list = NIL(DFALINK);
- X
- X DB_ENTER( "Match_dfa" );
- X DB_PRINT( "dfa", ("Matching %s", buf) );
- X
- X /* Run each of the DFA's on the input string in parallel, we terminate
- X * when all DFA's have either failed or ACCEPTED, if more than one DFA
- X * accepts we build a list of all accepting DFA's sorted on states with
- X * those matching in a higher numbered state heading the list. */
- X
- X do {
- X adv = FALSE;
- X
- X for( nfa = _nfa; nfa != NIL( NFA ); nfa = nfa->next )
- X if( nfa->status != (char) FAIL && nfa->status != (char) ACCEPT ) {
- X adv++;
- X nfa->status = Advance_dfa( nfa->dfa, buf );
- X
- X /* Construct the list of matching DFA's */
- X if( nfa->status == (char) ACCEPT ) {
- X DFALINKPTR dl;
- X
- X TALLOC( dl, 1, DFALINK );
- X dl->dl_meta = nfa->dfa->node;
- X dl->dl_per = _substr( nfa->dfa->pstart, nfa->dfa->pend );
- X dl->dl_state = nfa->dfa->n_states;
- X
- X if( dfa_list == NIL(DFALINK) )
- X dfa_list = dl;
- X else {
- X DFALINKPTR tdli = dfa_list;
- X DFALINKPTR tdlp = NIL(DFALINK);
- X
- X for( ; tdli != NIL(DFALINK); tdli = tdli->dl_next ) {
- X if( dl->dl_state >= tdli->dl_state )
- X break;
- X tdlp = tdli;
- X }
- X
- X if( tdli != NIL(DFALINK) ) {
- X tdli->dl_prev = dl;
- X dl->dl_next = tdli;
- X }
- X
- X if( tdlp != NIL(DFALINK) ) {
- X tdlp->dl_next = dl;
- X dl->dl_prev = tdlp;
- X }
- X else
- X dfa_list = dl;
- X }
- X
- X DB_PRINT( "dfa", ("Matched [%s]", dl->dl_meta->CE_NAME) );
- X }
- X }
- X
- X buf++;
- X }
- X while ( adv );
- X
- X for( nfa = _nfa; nfa != NIL( NFA ); nfa = nfa->next )
- X nfa->status = nfa->dfa->c_state = 0;
- X
- X DB_RETURN( dfa_list );
- X}
- X
- X
- X
- Xvoid
- XAdd_dfa( buf )/*
- X================
- X This function adds a DFA to the string of DFA's that form the NFA.
- X The DFA is added at the head of the list because ordering is unimportant,
- X when we do a match all DFA are run in parallel. */
- Xchar *buf;
- X{
- X NFAPTR nfa;
- X
- X DB_ENTER( "Add_dfa" );
- X DB_PRINT( "dfa", ("Adding dfa [%s]", buf) );
- X
- X TALLOC( nfa, 1, NFA );
- X nfa->dfa = Construct_dfa( buf );
- X
- X if( _nfa != NIL(NFA) )
- X nfa->next = _nfa;
- X
- X _nfa = nfa;
- X
- X DB_VOID_RETURN;
- X}
- X
- X
- X
- XDFAPTR
- XConstruct_dfa( pat )/*
- X======================
- X This routine takes a string pattern which possibly contains a single %
- X and returns a dfa which will recognize the string, treating the % as
- X a token which accepts any char upto the next following char. So for
- X example:
- X
- X %.o ==> accepts f.o % = f, fred.o % = fred, fred.c FAILS
- X f%.o ==> accepts f.o % = , fred.o % = red, fred.c FAILS
- X
- X and so on. The function constructs the DFA and returns a pointer to the
- X DFA struct. */
- X
- Xchar *pat;
- X{
- X register int i;
- X register DFAPTR dfa;
- X register STATEPTR state;
- X int l = strlen( pat ) + 1;
- X int n;
- X int no_match = -1;
- X int pend = 0;
- X char *_strdup();
- X
- X DB_ENTER( "Construct_dfa" );
- X DB_PRINT( "dfa", ("Constructing dfa for %s", pat) );
- X
- X n = l + 2;
- X
- X TALLOC( dfa, 1, DFA );
- X TALLOC( dfa->states, n, STATE );
- X
- X dfa->n_states = n;
- X dfa->node = Def_cell( pat, NIL(CELL) );
- X
- X for( i=0; i<l; i++, pat++ ) {
- X state = dfa->states + i;
- X
- X if( pend == 1 ) {
- X state->action |= END_PERCENT;
- X pend++;
- X }
- X
- X switch( *pat ) {
- X case '%': /* % start state */
- X if( pend > 0 )
- X Error( "Only a single %% allowed in a target pattern" );
- X pend++;
- X state->symbol = 0;
- X state->next = i+1;
- X state->no_match = no_match;
- X state->action |= START_PERCENT | EPSILON;
- X no_match = i+1;
- X break;
- X
- X case '\0': /* termination state */
- X state->symbol = *pat;
- X state->next = -1;
- X state->no_match = no_match;
- X state->action |= ACCEPT;
- X break;
- X
- X default: /* generate a new state */
- X state->symbol = *pat;
- X state->next = i+1;
- X state->no_match = no_match;
- X break;
- X }
- X }
- X
- X DB_RETURN( dfa );
- X}
- X
- X
- X
- Xint
- XAdvance_dfa( dfa, pch )/*
- X=========================
- X This function takes the DFA that is provided and advances it to the next
- X states based on the value of *pch. The function returns either 0 for
- X everything ok, -1 for fail, and ACCEPT if the dfa accepts the string. */
- XDFAPTR dfa;
- Xchar *pch;
- X{
- X STATEPTR s;
- X char ch = *pch;
- X int done = FALSE;
- X int ret = 0;
- X
- X DB_ENTER( "Advance_dfa" );
- X DB_PRINT( "dfa", ("Advancing [%s] by %c", dfa->node->CE_NAME, *pch) );
- X
- X while( !done ) {
- X#ifdef DEBUG
- X if( dfa->c_state < 0 || dfa->c_state >= dfa->n_states )
- X Fatal( "Internal, bad current dfa state %d in [%s]",
- X dfa->c_state, dfa->node->CE_NAME );
- X#endif
- X
- X s = dfa->states + dfa->c_state;
- X
- X if( ch == '\0' && s->symbol != '\0' ) {
- X done = TRUE; /* FAIL string terminated first */
- X ret = -1;
- X }
- X else if( s->action & EPSILON ) { /* set the start of % string */
- X if( s->action & START_PERCENT ) dfa->pstart = pch;
- X dfa->c_state = s->next;
- X }
- X else if( s->symbol == ch ) { /* normal shift action */
- X ret = s->action & ACCEPT;
- X
- X if( s->action & END_PERCENT ) dfa->pend = pch;
- X dfa->c_state = s->next;
- X done = TRUE;
- X }
- X else { /* non-match shift action */
- X if( s->no_match == dfa->c_state || s->no_match == -1 ) {
- X done = TRUE;
- X if( s->no_match == -1 ) ret = -1; /* FAIL */
- X }
- X
- X dfa->c_state = s->no_match;
- X }
- X }
- X
- X DB_RETURN( ret );
- X}
- X
- X
- Xvoid
- XCheck_circle_dfa()/*
- X====================
- X This function is called to test for circularities in the DFA lists
- X constructed from %-meta targets. */
- X{
- X register NFAPTR nfa;
- X
- X for( nfa = _nfa; nfa != NIL(NFA); nfa = nfa->next )
- X if( Test_circle( nfa->dfa->node, TRUE ) )
- X Fatal( "Detected circular dependency in inference graph at [%s]",
- X nfa->dfa->node->CE_NAME );
- X}
- SHAR_EOF
- chmod 0440 percent.c || echo "restore of percent.c fails"
- echo "x - extracting path.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > path.c &&
- X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/path.c,v 1.1 90/07/19 13:53:25 dvadura Exp $
- X-- SYNOPSIS -- pathname manipulation code
- X--
- X-- DESCRIPTION
- X-- Pathname routines to handle building and pulling appart
- X-- pathnames.
- 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: path.c,v $
- X * Revision 1.1 90/07/19 13:53:25 dvadura
- X * Initial Revision of Version 3.5
- X *
- X*/
- X
- X#include "extern.h"
- X#include "alloc.h"
- X#include <string.h>
- X
- X/*
- X** Return the suffix portion of a filename, assumed to begin with a `.'.
- X*/
- Xchar *
- XGet_suffix(name)
- Xchar *name;
- X{
- X char *suff;
- X
- X if(name == NIL(char) || (suff = strrchr(name, '.')) == NIL(char))
- X suff = ".NULL";
- X
- X return (suff);
- X}
- X
- X
- X
- X/*
- X** Take dir and name, and return a path which has dir as the directory
- X** and name afterwards.
- X**
- X** N.B. Assumes that the dir separator string is in DirSepStr.
- X** Return path is built in a static buffer, if you need to use it
- X** again you must _strdup the result returned by Build_path.
- X*/
- Xchar *
- XBuild_path(dir, name)
- Xchar *dir;
- Xchar *name;
- X{
- X static char *path = NIL(char);
- X static unsigned buflen = 0;
- X int plen = 0;
- X int dlen = 0;
- X int len;
- X
- X if( dir != NIL(char) ) dlen = strlen( dir );
- X if( name != NIL(char) ) plen = strlen( name );
- X len = plen+dlen+strlen(DirSepStr)+1;
- X
- X if( len > buflen ) {
- X buflen = (len+16) & ~0xf; /* buf is always multiple of 16 */
- X
- X if( path == NIL(char) )
- X path = MALLOC( buflen, char );
- X else
- X path = realloc( path, (unsigned) (buflen*sizeof(char)) );
- X }
- X
- X *path = '\0';
- X
- X if( dlen ) {
- X strcpy( path, dir );
- X
- X if( strchr(DirSepStr, dir[dlen-1]) == NIL(char) )
- X strcat( path, DirSepStr );
- X }
- X
- X strcat( path, name );
- X return( path );
- X}
- SHAR_EOF
- chmod 0440 path.c || echo "restore of path.c fails"
- echo "x - extracting patchlvl.h (Text)"
- sed 's/^X//' << 'SHAR_EOF' > patchlvl.h &&
- X/* dmake patch level, reset to 1 for each new version release. */
- X
- X#define PATCHLEVEL 1
- SHAR_EOF
- chmod 0440 patchlvl.h || echo "restore of patchlvl.h fails"
- echo "x - extracting parse.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > parse.c &&
- X/* RCS -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/parse.c,v 1.1 90/07/19 13:53:23 dvadura Exp $
- X-- SYNOPSIS -- parse the input, and perform semantic analysis
- X--
- X-- DESCRIPTION
- X-- This file contains the routines that parse the input makefile and
- X-- call the appropriate routines to perform the semantic analysis and
- X-- build the internal dag.
- 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: parse.c,v $
- X * Revision 1.1 90/07/19 13:53:23 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
- Xvoid
- XParse( fil )/*
- X============== Parse the makefile input */
- XFILE *fil;
- X{
- X int state = NORMAL_SCAN; /* indicates current parser state */
- X int group = FALSE; /* true if scanning a group rcpe */
- X int rule = FALSE; /* have seen a recipe line */
- X char *p; /* termporary pointer into Buffer */
- X
- X DB_ENTER( "Parse" );
- X
- X while( TRUE ) {
- X if( Get_line( Buffer, fil ) ) {
- X if( fil != NIL( FILE ) ) /* end of parsable input */
- X Closefile();
- X
- X Bind_rules_to_targets( F_DEFAULT );
- X if( group ) Fatal( "Incomplete rule recipe group detected" );
- X
- X DB_VOID_RETURN;
- X }
- X else
- X switch( state ) {
- X case RULE_SCAN:
- X
- X /* Check for the `[' that starts off a group rule definition. It
- X * must appear as the first non-white space
- X * character in the line. */
- X
- X p = _strspn( Buffer, " \t" );
- X if( Set_group_attributes( p ) ) {
- X if( rule && group )
- X Fatal( "Cannot mix single and group recipe lines" );
- X else
- X group = TRUE;
- X
- X rule = TRUE;
- X
- X break; /* ignore the group start */
- X }
- X
- X if( group ) {
- X if( *p != ']' ) {
- X Add_recipe_to_list( Buffer, TRUE, TRUE );
- X rule = TRUE;
- X }
- X else
- X state = NORMAL_SCAN;
- X }
- X else {
- X if( *Buffer == '\t' ) {
- X Add_recipe_to_list( Buffer, FALSE, FALSE );
- X rule = TRUE;
- X }
- X else if( *p == ']' )
- X Fatal( "Found unmatched ']'" );
- X else if( *Buffer )
- X state = NORMAL_SCAN;
- X }
- X
- X if( state == RULE_SCAN ) break; /* ie. keep going */
- X
- X Bind_rules_to_targets( (group) ? F_GROUP: F_DEFAULT );
- X
- X rule = FALSE;
- X if( group ) {
- X group = FALSE;
- X break;
- X }
- X /*FALLTRHOUGH*/
- X
- X /* In this case we broke out of the rule scan because we do not
- X * have a recipe line that begins with a <TAB>, so lets
- X * try to scan the thing as a macro or rule definition. */
- X
- X
- X case NORMAL_SCAN:
- X if( !*Buffer ) continue; /* we have null input line */
- X
- X /* STUPID AUGMAKE uses "include" at the start of a line as
- X * a signal to include a new file, so let's look for it.
- X * if we see it replace it by .INCLUDE: and stick this back
- X * into the buffer. */
- X if( !strncmp( "include", Buffer, 7 ) &&
- X (Buffer[7] == ' ' || Buffer[7] == '\t') )
- X {
- X char *tmp;
- X
- X tmp = _strjoin( ".INCLUDE:", Buffer+7, -1, FALSE );
- X strcpy( Buffer, tmp );
- X FREE( tmp );
- X }
- X
- X /* look for a macro definition, they all contain an = sign
- X * if we fail to recognize it as a legal macro op then try to
- X * parse the same line as a rule definition, it's one or the
- X * other */
- X
- X if( Parse_macro(Buffer, M_DEFAULT) ) break;/* it's a macro def */
- X if( Parse_rule_def( &state ) ) break;/* it's a rule def */
- X
- X /* if just blank line then ignore it */
- SHAR_EOF
- echo "End of part 5"
- echo "File parse.c is continued in part 6"
- echo "6" > s2_seq_.tmp
- exit 0
-
-