Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2 Rev 7
Line -... Line 1...
-
 
1
/*
-
 
2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
-
 
3
 * All rights reserved.
-
 
4
 *
-
 
5
 * Redistribution and use in source and binary forms, with or without
-
 
6
 * modification, are permitted provided that the following conditions are met:
-
 
7
 *
-
 
8
 * 1. Redistributions of source code must retain the above copyright notice,
-
 
9
 *    this list of conditions and the following disclaimer.
-
 
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
-
 
11
 *    this list of conditions and the following disclaimer in the documentation
-
 
12
 *    and/or other materials provided with the distribution.
-
 
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
-
 
14
 *    may be used to endorse or promote products derived from this software
-
 
15
 *    without specific, prior written permission.
-
 
16
 *
-
 
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
-
 
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-
 
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-
 
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-
 
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-
 
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-
 
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-
 
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-
 
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-
 
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-
 
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 
28
 *
-
 
29
 * $Id$
-
 
30
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
    
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
36
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
37
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
38
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
39
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
40
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
41
    shall be deemed to be acceptance of the following conditions:-
12
    
42
 
13
        (1) Its Recipients shall ensure that this Notice is
43
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
44
        reproduced upon any copies or amended versions of it;
15
    
45
 
16
        (2) Any amended version of it shall be clearly marked to
46
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
47
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
48
        for the relevant amendment or amendments;
19
    
49
 
20
        (3) Its onward transfer from a recipient to another
50
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
51
        party shall be deemed to be that party's acceptance of
22
        these conditions;
52
        these conditions;
23
    
53
 
24
        (4) DERA gives no warranty or assurance as to its
54
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
55
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
56
        no liability whatsoever in relation to any use to which
27
        it may be put.
57
        it may be put.
28
*/
58
*/
29
 
59
 
30
 
60
 
31
#include "config.h"
61
#include "config.h"
32
#include "filename.h"
62
#include "filename.h"
33
#include "list.h"
63
#include "list.h"
34
#include "environ.h"
64
#include "environ.h"
Line 36... Line 66...
36
#include "options.h"
66
#include "options.h"
37
#include "suffix.h"
67
#include "suffix.h"
38
#include "utility.h"
68
#include "utility.h"
39
 
69
 
40
 
70
 
41
/*
71
/*
42
    THE CURRENT ENVIRONMENTS PATH
72
 * THE CURRENT ENVIRONMENTS PATH
43
 
73
 *
44
    The environment path is a colon-separated list of directories which
74
 * The environment path is a colon-separated list of directories which are
45
    are searched for tcc environments.
75
 * searched for tcc environments.
46
*/
76
 */
47
 
77
 
48
static char *envpath = "." ;
78
static char *envpath = ".";
-
 
79
 
-
 
80
 
-
 
81
/*
-
 
82
 * UPDATE THE ENVIRONMENTS PATH
-
 
83
 *
-
 
84
 * This routine initialises and updates the environments path. This is given by
-
 
85
 * the contents of the system variable TCCENV, plus the default directory
-
 
86
 * (environ_dir), plus the current directory.
-
 
87
 */
-
 
88
 
-
 
89
void
-
 
90
find_envpath(void)
-
 
91
{
-
 
92
	char *p = buffer;
-
 
93
	char *tcc_env = getenv(TCCENV_VAR);
-
 
94
	if (tcc_env) {
-
 
95
		IGNORE sprintf(p, "%s:", tcc_env);
-
 
96
		p += strlen(p);
-
 
97
	}
-
 
98
	IGNORE sprintf(p, "%s:.", environ_dir);
-
 
99
	if (!streq(buffer, envpath)) {
-
 
100
		envpath = string_copy(buffer);
-
 
101
	}
-
 
102
	return;
-
 
103
}
-
 
104
 
-
 
105
 
-
 
106
/*
-
 
107
 * PRINT THE ENVIRONMENTS PATH
-
 
108
 *
-
 
109
 * This routine prints the environment path.
-
 
110
 */
-
 
111
 
