2 |
7u83 |
1 |
/*
|
|
|
2 |
Crown Copyright (c) 1997
|
|
|
3 |
|
|
|
4 |
This TenDRA(r) Computer Program is subject to Copyright
|
|
|
5 |
owned by the United Kingdom Secretary of State for Defence
|
|
|
6 |
acting through the Defence Evaluation and Research Agency
|
|
|
7 |
(DERA). It is made available to Recipients with a
|
|
|
8 |
royalty-free licence for its use, reproduction, transfer
|
|
|
9 |
to other parties and amendment for any purpose not excluding
|
|
|
10 |
product development provided that any such use et cetera
|
|
|
11 |
shall be deemed to be acceptance of the following conditions:-
|
|
|
12 |
|
|
|
13 |
(1) Its Recipients shall ensure that this Notice is
|
|
|
14 |
reproduced upon any copies or amended versions of it;
|
|
|
15 |
|
|
|
16 |
(2) Any amended version of it shall be clearly marked to
|
|
|
17 |
show both the nature of and the organisation responsible
|
|
|
18 |
for the relevant amendment or amendments;
|
|
|
19 |
|
|
|
20 |
(3) Its onward transfer from a recipient to another
|
|
|
21 |
party shall be deemed to be that party's acceptance of
|
|
|
22 |
these conditions;
|
|
|
23 |
|
|
|
24 |
(4) DERA gives no warranty or assurance as to its
|
|
|
25 |
quality or suitability for any purpose and DERA accepts
|
|
|
26 |
no liability whatsoever in relation to any use to which
|
|
|
27 |
it may be put.
|
|
|
28 |
*/
|
|
|
29 |
|
|
|
30 |
|
|
|
31 |
#include "config.h"
|
|
|
32 |
#include "filename.h"
|
|
|
33 |
#include "list.h"
|
|
|
34 |
#include "archive.h"
|
|
|
35 |
#include "environ.h"
|
|
|
36 |
#include "flags.h"
|
|
|
37 |
#include "main.h"
|
|
|
38 |
#include "options.h"
|
|
|
39 |
#include "startup.h"
|
|
|
40 |
#include "suffix.h"
|
|
|
41 |
#include "utility.h"
|
|
|
42 |
|
|
|
43 |
|
|
|
44 |
/*
|
|
|
45 |
THE LIST OF ALL INPUT FILES
|
|
|
46 |
|
|
|
47 |
All input files found by process_options are added to this list.
|
|
|
48 |
*/
|
|
|
49 |
|
|
|
50 |
filename *input_files = null ;
|
|
|
51 |
|
|
|
52 |
|
|
|
53 |
/*
|
|
|
54 |
THE MAIN OPTION MAP
|
|
|
55 |
|
|
|
56 |
This table gives all the command-line options.
|
|
|
57 |
*/
|
|
|
58 |
|
|
|
59 |
optmap main_optmap [] = {
|
|
|
60 |
/* Common options */
|
|
|
61 |
{ "^-$", "I?$0", "specifies an input file" },
|
|
|
62 |
{ "-o+$", "SFN$1", "specifies output file name" },
|
|
|
63 |
{ "-D+$=$", "D#define$s$1$s$2$n|AOC$0", "defines a macro" },
|
|
|
64 |
{ "-D+$", "D#define$s$1$s1$n|AOC$0", "defines a macro to be 1" },
|
|
|
65 |
{ "-F?", "H$1", "halts the compilation at the given stage" },
|
|
|
66 |
{ "-I+$", "AUI$0|AOC$0|AUP$0", "specifies an include file directory" },
|
|
|
67 |
{ "-L+$", "1ON|Io$0|AUL$0", "specifies a system library directory" },
|
|
|
68 |
{ "-N+$:+$", "AUI$0|AOC-I$2",
|
|
|
69 |
"specifies an include file directory (with mode)" },
|
|
|
70 |
{ "-O$", "1OP|AOC$0", "switches optimisation level" },
|
|
|
71 |
{ "-P?*", "K$1", "causes intermediate files to be preserved" },
|
|
|
72 |
{ "-S", "Hs", "halts compilation after creating .s files" },
|
|
|
73 |
{ "-T+$", "CAT:$1|AOC-D$1", "specifies a command-line token" },
|
|
|
74 |
{ "-U+$", "D#undef$s$1$n|AOC$0", "undefines a macro" },
|
|
|
75 |
{ "-W?,+$,+*", "AQ$1$2", "passed an option to a compilation tool" },
|
|
|
76 |
{ "-W?:+$", "AQ$1$2", "passed an option to a compilation tool" },
|
|
|
77 |
{ "-X:+$,+*", "CAP:$1", "specifies a compilation option" },
|
|
|
78 |
{ "-X$", "EX$1", "specifies a compilation mode" },
|
|
|
79 |
{ "-Y+$", "E$1", "reads an environment" },
|
|
|
80 |
{ "-copyright", "1CR", "outputs copyright notice" },
|
|
|
81 |
{ "-c", "Ho", "halts compilation after creating .o files" },
|
|
|
82 |
{ "-d", "Hd", "halts compilation after creating .d files" },
|
|
|
83 |
{ "-dry", "1VB|1DR", "causes a dry run" },
|
|
|
84 |
{ "-e+$", "AUe$0", "specifies a producer end-up file" },
|
|
|
85 |
{ "-f+$", "AUf$0", "specifies a producer start-up file" },
|
|
|
86 |
{ "-g", "1DG", "produces debugging information (default format)" },
|
|
|
87 |
{ "-g1", "1DG", "produces debugging information (old format)" },
|
|
|
88 |
{ "-g2", "2DG", "produces debugging information (new format)" },
|
|
|
89 |
{ "-g3", "3DG", "produces debugging information (new format)" },
|
|
|
90 |
{ "-k", "Hk|HK", "halts compilation after creating .k and .K files" },
|
|
|
91 |
{ "-l+$", "1ON|Io$0|AUl$0", "specifies a system library" },
|
|
|
92 |
{ "-not_ansi", "ASs-fnot_ansi", "allows some non-ANSI C features" },
|
|
|
93 |
{ "-nepc", "1NE|ASs-fnepc", "switches off extra portability checks" },
|
|
|
94 |
{ "-sym", "1CS|SDO-d=", "enables symbol table dump linking" },
|
|
|
95 |
{ "-sym:$", "1CS|SDO-d$1=", "enables symbol table dump linking with flags" },
|
|
|
96 |
{ "-v", "1VB", "specifies verbose mode" },
|
|
|
97 |
{ "-vb", "1TC", "specifies fairly verbose mode" },
|
|
|
98 |
|
|
|
99 |
/* Options not allowed in checker */
|
|
|
100 |
{ "-J+$", "AUJ-L$1", "specifies a TDF library directory" },
|
|
|
101 |
{ "-M", "1MC", "causes all .j files to be merged" },
|
|
|
102 |
{ "-MA", "1MC|1MP", "as -M, but with hiding" },
|
|
|
103 |
{ "-ch", "1CH", "invokes checker mode" },
|
|
|
104 |
{ "-disp", "1PP", "causes all .j files to be pretty printed" },
|
|
|
105 |
{ "-disp_t", "2PP", "causes all .t files to be pretty printed" },
|
|
|
106 |
{ "-i", "Hj", "halts compilation after creating .j files" },
|
|
|
107 |
{ "-im", "1CS", "enables intermodular checks" },
|
|
|
108 |
{ "-j+$", "AUj-l$1", "specifies a TDF library" },
|
|
|
109 |
{ "-prod", "1AR", "causes a TDF archive to be produced" },
|
|
|
110 |
|
|
|
111 |
/* Less common options */
|
|
|
112 |
{ "-A+-", "AOC$0", "unasserts all built-in predicates" },
|
|
|
113 |
{ "-A+$", "D#pragma$saccept$sdirective$sassert$n|D#assert$s$1$n|AOC$0",
|
|
|
114 |
"asserts a predicate" },
|
|
|
115 |
{ "-B+$", "1ON|Io$0", "passed to the system linker" },
|
|
|
116 |
{ "-C", "AOC$0", "preserves comments when preprocessing" },
|
|
|
117 |
{ "-E", "1PR", "causes C source files to be preprocessed" },
|
|
|
118 |
{ "-E?:+$", "LE$1$2", "specifies an executable to be used" },
|
|
|
119 |
{ "-H", "1PI", "causes included files to be printed" },
|
|
|
120 |
{ "-S?,+$,+*", "I$1$2", "specifies input files" },
|
|
|
121 |
{ "-S?:+$", "I$1$2", "specifies input files" },
|
|
|
122 |
{ "-V", "EVersions|1CR", "causes all tools to print their version numbers" },
|
|
|
123 |
{ "-cc", "1CC", "forces the system compiler to be used" },
|
|
|
124 |
{ "-cc_only", "2CC", "forces only the system compiler to be used" },
|
|
|
125 |
{ "-do?+$", "SN$1$2", "sets a default output file name" },
|
|
|
126 |
{ "-dump", "CDS", "dumps the current status" },
|
|
|
127 |
{ "-ignore_case", "1LC", "ignores case in file names" },
|
|
|
128 |
{ "-im0", "2CS", "disables intermodular checks" },
|
|
|
129 |
{ "-info", "1SA", "causes API information to be printed" },
|
|
|
130 |
{ "-keep_errors", "1KE", "causes files to be preserved on errors" },
|
|
|
131 |
{ "-make_up_names", "1MN", "makes up names for intermediate files" },
|
|
|
132 |
{ "-message+$", "@X$1", "causes %s to print a message" },
|
|
|
133 |
{ "-p", "1PF", "causes profiling information to be produced" },
|
|
|
134 |
{ "-q", "0VB", "specifies quiet mode" },
|
|
|
135 |
{ "-quiet", "0VB", "equivalent to -q" },
|
|
|
136 |
{ "-query", "Q", "causes a list of options to be printed" },
|
|
|
137 |
{ "-s?:+$", "SS$1$2|1SO", "specifies a suffix override" },
|
|
|
138 |
{ "-show_errors", "1SE", "causes error producing commands to be shown" },
|
|
|
139 |
{ "-show_env", "CSE", "causes the environment path to be printed" },
|
|
|
140 |
{ "-special+$", "SXX$1|CSP", "allows various internal options" },
|
|
|
141 |
{ "-startup+$", "@D$1$n", "specifies a start-up option" },
|
|
|
142 |
{ "-target+$", "AOC-target|AOC$1", "provided for cc compatibility" },
|
|
|
143 |
{ "-temp+$", "STD$1", "specifies the temporary directory" },
|
|
|
144 |
{ "-tidy", "1TU", "causes %s to tidy up as it goes along" },
|
|
|
145 |
{ "-time", "1TI|1VB", "causes all commands to be timed" },
|
|
|
146 |
{ "-verbose", "1VB", "equivalent to -v" },
|
|
|
147 |
{ "-version", "CPV", "causes %s to print its version number" },
|
|
|
148 |
{ "-w", "0WA", "suppresses %s warnings" },
|
|
|
149 |
{ "-work+$", "SWD$1", "specifies the work directory" },
|
|
|
150 |
|
|
|
151 |
/* Options not allowed in checker */
|
|
|
152 |
{ "-G", "EGoption", "provided for cc compatibility" },
|
|
|
153 |
{ "-K+$,+*", "EK-$1", "provided for cc compatibility" },
|
|
|
154 |
{ "-Z$", "EZ-$1", "provided for cc compatibility" },
|
|
|
155 |
{ "-b", "LSc", "suppresses -lc in system linking" },
|
|
|
156 |
{ "-dn", "AOl$0", "passed to the system linker" },
|
|
|
157 |
{ "-dy", "AOl$0", "passed to the system linker" },
|
|
|
158 |
{ "-h+$", "AOl$0", "passed to the system linker" },
|
|
|
159 |
{ "-no_startup_options", "0ST", "suppresses start-up options" },
|
|
|
160 |
{ "-s", "1SR", "passed to the system linker" },
|
|
|
161 |
{ "-u+$", "AOl$0", "passed to the system linker" },
|
|
|
162 |
{ "-wsl", "Ewsl", "causes string literals to be made writable" },
|
|
|
163 |
{ "-z+$", "AOl$0", "passed to the system linker" },
|
|
|
164 |
{ "-#", "1VB", "equivalent to -v" },
|
|
|
165 |
{ "-##", "1VB", "equivalent to -v" },
|
|
|
166 |
{ "-###", "1VB|1DR", "equivalent to -dry" },
|
|
|
167 |
|
|
|
168 |
/* Default options */
|
|
|
169 |
{ "--+$,+*", "$1", "communicates directly with the option interpreter" },
|
|
|
170 |
{ "$", "XUnknown option,$s$0|AXO$0", "unknown option" },
|
|
|
171 |
|
|
|
172 |
/* End marker */
|
|
|
173 |
{ null, null, null }
|
|
|
174 |
} ;
|
|
|
175 |
|
|
|
176 |
|
|
|
177 |
/*
|
|
|
178 |
THE ENVIRONMENT OPTION MAP
|
|
|
179 |
|
|
|
180 |
This table gives all the environment options. It needs to be kept
|
|
|
181 |
in line with Table 4.
|
|
|
182 |
*/
|
|
|
183 |
|
|
|
184 |
optmap environ_optmap [] = {
|
|
|
185 |
/* Options */
|
|
|
186 |
{ "\\+FLAG $", "=$1", null },
|
|
|
187 |
{ "\\+FLAG_TDFC $", "AOc$1", null },
|
|
|
188 |
{ "\\+FLAG_TDFCPP $", "AOp$1", null },
|
|
|
189 |
{ "\\+FLAG_TCPPLUS $", "AOx$1", null },
|
|
|
190 |
{ "\\+FLAG_TCPPLUSPP $", "AOg$1", null },
|
|
|
191 |
{ "\\+FLAG_TOT_CAT $", "", null },
|
|
|
192 |
{ "\\+FLAG_TLD $", "AOL$1", null },
|
|
|
193 |
{ "\\+FLAG_TRANS $", "AOt$1", null },
|
|
|
194 |
{ "\\+FLAG_AS $", "AOa$1", null },
|
|
|
195 |
{ "\\+FLAG_DYN_LINK $", "AOD$1", null },
|
|
|
196 |
{ "\\+FLAG_LD $", "AOl$1", null },
|
|
|
197 |
{ "\\+FLAG_DISP $", "AOd$1", null },
|
|
|
198 |
{ "\\+FLAG_TNC $", "AOn$1", null },
|
|
|
199 |
{ "\\+FLAG_PL_TDF $", "AOP$1", null },
|
|
|
200 |
{ "\\+FLAG_AS1 $", "AOA$1", null },
|
|
|
201 |
{ "\\+FLAG_TDFOPT $", "", null },
|
|
|
202 |
{ "\\+FLAG_SPEC_LINK $", "AOs$1", null },
|
|
|
203 |
{ "\\+FLAG_CPP_SPEC_LINK $", "AOS$1", null },
|
|
|
204 |
{ "\\+FLAG_DUMP_ANAL $", "AOe$1", null },
|
|
|
205 |
{ "\\+FLAG_DUMP_LINK $", "AOu$1", null },
|
|
|
206 |
{ "\\+FLAG_CC $", "AOC$1", null },
|
|
|
207 |
{ "\\+FLAG_INSTALL $", "AOI$1", null },
|
|
|
208 |
|
|
|
209 |
/* Additional filename suffixes */
|
|
|
210 |
{ "\\+SUFFIX_CPP $", "SSC$1|1SO", null },
|
|
|
211 |
|
|
|
212 |
/* Executables */
|
|
|
213 |
{ "?AS $", "$1Ea$2", null },
|
|
|
214 |
{ "?AS1 $", "$1EA$2", null },
|
|
|
215 |
{ "?BUILD_ARCH $", "$1BB$2", null },
|
|
|
216 |
{ "?CAT $", "$1BC$2", null },
|
|
|
217 |
{ "?CC $", "$1EC$2", null },
|
|
|
218 |
{ "?CPP_SPEC_LINK $", "$1ES$2", null },
|
|
|
219 |
{ "?DISP $", "$1Ed$2", null },
|
|
|
220 |
{ "?DUMP_ANAL $", "$1Ee$2", null },
|
|
|
221 |
{ "?DUMP_LINK $", "$1Eu$2", null },
|
|
|
222 |
{ "?DYN_LINK $", "$1ED$2", null },
|
|
|
223 |
{ "?LD $", "$1El$2", null },
|
|
|
224 |
{ "?MKDIR $", "$1BD$2", null },
|
|
|
225 |
{ "?MOVE $", "$1BM$2", null },
|
|
|
226 |
{ "?PL_TDF $", "$1EP$2", null },
|
|
|
227 |
{ "?REMOVE $", "$1BR$2", null },
|
|
|
228 |
{ "?SPEC_LINK $", "$1Es$2", null },
|
|
|
229 |
{ "?SPLIT_ARCH $", "$1BS$2", null },
|
|
|
230 |
{ "?TCPPLUS $", "$1Ex$2", null },
|
|
|
231 |
{ "?TCPPLUSPP $", "$1Eg$2", null },
|
|
|
232 |
{ "?TDFC $", "$1Ec$2", null },
|
|
|
233 |
{ "?TDFCPP $", "$1Ep$2", null },
|
|
|
234 |
{ "?TDFOPT $", "", null },
|
|
|
235 |
{ "?TLD $", "$1EL$2", null },
|
|
|
236 |
{ "?TNC $", "$1En$2", null },
|
|
|
237 |
{ "?TOUCH $", "$1BT$2", null },
|
|
|
238 |
{ "?TRANS $", "$1Et$2", null },
|
|
|
239 |
|
|
|
240 |
/* Flags */
|
|
|
241 |
{ "?API $", "", null },
|
|
|
242 |
{ "?API_NAME $", "", null },
|
|
|
243 |
{ "?INCL $", "$1SI$2", null },
|
|
|
244 |
{ "?INCL_CPP $", "$1Si$2", null },
|
|
|
245 |
{ "?STARTUP_DIR $", "$1Sd$2", null },
|
|
|
246 |
{ "?STARTUP $", "$1Ss$2", null },
|
|
|
247 |
{ "?STARTUP_CPP_DIR $", "$1SD$2", null },
|
|
|
248 |
{ "?STARTUP_CPP $", "$1SS$2", null },
|
|
|
249 |
{ "?PORTABILITY $", "$1SP$2", null },
|
|
|
250 |
{ "?LINK $", "$1SJ$2", null },
|
|
|
251 |
{ "?LIB $", "$1Sj$2", null },
|
|
|
252 |
{ "?CRT0 $", "$1S0$2", null },
|
|
|
253 |
{ "?CRT1 $", "$1S1$2", null },
|
|
|
254 |
{ "?CRTN $", "$1S2$2", null },
|
|
|
255 |
{ "?CRTP_N $", "$1S3$2", null },
|
|
|
256 |
{ "?SYS_LINK $", "$1SL$2", null },
|
|
|
257 |
{ "?SYS_LIB $", "$1Sl$2", null },
|
|
|
258 |
{ "?SYS_LIBC $", "$1Sc$2", null },
|
|
|
259 |
{ "?LINK_ENTRY $", "$1Se$2", null },
|
|
|
260 |
|
|
|
261 |
/* Startup and endup lines */
|
|
|
262 |
{ "\\+COMP_OPTION $", "@CAP:$1", null },
|
|
|
263 |
{ "\\+LINE_START $", "@D$1$n", null },
|
|
|
264 |
{ "\\+LINE_END $", "@F$1$n", null },
|
|
|
265 |
|
|
|
266 |
/* Miscellaneous */
|
|
|
267 |
{ "\\+INFO $", "@SAI$1", null },
|
|
|
268 |
{ ">INFO $", "@SAI$SAI@plus@$1", null },
|
|
|
269 |
{ "<INFO $", "@SAI$1@plus@$SAI", null },
|
|
|
270 |
{ "\\+ENVDIR $", "SED$1|CFE", null },
|
|
|
271 |
{ "\\?ENVDIR $", "?:ED$1", null },
|
|
|
272 |
{ "\\+MACHINE $", "SMN$1|CSM", null },
|
|
|
273 |
{ "\\?MACHINE $", "?:MN$1", null },
|
|
|
274 |
{ "\\+SUFFIX $", "STD$1", null }, /* this MUST be wrong !!! */
|
|
|
275 |
{ "\\+TEMP $", "STD$1", null },
|
|
|
276 |
{ "\\?TEMP $", "?:TD$1", null },
|
|
|
277 |
{ "\\+VERSION $", "SVF$1", null },
|
|
|
278 |
{ "\\?VERSION $", "?:VF$1", null },
|
|
|
279 |
|
|
|
280 |
/* Errors */
|
|
|
281 |
{ "\\+E$ $", "X+E$soptions$sno$slonger$ssupported", null },
|
|
|
282 |
{ "$ $", "XUnknown$senvironmental$svariable,$s$1", null },
|
|
|
283 |
{ "$", "XIllegal$senvironmental$soption,$s$0", null },
|
|
|
284 |
|
|
|
285 |
/* End marker */
|
|
|
286 |
{ null, null, null }
|
|
|
287 |
} ;
|
|
|
288 |
|
|
|
289 |
|
|
|
290 |
/*
|
|
|
291 |
OPTION INTERPRETER DEBUGGING FLAG
|
|
|
292 |
|
|
|
293 |
This flag indicates whether option interpreter debugging information
|
|
|
294 |
should be printed.
|
|
|
295 |
*/
|
|
|
296 |
|
|
|
297 |
static boolean debug_options = 0 ;
|
|
|
298 |
|
|
|
299 |
|
|
|
300 |
/*
|
|
|
301 |
LOCAL FLAGS
|
|
|
302 |
|
|
|
303 |
These values may be used for temporary storage by the option
|
|
|
304 |
interpreter.
|
|
|
305 |
*/
|
|
|
306 |
|
|
|
307 |
static boolean xx_bool = 0 ;
|
|
|
308 |
static list *xx_list = null ;
|
|
|
309 |
static char *xx_string = null ;
|
|
|
310 |
|
|
|
311 |
|
|
|
312 |
/*
|
|
|
313 |
ROUTINE IMPLEMENTING THE -SPECIAL OPTION
|
|
|
314 |
|
|
|
315 |
This routine enables certain internal options depending on the
|
|
|
316 |
value of the string held in xx_string.
|
|
|
317 |
*/
|
|
|
318 |
|
|
|
319 |
static void special_option
|
|
|
320 |
PROTO_Z ()
|
|
|
321 |
{
|
|
|
322 |
boolean b = 1 ;
|
|
|
323 |
char *s = xx_string ;
|
|
|
324 |
if ( strneq ( s, "no_", 3 ) ) {
|
|
|
325 |
b = 0 ;
|
|
|
326 |
s += 3 ;
|
|
|
327 |
}
|
|
|
328 |
if ( streq ( s, "cpp" ) ) {
|
|
|
329 |
allow_cpp = b ;
|
|
|
330 |
} else if ( streq ( s, "tnc" ) && !checker ) {
|
|
|
331 |
allow_notation = b ;
|
|
|
332 |
} else if ( streq ( s, "pl_tdf" ) && !checker ) {
|
|
|
333 |
allow_pl_tdf = b ;
|
|
|
334 |
} else if ( streq ( s, "c_spec" ) || streq ( s, "cpp_spec" ) ) {
|
|
|
335 |
allow_specs = b ;
|
|
|
336 |
} else if ( streq ( s, "dump" ) || streq ( s, "cpp_dump" ) ) {
|
|
|
337 |
allow_specs = b ;
|
|
|
338 |
if ( dump_opts == null ) dump_opts = "-d=" ;
|
|
|
339 |
} else {
|
|
|
340 |
error ( WARNING, "Unknown special option, '%s'", s ) ;
|
|
|
341 |
}
|
|
|
342 |
return ;
|
|
|
343 |
}
|
|
|
344 |
|
|
|
345 |
|
|
|
346 |
/*
|
|
|
347 |
CONVERT A TWO LETTER CODE INTO A BOOLEAN
|
|
|
348 |
|
|
|
349 |
This routine takes a two letter code, s, and returns a pointer to
|
|
|
350 |
the corresponding boolean variable.
|
|
|
351 |
*/
|
|
|
352 |
|
|
|
353 |
static boolean *lookup_bool
|
|
|
354 |
PROTO_N ( ( s ) )
|
|
|
355 |
PROTO_T ( char *s )
|
|
|
356 |
{
|
|
|
357 |
char a = s [0] ;
|
|
|
358 |
char b = 0 ;
|
|
|
359 |
if ( a ) b = s [1] ;
|
|
|
360 |
switch ( a ) {
|
|
|
361 |
case 'A' : {
|
|
|
362 |
if ( b == 'A' ) return ( &use_alpha_assembler ) ;
|
|
|
363 |
if ( b == 'C' ) return ( &api_checks ) ;
|
|
|
364 |
if ( b == 'R' ) return ( &make_archive ) ;
|
|
|
365 |
if ( b == 'S' ) return ( &use_assembler ) ;
|
|
|
366 |
break ;
|
|
|
367 |
}
|
|
|
368 |
case 'C' : {
|
|
|
369 |
if ( b == 'C' ) return ( &use_system_cc ) ;
|
|
|
370 |
if ( b == 'H' ) return ( &checker ) ;
|
|
|
371 |
if ( b == 'R' ) return ( ©right ) ;
|
|
|
372 |
if ( b == 'S' ) return ( &allow_specs ) ;
|
|
|
373 |
break ;
|
|
|
374 |
}
|
|
|
375 |
case 'D' : {
|
|
|
376 |
if ( b == 'B' ) return ( &debug_options ) ;
|
|
|
377 |
if ( b == 'G' ) return ( &flag_diag ) ;
|
|
|
378 |
if ( b == 'L' ) return ( &use_dynlink ) ;
|
|
|
379 |
if ( b == 'R' ) return ( &dry_run ) ;
|
|
|
380 |
break ;
|
|
|
381 |
}
|
|
|
382 |
case 'H' : {
|
|
|
383 |
if ( b == 'L' ) return ( &use_hp_linker ) ;
|
|
|
384 |
break ;
|
|
|
385 |
}
|
|
|
386 |
case 'K' : {
|
|
|
387 |
if ( b == 'E' ) return ( &flag_keep_err ) ;
|
|
|
388 |
break ;
|
|
|
389 |
}
|
|
|
390 |
case 'L' : {
|
|
|
391 |
if ( b == 'C' ) return ( &case_insensitive ) ;
|
|
|
392 |
if ( b == 'S' ) return ( &link_specs ) ;
|
|
|
393 |
break ;
|
|
|
394 |
}
|
|
|
395 |
case 'M' : {
|
|
|
396 |
if ( b == 'A' ) return ( &use_mips_assembler ) ;
|
|
|
397 |
if ( b == 'C' ) return ( &make_complex ) ;
|
|
|
398 |
if ( b == 'N' ) return ( &make_up_names ) ;
|
|
|
399 |
if ( b == 'P' ) return ( &flag_merge_all ) ;
|
|
|
400 |
break ;
|
|
|
401 |
}
|
|
|
402 |
case 'N' : {
|
|
|
403 |
if ( b == 'E' ) return ( &flag_nepc ) ;
|
|
|
404 |
break ;
|
|
|
405 |
}
|
|
|
406 |
case 'O' : {
|
|
|
407 |
if ( b == 'N' ) return ( &option_next ) ;
|
|
|
408 |
if ( b == 'P' ) return ( &flag_optim ) ;
|
|
|
409 |
break ;
|
|
|
410 |
}
|
|
|
411 |
case 'P' : {
|
|
|
412 |
if ( b == 'F' ) return ( &flag_prof ) ;
|
|
|
413 |
if ( b == 'I' ) return ( &flag_incl ) ;
|
|
|
414 |
if ( b == 'L' ) return ( &allow_pl_tdf ) ;
|
|
|
415 |
if ( b == 'P' ) return ( &make_pretty ) ;
|
|
|
416 |
if ( b == 'R' ) return ( &make_preproc ) ;
|
|
|
417 |
break ;
|
|
|
418 |
}
|
|
|
419 |
case 'S' : {
|
|
|
420 |
if ( b == 'A' ) return ( &show_api ) ;
|
|
|
421 |
if ( b == 'C' ) return ( &use_sparc_cc ) ;
|
|
|
422 |
if ( b == 'E' ) return ( &show_errors ) ;
|
|
|
423 |
if ( b == 'O' ) return ( &suffix_overrides ) ;
|
|
|
424 |
if ( b == 'R' ) return ( &flag_strip ) ;
|
|
|
425 |
if ( b == 'T' ) return ( &flag_startup ) ;
|
|
|
426 |
break ;
|
|
|
427 |
}
|
|
|
428 |
case 'T' : {
|
|
|
429 |
if ( b == 'C' ) return ( &taciturn ) ;
|
|
|
430 |
if ( b == 'I' ) return ( &time_commands ) ;
|
|
|
431 |
if ( b == 'N' ) return ( &allow_notation ) ;
|
|
|
432 |
if ( b == 'S' ) return ( &make_tspec ) ;
|
|
|
433 |
if ( b == 'U' ) return ( &tidy_up ) ;
|
|
|
434 |
break ;
|
|
|
435 |
}
|
|
|
436 |
case 'V' : {
|
|
|
437 |
if ( b == 'B' ) return ( &verbose ) ;
|
|
|
438 |
break ;
|
|
|
439 |
}
|
|
|
440 |
case 'W' : {
|
|
|
441 |
if ( b == 'A' ) return ( &warnings ) ;
|
|
|
442 |
break ;
|
|
|
443 |
}
|
|
|
444 |
case 'X' : {
|
|
|
445 |
if ( b == 'X' ) return ( &xx_bool ) ;
|
|
|
446 |
break ;
|
|
|
447 |
}
|
|
|
448 |
}
|
|
|
449 |
error ( OPTION, "Unknown boolean identifier, '%c%c'", a, b ) ;
|
|
|
450 |
return ( null ) ;
|
|
|
451 |
}
|
|
|
452 |
|
|
|
453 |
|
|
|
454 |
/*
|
|
|
455 |
CONVERT A TWO LETTER CODE INTO A LIST
|
|
|
456 |
|
|
|
457 |
This routine takes a two letter code, s, and returns a pointer to
|
|
|
458 |
the corresponding list variable. This routine needs to be kept in
|
|
|
459 |
step with Table 4.
|
|
|
460 |
*/
|
|
|
461 |
|
|
|
462 |
static list **lookup_list
|
|
|
463 |
PROTO_N ( ( s ) )
|
|
|
464 |
PROTO_T ( char *s )
|
|
|
465 |
{
|
|
|
466 |
char a = s [0] ;
|
|
|
467 |
char b = 0 ;
|
|
|
468 |
if ( a ) b = s [1] ;
|
|
|
469 |
switch ( a ) {
|
|
|
470 |
case 'B' : {
|
|
|
471 |
switch ( b ) {
|
|
|
472 |
case 'B' : return ( &exec_build_arch ) ;
|
|
|
473 |
case 'C' : return ( &exec_cat ) ;
|
|
|
474 |
case 'D' : return ( &exec_mkdir ) ;
|
|
|
475 |
case 'M' : return ( &exec_move ) ;
|
|
|
476 |
case 'R' : return ( &exec_remove ) ;
|
|
|
477 |
case 'S' : return ( &exec_split_arch ) ;
|
|
|
478 |
case 'T' : return ( &exec_touch ) ;
|
|
|
479 |
}
|
|
|
480 |
break ;
|
|
|
481 |
}
|
|
|
482 |
case 'E' : {
|
|
|
483 |
switch ( b ) {
|
|
|
484 |
case PRODUCE_ID : return ( &exec_produce ) ;
|
|
|
485 |
case PREPROC_ID : return ( &exec_preproc ) ;
|
|
|
486 |
case CPP_PRODUCE_ID : return ( &exec_cpp_produce ) ;
|
|
|
487 |
case CPP_PREPROC_ID : return ( &exec_cpp_preproc ) ;
|
|
|
488 |
case TDF_LINK_ID : return ( &exec_tdf_link ) ;
|
|
|
489 |
case TRANSLATE_ID : return ( &exec_translate ) ;
|
|
|
490 |
case ASSEMBLE_ID : return ( &exec_assemble ) ;
|
|
|
491 |
case LINK_ID : return ( &exec_link ) ;
|
|
|
492 |
case PRETTY_ID : return ( &exec_pretty ) ;
|
|
|
493 |
case NOTATION_ID : return ( &exec_notation ) ;
|
|
|
494 |
case PL_TDF_ID : return ( &exec_pl_tdf ) ;
|
|
|
495 |
case ASSEMBLE_MIPS_ID : return ( &exec_assemble_mips ) ;
|
|
|
496 |
case SPEC_LINK_ID : return ( &exec_spec_link ) ;
|
|
|
497 |
case CPP_SPEC_LINK_ID : return ( &exec_cpp_spec_link ) ;
|
|
|
498 |
case CC_ID : return ( &exec_cc ) ;
|
|
|
499 |
case DYNLINK_ID : return ( &exec_dynlink );
|
|
|
500 |
case DUMP_ANAL_ID : return ( &exec_dump_anal );
|
|
|
501 |
case DUMP_LINK_ID : return ( &exec_dump_link );
|
|
|
502 |
}
|
|
|
503 |
error ( OPTION, "Unknown compilation stage, '%c'", b ) ;
|
|
|
504 |
return ( null ) ;
|
|
|
505 |
}
|
|
|
506 |
case 'Q' : {
|
|
|
507 |
if ( checker ) {
|
|
|
508 |
switch ( b ) {
|
|
|
509 |
case PRODUCE_ID : return ( &opt_produce ) ;
|
|
|
510 |
case CPP_PRODUCE_ID : return ( &opt_cpp_produce ) ;
|
|
|
511 |
case SPEC_LINK_ID : return ( &opt_spec_link ) ;
|
|
|
512 |
case CPP_SPEC_LINK_ID : return ( &opt_cpp_spec_link ) ;
|
|
|
513 |
case ARCHIVER_ID : return ( &opt_joiner ) ;
|
|
|
514 |
case CC_ID : return ( &opt_cc ) ;
|
|
|
515 |
}
|
|
|
516 |
error ( OPTION, "Unknown compilation stage, '%c'", b ) ;
|
|
|
517 |
return ( null ) ;
|
|
|
518 |
}
|
|
|
519 |
goto case_O ;
|
|
|
520 |
}
|
|
|
521 |
case 'O' :
|
|
|
522 |
case_O :{
|
|
|
523 |
switch ( b ) {
|
|
|
524 |
case PRODUCE_ID : return ( &opt_produce ) ;
|
|
|
525 |
case PREPROC_ID : return ( &opt_preproc ) ;
|
|
|
526 |
case CPP_PRODUCE_ID : return ( &opt_cpp_produce ) ;
|
|
|
527 |
case CPP_PREPROC_ID : return ( &opt_cpp_preproc ) ;
|
|
|
528 |
case TDF_LINK_ID : return ( &opt_tdf_link ) ;
|
|
|
529 |
case TRANSLATE_ID : return ( &opt_translate ) ;
|
|
|
530 |
case ASSEMBLE_ID : return ( &opt_assemble ) ;
|
|
|
531 |
case DYNLINK_ID : return ( &opt_dynlink ) ;
|
|
|
532 |
case LINK_ID : return ( &opt_link ) ;
|
|
|
533 |
case PRETTY_ID : return ( &opt_pretty ) ;
|
|
|
534 |
case NOTATION_ID : return ( &opt_notation ) ;
|
|
|
535 |
case PL_TDF_ID : return ( &opt_pl_tdf ) ;
|
|
|
536 |
case ASSEMBLE_MIPS_ID : return ( &opt_assemble_mips ) ;
|
|
|
537 |
case SPEC_LINK_ID : return ( &opt_spec_link ) ;
|
|
|
538 |
case CPP_SPEC_LINK_ID : return ( &opt_cpp_spec_link ) ;
|
|
|
539 |
case INSTALL_ID : return ( &opt_archive ) ;
|
|
|
540 |
case ARCHIVER_ID : return ( &opt_joiner ) ;
|
|
|
541 |
case CC_ID : return ( &opt_cc ) ;
|
|
|
542 |
case DUMP_ANAL_ID : return ( &opt_dump_anal );
|
|
|
543 |
case DUMP_LINK_ID : return ( &opt_dump_link );
|
|
|
544 |
}
|
|
|
545 |
error ( OPTION, "Unknown compilation stage, '%c'", b ) ;
|
|
|
546 |
return ( null ) ;
|
|
|
547 |
}
|
|
|
548 |
case 'S' : {
|
|
|
549 |
switch ( b ) {
|
|
|
550 |
case 'I' : return ( &std_prod_incldirs ) ;
|
|
|
551 |
case 'P' : return ( &std_prod_portfile ) ;
|
|
|
552 |
case 'd' : return ( &std_prod_startdirs ) ;
|
|
|
553 |
case 's' : return ( &std_prod_startup ) ;
|
|
|
554 |
case 'i' : return ( &std_cpp_prod_incldirs ) ;
|
|
|
555 |
case 'D' : return ( &std_cpp_prod_startdirs ) ;
|
|
|
556 |
case 'S' : return ( &std_cpp_prod_startup ) ;
|
|
|
557 |
case 'J' : return ( &std_tdf_link_libdirs ) ;
|
|
|
558 |
case 'j' : return ( &std_tdf_link_libs ) ;
|
|
|
559 |
case '0' : return ( &std_link_crt0 ) ;
|
|
|
560 |
case '1' : return ( &std_link_crt1 ) ;
|
|
|
561 |
case '2' : return ( &std_link_crtn ) ;
|
|
|
562 |
case '3' : return ( &std_link_crtp_n ) ;
|
|
|
563 |
case 'L' : return ( &std_link_libdirs ) ;
|
|
|
564 |
case 'l' : return ( &std_link_libs ) ;
|
|
|
565 |
case 'c' : return ( &std_link_c_libs ) ;
|
|
|
566 |
case 'e' : return ( &std_link_entry ) ;
|
|
|
567 |
}
|
|
|
568 |
break ;
|
|
|
569 |
}
|
|
|
570 |
case 'U' : {
|
|
|
571 |
switch ( b ) {
|
|
|
572 |
case 'I' : return ( &usr_prod_incldirs ) ;
|
|
|
573 |
case 's' : return ( &usr_prod_startup ) ;
|
|
|
574 |
case 'e' : return ( &usr_prod_eoptions ) ;
|
|
|
575 |
case 'f' : return ( &usr_prod_foptions ) ;
|
|
|
576 |
case 'P' : return ( &usr_pl_tdf_incldirs ) ;
|
|
|
577 |
case 'J' : return ( &usr_tdf_link_libdirs ) ;
|
|
|
578 |
case 'j' : return ( &usr_tdf_link_libs ) ;
|
|
|
579 |
case 'L' : return ( &usr_link_libdirs ) ;
|
|
|
580 |
case 'l' : return ( &usr_link_libs ) ;
|
|
|
581 |
}
|
|
|
582 |
break ;
|
|
|
583 |
}
|
|
|
584 |
case 'X' : {
|
|
|
585 |
switch ( b ) {
|
|
|
586 |
case 'O' : return ( &opt_unknown ) ;
|
|
|
587 |
case 'X' : return ( &xx_list ) ;
|
|
|
588 |
}
|
|
|
589 |
break ;
|
|
|
590 |
}
|
|
|
591 |
}
|
|
|
592 |
error ( OPTION, "Unknown list identifier, '%c%c'", a, b ) ;
|
|
|
593 |
return ( null ) ;
|
|
|
594 |
}
|
|
|
595 |
|
|
|
596 |
|
|
|
597 |
/*
|
|
|
598 |
CONVERT A TWO LETTER CODE INTO A STRING
|
|
|
599 |
|
|
|
600 |
This routine takes a two letter code, s, and returns a pointer to
|
|
|
601 |
the corresponding string variable.
|
|
|
602 |
*/
|
|
|
603 |
|
|
|
604 |
static char **lookup_string
|
|
|
605 |
PROTO_N ( ( s ) )
|
|
|
606 |
PROTO_T ( char *s )
|
|
|
607 |
{
|
|
|
608 |
char a = s [0] ;
|
|
|
609 |
char b = 0 ;
|
|
|
610 |
if ( a ) b = s [1] ;
|
|
|
611 |
if ( a == 'N' ) {
|
|
|
612 |
switch ( b ) {
|
|
|
613 |
case INDEP_TDF_KEY : return ( &name_j_file ) ;
|
|
|
614 |
case C_SPEC_KEY : return ( &name_k_file ) ;
|
|
|
615 |
case CPP_SPEC_KEY : return ( &name_K_file ) ;
|
|
|
616 |
case STARTUP_FILE_KEY : return ( &name_h_file ) ;
|
|
|
617 |
case PRETTY_TDF_KEY : return ( &name_p_file ) ;
|
|
|
618 |
}
|
|
|
619 |
error ( OPTION, "Unknown output file specifier, '%c'", b ) ;
|
|
|
620 |
return ( null ) ;
|
|
|
621 |
}
|
|
|
622 |
if ( a == 'S' ) {
|
|
|
623 |
int t = find_type ( b, 0 ) ;
|
|
|
624 |
return ( suffixes + t ) ;
|
|
|
625 |
}
|
|
|
626 |
if ( a == 'A' && b == 'I' ) return ( &api_info ) ;
|
|
|
627 |
if ( a == 'A' && b == 'O' ) return ( &api_output ) ;
|
|
|
628 |
if ( a == 'D' && b == 'O' ) return ( &dump_opts ) ;
|
|
|
629 |
if ( a == 'E' && b == 'D' ) return ( &environ_dir ) ;
|
|
|
630 |
if ( a == 'F' && b == 'N' ) return ( &final_name ) ;
|
|
|
631 |
if ( a == 'M' && b == 'N' ) return ( &machine_name ) ;
|
|
|
632 |
if ( a == 'P' && b == 'N' ) return ( &progname ) ;
|
|
|
633 |
if ( a == 'T' && b == 'D' ) return ( &temporary_dir ) ;
|
|
|
634 |
if ( a == 'V' && b == 'F' ) return ( &version_flag ) ;
|
|
|
635 |
if ( a == 'W' && b == 'D' ) return ( &workdir ) ;
|
|
|
636 |
if ( a == 'X' && b == 'X' ) return ( &xx_string ) ;
|
|
|
637 |
error ( OPTION, "Unknown string identifier, '%c%c'", a, b ) ;
|
|
|
638 |
return ( null ) ;
|
|
|
639 |
}
|
|
|
640 |
|
|
|
641 |
|
|
|
642 |
/*
|
|
|
643 |
DUMMY ARGUMENT FOR PROCEDURE
|
|
|
644 |
|
|
|
645 |
This variable is used to hold any argument passed to one of the procedures
|
|
|
646 |
in lookup_proc.
|
|
|
647 |
*/
|
|
|
648 |
|
|
|
649 |
static char *lookup_proc_arg = null ;
|
|
|
650 |
|
|
|
651 |
|
|
|
652 |
/*
|
|
|
653 |
DUMMY WRAPPER PROCEDURES
|
|
|
654 |
|
|
|
655 |
These routine(s) are used to call procedures with an argument using
|
|
|
656 |
lookup_proc.
|
|
|
657 |
*/
|
|
|
658 |
|
|
|
659 |
static void add_pragma_aux
|
|
|
660 |
PROTO_Z ()
|
|
|
661 |
{
|
|
|
662 |
add_pragma ( lookup_proc_arg ) ;
|
|
|
663 |
return ;
|
|
|
664 |
}
|
|
|
665 |
|
|
|
666 |
static void add_token_aux
|
|
|
667 |
PROTO_Z ()
|
|
|
668 |
{
|
|
|
669 |
add_token ( lookup_proc_arg ) ;
|
|
|
670 |
return ;
|
|
|
671 |
}
|
|
|
672 |
|
|
|
673 |
|
|
|
674 |
/*
|
|
|
675 |
CONVERT A TWO LETTER CODE INTO A PROCEDURE
|
|
|
676 |
|
|
|
677 |
This routine takes a two letter code, s, and returns a pointer to
|
|
|
678 |
the corresponding procedure.
|
|
|
679 |
*/
|
|
|
680 |
|
|
|
681 |
typedef void ( *proc ) PROTO_Z () ;
|
|
|
682 |
|
|
|
683 |
static proc lookup_proc
|
|
|
684 |
PROTO_N ( ( s ) )
|
|
|
685 |
PROTO_T ( char *s )
|
|
|
686 |
{
|
|
|
687 |
char a = s [0] ;
|
|
|
688 |
char b = 0 ;
|
|
|
689 |
if ( a ) b = s [1] ;
|
|
|
690 |
if ( a == 'A' && b == 'P' ) return ( add_pragma_aux ) ;
|
|
|
691 |
if ( a == 'A' && b == 'T' ) return ( add_token_aux ) ;
|
|
|
692 |
if ( a == 'F' && b == 'E' ) return ( find_envpath ) ;
|
|
|
693 |
if ( a == 'P' && b == 'V' ) return ( print_version ) ;
|
|
|
694 |
if ( a == 'S' && b == 'E' ) return ( show_envpath ) ;
|
|
|
695 |
if ( a == 'S' && b == 'M' ) return ( set_machine ) ;
|
|
|
696 |
if ( a == 'S' && b == 'P' ) return ( special_option ) ;
|
|
|
697 |
error ( OPTION, "Unknown procedure identifier, '%c%c'", a, b ) ;
|
|
|
698 |
return ( null ) ;
|
|
|
699 |
}
|
|
|
700 |
|
|
|
701 |
|
|
|
702 |
/*
|
|
|
703 |
RETURN VALUES FOR MATCH_OPTION
|
|
|
704 |
|
|
|
705 |
These values are returned by match_option. MATCH_OK means that the
|
|
|
706 |
option matches, MATCH_MORE means that it may match with an additional
|
|
|
707 |
option, MATCH_FAILED means it does not match, and the other values
|
|
|
708 |
indicate errors of some kind.
|
|
|
709 |
*/
|
|
|
710 |
|
|
|
711 |
#define MATCH_OK 0
|
|
|
712 |
#define MATCH_MORE 1
|
|
|
713 |
#define MATCH_FAILED 2
|
|
|
714 |
#define MATCH_IN_ERR 3
|
|
|
715 |
#define MATCH_OUT_ERR 4
|
|
|
716 |
#define MATCH_OPT_ERR 5
|
|
|
717 |
|
|
|
718 |
|
|
|
719 |
/*
|
|
|
720 |
MATCH AN OPTION
|
|
|
721 |
*/
|
|
|
722 |
|
|
|
723 |
static int match_option
|
|
|
724 |
PROTO_N ( ( in, out, opt, res ) )
|
|
|
725 |
PROTO_T ( char *in X char *out X char *opt X args_out *res )
|
|
|
726 |
{
|
|
|
727 |
char *p = in ;
|
|
|
728 |
char *q = opt ;
|
|
|
729 |
|
|
|
730 |
int i, a, v = 1 ;
|
|
|
731 |
int go = 1, loop = 1, loopv = -1 ;
|
|
|
732 |
struct { char *txt ; int len ; } var [ max_var ] ;
|
|
|
733 |
|
|
|
734 |
/* Process input */
|
|
|
735 |
while ( *p && go ) {
|
|
|
736 |
if ( *p == '$' ) {
|
|
|
737 |
char c = p [1] ;
|
|
|
738 |
if ( c ) {
|
|
|
739 |
int wraps = 0 ;
|
|
|
740 |
if ( p [2] == '+' && p [3] == '*' ) {
|
|
|
741 |
/* List of strings with breaks : $c+* */
|
|
|
742 |
wraps = 1 ;
|
|
|
743 |
p++ ;
|
|
|
744 |
}
|
|
|
745 |
if ( p [2] == '*' ) {
|
|
|
746 |
/* List of strings : $c* */
|
|
|
747 |
loop = 0 ;
|
|
|
748 |
loopv = v ;
|
|
|
749 |
if ( p [3] ) return ( MATCH_IN_ERR ) ;
|
|
|
750 |
while ( *q ) {
|
|
|
751 |
int l = 0 ;
|
|
|
752 |
var [v].txt = q ;
|
|
|
753 |
while ( *q && *q != c ) {
|
|
|
754 |
l++ ;
|
|
|
755 |
q++ ;
|
|
|
756 |
}
|
|
|
757 |
var [v].len = l ;
|
|
|
758 |
if ( *q ) {
|
|
|
759 |
/* Found c */
|
|
|
760 |
q++ ;
|
|
|
761 |
if ( *q == 0 && wraps ) return ( MATCH_MORE ) ;
|
|
|
762 |
}
|
|
|
763 |
if ( ++v >= max_var ) return ( MATCH_OPT_ERR ) ;
|
|
|
764 |
loop++ ;
|
|
|
765 |
}
|
|
|
766 |
go = 0 ;
|
|
|
767 |
} else {
|
|
|
768 |
/* Terminated string : $c */
|
|
|
769 |
int l = 0 ;
|
|
|
770 |
var [v].txt = q ;
|
|
|
771 |
while ( *q != c ) {
|
|
|
772 |
if ( *q == 0 ) return ( MATCH_FAILED ) ;
|
|
|
773 |
l++ ;
|
|
|
774 |
q++ ;
|
|
|
775 |
}
|
|
|
776 |
var [v].len = l ;
|
|
|
777 |
if ( ++v >= max_var ) return ( MATCH_OPT_ERR ) ;
|
|
|
778 |
}
|
|
|
779 |
} else {
|
|
|
780 |
/* Simple string : $ */
|
|
|
781 |
int l = ( int ) strlen ( q ) ;
|
|
|
782 |
var [v].txt = q ;
|
|
|
783 |
var [v].len = l ;
|
|
|
784 |
if ( ++v >= max_var ) return ( MATCH_OPT_ERR ) ;
|
|
|
785 |
go = 0 ;
|
|
|
786 |
}
|
|
|
787 |
} else if ( *p == '?' ) {
|
|
|
788 |
if ( p [1] == '*' ) {
|
|
|
789 |
/* List of characters : ?* */
|
|
|
790 |
if ( p [2] ) return ( MATCH_IN_ERR ) ;
|
|
|
791 |
loop = 0 ;
|
|
|
792 |
loopv = v ;
|
|
|
793 |
while ( *q ) {
|
|
|
794 |
var [v].txt = q ;
|
|
|
795 |
var [v].len = 1 ;
|
|
|
796 |
if ( ++v >= max_var ) return ( MATCH_OPT_ERR ) ;
|
|
|
797 |
q++ ;
|
|
|
798 |
loop++ ;
|
|
|
799 |
}
|
|
|
800 |
go = 0 ;
|
|
|
801 |
} else {
|
|
|
802 |
/* Simple character : ? */
|
|
|
803 |
if ( *q == 0 ) return ( MATCH_FAILED ) ;
|
|
|
804 |
var [v].txt = q ;
|
|
|
805 |
var [v].len = 1 ;
|
|
|
806 |
if ( ++v >= max_var ) return ( MATCH_OPT_ERR ) ;
|
|
|
807 |
q++ ;
|
|
|
808 |
}
|
|
|
809 |
} else if ( *p == '+' ) {
|
|
|
810 |
/* Potential break : + */
|
|
|
811 |
if ( *q == 0 ) return ( MATCH_MORE ) ;
|
|
|
812 |
} else if ( *p == '^' ) {
|
|
|
813 |
/* Negated letter */
|
|
|
814 |
p++ ;
|
|
|
815 |
if ( *p == 0 ) return ( MATCH_IN_ERR ) ;
|
|
|
816 |
if ( *p == *q ) return ( MATCH_FAILED ) ;
|
|
|
817 |
q++ ;
|
|
|
818 |
} else if ( *p == '\\' ) {
|
|
|
819 |
/* Escaped letter : \c */
|
|
|
820 |
p++ ;
|
|
|
821 |
if ( *p == 0 ) return ( MATCH_IN_ERR ) ;
|
|
|
822 |
if ( *p != *q ) return ( MATCH_FAILED ) ;
|
|
|
823 |
q++ ;
|
|
|
824 |
} else {
|
|
|
825 |
/* Letter : c */
|
|
|
826 |
if ( *p != *q ) return ( MATCH_FAILED ) ;
|
|
|
827 |
q++ ;
|
|
|
828 |
}
|
|
|
829 |
p++ ;
|
|
|
830 |
}
|
|
|
831 |
|
|
|
832 |
/* Check end of option */
|
|
|
833 |
if ( go && *q ) return ( MATCH_FAILED ) ;
|
|
|
834 |
|
|
|
835 |
/* The first variable is the whole option */
|
|
|
836 |
var [0].txt = opt ;
|
|
|
837 |
var [0].len = ( int ) strlen ( opt ) ;
|
|
|
838 |
|
|
|
839 |
/* Print output */
|
|
|
840 |
a = 0 ;
|
|
|
841 |
for ( i = 0 ; i < loop ; i++ ) {
|
|
|
842 |
char buff [1000] ;
|
|
|
843 |
q = buff ;
|
|
|
844 |
for ( p = out ; *p ; p++ ) {
|
|
|
845 |
if ( *p == '$' ) {
|
|
|
846 |
/* Variable */
|
|
|
847 |
int n ;
|
|
|
848 |
char c = *( ++p ) ;
|
|
|
849 |
if ( c == 's' ) {
|
|
|
850 |
/* $s expands to a space */
|
|
|
851 |
*( q++ ) = ' ' ;
|
|
|
852 |
} else if ( c == 'n' ) {
|
|
|
853 |
/* $n expands to a newline */
|
|
|
854 |
*( q++ ) = '\n' ;
|
|
|
855 |
} else if ( c >= '0' && c <= '9' ) {
|
|
|
856 |
n = ( c - '0' ) ;
|
|
|
857 |
if ( n == loopv ) n += i ;
|
|
|
858 |
if ( n < v ) {
|
|
|
859 |
int l = var [n].len ;
|
|
|
860 |
IGNORE strncpy ( q, var [n].txt, ( size_t ) l ) ;
|
|
|
861 |
q += l ;
|
|
|
862 |
}
|
|
|
863 |
} else if ( c == 'B' ) {
|
|
|
864 |
boolean *b = lookup_bool ( p + 1 ) ;
|
|
|
865 |
if ( b == null ) return ( MATCH_OUT_ERR ) ;
|
|
|
866 |
IGNORE sprintf ( q, "%d", ( int ) *b ) ;
|
|
|
867 |
while ( *q ) q++ ;
|
|
|
868 |
p += 2 ;
|
|
|
869 |
} else if ( c == 'L' ) {
|
|
|
870 |
list *pt ;
|
|
|
871 |
list **sp = lookup_list ( p + 1 ) ;
|
|
|
872 |
if ( sp == null ) return ( MATCH_OUT_ERR ) ;
|
|
|
873 |
for ( pt = *sp ; pt ; pt = pt->next ) {
|
|
|
874 |
int l = ( int ) strlen ( pt->item ) ;
|
|
|
875 |
IGNORE strncpy ( q, pt->item, ( size_t ) l ) ;
|
|
|
876 |
q += l ;
|
|
|
877 |
*( q++ ) = ' ' ;
|
|
|
878 |
}
|
|
|
879 |
p += 2 ;
|
|
|
880 |
} else if ( c == 'S' ) {
|
|
|
881 |
int l ;
|
|
|
882 |
char **sp = lookup_string ( p + 1 ) ;
|
|
|
883 |
if ( sp == null ) return ( MATCH_OUT_ERR ) ;
|
|
|
884 |
if ( *sp ) {
|
|
|
885 |
l = ( int ) strlen ( *sp ) ;
|
|
|
886 |
IGNORE strncpy ( q, *sp, ( size_t ) l ) ;
|
|
|
887 |
q += l ;
|
|
|
888 |
}
|
|
|
889 |
p += 2 ;
|
|
|
890 |
} else {
|
|
|
891 |
return ( MATCH_OUT_ERR ) ;
|
|
|
892 |
}
|
|
|
893 |
} else if ( *p == '|' ) {
|
|
|
894 |
/* Multiple output */
|
|
|
895 |
*q = 0 ;
|
|
|
896 |
res->argv [a] = string_copy ( buff ) ;
|
|
|
897 |
if ( ++a >= max_var ) return ( MATCH_OPT_ERR ) ;
|
|
|
898 |
q = buff ;
|
|
|
899 |
} else if ( *p == '\\' ) {
|
|
|
900 |
/* Escaped output character */
|
|
|
901 |
if ( *( ++p ) == 0 ) return ( MATCH_OUT_ERR ) ;
|
|
|
902 |
*( q++ ) = *p ;
|
|
|
903 |
} else {
|
|
|
904 |
/* Simple output character */
|
|
|
905 |
*( q++ ) = *p ;
|
|
|
906 |
}
|
|
|
907 |
}
|
|
|
908 |
*q = 0 ;
|
|
|
909 |
res->argv [a] = string_copy ( buff ) ;
|
|
|
910 |
if ( ++a >= max_var ) return ( MATCH_OPT_ERR ) ;
|
|
|
911 |
}
|
|
|
912 |
res->argc = a ;
|
|
|
913 |
return ( MATCH_OK ) ;
|
|
|
914 |
}
|
|
|
915 |
|
|
|
916 |
|
|
|
917 |
/*
|
|
|
918 |
INTERPRET AN OPTION COMMAND
|
|
|
919 |
*/
|
|
|
920 |
|
|
|
921 |
static void interpret_cmd
|
|
|
922 |
PROTO_N ( ( cmd ) )
|
|
|
923 |
PROTO_T ( char *cmd )
|
|
|
924 |
{
|
|
|
925 |
char c = *cmd ;
|
|
|
926 |
|
|
|
927 |
/* Debugging */
|
|
|
928 |
if ( debug_options ) error ( OPTION, "Interpreting '%s'", cmd ) ;
|
|
|
929 |
|
|
|
930 |
/* Deal with at-hack */
|
|
|
931 |
if ( c == '@' ) {
|
|
|
932 |
char *p = string_copy ( cmd + 1 ), *q ;
|
|
|
933 |
for ( q = p ; *q ; q++ ) {
|
|
|
934 |
if ( *q == '@' ) *q = ' ' ;
|
|
|
935 |
}
|
|
|
936 |
cmd = p ;
|
|
|
937 |
c = *p ;
|
|
|
938 |
}
|
|
|
939 |
|
|
|
940 |
/* Deal with empty strings */
|
|
|
941 |
if ( c == 0 ) return ;
|
|
|
942 |
|
|
|
943 |
/* Digits set values */
|
|
|
944 |
if ( c >= '0' && c <= '9' ) {
|
|
|
945 |
boolean *b = lookup_bool ( cmd + 1 ) ;
|
|
|
946 |
if ( b == null ) return ;
|
|
|
947 |
*b = ( boolean ) ( c - '0' ) ;
|
|
|
948 |
return ;
|
|
|
949 |
}
|
|
|
950 |
|
|
|
951 |
/* Translations */
|
|
|
952 |
if ( c == '>' ) c = 'A' ;
|
|
|
953 |
if ( c == '<' ) c = 'B' ;
|
|
|
954 |
if ( c == '+' ) c = 'L' ;
|
|
|
955 |
|
|
|
956 |
/* Deal with list query */
|
|
|
957 |
if ( c == '?' ) {
|
|
|
958 |
if ( cmd [1] == ':' ) {
|
|
|
959 |
char **sp = lookup_string ( cmd + 2 ) ;
|
|
|
960 |
if ( sp == null ) return ;
|
|
|
961 |
comment ( 1, "%s=\"%s\"\n", cmd + 4, *sp ) ;
|
|
|
962 |
} else {
|
|
|
963 |
list *p ;
|
|
|
964 |
list **sp = lookup_list ( cmd + 1 ) ;
|
|
|
965 |
if ( sp == null ) return ;
|
|
|
966 |
comment ( 1, "%s=\"", cmd + 3 ) ;
|
|
|
967 |
for ( p = *sp ; p != null ; p = p->next ) {
|
|
|
968 |
comment ( 1, "%s", p->item ) ;
|
|
|
969 |
if ( p->next ) comment ( 1, " " ) ;
|
|
|
970 |
}
|
|
|
971 |
comment ( 1, "\"\n" ) ;
|
|
|
972 |
}
|
|
|
973 |
return ;
|
|
|
974 |
}
|
|
|
975 |
|
|
|
976 |
/* Deal with equivalences */
|
|
|
977 |
if ( c == '=' ) {
|
|
|
978 |
list *p = make_list ( cmd + 1 ) ;
|
|
|
979 |
process_options ( p, main_optmap ) ;
|
|
|
980 |
free_list ( p ) ;
|
|
|
981 |
return ;
|
|
|
982 |
}
|
|
|
983 |
|
|
|
984 |
/* Deal with primitives */
|
|
|
985 |
switch ( c ) {
|
|
|
986 |
|
|
|
987 |
case 'A' : {
|
|
|
988 |
/* Change list */
|
|
|
989 |
list **sp = lookup_list ( cmd + 1 ) ;
|
|
|
990 |
if ( sp == null ) return ;
|
|
|
991 |
*sp = add_list ( *sp, make_list ( cmd + 3 ) ) ;
|
|
|
992 |
return ;
|
|
|
993 |
}
|
|
|
994 |
|
|
|
995 |
case 'B' : {
|
|
|
996 |
/* Change list */
|
|
|
997 |
list **sp = lookup_list ( cmd + 1 ) ;
|
|
|
998 |
if ( sp == null ) return ;
|
|
|
999 |
*sp = add_list ( make_list ( cmd + 3 ), *sp ) ;
|
|
|
1000 |
return ;
|
|
|
1001 |
}
|
|
|
1002 |
|
|
|
1003 |
case 'L' : {
|
|
|
1004 |
/* Change list */
|
|
|
1005 |
list **sp = lookup_list ( cmd + 1 ) ;
|
|
|
1006 |
if ( sp == null ) return ;
|
|
|
1007 |
free_list ( *sp ) ;
|
|
|
1008 |
*sp = make_list ( cmd + 3 ) ;
|
|
|
1009 |
return ;
|
|
|
1010 |
}
|
|
|
1011 |
|
|
|
1012 |
case 'C' : {
|
|
|
1013 |
/* Call */
|
|
|
1014 |
proc p = lookup_proc ( cmd + 1 ) ;
|
|
|
1015 |
if ( p == null ) return ;
|
|
|
1016 |
if ( cmd [3] == ':' ) {
|
|
|
1017 |
lookup_proc_arg = cmd + 4 ;
|
|
|
1018 |
} else {
|
|
|
1019 |
lookup_proc_arg = null ;
|
|
|
1020 |
}
|
|
|
1021 |
( *p ) () ;
|
|
|
1022 |
return ;
|
|
|
1023 |
}
|
|
|
1024 |
|
|
|
1025 |
case 'D' : {
|
|
|
1026 |
/* Startup options */
|
|
|
1027 |
add_to_startup ( cmd + 1 ) ;
|
|
|
1028 |
return ;
|
|
|
1029 |
}
|
|
|
1030 |
|
|
|
1031 |
case 'E' : {
|
|
|
1032 |
/* Environment */
|
|
|
1033 |
read_env ( cmd + 1 ) ;
|
|
|
1034 |
return ;
|
|
|
1035 |
}
|
|
|
1036 |
|
|
|
1037 |
case 'F' : {
|
|
|
1038 |
/* Endup options */
|
|
|
1039 |
add_to_endup ( cmd + 1 ) ;
|
|
|
1040 |
return ;
|
|
|
1041 |
}
|
|
|
1042 |
|
|
|
1043 |
case 'H' : {
|
|
|
1044 |
/* Halt */
|
|
|
1045 |
char stage = cmd [1] ;
|
|
|
1046 |
set_stage ( find_type ( stage, 0 ), STOP_STAGE ) ;
|
|
|
1047 |
return ;
|
|
|
1048 |
}
|
|
|
1049 |
|
|
|
1050 |
case 'I' : {
|
|
|
1051 |
/* Input file */
|
|
|
1052 |
int t ;
|
|
|
1053 |
filename *f ;
|
|
|
1054 |
char stage = cmd [1] ;
|
|
|
1055 |
char *name = cmd + 2 ;
|
|
|
1056 |
if ( stage == '?' ) {
|
|
|
1057 |
t = UNKNOWN_TYPE ;
|
|
|
1058 |
} else {
|
|
|
1059 |
t = find_type ( stage, 0 ) ;
|
|
|
1060 |
}
|
|
|
1061 |
f = find_filename ( name, t ) ;
|
|
|
1062 |
input_files = add_filename ( input_files, f ) ;
|
|
|
1063 |
return ;
|
|
|
1064 |
}
|
|
|
1065 |
|
|
|
1066 |
case 'K' : {
|
|
|
1067 |
/* Keep */
|
|
|
1068 |
static int k = KEEP_STAGE ;
|
|
|
1069 |
char stage = cmd [1] ;
|
|
|
1070 |
if ( stage == '-' ) {
|
|
|
1071 |
k = DONT_KEEP_STAGE ;
|
|
|
1072 |
} else {
|
|
|
1073 |
set_stage ( find_type ( stage, 0 ), k ) ;
|
|
|
1074 |
k = KEEP_STAGE ;
|
|
|
1075 |
}
|
|
|
1076 |
return ;
|
|
|
1077 |
}
|
|
|
1078 |
|
|
|
1079 |
case 'Q' : {
|
|
|
1080 |
/* Query */
|
|
|
1081 |
char *s ;
|
|
|
1082 |
optmap *t = main_optmap ;
|
|
|
1083 |
error ( INFO, "List of recognised options" ) ;
|
|
|
1084 |
while ( s = t->in, s != null ) {
|
|
|
1085 |
if ( *s == '-' ) {
|
|
|
1086 |
char d ;
|
|
|
1087 |
comment ( 0, " " ) ;
|
|
|
1088 |
while ( d = *( s++ ), d != 0 ) {
|
|
|
1089 |
switch ( d ) {
|
|
|
1090 |
case '$' : {
|
|
|
1091 |
IGNORE fputs ( "<string>", stderr ) ;
|
|
|
1092 |
break ;
|
|
|
1093 |
}
|
|
|
1094 |
case '?' : {
|
|
|
1095 |
IGNORE fputs ( "<letter>", stderr ) ;
|
|
|
1096 |
break ;
|
|
|
1097 |
}
|
|
|
1098 |
case '*' : {
|
|
|
1099 |
IGNORE fputs ( "...", stderr ) ;
|
|
|
1100 |
break ;
|
|
|
1101 |
}
|
|
|
1102 |
case '+' : {
|
|
|
1103 |
IGNORE fputc ( ' ', stderr ) ;
|
|
|
1104 |
break ;
|
|
|
1105 |
}
|
|
|
1106 |
case '\\' : {
|
|
|
1107 |
IGNORE fputc ( *( s++ ), stderr ) ;
|
|
|
1108 |
break ;
|
|
|
1109 |
}
|
|
|
1110 |
default : {
|
|
|
1111 |
IGNORE fputc ( d, stderr ) ;
|
|
|
1112 |
break ;
|
|
|
1113 |
}
|
|
|
1114 |
}
|
|
|
1115 |
}
|
|
|
1116 |
s = t->explain ;
|
|
|
1117 |
if ( s == null ) s = "not documented" ;
|
|
|
1118 |
comment ( 0, " : " ) ;
|
|
|
1119 |
comment ( 0, s, progname ) ;
|
|
|
1120 |
comment ( 0, ".\n" ) ;
|
|
|
1121 |
}
|
|
|
1122 |
t++ ;
|
|
|
1123 |
}
|
|
|
1124 |
return ;
|
|
|
1125 |
}
|
|
|
1126 |
|
|
|
1127 |
case 'S' : {
|
|
|
1128 |
/* String */
|
|
|
1129 |
char **s = lookup_string ( cmd + 1 ) ;
|
|
|
1130 |
if ( s == null ) return ;
|
|
|
1131 |
*s = cmd + 3 ;
|
|
|
1132 |
return ;
|
|
|
1133 |
}
|
|
|
1134 |
|
|
|
1135 |
case 'V' : {
|
|
|
1136 |
if ( cmd [1] == 'B' ) {
|
|
|
1137 |
boolean *b = lookup_bool ( cmd + 2 ) ;
|
|
|
1138 |
if ( b == null ) return ;
|
|
|
1139 |
comment ( 1, "%c%c = %d\n", cmd [2], cmd [3], *b ) ;
|
|
|
1140 |
return ;
|
|
|
1141 |
} else if ( cmd [1] == 'L' ) {
|
|
|
1142 |
list **sp = lookup_list ( cmd + 2 ), *pt ;
|
|
|
1143 |
if ( sp == null ) return ;
|
|
|
1144 |
comment ( 1, "%c%c =", cmd [2], cmd [3] ) ;
|
|
|
1145 |
for ( pt = *sp ; pt != null ; pt = pt->next ) {
|
|
|
1146 |
if ( pt->item ) {
|
|
|
1147 |
comment ( 1, " %s", pt->item ) ;
|
|
|
1148 |
} else {
|
|
|
1149 |
comment ( 1, " (null)" ) ;
|
|
|
1150 |
}
|
|
|
1151 |
}
|
|
|
1152 |
comment ( 1, "\n" ) ;
|
|
|
1153 |
return ;
|
|
|
1154 |
} else if ( cmd [1] == 'S' ) {
|
|
|
1155 |
char **s = lookup_string ( cmd + 2 ) ;
|
|
|
1156 |
if ( s == null ) return ;
|
|
|
1157 |
if ( *s ) {
|
|
|
1158 |
comment ( 1, "%c%c = %s\n", cmd [2], cmd [3], *s ) ;
|
|
|
1159 |
} else {
|
|
|
1160 |
comment ( 1, "%c%c = (null)\n", cmd [2], cmd [3] ) ;
|
|
|
1161 |
}
|
|
|
1162 |
return ;
|
|
|
1163 |
}
|
|
|
1164 |
break ;
|
|
|
1165 |
}
|
|
|
1166 |
|
|
|
1167 |
case 'X' : {
|
|
|
1168 |
/* Error */
|
|
|
1169 |
error ( WARNING, "%s", cmd + 1 ) ;
|
|
|
1170 |
return ;
|
|
|
1171 |
}
|
|
|
1172 |
}
|
|
|
1173 |
error ( OPTION, "Syntax error, '%s'", cmd ) ;
|
|
|
1174 |
return ;
|
|
|
1175 |
}
|
|
|
1176 |
|
|
|
1177 |
|
|
|
1178 |
/*
|
|
|
1179 |
PROCESS A LIST OF OPTIONS
|
|
|
1180 |
|
|
|
1181 |
This routine processes a list of options, opt, using the options
|
|
|
1182 |
from table tab.
|
|
|
1183 |
*/
|
|
|
1184 |
|
|
|
1185 |
void process_options
|
|
|
1186 |
PROTO_N ( ( opt, tab ) )
|
|
|
1187 |
PROTO_T ( list *opt X optmap *tab )
|
|
|
1188 |
{
|
|
|
1189 |
optmap *t ;
|
|
|
1190 |
list *p = opt ;
|
|
|
1191 |
char *arg = null ;
|
|
|
1192 |
int status = MATCH_OK ;
|
|
|
1193 |
|
|
|
1194 |
/* Scan through the options */
|
|
|
1195 |
while ( p != null ) {
|
|
|
1196 |
if ( status == MATCH_MORE ) {
|
|
|
1197 |
arg = string_concat ( arg, p->item ) ;
|
|
|
1198 |
} else {
|
|
|
1199 |
arg = p->item ;
|
|
|
1200 |
}
|
|
|
1201 |
status = MATCH_FAILED ;
|
|
|
1202 |
for ( t = tab ; t->in != null ; t++ ) {
|
|
|
1203 |
args_out res ;
|
|
|
1204 |
status = match_option ( t->in, t->out, arg, &res ) ;
|
|
|
1205 |
switch ( status ) {
|
|
|
1206 |
case MATCH_OK : {
|
|
|
1207 |
/* Complete option - interpret result */
|
|
|
1208 |
int a ;
|
|
|
1209 |
for ( a = 0 ; a < res.argc ; a++ ) {
|
|
|
1210 |
interpret_cmd ( res.argv [a] ) ;
|
|
|
1211 |
}
|
|
|
1212 |
goto end_search ;
|
|
|
1213 |
}
|
|
|
1214 |
case MATCH_MORE : {
|
|
|
1215 |
/* Incomplete option - move on to next option */
|
|
|
1216 |
goto end_search ;
|
|
|
1217 |
}
|
|
|
1218 |
case MATCH_FAILED : {
|
|
|
1219 |
/* Try again */
|
|
|
1220 |
break ;
|
|
|
1221 |
}
|
|
|
1222 |
case MATCH_IN_ERR : {
|
|
|
1223 |
/* Error in optmap input */
|
|
|
1224 |
error ( OPTION, "Illegal input '%s'", t->in ) ;
|
|
|
1225 |
status = MATCH_FAILED ;
|
|
|
1226 |
break ;
|
|
|
1227 |
}
|
|
|
1228 |
case MATCH_OUT_ERR : {
|
|
|
1229 |
/* Error in optmap output */
|
|
|
1230 |
error ( OPTION, "Illegal option '%s'", t->out ) ;
|
|
|
1231 |
status = MATCH_FAILED ;
|
|
|
1232 |
break ;
|
|
|
1233 |
}
|
|
|
1234 |
case MATCH_OPT_ERR : {
|
|
|
1235 |
/* Ran out of space for result */
|
|
|
1236 |
error ( OPTION, "Too many components, '%s'", arg ) ;
|
|
|
1237 |
status = MATCH_FAILED ;
|
|
|
1238 |
break ;
|
|
|
1239 |
}
|
|
|
1240 |
}
|
|
|
1241 |
}
|
|
|
1242 |
error ( OPTION, "Can't interpret '%s'", arg ) ;
|
|
|
1243 |
end_search : p = p->next ;
|
|
|
1244 |
}
|
|
|
1245 |
|
|
|
1246 |
/* Check for incomplete options */
|
|
|
1247 |
if ( status == MATCH_MORE ) {
|
|
|
1248 |
error ( WARNING, "Option '%s' is incomplete", arg ) ;
|
|
|
1249 |
}
|
|
|
1250 |
|
|
|
1251 |
return ;
|
|
|
1252 |
}
|