Imported Upstream version 1.51.0
[platform/upstream/boost.git] / tools / build / v2 / engine / rules.c
1 /*
2  * Copyright 1993, 1995 Christopher Seiwald.
3  *
4  * This file is part of Jam - see jam.c for Copyright information.
5  */
6
7 # include "jam.h"
8 # include "lists.h"
9 # include "parse.h"
10 # include "variable.h"
11 # include "rules.h"
12 # include "object.h"
13 # include "hash.h"
14 # include "modules.h"
15 # include "search.h"
16 # include "lists.h"
17 # include "pathsys.h"
18 # include "timestamp.h"
19
20 /*  This file is ALSO:
21  *  Copyright 2001-2004 David Abrahams.
22  *  Distributed under the Boost Software License, Version 1.0.
23  *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
24  */
25
26 /*
27  * rules.c - access to RULEs, TARGETs, and ACTIONs
28  *
29  * External routines:
30  *
31  *    bindrule()     - return pointer to RULE, creating it if necessary.
32  *    bindtarget()   - return pointer to TARGET, creating it if necessary.
33  *    touch_target() - mark a target to simulate being new.
34  *    targetlist()   - turn list of target names into a TARGET chain.
35  *    targetentry()  - add a TARGET to a chain of TARGETS.
36  *    actionlist()   - append to an ACTION chain.
37  *    addsettings()  - add a deferred "set" command to a target.
38  *    pushsettings() - set all target specific variables.
39  *    popsettings()  - reset target specific variables to their pre-push values.
40  *    freesettings() - delete a settings list.
41  *    rules_done()   - free RULE and TARGET tables.
42  *
43  * 04/12/94 (seiwald) - actionlist() now just appends a single action.
44  * 08/23/94 (seiwald) - Support for '+=' (append to variable)
45  */
46
47 static void set_rule_actions( RULE *, rule_actions * );
48 static void set_rule_body   ( RULE *, FUNCTION * procedure );
49
50 static struct hash * targethash = 0;
51
52
53 /*
54  * target_include() - adds the 'included' TARGET to the list of targets included
55  * by the 'including' TARGET. Such targets are modeled as dependencies of the
56  * internal include node belonging to the 'including' TARGET.
57  */
58
59 void target_include( TARGET * including, TARGET * included )
60 {
61     TARGET * internal;
62     if ( !including->includes )
63     {
64         including->includes = copytarget( including );
65         including->includes->original_target = including;
66     }
67     internal = including->includes;
68     internal->depends = targetentry( internal->depends, included );
69 }
70
71
72 /*
73  * enter_rule() - return pointer to RULE, creating it if necessary in
74  * target_module.
75  */
76
77 static RULE * enter_rule( OBJECT * rulename, module_t * target_module )
78 {
79     int found;
80     RULE * r;
81
82     r = (RULE *)hash_insert( demand_rules(target_module), rulename, &found );
83     if ( !found )
84     {
85         r->name = object_copy( rulename );
86         r->procedure = 0;
87         r->module = 0;
88         r->actions = 0;
89         r->exported = 0;
90         r->module = target_module;
91     }
92     return r;
93 }
94
95
96 /*
97  * define_rule() - return pointer to RULE, creating it if necessary in
98  * target_module. Prepare it to accept a body or action originating in
99  * src_module.
100  */
101
102 static RULE * define_rule
103 (
104     module_t * src_module,
105     OBJECT   * rulename,
106     module_t * target_module
107 )
108 {
109     RULE * r = enter_rule( rulename, target_module );
110     if ( r->module != src_module ) /* if the rule was imported from elsewhere, clear it now */
111     {
112         set_rule_body( r, 0 );
113         set_rule_actions( r, 0 );
114         r->module = src_module; /* r will be executed in the source module */
115     }
116     return r;
117 }
118
119
120 void rule_free( RULE * r )
121 {
122     object_free( r->name );
123     r->name = 0;
124     if ( r->procedure )
125         function_free( r->procedure );
126     r->procedure = 0;
127     if ( r->actions )
128         actions_free( r->actions );
129     r->actions = 0;
130 }
131
132
133 /*
134  * bindtarget() - return pointer to TARGET, creating it if necessary.
135  */
136
137 TARGET * bindtarget( OBJECT * target_name )
138 {
139     int found;
140     TARGET * t;
141
142     if ( !targethash )
143         targethash = hashinit( sizeof( TARGET ), "targets" );
144
145     t = (TARGET *)hash_insert( targethash, target_name, &found );
146     if ( !found )
147     {
148         memset( (char *)t, '\0', sizeof( *t ) );
149         t->name = object_copy( target_name );
150         t->boundname = object_copy( t->name );  /* default for T_FLAG_NOTFILE */
151     }
152
153     return t;
154 }
155
156
157 static void bind_explicitly_located_target( void * xtarget, void * data )
158 {
159     TARGET * t = (TARGET *)xtarget;
160     if ( !( t->flags & T_FLAG_NOTFILE ) )
161     {
162         /* Check if there's a setting for LOCATE */
163         SETTINGS * s = t->settings;
164         for ( ; s ; s = s->next )
165         {
166             if ( strcmp( object_str( s->symbol ), "LOCATE" ) == 0 )
167             {
168                 pushsettings( root_module(), t->settings );
169                 /* We are binding a target with explicit LOCATE. So third
170                  * argument is of no use: nothing will be returned through it.
171                  */
172                 object_free( t->boundname );
173                 t->boundname = search( t->name, &t->time, 0, 0 );
174                 popsettings( root_module(), t->settings );
175                 break;
176             }
177         }
178     }
179 }
180
181
182 void bind_explicitly_located_targets()
183 {
184     if ( targethash )
185         hashenumerate( targethash, bind_explicitly_located_target, (void *)0 );
186 }
187
188
189 /*
190  * copytarget() - make a new target with the old target's name.
191  *
192  * Not entered into hash table -- for internal nodes.
193  */
194
195 TARGET * copytarget( const TARGET * ot )
196 {
197     TARGET * t = (TARGET *)BJAM_MALLOC( sizeof( *t ) );
198     memset( (char *)t, '\0', sizeof( *t ) );
199     t->name = object_copy( ot->name );
200     t->boundname = object_copy( t->name );
201
202     t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;
203
204     return t;
205 }
206
207
208 /*
209  * touch_target() - mark a target to simulate being new.
210  */
211
212 void touch_target( OBJECT * t )
213 {
214     bindtarget( t )->flags |= T_FLAG_TOUCHED;
215 }
216
217
218 /*
219  * targetlist() - turn list of target names into a TARGET chain.
220  *
221  * Inputs:
222  *  chain   existing TARGETS to append to
223  *  targets list of target names
224  */
225
226 TARGETS * targetlist( TARGETS * chain, LIST * target_names )
227 {
228     LISTITER iter = list_begin( target_names ), end = list_end( target_names );
229     for ( ; iter != end; iter = list_next( iter ) )
230         chain = targetentry( chain, bindtarget( list_item( iter ) ) );
231     return chain;
232 }
233
234
235 /*
236  * targetentry() - add a TARGET to a chain of TARGETS.
237  *
238  * Inputs:
239  *  chain   existing TARGETS to append to
240  *  target  new target to append
241  */
242
243 TARGETS * targetentry( TARGETS * chain, TARGET * target )
244 {
245     TARGETS * c = (TARGETS *)BJAM_MALLOC( sizeof( TARGETS ) );
246     c->target = target;
247
248     if ( !chain ) chain = c;
249     else chain->tail->next = c;
250     chain->tail = c;
251     c->next = 0;
252
253     return chain;
254 }
255
256
257 /*
258  * targetchain() - append two TARGET chains.
259  *
260  * Inputs:
261  *  chain   exisitng TARGETS to append to
262  *  target  new target to append
263  */
264
265 TARGETS * targetchain( TARGETS * chain, TARGETS * targets )
266 {
267     if ( !targets ) return chain;
268     if ( !chain   ) return targets;
269
270     chain->tail->next = targets;
271     chain->tail = targets->tail;
272
273     return chain;
274 }
275
276 /*
277  * action_free - decrement the ACTIONs refrence count
278  * and (maybe) free it.
279  */
280
281 void action_free ( ACTION * action )
282 {
283     if ( --action->refs == 0 )
284     {
285         freetargets( action->targets );
286         freetargets( action->sources );
287         BJAM_FREE( action );
288     }
289 }
290
291 /*
292  * actionlist() - append to an ACTION chain.
293  */
294
295 ACTIONS * actionlist( ACTIONS * chain, ACTION * action )
296 {
297     ACTIONS * actions = (ACTIONS *)BJAM_MALLOC( sizeof( ACTIONS ) );
298
299     actions->action = action;
300
301     ++action->refs;
302     if ( !chain ) chain = actions;
303     else chain->tail->next = actions;
304     chain->tail = actions;
305     actions->next = 0;
306
307     return chain;
308 }
309
310 static SETTINGS * settings_freelist;
311
312
313 /*
314  * addsettings() - add a deferred "set" command to a target.
315  *
316  * Adds a variable setting (varname=list) onto a chain of settings for a
317  * particular target. 'flag' controls the relationship between new and old
318  * values in the same way as in var_set() function (see variable.c). Returns
319  * the head of the settings chain.
320  */
321
322 SETTINGS * addsettings( SETTINGS * head, int flag, OBJECT * symbol, LIST * value )
323 {
324     SETTINGS * v;
325
326     /* Look for previous settings. */
327     for ( v = head; v; v = v->next )
328         if ( object_equal( v->symbol, symbol ) )
329             break;
330
331     /* If not previously set, alloc a new. */
332     /* If appending, do so. */
333     /* Else free old and set new. */
334     if ( !v )
335     {
336         v = settings_freelist;
337
338         if ( v )
339             settings_freelist = v->next;
340         else
341             v = (SETTINGS *)BJAM_MALLOC( sizeof( *v ) );
342
343         v->symbol = object_copy( symbol );
344         v->value = value;
345         v->next = head;
346         head = v;
347     }
348     else if ( flag == VAR_APPEND )
349     {
350         v->value = list_append( v->value, value );
351     }
352     else if ( flag != VAR_DEFAULT )
353     {
354         list_free( v->value );
355         v->value = value;
356     }
357     else
358         list_free( value );
359
360     /* Return (new) head of list. */
361     return head;
362 }
363
364
365 /*
366  * pushsettings() - set all target specific variables.
367  */
368
369 void pushsettings( struct module_t * module, SETTINGS * v )
370 {
371     for ( ; v; v = v->next )
372         v->value = var_swap( module, v->symbol, v->value );
373 }
374
375
376 /*
377  * popsettings() - reset target specific variables to their pre-push values.
378  */
379
380 void popsettings( struct module_t * module, SETTINGS * v )
381 {
382     pushsettings( module, v );  /* just swap again */
383 }
384
385
386 /*
387  * copysettings() - duplicate a settings list, returning the new copy.
388  */
389
390 SETTINGS * copysettings( SETTINGS * head )
391 {
392     SETTINGS * copy = 0;
393     SETTINGS * v;
394     for ( v = head; v; v = v->next )
395         copy = addsettings( copy, VAR_SET, v->symbol, list_copy( v->value ) );
396     return copy;
397 }
398
399
400 /*
401  * freetargets() - delete a targets list.
402  */
403
404 void freetargets( TARGETS * chain )
405 {
406     while ( chain )
407     {
408         TARGETS * n = chain->next;
409         BJAM_FREE( chain );
410         chain = n;
411     }
412 }
413
414
415 /*
416  * freeactions() - delete an action list.
417  */
418
419 void freeactions( ACTIONS * chain )
420 {
421     while ( chain )
422     {
423         ACTIONS * n = chain->next;
424         action_free( chain->action );
425         BJAM_FREE( chain );
426         chain = n;
427     }
428 }
429
430
431 /*
432  * freesettings() - delete a settings list.
433  */
434
435 void freesettings( SETTINGS * v )
436 {
437     while ( v )
438     {
439         SETTINGS * n = v->next;
440         object_free( v->symbol );
441         list_free( v->value );
442         v->next = settings_freelist;
443         settings_freelist = v;
444         v = n;
445     }
446 }
447
448
449 static void freetarget( void * xt, void * data )
450 {
451     TARGET * t = (TARGET *)xt;
452     if ( t->name       ) object_free ( t->name       );
453     if ( t->boundname  ) object_free ( t->boundname  );
454     if ( t->settings   ) freesettings( t->settings   );
455     if ( t->depends    ) freetargets ( t->depends    );
456     if ( t->dependants ) freetargets ( t->dependants );
457     if ( t->parents    ) freetargets ( t->parents    );
458     if ( t->actions    ) freeactions ( t->actions    );
459
460     if ( t->includes   )
461     {
462         freetarget( t->includes, (void *)0 );
463         BJAM_FREE( t->includes );
464     }
465 }
466
467
468 /*
469  * rules_done() - free RULE and TARGET tables.
470  */
471
472 void rules_done()
473 {
474     if ( targethash )
475     {
476         hashenumerate( targethash, freetarget, 0 );
477         hashdone( targethash );
478     }
479     while ( settings_freelist )
480     {
481         SETTINGS * n = settings_freelist->next;
482         BJAM_FREE( settings_freelist );
483         settings_freelist = n;
484     }
485 }
486
487
488 /*
489  * actions_refer() - add a new reference to the given actions.
490  */
491
492 void actions_refer( rule_actions * a )
493 {
494     ++a->reference_count;
495 }
496
497
498 /*
499  * actions_free() - release a reference to the given actions.
500  */
501
502 void actions_free( rule_actions * a )
503 {
504     if ( --a->reference_count <= 0 )
505     {
506         function_free( a->command );
507         list_free( a->bindlist );
508         BJAM_FREE( a );
509     }
510 }
511
512 /*
513  * set_rule_body() - set the argument list and procedure of the given rule.
514  */
515
516 static void set_rule_body( RULE * rule, FUNCTION * procedure )
517 {
518     if ( procedure )
519         function_refer( procedure );
520     if ( rule->procedure )
521         function_free( rule->procedure );
522     rule->procedure = procedure;
523 }
524
525
526 /*
527  * global_name() - given a rule, return the name for a corresponding rule in the
528  * global module.
529  */
530
531 static OBJECT * global_rule_name( RULE * r )
532 {
533     if ( r->module == root_module() )
534         return object_copy( r->name );
535
536     {
537         char name[4096] = "";
538         if ( r->module->name )
539         {
540             strncat( name, object_str( r->module->name ), sizeof( name ) - 1 );
541             strncat( name, ".", sizeof( name ) - 1 );
542         }
543         strncat( name, object_str( r->name ), sizeof( name ) - 1 );
544         return object_new( name );
545     }
546 }
547
548
549 /*
550  * global_rule() - given a rule, produce the corresponding entry in the global
551  * module.
552  */
553
554 static RULE * global_rule( RULE * r )
555 {
556     if ( r->module == root_module() )
557         return r;
558
559     {
560         OBJECT * name = global_rule_name( r );
561         RULE * result = define_rule( r->module, name, root_module() );
562         object_free( name );
563         return result;
564     }
565 }
566
567
568 /*
569  * new_rule_body() - make a new rule named rulename in the given module, with
570  * the given argument list and procedure. If exported is true, the rule is
571  * exported to the global module as modulename.rulename.
572  */
573
574 RULE * new_rule_body( module_t * m, OBJECT * rulename, FUNCTION * procedure, int exported )
575 {
576     RULE * local = define_rule( m, rulename, m );
577     local->exported = exported;
578     set_rule_body( local, procedure );
579
580     /* Mark the procedure with the global rule name, regardless of whether the
581      * rule is exported. That gives us something reasonably identifiable that we
582      * can use, e.g. in profiling output. Only do this once, since this could be
583      * called multiple times with the same procedure.
584      */
585     if ( function_rulename( procedure ) == 0 )
586         function_set_rulename( procedure, global_rule_name( local ) );
587
588     return local;
589 }
590
591
592 static void set_rule_actions( RULE * rule, rule_actions * actions )
593 {
594     if ( actions )
595         actions_refer( actions );
596     if ( rule->actions )
597         actions_free( rule->actions );
598     rule->actions = actions;
599 }
600
601
602 static rule_actions * actions_new( FUNCTION * command, LIST * bindlist, int flags )
603 {
604     rule_actions * result = (rule_actions *)BJAM_MALLOC( sizeof( rule_actions ) );
605     function_refer( command );
606     result->command = command;
607     result->bindlist = bindlist;
608     result->flags = flags;
609     result->reference_count = 0;
610     return result;
611 }
612
613
614 RULE * new_rule_actions( module_t * m, OBJECT * rulename, FUNCTION * command, LIST * bindlist, int flags )
615 {
616     RULE * local = define_rule( m, rulename, m );
617     RULE * global = global_rule( local );
618     set_rule_actions( local, actions_new( command, bindlist, flags ) );
619     set_rule_actions( global, local->actions );
620     return local;
621 }
622
623
624 /*
625  * Looks for a rule in the specified module, and returns it, if found. First
626  * checks if the rule is present in the module's rule table. Second, if name of
627  * the rule is in the form name1.name2 and name1 is in the list of imported
628  * modules, look in module 'name1' for rule 'name2'.
629  */
630
631 RULE * lookup_rule( OBJECT * rulename, module_t * m, int local_only )
632 {
633     RULE     * r;
634     RULE     * result = 0;
635     module_t * original_module = m;
636
637     if ( m->class_module )
638         m = m->class_module;
639
640     if ( m->rules && ( r = (RULE *)hash_find( m->rules, rulename ) ) )
641         result = r;
642     else if ( !local_only && m->imported_modules )
643     {
644         /* Try splitting the name into module and rule. */
645         char *p = strchr( object_str( rulename ), '.' ) ;
646         if ( p )
647         {
648             string buf[1];
649             OBJECT * module_part;
650             OBJECT * rule_part;
651             string_new( buf );
652             string_append_range( buf, object_str( rulename ), p );
653             module_part = object_new( buf->value );
654             rule_part = object_new( p + 1 );
655             /* Now, r->name keeps the module name, and p+1 keeps the rule name.
656              */
657             if ( hash_find( m->imported_modules, module_part ) )
658                 result = lookup_rule( rule_part, bindmodule( module_part ), 1 );
659             object_free( rule_part );
660             object_free( module_part );
661             string_free( buf );
662         }
663     }
664
665     if ( result )
666     {
667         if ( local_only && !result->exported )
668             result = 0;
669         else
670         {
671             /* Lookup started in class module. We have found a rule in class
672              * module, which is marked for execution in that module, or in some
673              * instances. Mark it for execution in the instance where we started
674              * the lookup.
675              */
676             int execute_in_class = ( result->module == m );
677             int execute_in_some_instance = ( result->module->class_module &&
678                 ( result->module->class_module == m ) );
679             if ( ( original_module != m ) &&
680                 ( execute_in_class || execute_in_some_instance ) )
681                 result->module = original_module;
682         }
683     }
684
685     return result;
686 }
687
688
689 RULE * bindrule( OBJECT * rulename, module_t * m )
690 {
691     RULE * result = lookup_rule( rulename, m, 0 );
692     if ( !result )
693         result = lookup_rule( rulename, root_module(), 0 );
694     /* We have only one caller, 'evaluate_rule', which will complain about
695      * calling an undefined rule. We could issue the error here, but we do not
696      * have the necessary information, such as frame.
697      */
698     if ( !result )
699         result = enter_rule( rulename, m );
700     return result;
701 }
702
703
704 RULE * import_rule( RULE * source, module_t * m, OBJECT * name )
705 {
706     RULE * dest = define_rule( source->module, name, m );
707     set_rule_body( dest, source->procedure );
708     set_rule_actions( dest, source->actions );
709     return dest;
710 }
711
712
713 void rule_localize( RULE * rule, module_t * m )
714 {
715     rule->module = m;
716     if ( rule->procedure )
717     {
718         FUNCTION * procedure = function_unbind_variables( rule->procedure );
719         function_refer( procedure );
720         function_free( rule->procedure );
721         rule->procedure = procedure;
722     }
723 }
724