-
 
112
void
-
 
113
show_envpath(void)
-
 
114
{
-
 
115
	find_envpath();
-
 
116
	error(INFO, "Environment path is '%s'", envpath);
-
 
117
	return;
-
 
118
}
49
 
119
 
50
 
120
 
51
/*
121
/*
52
    UPDATE THE ENVIRONMENTS PATH
122
 * READ AN ENVIRONMENT - AUXILIARY ROUTINE
53
 
123
 *
54
    This routine initialises and updates the environments path.  This is
124
 * This routine reads the environment named nm, returning zero if it is
55
    given by the contents of the system variable TCCENV, plus the default
125
 * successful. A return value of 1 indicates that the environment could not be
56
    directory (environ_dir), plus the current directory.
-
 
57
*/
-
 
58
 
-
 
59
void find_envpath
-
 
60
    PROTO_Z ()
-
 
61
{
-
 
62
    char *p = buffer ;
126
 * found, otherwise 2 is returned.
63
    char *tcc_env = getenv ( TCCENV_VAR ) ;
-
 
64
    if ( tcc_env ) {
-
 
65
	IGNORE sprintf ( p, "%s:", tcc_env ) ;
-
 
66
	p += strlen ( p ) ;
-
 
67
    }
-
 
68
    IGNORE sprintf ( p, "%s:.", environ_dir ) ;
-
 
69
    if ( !streq ( buffer, envpath ) ) envpath = string_copy ( buffer ) ;
-
 
70
    return ;
-
 
71
}
-
 
72
 
-
 
73
 
-
 
74
/*
127
 *
75
    PRINT THE ENVIRONMENTS PATH
-
 
76
 
-
 
77
    This routine prints the environment path.
128
 * In the revision to this function, the strategy is to minimize copying chars.
78
*/
-
 
79
 
-
 
80
void show_envpath
-
 
81
    PROTO_Z ()
-
 
82
{
-
 
83
    find_envpath () ;
-
 
84
    error ( INFO, "Environment path is '%s'", envpath ) ;
129
 * This routine opens the file, and examines each env file a line at a time.
85
    return ;
-
 
86
}
-
 
87
 
-
 
88
 
-
 
89
/*
-
 
90
    CHARACTER TYPES
-
 
91
 
-
 
92
    These macros identify various character types.
130
 * Line analysis scans past the key, until the first whitespace is found. Then,
93
*/
-
 
94
 
-
 
95
#define is_alphanum( X )	( ( ( X ) >= 'A' && ( X ) <= 'Z' ) ||\
131
 * the routine scans forward to the start of the value, and cut the line buffer
96
				  ( ( X ) >= '0' && ( X ) <= '9' ) ||\
-
 
97
				  ( ( X ) == '_' ) )
-
 
98
#define is_whitespace( X )	( ( X ) == ' ' || ( X ) == '\t' )
132
 * in half by making the whitespace a '\0' character. The routine continues
99
#define is_quote( X )		( ( X ) == '"' )
-
 
100
#define is_newline( X )		( ( X ) == '\n' )
133
 * scanning the value, performing appropriate substitutions for <vars>.
101
 
-
 
102
 
-
 
103
/*
134
 *
104
    READ AN ENVIRONMENT - AUXILIARY ROUTINE
135
 * TODO: The two resulting strings in the buffer (key and value) must be
105
 
-
 
106
    This routine reads the environment named nm, returning zero if it
136
 * strdup'd. A future revision to this function may just read entire file into
107
    is successful.  A return value of 1 indicates that the environment
137
 * memory, and convert key whitespace to NULL characters, thereby breaking up
108
    could not be found, otherwise 2 is returned.
138
 * the lines into appropriate tokens, and avoiding copying strings around in
-
 
139
 * memory.
109
*/
140
*/
110
 
141
 
111
int read_env_aux
142
int
112
    PROTO_N ( ( nm ) )
-
 
113
    PROTO_T ( char *nm )
