]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/compile.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / tools / build / src / engine / compile.cpp
1 /*
2 * Copyright 1993, 2000 Christopher Seiwald.
3 *
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6
7 /* This file is ALSO:
8 * Copyright 2022 René Ferdinand Rivera Morell
9 * Copyright 2001-2004 David Abrahams.
10 * Distributed under the Boost Software License, Version 1.0.
11 * (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt)
12 */
13
14 /*
15 * compile.c - compile parsed jam statements
16 *
17 * External routines:
18 * evaluate_rule() - execute a rule invocation
19 *
20 * Internal routines:
21 * debug_compile() - printf with indent to show rule expansion
22 */
23
24 #include "jam.h"
25 #include "compile.h"
26
27 #include "builtins.h"
28 #include "class.h"
29 #include "constants.h"
30 #include "hash.h"
31 #include "hdrmacro.h"
32 #include "make.h"
33 #include "modules.h"
34 #include "parse.h"
35 #include "rules.h"
36 #include "search.h"
37 #include "jam_strings.h"
38 #include "variable.h"
39 #include "output.h"
40
41 #include <assert.h>
42 #include <stdarg.h>
43 #include <string.h>
44
45
46 static void debug_compile( int which, char const * s, FRAME * );
47
48 /* Internal functions from builtins.c */
49 void backtrace( FRAME * );
50 void backtrace_line( FRAME * );
51 void print_source_line( FRAME * );
52 void unknown_rule( FRAME *, char const * key, module_t *, OBJECT * rule_name );
53
54
55 /*
56 * evaluate_rule() - execute a rule invocation
57 */
58
59 LIST * evaluate_rule( RULE * rule, OBJECT * rulename, FRAME * frame )
60 {
61 LIST * result = L0;
62 profile_frame prof[ 1 ];
63 module_t * prev_module = frame->module;
64
65 if ( DEBUG_COMPILE )
66 {
67 /* Try hard to indicate in which module the rule is going to execute. */
68 char buf[ 256 ] = "";
69 if ( rule->module->name )
70 {
71 strncat( buf, object_str( rule->module->name ), sizeof( buf ) -
72 1 );
73 strncat( buf, ".", sizeof( buf ) - 1 );
74 if ( strncmp( buf, object_str( rule->name ), strlen( buf ) ) == 0 )
75 {
76 buf[ 0 ] = 0;
77 }
78 }
79 strncat( buf, object_str( rule->name ), sizeof( buf ) - 1 );
80 debug_compile( 1, buf, frame );
81
82 lol_print( frame->args );
83 out_printf( "\n" );
84 }
85
86 if ( rule->procedure && rule->module != prev_module )
87 {
88 /* Propagate current module to nested rule invocations. */
89 frame->module = rule->module;
90 }
91
92 /* Record current rule name in frame. */
93 if ( rule->procedure )
94 {
95 frame->rulename = object_str( rulename );
96 /* And enter record profile info. */
97 if ( DEBUG_PROFILE )
98 profile_enter( function_rulename( rule->procedure ), prof );
99 }
100
101 /* Check traditional targets $(<) and sources $(>). */
102 if ( !rule->actions && !rule->procedure )
103 unknown_rule( frame, NULL, frame->module, rulename );
104
105 /* If this rule will be executed for updating the targets then construct the
106 * action for make().
107 */
108 if ( rule->actions )
109 {
110 targets_ptr t;
111
112 /* The action is associated with this instance of this rule. */
113 ACTION * const action = b2::jam::make_ptr<ACTION>();
114
115 action->rule = rule;
116 action->targets.reset(); targetlist( action->targets, lol_get( frame->args, 0 ) );
117 action->sources.reset(); targetlist( action->sources, lol_get( frame->args, 1 ) );
118 action->refs = 1;
119
120 /* If we have a group of targets all being built using the same action
121 * and any of these targets is updated, then we have to consider them
122 * all to be out-dated. We do this by adding a REBUILDS in both directions
123 * between the first target and all the other targets.
124 */
125 if ( action->targets )
126 {
127 TARGET * const t0 = action->targets->target;
128 for ( t = action->targets->next.get(); t; t = t->next.get() )
129 {
130 targetentry( t->target->rebuilds, t0 );
131 targetentry( t0->rebuilds, t->target );
132 }
133 }
134
135 /* Append this action to the actions of each target. */
136 for ( t = action->targets.get(); t; t = t->next.get() )
137 t->target->actions = actionlist( t->target->actions, action );
138
139 action_free( action );
140 }
141
142 /* Now recursively compile any parse tree associated with this rule.
143 * function_refer()/function_free() call pair added to ensure the rule does
144 * not get freed while in use.
145 */
146 if ( rule->procedure )
147 {
148 auto function = b2::jam::make_unique_bare_jptr( rule->procedure, function_refer, function_free );
149 result = function_run( function.get(), frame, stack_global() );
150 }
151
152 if ( DEBUG_PROFILE && rule->procedure )
153 profile_exit( prof );
154
155 if ( DEBUG_COMPILE )
156 debug_compile( -1, 0, frame );
157
158 return result;
159 }
160
161
162 /*
163 * Call the given rule with the specified parameters. The parameters should be
164 * of type LIST* and end with a NULL pointer. This differs from 'evaluate_rule'
165 * in that frame for the called rule is prepared inside 'call_rule'.
166 *
167 * This function is useful when a builtin rule (in C) wants to call another rule
168 * which might be implemented in Jam.
169 */
170
171 LIST * call_rule( OBJECT * rulename, FRAME * caller_frame, ... )
172 {
173 va_list va;
174 LIST * result;
175
176 FRAME inner[ 1 ];
177 frame_init( inner );
178 inner->prev = caller_frame;
179 inner->prev_user = caller_frame->module->user_module
180 ? caller_frame
181 : caller_frame->prev_user;
182 inner->module = caller_frame->module;
183
184 va_start( va, caller_frame );
185 for ( ; ; )
186 {
187 LIST * const l = va_arg( va, LIST * );
188 if ( !l )
189 break;
190 lol_add( inner->args, l );
191 }
192 va_end( va );
193
194 result = evaluate_rule( bindrule( rulename, inner->module ), rulename, inner );
195
196 frame_free( inner );
197
198 return result;
199 }
200
201
202 /*
203 * debug_compile() - printf with indent to show rule expansion
204 */
205
206 static void debug_compile( int which, char const * s, FRAME * frame )
207 {
208 static int level = 0;
209 static char indent[ 36 ] = ">>>>|>>>>|>>>>|>>>>|>>>>|>>>>|>>>>|";
210
211 if ( which >= 0 )
212 {
213 int i;
214
215 print_source_line( frame );
216
217 i = ( level + 1 ) * 2;
218 while ( i > 35 )
219 {
220 out_puts( indent );
221 i -= 35;
222 }
223
224 out_printf( "%*.*s ", i, i, indent );
225 }
226
227 if ( s )
228 out_printf( "%s ", s );
229
230 level += which;
231 }