Line data Source code
1 : /*
2 : --
3 : -- SYNOPSIS
4 : -- Routines to construct the internal dag.
5 : --
6 : -- DESCRIPTION
7 : -- This file contains all the routines that are responsible for
8 : -- defining and manipulating all objects used by the make facility.
9 : --
10 : -- AUTHOR
11 : -- Dennis Vadura, dvadura@dmake.wticorp.com
12 : --
13 : -- WWW
14 : -- http://dmake.wticorp.com/
15 : --
16 : -- COPYRIGHT
17 : -- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
18 : --
19 : -- This program is NOT free software; you can redistribute it and/or
20 : -- modify it under the terms of the Software License Agreement Provided
21 : -- in the file <distribution-root>/readme/license.txt.
22 : --
23 : -- LOG
24 : -- Use cvs log to obtain detailed change logs.
25 : */
26 :
27 : #include "extern.h"
28 :
29 :
30 : static void
31 9112 : set_macro_value(hp)/*
32 : =====================
33 : Set the macro according to its type. In addition to the string value
34 : in hp->ht_value a macro can stores a value casted with its type.
35 : */
36 : HASHPTR hp;
37 : {
38 9112 : switch( hp->ht_flag & M_VAR_MASK ) /* only one var type per var */
39 : {
40 : case M_VAR_STRING:
41 2024 : *hp->MV_SVAR = hp->ht_value;
42 : /* Add special treatment for PWD/MAKEDIR for .WINPATH. */
43 2024 : if( hp->MV_SVAR == &Pwd_macval ) {
44 0 : if( Pwd )
45 0 : FREE(Pwd);
46 0 : Pwd = hp->ht_value;
47 : /* Use the "DOSified" path for the macro. */
48 0 : *hp->MV_SVAR = hp->ht_value = DmStrDup(DO_WINPATH(hp->ht_value));
49 : DB_PRINT( "smv", ("PWD: %s/%s", Pwd_macval, Pwd) );
50 2024 : } else if( hp->MV_SVAR == &Makedir_macval ) {
51 0 : if( Makedir )
52 0 : FREE(Makedir);
53 0 : Makedir = hp->ht_value;
54 : /* Use the "DOSified" path for the macro. */
55 0 : *hp->MV_SVAR = hp->ht_value = DmStrDup(DO_WINPATH(hp->ht_value));
56 : DB_PRINT( "smv", ("MAKEDIR: %s/%s", Makedir_macval, Makedir) );
57 : }
58 : /* No special treatment for TMD needed. */
59 2024 : break;
60 :
61 : case M_VAR_CHAR:
62 0 : *hp->MV_CVAR = (hp->ht_value == NIL(char)) ? '\0':*hp->ht_value;
63 0 : break;
64 :
65 : case M_VAR_INT: {
66 : int tvalue;
67 924 : if( hp->MV_IVAR == NIL(int) ) break; /* first time */
68 :
69 924 : tvalue = atoi(hp->ht_value);
70 924 : if( hp->MV_IVAR == &Buffer_size ) {
71 : /* If Buffer_size (MAXLINELENGTH) is modified then make sure
72 : * you change the size of the real buffer as well. As the
73 : * value will at least be BUFSIZ this might lead to the
74 : * situation that the (string) value of MAXLINELENGTH is
75 : * smaller than the integer value. */
76 556 : tvalue = (tvalue < (BUFSIZ-2)) ? BUFSIZ : tvalue+2;
77 556 : if( Buffer_size == tvalue ) break;
78 556 : if( Buffer ) FREE(Buffer);
79 556 : if((Buffer=MALLOC(tvalue, char)) == NIL(char)) No_ram();
80 556 : *Buffer = '\0';
81 : }
82 924 : *hp->MV_IVAR = tvalue;
83 :
84 924 : if( hp->MV_IVAR == &Max_proc || hp->MV_IVAR == &Max_proclmt ) {
85 368 : if( tvalue < 1 )
86 0 : Fatal( "Process limit value must be > 1" );
87 :
88 : #if defined(USE_CREATEPROCESS)
89 : if( Max_proclmt > MAXIMUM_WAIT_OBJECTS )
90 : Fatal( "Specified maximum # of processes (MAXPROCESSLIMIT)"
91 : " exceeds OS limit of [%d].", MAXIMUM_WAIT_OBJECTS );
92 : #endif
93 :
94 368 : if( Max_proc > Max_proclmt )
95 0 : Fatal( "Specified # of processes exceeds limit of [%d]",
96 : Max_proclmt );
97 :
98 : /* Don't change MAXPROCESS value if .SEQUENTIAL is set. */
99 368 : if( (Glob_attr & A_SEQ) && (Max_proc != 1) ) {
100 0 : Warning( "Macro MAXPROCESS set to 1 because .SEQUENTIAL is set." );
101 0 : Max_proc = 1;
102 0 : if( hp->ht_value != NIL(char) ) FREE(hp->ht_value);
103 0 : hp->ht_value = DmStrDup( "1" );
104 : }
105 : }
106 924 : } break;
107 :
108 : case M_VAR_BIT:
109 : /* Bit variables are set to 1 if ht_value is not NULL and 0
110 : * otherwise */
111 :
112 368 : if( hp->ht_value == NIL(char) )
113 184 : *hp->MV_BVAR &= ~hp->MV_MASK;
114 : else {
115 184 : *hp->MV_BVAR |= hp->MV_MASK;
116 : /* If we're setting .SEQUENTIAL set MAXPROCESS=1. */
117 184 : if( (hp->MV_MASK & A_SEQ) && (Max_proc != 1) )
118 0 : Def_macro( "MAXPROCESS", "1", M_MULTI|M_EXPANDED);
119 : }
120 :
121 : #if defined(__CYGWIN__)
122 : /* Global .WINPATH change. Only needed for cygwin. */
123 : if(hp->MV_MASK & A_WINPATH) {
124 : UseWinpath = ((Glob_attr&A_WINPATH) != 0);
125 : /* Change MAKEDIR, PWD according to .WINPATH. During
126 : * makefile evaluation this cannot change TMD (it is "."
127 : * and later TMD is set in Make() according to the
128 : * .WINPATH attribute. */
129 : Def_macro( "MAKEDIR", Makedir, M_FORCE | M_EXPANDED );
130 : Def_macro( "PWD", Pwd, M_FORCE | M_EXPANDED );
131 : }
132 : #endif
133 368 : break;
134 : }
135 9112 : }
136 :
137 :
138 : PUBLIC HASHPTR
139 1827870 : Get_name( name, tab, define )/*
140 : ===============================
141 : Look to see if the name is defined, if it is then return
142 : a pointer to its node, if not return NIL(HASH).
143 : If define is TRUE and the name is not found it will be added. */
144 :
145 : char *name; /* name we are looking for */
146 : HASHPTR *tab; /* the hash table to look in */
147 : int define; /* TRUE => add to table */
148 : {
149 : register HASHPTR hp;
150 : register char *p;
151 : uint16 hv;
152 : uint32 hash_key;
153 :
154 : DB_ENTER( "Get_name" );
155 : DB_PRINT( "name", ("Looking for %s", name) );
156 :
157 1827870 : hp = Search_table( tab, name, &hv, &hash_key );
158 :
159 1827870 : if( hp == NIL(HASH) && define ) {
160 : /* Check to make sure that CELL name contains only printable chars */
161 7758840 : for( p=name; *p; p++ )
162 7358336 : if( !isprint(*p) && !iswhite(*p) && *p != '\n' )
163 0 : Fatal( "Name contains non-printable character [0x%02x]", *p );
164 :
165 400504 : TALLOC( hp, 1, HASH ); /* allocate a cell and add it in */
166 :
167 400504 : hp->ht_name = DmStrDup( name );
168 400504 : hp->ht_hash = hash_key;
169 400504 : hp->ht_next = tab[ hv ];
170 400504 : tab[ hv ] = hp;
171 :
172 : DB_PRINT( "name", ("Adding %s", name) );
173 : }
174 :
175 : DB_PRINT( "name",("Returning: [%s,%lu]",
176 : (hp == NIL(HASH)) ? "":hp->ht_name, hv) );
177 1827870 : DB_RETURN( hp );
178 : }
179 :
180 :
181 : PUBLIC HASHPTR
182 1827870 : Search_table( tab, name, phv, phkey )
183 : HASHPTR *tab;
184 : char *name;
185 : uint16 *phv;
186 : uint32 *phkey;
187 : {
188 : HASHPTR hp;
189 :
190 1827870 : *phv = Hash( name, phkey );
191 :
192 9124707 : for( hp = tab[ *phv ]; hp != NIL(HASH); hp = hp->ht_next )
193 8584896 : if( hp->ht_hash == *phkey
194 1288059 : && !strcmp(hp->ht_name, name) )
195 1288059 : break;
196 :
197 1827870 : return( hp );
198 : }
199 :
200 :
201 : PUBLIC HASHPTR
202 5796 : Push_macro(hp)/*
203 : ================
204 : This function pushes hp into the hash of all macros. If a previous
205 : instance of the macro exists it is hidden by the new one. If one
206 : existed before the new instance inherits some values from the preexisting
207 : macro (see below for details).
208 : */
209 : HASHPTR hp;
210 : {
211 : HASHPTR cur,prev;
212 : uint16 hv;
213 : uint32 key;
214 :
215 5796 : hv = Hash(hp->ht_name, &key);
216 :
217 : /* Search for an existing instance of hp->ht_name, if found cur will point
218 : * to it. */
219 8154 : for(prev=NIL(HASH),cur=Macs[hv]; cur!=NIL(HASH); prev=cur,cur=cur->ht_next)
220 8154 : if( cur->ht_hash == key
221 5796 : && !strcmp(cur->ht_name, hp->ht_name) )
222 5796 : break;
223 :
224 5796 : if (cur == NIL(HASH) || prev == NIL(HASH)) {
225 : /* If no match or was found or the first element of Macs[hv] was
226 : * the match insert hp at the beginning. */
227 5208 : hp->ht_next = Macs[hv];
228 5208 : Macs[hv] = hp;
229 : }
230 : else {
231 : /* otherwise insert hp in the chain. */
232 588 : hp->ht_next = prev->ht_next;
233 588 : prev->ht_next = hp;
234 : }
235 :
236 : /* Inherit some parts of the former instance. Copying cur->var to hp->var
237 : * copies the old value. Keeping the M_VAR_MASK (variable type) makes sure
238 : * the type stays the same keeping M_PRECIOUS assures that the old values
239 : * cannot be overridden if it is/was set. */
240 5796 : if (cur) {
241 5796 : memcpy((void *)&hp->var, (void *)&cur->var, sizeof(hp->var));
242 5796 : hp->ht_flag |= ((M_VAR_MASK|M_PRECIOUS) & cur->ht_flag);
243 : }
244 :
245 5796 : return(hp);
246 : }
247 :
248 :
249 : PUBLIC HASHPTR
250 5796 : Pop_macro(hp)/*
251 : ================
252 : This function pops (removes) hp from the hash of all macros. If a previous
253 : instance of the macro existed it becomes accessible again.
254 : */
255 :
256 : HASHPTR hp;
257 : {
258 : HASHPTR cur,prev;
259 : uint16 hv;
260 : uint32 key;
261 :
262 5796 : hv = Hash(hp->ht_name, &key);
263 :
264 : /* Try to find hp. */
265 8154 : for(prev=NIL(HASH),cur=Macs[hv]; cur != NIL(HASH);prev=cur,cur=cur->ht_next)
266 8154 : if (cur == hp)
267 5796 : break;
268 :
269 : /* If cur == NIL macros was not found. */
270 5796 : if (cur == NIL(HASH))
271 0 : return(NIL(HASH));
272 :
273 : /* Remove hp from the linked list. */
274 5796 : if (prev)
275 588 : prev->ht_next = cur->ht_next;
276 : else
277 5208 : Macs[hv] = cur->ht_next;
278 :
279 : /* Look for a previous (older) instance of hp->ht_name. */
280 5796 : for(cur=cur->ht_next; cur != NIL(HASH); cur=cur->ht_next)
281 5796 : if( cur->ht_hash == key
282 5796 : && !strcmp(cur->ht_name, hp->ht_name) )
283 5796 : break;
284 :
285 : /* If one was found we restore the typecast values. */
286 5796 : if (cur)
287 5796 : set_macro_value(cur);
288 :
289 5796 : hp->ht_next = NIL(HASH);
290 5796 : return(hp);
291 : }
292 :
293 :
294 :
295 : PUBLIC HASHPTR
296 771959 : Def_macro( name, value, flags )/*
297 : =================================
298 : This routine is used to define a macro, and it's value. A copy of
299 : the content of value is stored and not the pointer to the value.
300 : The flags indicates if it is a permanent macro or if it's value
301 : can be redefined. A flags of M_PRECIOUS means it is a precious
302 : macro and cannot be further redefined unless M_FORCE is used.
303 : If the flags flag contains the M_MULTI bit it means that the macro
304 : can be redefined multiple times and no warning of the redefinitions
305 : should be issued.
306 : Once a macro's VAR flags are set they are preserved through all future
307 : macro definitions.
308 :
309 : Macro definitions that have one of the variable bits set are treated
310 : specially. In each case the hash table entry var field points at the
311 : global variable that can be set by assigning to the macro.
312 :
313 : bit valued global vars must be computed when the macro value is changed.
314 : char valued global vars must have the first char of ht_value copied to
315 : them. string valued global vars have the same value as ht_value and should
316 : just have the new value of ht_value copied to them. */
317 :
318 : char *name; /* macro name to define */
319 : char *value; /* macro value to set */
320 : int flags; /* initial ht_flags */
321 : {
322 : register HASHPTR hp;
323 : register char *p, *q;
324 :
325 : DB_ENTER( "Def_macro" );
326 : DB_PRINT( "mac", ("Defining macro %s = %s, %x", name, value, flags) );
327 :
328 : /* check to see if name is in the table, if so then just overwrite
329 : the previous definition. Otherwise allocate a new node, and
330 : stuff it in the hash table, at the front of any linked list */
331 :
332 771959 : if( Readenv ) flags |= M_LITERAL|M_EXPANDED;
333 :
334 771959 : hp = Get_name( name, Macs, TRUE );
335 :
336 771959 : if ((flags & M_PUSH) && hp->ht_name != NIL(char)) {
337 5796 : HASHPTR thp=hp;
338 5796 : TALLOC(hp,1,HASH);
339 5796 : hp->ht_name = DmStrDup(thp->ht_name);
340 5796 : hp->ht_hash = thp->ht_hash;
341 5796 : Push_macro(hp);
342 5796 : flags |= hp->ht_flag;
343 : }
344 771959 : flags &= ~M_PUSH;
345 :
346 771959 : if( (hp->ht_flag & M_PRECIOUS) && !(flags & M_FORCE) ) {
347 368 : if (Verbose & V_WARNALL)
348 0 : Warning( "Macro `%s' cannot be redefined", name );
349 368 : DB_RETURN( hp );
350 : }
351 :
352 : /* Make sure we don't export macros whose names contain legal macro
353 : * assignment operators, since we can't do proper quoting in the
354 : * environment. */
355 771591 : if( *DmStrPbrk(name, "*+:=") != '\0' ) flags |= M_NOEXPORT;
356 :
357 771591 : if( hp->ht_value != NIL(char) ) FREE( hp->ht_value );
358 :
359 771591 : if( (hp->ht_flag & M_USED) && !((flags | hp->ht_flag) & M_MULTI) )
360 186 : Warning( "Macro `%s' redefined after use", name );
361 :
362 : /* If an empty string ("") is given set ht_value to NIL(char) */
363 771591 : if( (value != NIL(char)) && (*value) ) {
364 :
365 419323 : if( !(flags & M_LITERAL) ) {
366 332107 : q = DmStrDup(value);
367 : /* strip out any \<nl> combinations where \ is the current
368 : * CONTINUATION char */
369 712212 : for(p=q; (p=strchr(p,CONTINUATION_CHAR))!=NIL(char); )
370 47998 : if( p[1] == '\n' ) {
371 45970 : size_t len = strlen(p+2)+1;
372 45970 : memmove ( p, p+2, len );
373 : }
374 : else
375 2028 : p++;
376 :
377 332107 : p = DmStrSpn(q ," \t"); /* Strip white space before ... */
378 332107 : if( p != q ) {
379 968 : size_t len = strlen(p)+1;
380 968 : memmove( q, p, len );
381 968 : p = q;
382 : }
383 :
384 332107 : if( *p ) { /* ... and after the value. */
385 331545 : for(q=p+strlen(p)-1; ((*q == ' ')||(*q == '\t')); q--);
386 331545 : *++q = '\0';
387 : }
388 332107 : flags &= ~M_LITERAL;
389 : }
390 : else
391 87216 : p = DmStrDup( value ); /* take string literally */
392 :
393 419323 : if( !*p ) { /* check if result is "" */
394 562 : FREE( p );
395 562 : p = NIL(char);
396 562 : flags |= M_EXPANDED;
397 : }
398 418761 : else if( *DmStrPbrk( p, "${}" ) == '\0' )
399 326953 : flags |= M_EXPANDED;
400 :
401 419323 : hp->ht_value = p;
402 : }
403 : else {
404 352268 : hp->ht_value = NIL(char);
405 352268 : flags |= M_EXPANDED;
406 : }
407 :
408 : /* Assign the hash table flag less the M_MULTI flag, it is used only
409 : * to silence the warning. But carry it over if it was previously
410 : * defined in ht_flag, as this is a permanent M_MULTI variable. Keep
411 : * the M_PRECIOUS flag and strip the M_INIT flag. */
412 :
413 2314773 : hp->ht_flag = ((flags & ~(M_MULTI|M_FORCE)) |
414 1543182 : (hp->ht_flag & (M_VAR_MASK|M_MULTI|M_PRECIOUS))) & ~M_INIT;
415 :
416 : /* Check for macro variables and make the necessary adjustment in the
417 : * corresponding global variables */
418 :
419 771591 : if( hp->ht_flag & M_VAR_MASK ) {
420 3316 : if( !(flags & M_EXPANDED) )
421 0 : Error( "Macro variable '%s' must be assigned with :=", name );
422 : else
423 3316 : set_macro_value(hp);
424 : }
425 :
426 771591 : DB_RETURN( hp );
427 : }
428 :
429 :
430 :
431 : PUBLIC CELLPTR
432 126972 : Def_cell( name )/*
433 : ==================
434 : Check if a cell for "name" already exists, if not create a new cell.
435 : The value of name is normalized before checking/creating the cell to
436 : avoid creating multiple cells for the same target file.
437 : The function returns a pointer to the cell. */
438 : char *name;
439 : {
440 : register HASHPTR hp;
441 : register CELLPTR cp;
442 : register CELLPTR lib;
443 : char *member;
444 : char *end;
445 :
446 : DB_ENTER( "Def_cell" );
447 :
448 : /* Check to see if the cell is a member of the form lib(member) or
449 : * lib((symbol)) and handle the cases appropriately.
450 : * What we do is we look at the target, if it is of the above two
451 : * forms we get the lib, and add the member/symbol to the list of
452 : * prerequisites for the library. If this is a symbol name def'n
453 : * we additionally add the attribute A_SYMBOL, so that stat can
454 : * try to do the right thing. */
455 :
456 126972 : if( ((member = strchr(name, '(')) != NIL(char)) &&
457 18934 : ((end = strrchr(member, ')')) != NIL(char)) &&
458 18934 : (member > name) && (member[-1] != '$') &&
459 0 : (end > member+1) && (end[1] == '\0') )
460 : {
461 0 : *member++ = *end = '\0';
462 :
463 0 : if( (*member == '(') && (member[strlen(member)-1] == ')') ) {
464 0 : member[ strlen(member)-1 ] = '\0';
465 0 : cp = Def_cell( member+1 );
466 0 : cp->ce_attr |= A_SYMBOL;
467 : }
468 : else
469 0 : cp = Def_cell( member );
470 :
471 0 : lib = Def_cell( name );
472 :
473 0 : Add_prerequisite( lib, cp, FALSE, FALSE );
474 0 : lib->ce_attr |= A_LIBRARY | A_COMPOSITE;
475 :
476 0 : if( !Def_targets ) cp = lib;
477 : }
478 : else {
479 : /* Normalize the name. */
480 : DB_PRINT( "path", ("Normalizing [%s]", name) );
481 :
482 : /* The normalizing function returns a pointer to a static buffer. */
483 126972 : name = normalize_path(name);
484 :
485 126972 : hp = Get_name( name, Defs, TRUE );/* get the name from hash table */
486 :
487 126972 : if( hp->CP_OWNR == NIL(CELL) ) /* was it previously defined */
488 : { /* NO, so define a new cell */
489 : DB_PRINT( "cell", ("Defining cell [%s]", name) );
490 :
491 73952 : TALLOC( cp, 1, CELL );
492 73952 : hp->CP_OWNR = cp;
493 73952 : cp->ce_name = hp;
494 73952 : cp->ce_fname = hp->ht_name;
495 73952 : cp->ce_all.cl_prq = cp;
496 : }
497 : else /* YES, so return the old cell */
498 : {
499 : DB_PRINT( "cell", ("Getting cell [%s]", hp->ht_name) );
500 53020 : cp = hp->CP_OWNR;
501 : }
502 : }
503 :
504 126972 : DB_RETURN( cp );
505 : }
506 :
507 :
508 :
509 :
510 : PUBLIC LINKPTR
511 69544 : Add_prerequisite( cell, prq, head, force )/*
512 : ============================================
513 : Add a dependency node to the dag. It adds it to the prerequisites,
514 : if any, of the cell and makes certain they are in linear order.
515 : If head == 1, then add to head of the prerequisite list, else
516 : add to tail. */
517 : CELLPTR cell;
518 : CELLPTR prq;
519 : int head;
520 : int force;
521 : {
522 : register LINKPTR lp, tlp;
523 :
524 : DB_ENTER( "Add_prerequisite" );
525 : DB_PRINT( "cell", ("Defining prerequisite %s", prq->CE_NAME) );
526 :
527 69544 : if( (prq->ce_flag & (F_MAGIC | F_PERCENT)) && !force )
528 0 : Fatal( "Special target [%s] cannot be a prerequisite",
529 0 : prq->CE_NAME );
530 :
531 69544 : if( cell->ce_prq == NIL(LINK) ) { /* it's the first one */
532 21768 : TALLOC( lp, 1, LINK );
533 21768 : lp->cl_prq = prq;
534 21768 : cell->ce_prq = lp;
535 : }
536 : else { /* search the list, checking for duplicates */
537 12242284 : for( lp = cell->ce_prq;
538 24341412 : (lp->cl_next != NIL(LINK)) && (lp->cl_prq != prq);
539 12146732 : lp = lp->cl_next );
540 :
541 : /* If the prq is not found and we are at the last prq in the list,
542 : * allocate a new prq and place it into the list, insert it at the
543 : * head if head == 1, else we add it to the end. */
544 :
545 47776 : if( lp->cl_prq != prq ) {
546 47432 : TALLOC( tlp, 1, LINK );
547 47432 : tlp->cl_prq = prq;
548 :
549 47432 : if( head ) {
550 0 : tlp->cl_next = cell->ce_prq;
551 0 : cell->ce_prq = tlp;
552 : }
553 : else
554 47432 : lp->cl_next = tlp;
555 :
556 47432 : lp = tlp;
557 : }
558 : }
559 :
560 69544 : DB_RETURN( lp );
561 : }
562 :
563 :
564 :
565 : PUBLIC void
566 2226 : Clear_prerequisites( cell )/*
567 : =============================
568 : Clear out the list of prerequisites, freeing all of the LINK nodes,
569 : and setting the list to NULL */
570 : CELLPTR cell;
571 : {
572 : LINKPTR lp, tlp;
573 :
574 : DB_ENTER( "Clear_prerequisites" );
575 : DB_PRINT( "cell", ("Nuking prerequisites") );
576 :
577 2226 : if( cell == NIL(CELL) ) { DB_VOID_RETURN; }
578 :
579 2962 : for( lp=cell->ce_prq; lp != NIL(LINK); lp=tlp ) {
580 736 : tlp=lp->cl_next;
581 736 : FREE( lp );
582 : }
583 :
584 2226 : cell->ce_prq = NIL(LINK);
585 :
586 2226 : DB_VOID_RETURN;
587 : }
588 :
589 :
590 : PUBLIC int
591 88190 : Test_circle( cp, fail )/*
592 : =========================
593 : Actually run through the graph */
594 : CELLPTR cp;
595 : int fail;
596 : {
597 : register LINKPTR lp;
598 88190 : int res = 0;
599 :
600 : DB_ENTER( "Test_circle" );
601 : DB_PRINT( "tc", ("checking [%s]", cp->CE_NAME) );
602 :
603 88190 : if( cp->ce_flag & F_MARK ) {
604 0 : if( fail )
605 0 : Fatal("Detected circular dependency in graph at [%s]", cp->CE_NAME);
606 : else
607 0 : DB_RETURN( 1 );
608 : }
609 :
610 88190 : cp->ce_flag |= F_MARK;
611 171524 : for( lp = cp->ce_prq; !res && lp != NIL(LINK); lp = lp->cl_next )
612 83334 : res = Test_circle( lp->cl_prq, fail );
613 88190 : cp->ce_flag ^= F_MARK;
614 :
615 88190 : DB_RETURN( res );
616 : }
617 :
618 :
619 :
620 : PUBLIC STRINGPTR
621 44922 : Def_recipe( rcp, sp, white_too, no_check )/*
622 : =============================================
623 : Take the recipe (rcp) and add it to the list of recipes pointed to by
624 : sp (sp points to the last element). If white_too == TRUE add the recipe
625 : even if it contains only white space or an empty string.
626 : Return a pointer to the new recipe (or sp if it was discarded).
627 : If no_check is true then don't look for -@ at the start of the recipe
628 : line. */
629 : char *rcp;
630 : STRINGPTR sp;
631 : int white_too;
632 : int no_check;
633 : {
634 : register STRINGPTR nsp;
635 : register char *rp;
636 :
637 : DB_ENTER( "Def_recipe" );
638 : DB_PRINT( "rul", ("Defining recipe %s", rcp) );
639 :
640 44922 : if( !white_too ) rcp = DmStrSpn( rcp, " \t" );
641 44922 : if( (rcp == NIL(char)) || (*rcp == 0 && !white_too) )
642 8 : DB_RETURN( sp ); /* return last recipe when new recipe not added */
643 :
644 44914 : rp = no_check ? rcp : DmStrSpn( rcp, " \t@-+%" );
645 :
646 44914 : TALLOC(nsp, 1, STRING);
647 44914 : nsp->st_string = DmStrDup( rp );
648 :
649 44914 : if( sp != NIL(STRING) ) sp->st_next = nsp;
650 44914 : nsp->st_next = NIL(STRING);
651 :
652 44914 : if( !no_check ) nsp->st_attr |= Rcp_attribute( rcp );
653 :
654 44914 : DB_RETURN( nsp );
655 : }
656 :
657 :
658 : PUBLIC t_attr
659 46174 : Rcp_attribute( rp )/*
660 : ======================
661 : Look at the recipe and return the set of attributes that it defines. */
662 : char *rp;
663 : {
664 46174 : t_attr flag = A_DEFAULT;
665 46174 : int done = FALSE;
666 46174 : int atcount = 0;
667 :
668 185146 : while( !done )
669 92798 : switch( *rp++ )
670 : {
671 39974 : case '@' : ++atcount; break;
672 6090 : case '-' : flag |= A_IGNORE; break;
673 552 : case '+' : flag |= A_SHELL; break;
674 : case '%' :
675 : #if defined(MSDOS)
676 : /* Ignore % in the non-MSDOS case. */
677 : flag |= A_SWAP;
678 : #endif
679 0 : break;
680 :
681 : case ' ' :
682 8 : case '\t': break;
683 :
684 46174 : default: done = TRUE; break;
685 : }
686 :
687 46174 : if( !(Verbose & V_FORCEECHO) && atcount-- ) {
688 34878 : flag |= A_SILENT;
689 : /* hide output if more than one @ are encountered. */
690 34878 : if( atcount )
691 5096 : flag |= A_MUTE;
692 : }
693 :
694 46174 : return(flag);
695 : }
|