143
read_env_aux(char *nm, hashtable *ht)
114
{
144
{
115
    /* Find the environment */
145
    /* Find the environment */
116
    FILE *f ;
146
    FILE *f;
117
    char *p, *q ;
147
    char *p, *q;
-
 
148
    int   line_num;
-
 
149
 
118
    if ( *nm == 0 ) {
150
    if (*nm == 0) {
119
	return ( 1 ) ;
151
	return (1);
120
    } else if ( *nm == '/' ) {
152
    } else if (*nm == '/') {
121
	f = fopen ( nm, "r" ) ;
153
	f = fopen(nm, "r");
122
    } else {
154
    } else {
123
	p = envpath ;
155
	p = envpath;
124
	do {
156
	do {
125
	    q = buffer ;
157
	    q = buffer;
126
	    while ( *p && *p != ':' ) *( q++ ) = *( p++ ) ;
158
	    while (*p && *p != ':') *(q++) = *(p++);
127
	    *( q++ ) = '/' ;
159
	    *(q++) = '/';
128
	    IGNORE strcpy ( q, nm ) ;
160
	    IGNORE strcpy(q, nm);
129
	    f = fopen ( buffer, "r" ) ;
161
	    f = fopen(buffer, "r");
130
	} while ( f == null && *( p++ ) ) ;
162
	} while (f == null && *(p++));
131
    }
163
    }
132
    if ( f == null ) return ( 1 ) ;
164
    if (f == null) {
-
 
165
	    return (1);
-
 
166
    }
133
 
167
 
-
 
168
    /*
134
    /* Read the environment one line at a time */
169
     * Parse each line of the environment file
-
 
170
     */
-
 
171
    line_num = 0;
-
 
172
 
135
    while ( fgets ( buffer, buffer_size, f ) != null ) {
173
    while (fgets(buffer, buffer_size, f) != null) {
-
 
174
	char	 c;	     /* temporary character */
-
 
175
	char	*p;          /* current pointer to scan buffer */
-
 
176
	char	*key_start;  /* points to +, <, > start of key */
-
 
177
	int	 key_length; /* length of key */
-
 
178
	char	*val_start;  /* start of value associated with key */
-
 
179
	char	*val_end;    /* end of value */
-
 
180
	char	*esc_start;  /* start of substituion field, always a '<' */
-
 
181
	char	*esc_end;    /* end of susbtitution field, always a '>' */
-
 
182
	int	 esc_len;    /* number of chars to escape over */
-
 
183
	char	*sub;	     /* character substitution for escape sequences */
-
 
184
	int	 count;      /* counter to stop scan at buffer_size */
-
 
185
	int	 line_len;   /* length of this buffer */
-
 
186
	char	*end = NULL; /* end of line */
-
 
187
	char	*cmd;	     /* final command string being built */
-
 
188
	list	 dummy;	     /* final command */
-
 
189
	htnode	*hn;	     /* wrapper for command storage */
-
 
190
 
-
 
191
	line_len = strlen(buffer);
-
 
192
	count = 1;
136
	char c = *buffer ;
193
	p = buffer;
-
 
194
	c = *p++;
-
 
195
	line_num++;
-
 
196
 
137
	if ( c == '<' || c == '>' || c == '+' || c == '?' ) {
197
	if (c == '<' || c == '>' || c == '+' || c == '?') {
-
 
198
	    key_start = (p - 1);
-
 
199
	    key_length = 0;
-
 
200
	    while (c = *p++, is_alphanum(c)) {
-
 
201
		if (count++ == buffer_size)
138
	    /* Only process lines beginning with these characters */
202
		    error(FATAL, "%s: line %d: Exceeded max line size", nm,
139
	    char *sp ;
203
			  line_num);
140
	    list dummy ;
204
		key_length++;
-
 
205
	    }
-
 
206
 
141
	    char line [1000] ;
207
	    /* mark off key from val */
142
	    line [0] = c ;
208
	    *(p - 1) = '\0';
-
 
209
 
-
 
210
	    /* skip over spacing between key and value */
143
	    p = buffer + 1 ;
211
	    while (c == ' ' || c == '\t') {
144
	    q = line + 1 ;
212
		c = *p++;
-
 
213
		if (count++ == buffer_size) {
145
	    while ( c = *( p++ ), is_alphanum ( c ) ) *( q++ ) = c ;
214
		    error(FATAL, "%s: line %d: Exceeded max line size", nm,
146
	    sp = q ;
215
			  line_num);
-
 
216
		}
-
 
217
	    }
-
 
218
 
147
	    *( q++ ) = 0 ;
219
	    /* sanity check */
148
	    if ( !is_whitespace ( c ) ) {
220
	    if (c == '\0') {
149
		error ( WARNING, "Illegal environmental variable, '%s'",
221
		error(WARNING, "%s: line %d: No value assigned to key %s",
-
 
222
		      nm, line_num, key_start);
150
			line ) ;
223
		continue;
151
	    }
224
	    }
-
 
225
 
152
	    while ( c = *( p++ ), is_whitespace ( c ) ) /* empty */ ;
226
	    /* All values assigned to a key must be in quotes */
153
	    if ( !is_quote ( c ) ) {
227
	    if (c != '"') {
154
		error ( WARNING, "Illegal environmental value for '%s'",
228
		error(WARNING, "%s: line %d: Value assigned to key %s"
-
 
229
		       " must be quoted", nm, line_num, key_start);
155
			line ) ;
230
		continue;
156
	    }
231
	    }
-
 
232
 
-
 
233
	    val_start = p;
-
 
234
 
157
	    while ( c = *( p++ ), !is_quote ( c ) ) {
235
	    /* remove leading quotation mark from val */
158
		if ( c == '\\' ) c = *( p++ ) ;
236
	    *(val_start - 1) = ' ';
-
 
237
 
159
		if ( c == 0 || is_newline ( c ) ) {
238
	    /* read the value, until the matching close quote */
160
		    error ( WARNING, "Illegal environmental value for '%s'",
239
	    while (c = *p++, (c != '"' && c != '\n' && c != '\0')) {
161
			    line ) ;
240
		if (count++ == buffer_size) {
-
 
241
		    error(FATAL, "%s: line %d: Exceeded max line size", nm,
162
		    break ;
242
			  line_num);
163
		}
243
		}
-
 
244
 
-
 
245
		if (c == '<') {
-
 
246
		    int sub_len;    /* length of substitution */
-
 
247
		    int diff;       /* difference between two lengths */
-
 
248
		    int delta;      /* direction of growth */
-
 
249
		    int cnt;        /* counter */
-
 
250
		    int shift_max;  /* amount to move */
-
 
251
		    char *pivot;    /* where to start shifting */
-
 
252
 
-
 
253
		    /* mark start of <> sequence */
-
 
254
		    esc_start = (p - 1);
-
 
255
		    esc_len = 2; /* accounts for <, > */
-
 
256
 
-
 
257
		    /* expand quote */
-
 
258
		    while (c = *p++, c != '>') {
-
 
259
			esc_len++;
-
 
260
			if (count++ == buffer_size) {
-
 
261
			    error(FATAL, "%s: line %d: Exceeded max line size",
-
 
262
				  nm, line_num);
-
 
263
			}
-
 
264
 
-
 
265
			if (c == '\n' || c == '\0') {
-
 
266
			    error(FATAL, "%s: line %d: Unmatched escape"
-
 
267
				   " sequence, missing >", nm, line_num);
-
 
268
			}
-
 
269
 
-
 
270
			if (c == '<') {
-
 
271
			    error(FATAL, "%s: line %d: Nested < > escape "
-
 
272
				  " sequences prohibited",
-
 
273
				  nm, line_num);
-
 
274
			    continue;
-
 
275
			}
-
 
276
		    }
-
 
277
 
-
 
278
		    /* mark end of <> sequence */
-
 
279
		    esc_end = (p - 1);
-
 
280
 
-
 
281
		    /*
-
 
282
		     * find a substitution; all error handling done in function
-
 
283
		     */
-
 
284
		    sub = dereference_var(esc_start + 1, esc_end, ht, nm,
-
 
285
					  line_num);
-
 
286
 
-
 
287
		    /* find length of substitution */
-
 
288
		    sub_len = strlen(sub);
-
 
289
 
-
 
290
		    /* do we grow or shrink */
-
 
291
		    diff = (sub_len - esc_len);
-
 
292
 
-
 
293
		    /* find the number of characters that must be moved */
-
 
294
		    shift_max = strlen(esc_end);
-
 
295
 
-
 
296
		    if (!end) {
-
 
297
			end = (buffer + line_len);
-
 
298
		    }
-
 
299
 
-
 
300
		    if (diff > 0) {
-
 
301
			/* grow */
-
 
302
			pivot = end;
164
		*( q++ ) = c ;
303
			delta = -1;
-
 
304
		    } else {
-
 
305
			/* shrink */
-
 
306
			delta = 1;
-
 
307
			pivot = esc_end + 1;
-
 
308
		    }
-
 
309
 
-
 
310
		    /* adjust end pointers and length counters */
-
 
311
		    end += diff;
-
 
312
		    line_len += diff;
-
 
313
		    count += diff;
-
 
314
		    if (count == buffer_size) {
-
 
315
			error(FATAL, "%s: line %d: Exceeded max line size",
-
 
316
			      nm, line_num);
-
 
317
		    }
-
 
318
 
-
 
319
		    /* make room for the substitution */
-
 
320
		    for (cnt = 0; cnt < shift_max; cnt++){
-
 
321
			*(pivot + (cnt * delta) + diff) =
-
 
322
			    *(pivot + (cnt * delta));
-
 
323
		    }
-
 
324
 
-
 
325
		    /* perform subsitution on resized line */
-
 
326
		    for (cnt = 0; cnt < sub_len; cnt++) {
-
 
327
			*(esc_start + cnt) = sub[cnt];
-
 
328
		    }
-
 
329
 
-
 
330
		    /* advance our scanning pointer */
-
 
331
		    p = esc_end + diff;
-
 
332
		} /* if escape '<' sequence */
-
 
333
	    } /* while *p != "" */
-
 
334
 
-
 
335
	    /* did we end the val scan on new line or EOF? */
-
 
336
	    if (c == '\n' || c == '\0') {
-
 
337
		error(WARNING, "%s: line %d: Value assigned to key %s"
-
 
338
		       " not terminated with end quote",
-
 
339
		       nm, line_num, key_start);
-
 
340
		continue;
-
 
341
	    }
-
 
342
 
-
 
343
	    /* mark end of the value */
-
 
344
	    val_end = (p - 1);
-
 
345
 
-
 
346
	    /* set close quote to null */
-
 
347
	    *(val_end) = '\0';
-
 
348
 
-
 
349
	    /* build the command string */
-
 
350
	    cmd = string_append(key_start, val_start, ' ');
-
 
351
	    key_start = string_copy(key_start);
-
 
352
	    val_start = (cmd + key_length + 2);
-
 
353
 
-
 
354
	    /*
-
 
355
	     * If the key/value pair is a tccenv variable, it's a finished
-
 
356
	     * command, and should be executed.
-
 
357
	     */
-
 
358
	    hn = lookup_table(ht, key_start);
-
 
359
	    if (hn && (hn->flag & TCCENV)) {
-
 
360
		/* process the command */
-
 
361
		dummy.item = cmd;
-
 
362
		dummy.next = null;
-
 
363
		process_options(&dummy, environ_optmap, 1);
165
	    }
364
	    }
166
	    while ( c = *( p++ ), is_whitespace ( c ) ) /* empty */ ;
-
 
167
	    if ( !is_newline ( c ) ) {
-
 
168
		error ( WARNING, "Illegal environmental value for '%s'",
-
 
169
			line ) ;
-
 
170
	    }
-
 
171
	    *sp = ' ' ;
-
 
172
	    *q = 0 ;
-
 
173
	    dummy.item = string_copy ( line ) ;
-
 
174
	    dummy.next = null ;
-
 
175
	    process_options ( &dummy, environ_optmap ) ;
-
 
176
	}
-
 
177
    }
-
 
178
    IGNORE fclose ( f ) ;
-
 
179
    return ( 0 ) ;
-
 
180
}
-
 
181
 
365
 
-
 
366
	    /* update hashtable with new key/value pair*/
-
 
367
	    hn = update_table(ht, key_start, val_start, USR, nm, line_num);
-
 
368
	} /* if the line is a +, >, < env action command */
-
 
369
    } /* for each line in the env file */
-
 
370
 
-
 
371
    return (0);
-
 
372
} /* read_env_aux() */
-
 
