[Tizen_6_build] Fixed 32-bit arm build with gcc 9
[platform/upstream/boost-jam.git] / 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 "newstr.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 *, argument_list *, PARSE * procedure );
49
50 static struct hash * targethash = 0;
51
52 struct _located_target
53 {
54     char   * file_name;
55     TARGET * target;
56 };
57 typedef struct _located_target LOCATED_TARGET ;
58
59 static struct hash * located_targets = 0;
60
61
62 /*
63  * target_include() - adds the 'included' TARGET to the list of targets included
64  * by the 'including' TARGET. Such targets are modeled as dependencies of the
65  * internal include node belonging to the 'including' TARGET.
66  */
67
68 void target_include( TARGET * including, TARGET * included )
69 {
70     TARGET * internal;
71     if ( !including->includes )
72     {
73         including->includes = copytarget( including );
74         including->includes->original_target = including;
75     }
76     internal = including->includes;
77     internal->depends = targetentry( internal->depends, included );
78 }
79
80
81 /*
82  * enter_rule() - return pointer to RULE, creating it if necessary in
83  * target_module.
84  */
85
86 static RULE * enter_rule( char * rulename, module_t * target_module )
87 {
88     RULE rule;
89     RULE * r = &rule;
90
91     r->name = rulename;
92
93     if ( hashenter( demand_rules( target_module ), (HASHDATA * *)&r ) )
94     {
95         r->name = newstr( rulename );   /* never freed */
96         r->procedure = (PARSE *)0;
97         r->module = 0;
98         r->actions = 0;
99         r->arguments = 0;
100         r->exported = 0;
101         r->module = target_module;
102 #ifdef HAVE_PYTHON
103         r->python_function = 0;
104 #endif
105     }
106     return r;
107 }
108
109
110 /*
111  * define_rule() - return pointer to RULE, creating it if necessary in
112  * target_module. Prepare it to accept a body or action originating in
113  * src_module.
114  */
115
116 static RULE * define_rule
117 (
118     module_t * src_module,
119     char     * rulename,
120     module_t * target_module
121 )
122 {
123     RULE * r = enter_rule( rulename, target_module );
124     if ( r->module != src_module ) /* if the rule was imported from elsewhere, clear it now */
125     {
126         set_rule_body( r, 0, 0 );
127         set_rule_actions( r, 0 );
128         r->module = src_module; /* r will be executed in the source module */
129     }
130     return r;
131 }
132
133
134 void rule_free( RULE * r )
135 {
136     freestr( r->name );
137     r->name = "";
138     parse_free( r->procedure );
139     r->procedure = 0;
140     if ( r->arguments )
141         args_free( r->arguments );
142     r->arguments = 0;
143     if ( r->actions )
144         actions_free( r->actions );
145     r->actions = 0;
146 }
147
148
149 /*
150  * bindtarget() - return pointer to TARGET, creating it if necessary.
151  */
152
153 TARGET * bindtarget( char const * target_name )
154 {
155     TARGET target;
156     TARGET * t = ⌖
157
158     if ( !targethash )
159         targethash = hashinit( sizeof( TARGET ), "targets" );
160
161     /* Perforce added const everywhere. No time to merge that change. */
162 #ifdef NT
163     target_name = short_path_to_long_path( (char *)target_name );
164 #endif
165     t->name = (char *)target_name;
166
167     if ( hashenter( targethash, (HASHDATA * *)&t ) )
168     {
169         memset( (char *)t, '\0', sizeof( *t ) );
170         t->name = newstr( (char *)target_name );  /* never freed */
171         t->boundname = t->name;  /* default for T_FLAG_NOTFILE */
172     }
173
174     return t;
175 }
176
177
178 static void bind_explicitly_located_target( void * xtarget, void * data )
179 {
180     TARGET * t = (TARGET *)xtarget;
181     if ( !( t->flags & T_FLAG_NOTFILE ) )
182     {
183         /* Check if there's a setting for LOCATE */
184         SETTINGS * s = t->settings;
185         for ( ; s ; s = s->next )
186         {
187             if ( strcmp( s->symbol, "LOCATE" ) == 0 )
188             {
189                 pushsettings( t->settings );
190                 /* We are binding a target with explicit LOCATE. So third
191                  * argument is of no use: nothing will be returned through it.
192                  */
193                 t->boundname = search( t->name, &t->time, 0, 0 );
194                 popsettings( t->settings );
195                 break;
196             }
197         }
198     }
199 }
200
201
202 void bind_explicitly_located_targets()
203 {
204     if ( targethash )
205         hashenumerate( targethash, bind_explicitly_located_target, (void *)0 );
206 }
207
208
209 /* TODO: It is probably not a good idea to use functions in other modules like
210   this. */
211 void call_bind_rule( char * target, char * boundname );
212
213
214 TARGET * search_for_target ( char * name, LIST * search_path )
215 {
216     PATHNAME f[1];
217     string buf[1];
218     LOCATED_TARGET lt;
219     LOCATED_TARGET * lta = <
220     time_t time;
221     int found = 0;
222     TARGET * result;
223
224     string_new( buf );
225
226     path_parse( name, f );
227
228     f->f_grist.ptr = 0;
229     f->f_grist.len = 0;
230
231     while ( search_path )
232     {
233         f->f_root.ptr = search_path->string;
234         f->f_root.len = strlen( search_path->string );
235
236         string_truncate( buf, 0 );
237         path_build( f, buf, 1 );
238
239         lt.file_name = buf->value ;
240
241         if ( !located_targets )
242             located_targets = hashinit( sizeof(LOCATED_TARGET),
243                                         "located targets" );
244
245         if ( hashcheck( located_targets, (HASHDATA * *)&lta ) )
246         {
247             return lta->target;
248         }
249
250         timestamp( buf->value, &time );
251         if ( time )
252         {
253             found = 1;
254             break;
255         }
256
257         search_path = list_next( search_path );
258     }
259
260     if ( !found )
261     {
262         f->f_root.ptr = 0;
263         f->f_root.len = 0;
264
265         string_truncate( buf, 0 );
266         path_build( f, buf, 1 );
267
268         timestamp( buf->value, &time );
269     }
270
271     result = bindtarget( name );
272     result->boundname = newstr( buf->value );
273     result->time = time;
274     result->binding = time ? T_BIND_EXISTS : T_BIND_MISSING;
275
276     call_bind_rule( result->name, result->boundname );
277
278     string_free( buf );
279
280     return result;
281 }
282
283
284 /*
285  * copytarget() - make a new target with the old target's name.
286  *
287  * Not entered into hash table -- for internal nodes.
288  */
289
290 TARGET * copytarget( const TARGET * ot )
291 {
292     TARGET * t = (TARGET *)BJAM_MALLOC( sizeof( *t ) );
293     memset( (char *)t, '\0', sizeof( *t ) );
294     t->name = copystr( ot->name );
295     t->boundname = t->name;
296
297     t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;
298
299     return t;
300 }
301
302
303 /*
304  * touch_target() - mark a target to simulate being new.
305  */
306
307 void touch_target( char * t )
308 {
309     bindtarget( t )->flags |= T_FLAG_TOUCHED;
310 }
311
312
313 /*
314  * targetlist() - turn list of target names into a TARGET chain.
315  *
316  * Inputs:
317  *  chain   existing TARGETS to append to
318  *  targets list of target names
319  */
320
321 TARGETS * targetlist( TARGETS * chain, LIST * target_names )
322 {
323     for ( ; target_names; target_names = list_next( target_names ) )
324         chain = targetentry( chain, bindtarget( target_names->string ) );
325     return chain;
326 }
327
328
329 /*
330  * targetentry() - add a TARGET to a chain of TARGETS.
331  *
332  * Inputs:
333  *  chain   existing TARGETS to append to
334  *  target  new target to append
335  */
336
337 TARGETS * targetentry( TARGETS * chain, TARGET * target )
338 {
339     TARGETS * c = (TARGETS *)BJAM_MALLOC( sizeof( TARGETS ) );
340     c->target = target;
341
342     if ( !chain ) chain = c;
343     else chain->tail->next = c;
344     chain->tail = c;
345     c->next = 0;
346
347     return chain;
348 }
349
350
351 /*
352  * targetchain() - append two TARGET chains.
353  *
354  * Inputs:
355  *  chain   exisitng TARGETS to append to
356  *  target  new target to append
357  */
358
359 TARGETS * targetchain( TARGETS * chain, TARGETS * targets )
360 {
361     if ( !targets ) return chain;
362     if ( !chain   ) return targets;
363
364     chain->tail->next = targets;
365     chain->tail = targets->tail;
366
367     return chain;
368 }
369
370 /*
371  * actionlist() - append to an ACTION chain.
372  */
373
374 ACTIONS * actionlist( ACTIONS * chain, ACTION * action )
375 {
376     ACTIONS * actions = (ACTIONS *)BJAM_MALLOC( sizeof( ACTIONS ) );
377
378     actions->action = action;
379
380     if ( !chain ) chain = actions;
381     else chain->tail->next = actions;
382     chain->tail = actions;
383     actions->next = 0;
384
385     return chain;
386 }
387
388 static SETTINGS * settings_freelist;
389
390
391 /*
392  * addsettings() - add a deferred "set" command to a target.
393  *
394  * Adds a variable setting (varname=list) onto a chain of settings for a
395  * particular target. 'flag' controls the relationship between new and old
396  * values in the same way as in var_set() function (see variable.c). Returns
397  * the head of the settings chain.
398  */
399
400 SETTINGS * addsettings( SETTINGS * head, int flag, char * symbol, LIST * value )
401 {
402     SETTINGS * v;
403
404     /* Look for previous settings. */
405     for ( v = head; v; v = v->next )
406         if ( !strcmp( v->symbol, symbol ) )
407             break;
408
409     /* If not previously set, alloc a new. */
410     /* If appending, do so. */
411     /* Else free old and set new. */
412     if ( !v )
413     {
414         v = settings_freelist;
415
416         if ( v )
417             settings_freelist = v->next;
418         else
419             v = (SETTINGS *)BJAM_MALLOC( sizeof( *v ) );
420
421         v->symbol = newstr( symbol );
422         v->value = value;
423         v->next = head;
424         v->multiple = 0;
425         head = v;
426     }
427     else if ( flag == VAR_APPEND )
428     {
429         v->value = list_append( v->value, value );
430     }
431     else if ( flag != VAR_DEFAULT )
432     {
433         list_free( v->value );
434         v->value = value;
435     }
436     else
437         list_free( value );
438
439     /* Return (new) head of list. */
440     return head;
441 }
442
443
444 /*
445  * pushsettings() - set all target specific variables.
446  */
447
448 void pushsettings( SETTINGS * v )
449 {
450     for ( ; v; v = v->next )
451         v->value = var_swap( v->symbol, v->value );
452 }
453
454
455 /*
456  * popsettings() - reset target specific variables to their pre-push values.
457  */
458
459 void popsettings( SETTINGS * v )
460 {
461     pushsettings( v );  /* just swap again */
462 }
463
464
465 /*
466  * copysettings() - duplicate a settings list, returning the new copy.
467  */
468
469 SETTINGS * copysettings( SETTINGS * head )
470 {
471     SETTINGS * copy = 0;
472     SETTINGS * v;
473     for ( v = head; v; v = v->next )
474         copy = addsettings( copy, VAR_SET, v->symbol, list_copy( 0, v->value ) );
475     return copy;
476 }
477
478
479 /*
480  * freetargets() - delete a targets list.
481  */
482
483 void freetargets( TARGETS * chain )
484 {
485     while ( chain )
486     {
487         TARGETS * n = chain->next;
488         BJAM_FREE( chain );
489         chain = n;
490     }
491 }
492
493
494 /*
495  * freeactions() - delete an action list.
496  */
497
498 void freeactions( ACTIONS * chain )
499 {
500     while ( chain )
501     {
502         ACTIONS * n = chain->next;
503         BJAM_FREE( chain );
504         chain = n;
505     }
506 }
507
508
509 /*
510  * freesettings() - delete a settings list.
511  */
512
513 void freesettings( SETTINGS * v )
514 {
515     while ( v )
516     {
517         SETTINGS * n = v->next;
518         freestr( v->symbol );
519         list_free( v->value );
520         v->next = settings_freelist;
521         settings_freelist = v;
522         v = n;
523     }
524 }
525
526
527 static void freetarget( void * xt, void * data )
528 {
529     TARGET * t = (TARGET *)xt;
530     if ( t->settings ) freesettings( t->settings            );
531     if ( t->depends  ) freetargets ( t->depends             );
532     if ( t->includes ) freetarget  ( t->includes, (void *)0 );
533     if ( t->actions  ) freeactions ( t->actions             );
534 }
535
536
537 /*
538  * rules_done() - free RULE and TARGET tables.
539  */
540
541 void rules_done()
542 {
543     hashenumerate( targethash, freetarget, 0 );
544     hashdone( targethash );
545     while ( settings_freelist )
546     {
547         SETTINGS * n = settings_freelist->next;
548         BJAM_FREE( settings_freelist );
549         settings_freelist = n;
550     }
551 }
552
553
554 /*
555  * args_new() - make a new reference-counted argument list.
556  */
557
558 argument_list * args_new()
559 {
560     argument_list * r = (argument_list *)BJAM_MALLOC( sizeof(argument_list) );
561     r->reference_count = 0;
562     lol_init( r->data );
563     return r;
564 }
565
566
567 /*
568  * args_refer() - add a new reference to the given argument list.
569  */
570
571 void args_refer( argument_list * a )
572 {
573     ++a->reference_count;
574 }
575
576
577 /*
578  * args_free() - release a reference to the given argument list.
579  */
580
581 void args_free( argument_list * a )
582 {
583     if ( --a->reference_count <= 0 )
584     {
585         lol_free( a->data );
586         BJAM_FREE( a );
587     }
588 }
589
590
591 /*
592  * actions_refer() - add a new reference to the given actions.
593  */
594
595 void actions_refer( rule_actions * a )
596 {
597     ++a->reference_count;
598 }
599
600
601 /*
602  * actions_free() - release a reference to the given actions.
603  */
604
605 void actions_free( rule_actions * a )
606 {
607     if ( --a->reference_count <= 0 )
608     {
609         freestr( a->command );
610         list_free( a->bindlist );
611         BJAM_FREE( a );
612     }
613 }
614
615
616 /*
617  * set_rule_body() - set the argument list and procedure of the given rule.
618  */
619
620 static void set_rule_body( RULE * rule, argument_list * args, PARSE * procedure )
621 {
622     if ( args )
623         args_refer( args );
624     if ( rule->arguments )
625         args_free( rule->arguments );
626     rule->arguments = args;
627
628     if ( procedure )
629         parse_refer( procedure );
630     if ( rule->procedure )
631         parse_free( rule->procedure );
632     rule->procedure = procedure;
633 }
634
635
636 /*
637  * global_name() - given a rule, return the name for a corresponding rule in the
638  * global module.
639  */
640
641 static char * global_rule_name( RULE * r )
642 {
643     if ( r->module == root_module() )
644         return r->name;
645
646     {
647         char name[4096] = "";
648         strncat( name, r->module->name, sizeof( name ) - 1 );
649         strncat( name, r->name, sizeof( name ) - 1 );
650         return newstr( name);
651     }
652 }
653
654
655 /*
656  * global_rule() - given a rule, produce the corresponding entry in the global
657  * module.
658  */
659
660 static RULE * global_rule( RULE * r )
661 {
662     if ( r->module == root_module() )
663         return r;
664
665     {
666         char * name = global_rule_name( r );
667         RULE * result = define_rule( r->module, name, root_module() );
668         freestr( name );
669         return result;
670     }
671 }
672
673
674 /*
675  * new_rule_body() - make a new rule named rulename in the given module, with
676  * the given argument list and procedure. If exported is true, the rule is
677  * exported to the global module as modulename.rulename.
678  */
679
680 RULE * new_rule_body( module_t * m, char * rulename, argument_list * args, PARSE * procedure, int exported )
681 {
682     RULE * local = define_rule( m, rulename, m );
683     local->exported = exported;
684     set_rule_body( local, args, procedure );
685
686     /* Mark the procedure with the global rule name, regardless of whether the
687      * rule is exported. That gives us something reasonably identifiable that we
688      * can use, e.g. in profiling output. Only do this once, since this could be
689      * called multiple times with the same procedure.
690      */
691     if ( procedure->rulename == 0 )
692         procedure->rulename = global_rule_name( local );
693
694     return local;
695 }
696
697
698 static void set_rule_actions( RULE * rule, rule_actions * actions )
699 {
700     if ( actions )
701         actions_refer( actions );
702     if ( rule->actions )
703         actions_free( rule->actions );
704     rule->actions = actions;
705 }
706
707
708 static rule_actions * actions_new( char * command, LIST * bindlist, int flags )
709 {
710     rule_actions * result = (rule_actions *)BJAM_MALLOC( sizeof( rule_actions ) );
711     result->command = copystr( command );
712     result->bindlist = bindlist;
713     result->flags = flags;
714     result->reference_count = 0;
715     return result;
716 }
717
718
719 RULE * new_rule_actions( module_t * m, char * rulename, char * command, LIST * bindlist, int flags )
720 {
721     RULE * local = define_rule( m, rulename, m );
722     RULE * global = global_rule( local );
723     set_rule_actions( local, actions_new( command, bindlist, flags ) );
724     set_rule_actions( global, local->actions );
725     return local;
726 }
727
728
729 /*
730  * Looks for a rule in the specified module, and returns it, if found. First
731  * checks if the rule is present in the module's rule table. Second, if name of
732  * the rule is in the form name1.name2 and name1 is in the list of imported
733  * modules, look in module 'name1' for rule 'name2'.
734  */
735
736 RULE * lookup_rule( char * rulename, module_t * m, int local_only )
737 {
738     RULE       rule;
739     RULE     * r = &rule;
740     RULE     * result = 0;
741     module_t * original_module = m;
742
743     r->name = rulename;
744
745     if ( m->class_module )
746         m = m->class_module;
747
748     if ( m->rules && hashcheck( m->rules, (HASHDATA * *)&r ) )
749         result = r;
750     else if ( !local_only && m->imported_modules )
751     {
752         /* Try splitting the name into module and rule. */
753         char *p = strchr( r->name, '.' ) ;
754         if ( p )
755         {
756             *p = '\0';
757             /* Now, r->name keeps the module name, and p+1 keeps the rule name.
758              */
759             if ( hashcheck( m->imported_modules, (HASHDATA * *)&r ) )
760                 result = lookup_rule( p + 1, bindmodule( rulename ), 1 );
761             *p = '.';
762         }
763     }
764
765     if ( result )
766     {
767         if ( local_only && !result->exported )
768             result = 0;
769         else
770         {
771             /* Lookup started in class module. We have found a rule in class
772              * module, which is marked for execution in that module, or in some
773              * instances. Mark it for execution in the instance where we started
774              * the lookup.
775              */
776             int execute_in_class = ( result->module == m );
777             int execute_in_some_instance = ( result->module->class_module &&
778                 ( result->module->class_module == m ) );
779             if ( ( original_module != m ) &&
780                 ( execute_in_class || execute_in_some_instance ) )
781                 result->module = original_module;
782         }
783     }
784
785     return result;
786 }
787
788
789 RULE * bindrule( char * rulename, module_t * m )
790 {
791     RULE * result = lookup_rule( rulename, m, 0 );
792     if ( !result )
793         result = lookup_rule( rulename, root_module(), 0 );
794     /* We have only one caller, 'evaluate_rule', which will complain about
795      * calling an undefined rule. We could issue the error here, but we do not
796      * have the necessary information, such as frame.
797      */
798     if ( !result )
799         result = enter_rule( rulename, m );
800     return result;
801 }
802
803
804 RULE * import_rule( RULE * source, module_t * m, char * name )
805 {
806     RULE * dest = define_rule( source->module, name, m );
807     set_rule_body( dest, source->arguments, source->procedure );
808     set_rule_actions( dest, source->actions );
809     return dest;
810 }