373
 
-
 
374
 
-
 
375
/*
-
 
376
 * Lookup value for tccenv(5) variables. This function takes in an escape
-
 
377
 * sequence from an env file, and attempts to find a definition. For example,
-
 
378
 * <TENDRA_BASEDIR> may be passed in, and be mapped to the value supplied
-
 
379
 * previously by -y arguments.
-
 
380
 *
-
 
381
 * The function looks up TENDRA_* variables first, since they are so common.
-
 
382
 * The TENDRA_* variable resolution also consults the shell environment, if no
-
 
383
 * -y argument or +TENDRA_* declaration was given in an env file. Failing that,
-
 
384
 * the function consults the hash table of tccenv key/value mappings. This
-
 
385
 * function performs all error handling; it will return a valid char *, or
-
 
386
 * fail.
-
 
387
 */
-
 
388
char *
-
 
389
dereference_var(char *esc_start, char *esc_end, hashtable *ht, char *nm,
-
 
390
		int line_num)
-
 
391
{
-
 
392
	htnode* hn;
-
 
393
	char *sub = NULL;
-
 
394
	/* temporarily replace '>' with '\0' to facilitate lookup */
-
 
395
	char tmp = *esc_end;
-
 
396
	*esc_end = '\0';
-
 
397
 
-
 
398
	/*
-
 
399
	 * Attempt to match TENDRA_* env arguments, which are most likely to
-
 
400
	 * occur.
-
 
401
	 */
-
 
402
	if (!strncmp("TENDRA", esc_start, 6)) {
-
 
403
		sub = find_path_subst(esc_start);
-
 
404
	}
-
 
405
 
-
 
406
	/* If we fail to find a TENDRA_* env match, look
-
 
407
	   up in hashtable */
-
 
408
	if (!sub) {
-
 
409
		hn = lookup_table(ht, esc_start);
-
 
410
		if (hn == NULL) {
-
 
411
			*esc_end = tmp;
-
 
412
			error(FATAL, "Undefined variable <%s> in %s line %d",
-
 
413
			      esc_start, nm, line_num);
-
 
414
		}
-
 
415
		sub = hn->val;
-
 
416
	}
-
 
417
 
-
 
418
	*esc_end = tmp;
-
 
419
	return sub;
-
 
420
}
-
 
421
 
-
 
422
 
-
 
423
/*
-
 
424
 * Reconcile the table of user-defined env options. At present this function
-
 
425
 * just makes sure that non-tccenv(5) variables declared by the user were used
-
 
426
 * in the env files. If not, it's likely a subtle bug or typo, and a warning
-
 
427
 * issues if the version -v switch is used.
-
 
428
 *
-
 
429
 * Future revisions may also attempt to supply definitions to hash keys that
-
 
430
 * were not found during the O(N) initial pass through the env files. (That is,
-
 
431
 * the env reading would be O(2N), and attempt to finding all possible
-
 
432
 * definitions, including those out of order.)
-
 
433
 */
-
 
434
 
-
 
435
void
-
 
436
reconcile_envopts(void)
-
 
437
{
-
 
438
	int i;
-
 
439
	htnode *hn;
-
 
440
 
-
 
441
	/*
-
 
442
	 * If no -Y args were given whatsoever, give a warning, since a
-
 
443
	 * mysterious internal error ("tcc: Internal: The tool 'C_producer' is
-
 
444
	 * not available'") is about to follow during the execute stage. This
-
 
445
	 * mistake is so fundamental, we give a warning even without verbose
-
 
446
	 * being set.
-
 
447
	 */
-
 
448
	if (environ_count == 0) {
-
 
449
		error(WARNING, "not invoked with any -Y env arguments");
-
 
450
	}
-
 
451
 
-
 
452
	/* All subsequent warnings require a verbose flag */
-
 
453
	if (!verbose) {
-
 
454
		return;
-
 
455
	}
-
 
456
 
-
 
457
	/*
-
 
458
	 * If the global env table is NULL, no -Y args succeeded, or none were
-
 
459
	 * given.
-
 
460
	 */
-
 
461
	if (!environ_hashtable) {
-
 
462
		/* -Y args given, but failed */
-
 
463
 
-
 
464
		if (environ_count > 0) {
-
 
465
			error(WARNING, "failed to load any environment files");
-
 
466
			return;
-
 
467
		}
-
 
468
	}
-
 
469
 
-
 
470
	for (i = 0; i < TCC_TBLSIZE; i++) {
-
 
471
		hn = environ_hashtable->node[i];
-
 
472
 
-
 
473
		if (hn && (hn->flag & USR) && !(hn->flag & READ)) {
-
 
474
			error(WARNING,
-
 
475
			      "%s, line %d: environment option %s declared"
-
 
476
			      " but never used", hn->file, hn->line_num,
-
 
477
			      hn->key);
-
 
478
		}
-
 
479
	}
-
 
480
}
-
 
481
 
-
 
482
/*
-
 
483
 * READ AN ENVIRONMENT
-
 
484
 *
-
 
485
 * This routine reads the environment named nm, reporting an error if it is
-
 
486
 * unsuccessful.
-
 
487
 */
-
 
488
 
-
 
489
void
-
 
490
read_env(char *nm)
-
 
491
{
-
 
492
	int e;
-
 
493
	static hashtable *ht;
-
 
494
 
-
 
495
	/* note attempt to load -Y env file */
-
 
496
	environ_count++;
-
 
497
 
-
 
498
	if (ht == NULL) {
-
 
499
		ht = init_table(TCC_TBLSIZE, TCC_KEYSIZE, &hash);
-
 
500
		environ_hashtable = ht; /* hack */
-
 
501
	}
-
 
502
 
-
 
503
	e = read_env_aux(nm, ht);
-
 
504
	if (e == 1) {
-
 
505
		error(WARNING, "Can't find environment, '%s'", nm);
-
 
506
	}
-
 
507
	return;
-
 
508
}
182
 
509
 
-
 
510
void
-
 
511
dump_env(void)
-
 
512
{
-
 
513
	htnode *hn;
-
 
514
	int i;
-
 
515
 
-
 
516
	if (environ_hashtable == NULL) {
-
 
517
		error(FATAL, "No environment information found\n");
183
/*
518
	}
-
 
519
 
-
 
520
	printf("Environment dump:\n");
-
 
521
	/* Traverse the hash tree and print all data in it */
184
    READ AN ENVIRONMENT
522
	for (i = 0; i < TCC_TBLSIZE; i++) {
-
 
523
		hn = environ_hashtable->node[i];
185
 
524
 
186
    This routine reads the environment named nm, reporting an error if
525
		if (hn) {
187
    it is unsuccessful.
526
			printf("\t%s = %s\n", hn->key, hn->val);
188
*/
527
		}
189
 
-
 
190
void read_env
-
 
191
    PROTO_N ( ( nm ) )
-
 
192
    PROTO_T ( char *nm )
-
 
193
{
528
	}
194
    int e = read_env_aux ( nm ) ;
-
 
195
    if ( e == 1 ) error ( WARNING, "Can't find environment, '%s'", nm ) ;
-
 
196
    return ;
-
 
197
}
529
}