Subversion Repositories tendra.SVN

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
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
#if FS_STDARG
62
#if FS_STDARG
33
#include <stdarg.h>
63
#include <stdarg.h>
34
#else
64
#else
35
#include <varargs.h>
65
#include <varargs.h>
36
#endif
66
#endif
37
#include "list.h"
67
#include "list.h"
-
 
68
#include "environ.h"
38
#include "flags.h"
69
#include "flags.h"
39
#include "main.h"
70
#include "main.h"
-
 
71
#include "options.h"
40
#include "suffix.h"
72
#include "suffix.h"
41
#include "utility.h"
73
#include "utility.h"
42
 
74
 
43
 
75
 
44
/*
76
/*
45
    ERROR VARIABLES
77
 * ERROR VARIABLES
46
 
78
 *
47
    The value exit_status gives the overall status of the program.  It
79
 * The value exit_status gives the overall status of the program. It can be
48
    can be EXIT_SUCCESS or EXIT_FAILURE.  The variable progname gives
80
 * EXIT_SUCCESS or EXIT_FAILURE. The variable progname gives the name of the
49
    the name of the program, which is used in error reports.
81
 * program, which is used in error reports.
50
*/
82
 */
51
 
83
 
52
int exit_status = EXIT_SUCCESS ;
84
int exit_status = EXIT_SUCCESS;
53
char *progname = PROGNAME_TCC ;
85
char *progname = PROGNAME_TCC;
-
 
86
 
-
 
87
 
-
 
88
/*
-
 
89
 * Static function prototypes.
-
 
90
 */
-
 
91
 
-
 
92
static int	key_match(char *, char *);
54
 
93
 
55
 
94
 
56
/*
95
/*
57
    PRINT AN ERROR MESSAGE
96
 * PRINT AN ERROR MESSAGE
58
 
97
 *
59
    This routine prints an error message s (a printf-style string,
98
 * This routine prints an error message s (a printf-style string, which may be
60
    which may be followed by any number of arguments) of severity e
99
 * followed by any number of arguments) of severity e (see utility.h).
-
 
100
 */
-
 
101
 
-
 
102
void
-
 
103
error(int e, char *s, ...) /* VARARGS */
-
 
104
{
-
 
105
	va_list args;
-
 
106
	char *errtype = null;
-
 
107
#if FS_STDARG
-
 
108
	va_start(args, s);
-
 
109
#else
-
 
110
	int e;
-
 
111
	char *s;
-
 
112
	va_start(args);
-
 
113
	e = va_arg(args, int);
-
 
114
	s = va_arg(args, char *);
-
 
115
#endif
-
 
116
	switch (e) {
-
 
117
	case FATAL:
-
 
118
		exit_status = EXIT_FAILURE;
-
 
119
		errtype = "Fatal";
-
 
120
		break;
-
 
121
	case INTERNAL:
-
 
122
		exit_status = EXIT_FAILURE;
-
 
123
		errtype = "Internal";
-
 
124
		break;
-
 
125
	case SERIOUS:
-
 
126
		exit_status = EXIT_FAILURE;
-
 
127
		errtype = "Error";
-
 
128
		break;
-
 
129
	case OPTION:
-
 
130
		exit_status = EXIT_FAILURE;
-
 
131
		errtype = "Option interpreter";
-
 
132
		break;
-
 
133
	case WARNING:
-
 
134
		if (!warnings) {
-
 
135
			va_end(args);
-
 
136
			return;
-
 
137
		}
-
 
138
		errtype = "Warning";
-
 
139
		break;
-
 
140
	case INFO:
-
 
141
		errtype = "Information";
-
 
142
		break;
-
 
143
	}
-
 
144
 
-
 
145
	if (checker) {
-
 
146
		progname = PROGNAME_TCHK;
-
 
147
	}
-
 
148
	IGNORE fprintf(stderr, "%s: ", progname);
-
 
149
	if (errtype) {
-
 
150
		IGNORE fprintf(stderr, "%s: ", errtype);
-
 
151
	}
-
 
152
	IGNORE vfprintf(stderr, s, args);
-
 
153
	IGNORE fprintf(stderr, ".\n");
-
 
154
	va_end(args);
-
 
155
	if (e == FATAL) {
-
 
156
		main_end();
-
 
157
	}
-
 
158
	return;
-
 
159
}
-
 
160
 
-
 
161
 
-
 
162
/*
-
 
163
 * HASH TABLE
-
 
164
 *
-
 
165
 * These functions provide access to a hash table of tccenv(5) keys and values.
-
 
166
 * When created, the hash table is populated with tccenv keys taken from the
-
 
167
 * environ_optmap[] array, and flaged as tccenv-derived instead of
61
    (see utility.h).
168
 * user-created.
62
*/
169
 */
-
 
170
 
-
 
171
hashtable*
-
 
172
init_table(int tblsize, int keysize, int (*hashfcn) (char*, int, int))
-
 
173
{
-
 
174
	int i;
-
 
175
	hashtable* ht;
-
 
176
	htnode *hn;
-
 
177
	optmap *t;
-
 
178
 
-
 
179
	ht = malloc(sizeof(hashtable));
-
 
180
	ht->tblsize = tblsize;
-
 
181
	ht->keysize = keysize;
-
 
182
	ht->hashfcn = hashfcn;
-
 
183
	ht->node = malloc(sizeof(htnode*) * tblsize);
-
 
184
 
-
 
185
	for (i = 0; i < tblsize; i++) {
-
 
186
		ht->node[i] = NULL;
-
 
187
	}
-
 
188
 
-
 
189
	for (t = environ_optmap; t->in != NULL; t++) {
-
 
190
		/* initialize hash table with tccenv keys */
-
 
191
		hn = update_table(ht, t->in, NULL, TCCENV, NULL, -1);
-
 
192
	}
-
 
193
 
-
 
194
	return ht;
-
 
195
}
-
 
196
 
-
 
197
htnode *
-
 
198
lookup_table(hashtable *ht, char *key)
-
 
199
{
-
 
200
	int  hashval;
-
 
201
	htnode *hn;
-
 
202
	char *v = NULL;
-
 
203
 
-
 
204
	if (!key) {
-
 
205
		error(WARNING, "Looking up null key in tccenv hashtable");
-
 
206
 
-
 
207
		return NULL;
-
 
208
	}
-
 
209
 
-
 
210
	hashval = ht->hashfcn(key, ht->tblsize, ht->keysize);
-
 
211
	hn = ht->node[hashval];
-
 
212
 
-
 
213
	if (hn) {
-
 
214
		v = hn->key;
-
 
215
	}
-
 
216
 
-
 
217
	while (hn != NULL && !key_match(key, hn->key)) {
-
 
218
		hn = hn->next;
-
 
219
	}
-
 
220
 
-
 
221
	if (hn) {
-
 
222
		hn->flag |= READ;
-
 
223
	}
-
 
224
 
-
 
225
	return hn;
-
 
226
}
-
 
227
 
-
 
228
static int
-
 
229
key_match(char *key, char *keyfield)
-
 
230
{
-
 
231
	int i;
-
 
232
 
-
 
233
	if (!key || !keyfield) {
-
 
234
		return 0;
-
 
235
	}
-
 
236
 
-
 
237
	/* advance pointers past command chars */
-
 
238
	while(key && !is_alphanum(*key)) {
-
 
239
		key++;
-
 
240
	}
-
 
241
 
-
 
242
	while(keyfield && !is_alphanum(*keyfield)) {
-
 
243
		keyfield++;
-
 
244
	}
-
 
245
 
-
 
246
	for (i = 0; i < strlen(key); i++) {
-
 
247
		if (key[i] != keyfield[i]) {
-
 
248
			return 0;
-
 
249
		}
-
 
250
	}
-
 
251
 
-
 
252
	return 1;
-
 
253
}
-
 
254
 
-
 
255
htnode *
-
 
256
update_table(hashtable *ht, char *key, char *val, unsigned int flag,
-
 
257
	     char *file, int line_num)
-
 
258
{
-
 
259
	int hashval;
-
 
260
	htnode *hn;
-
 
261
	hashval = ht->hashfcn(key, ht->tblsize, ht->keysize);
-
 
262
	hn = ht->node[hashval];
-
 
263
 
-
 
264
	/* locate matching node */
-
 
265
	while (hn != NULL && !key_match(key, hn->key)) {
-
 
266
		hn = hn->next;
-
 
267
	}
-
 
268
 
-
 
269
	/* Case 1.  Node was not found; push */
-
 
270
	if (hn == NULL) {
-
 
271
		hn = malloc(sizeof(htnode));
-
 
272
		hn->flag = flag;
-
 
273
		hn->key = key;
-
 
274
		hn->val = val;
-
 
275
		hn->file = file;
-
 
276
		hn->line_num = line_num;
-
 
277
		hn->next = ht->node[hashval];
-
 
278
		ht->node[hashval] = hn;
-
 
279
	} else {
-
 
280
		/* Case 2.  Update */
-
 
281
		if (!val) {
-
 
282
			hn->val = NULL;
-
 
283
		} else {
-
 
284
			switch (*key) {
-
 
285
			case '+':
-
 
286
				/* assignment */
-
 
287
				hn->val = val;
-
 
288
				break;
-
 
289
			case '>':
-
 
290
				/* append */
-
 
291
				if (hn->val) {
-
 
292
					hn->val =
-
 
293
					    string_append(hn->val, val, ' ');
-
 
294
				}
-
 
295
				hn->val = val;
-
 
296
				break;
-
 
297
			case '<':
-
 
298
				/* prepend */
-
 
299
				if (hn->val) {
-
 
300
					hn->val =
-
 
301
					    string_append(val, hn->val, ' ');
-
 
302
				}
-
 
303
				hn->val = val;
-
 
304
				break;
-
 
305
			default:
-
 
306
				/*
-
 
307
				 * This should never happen, since read_env_aux
-
 
308
				 * screens for this.
-
 
309
				 */
-
 
310
				error(FATAL, "Attempt to update hashtable with"
-
 
311
				      " invalid key %s\n", key);
-
 
312
			}
-
 
313
		}
-
 
314
	}
-
 
315
 
-
 
316
	return hn;
-
 
317
}
-
 
318
 
-
 
319
/*
-
 
320
 * Hash function. The function takes in a char * to a key, presumed to be in
-
 
321
 * the form of <cmd><tccenv_var>, e.g., "+AS /usr/bin/as". The hash calculated
-
 
322
 * skips over the leading command char, either +, <, >, or ?.
-
 
323
 */
-
 
324
int
-
 
325
hash(char *key, int tblsize, int keysize)
-
 
326
{
-
 
327
	int i = 1;
-
 
328
	int hashval = 0;
-
 
329
 
-
 
330
	/* skip leading +, <, >, ?, / chars */
-
 
331
	while (key && !(is_alphanum(*key))) {
-
 
332
		key++;
-
 
333
	}
-
 
334
 
-
 
335
	if (!key) {
-
 
336
		error(FATAL, "hash operation requested on empty key");
-
 
337
	}
-
 
338
 
-
 
339
	while (*key && !is_whitespace(*key) && i < keysize) {
-
 
340
		hashval += (hashval * 37) + (int) *key;
-
 
341
		*key++;
-
 
342
		i++;
-
 
343
	}
-
 
344
 
-
 
345
	hashval %= tblsize;
-
 
346
	if (hashval < 0) {
-
 
347
		hashval += tblsize;
-
 
348
	}
-
 
349
 
-
 
350
	return hashval;
-
 
351
}
-
 
352
 
-
 
353
 
-
 
354
/*
-
 
355
 * PRINT A COMMENT
-
 
356
 *
-
 
357
 * This routine prints the comments (a printf-style string, which may be
-
 
358
 * followed by any number of arguments) to the standard output.
-
 
359
 */
63
 
360
 
64
void error
361
void
65
    PROTO_V ( ( int e, char *s, ... ) ) /* VARARGS */
362
comment(int e, char *s, ...) /* VARARGS */
66
{
363
{
-
 
364
	FILE *f;
67
    va_list args ;
365
	va_list args;
68
    char *errtype = null ;
-
 
69
#if FS_STDARG
366
#if FS_STDARG
70
    va_start ( args, s ) ;
367
	va_start(args, s);
71
#else
368
#else
72
    int e ;
369
	int e;
73
    char *s ;
370
	char *s;
74
    va_start ( args ) ;
371
	va_start(args);
75
    e = va_arg ( args, int ) ;
372
	e = va_arg(args, int);
76
    s = va_arg ( args, char * ) ;
373
	s = va_arg(args, char *);
77
#endif
374
#endif
78
    switch ( e ) {
375
	f = (e ? stdout : stderr);
79
	case FATAL : {
376
	IGNORE fflush(f);
80
	    exit_status = EXIT_FAILURE ;
377
	IGNORE vfprintf(f, s, args);
81
	    errtype = "Fatal" ;
378
	IGNORE fflush(f);
82
	    break ;
379
	va_end(args);
-
 
380
	return;
83
	}
381
}
84
	case INTERNAL : {
-
 
85
	    exit_status = EXIT_FAILURE ;
-
 
86
	    errtype = "Internal" ;
-
 
-
 
382
 
87
	    break ;
383
 
88
	}
384
/*
89
	case SERIOUS : {
-
 
90
	    exit_status = EXIT_FAILURE ;
-
 
91
	    errtype = "Error" ;
385
 * ALLOCATE A BLOCK OF MEMORY
92
	    break ;
-
 
93
	}
386
 *
94
	case OPTION : {
-
 
95
	    exit_status = EXIT_FAILURE ;
-
 
96
	    errtype = "Option interpreter" ;
387
 * This routine allocates a block of memory of size sz and returns the result.
97
	    break ;
388
 */
98
	}
389
 
99
	case WARNING : {
-
 
100
	    if ( !warnings ) {
-
 
101
		va_end ( args ) ;
-
 
102
		return ;
390
pointer
103
	    }
-
 
104
	    errtype = "Warning" ;
-
 
105
	    break ;
391
xalloc(int sz)
106
	}
392
{
-
 
393
	pointer p = (pointer)malloc((size_t)sz);
107
	case INFO : {
394
	if (p == null) {
108
	    errtype = "Information" ;
395
		error(FATAL, "Memory allocation error");
109
	    break ;
-
 
110
	}
396
	}
-
 
397
	return (p);
-
 
398
}
-
 
399
 
-
 
400
 
-
 
401
/*
-
 
402
 * REALLOCATE A BLOCK OF MEMORY
-
 
403
 *
-
 
404
 * This routine reallocates the block of memory p to have size sz.
-
 
405
 * xrealloc(*null, sz) is equivalent to xalloc(sz).
-
 
406
 */
-
 
407
 
-
 
408
pointer
-
 
409
xrealloc(pointer p, int sz)
-
 
410
{
-
 
411
    pointer q;
-
 
412
    if (p == null) {
-
 
413
	    return (xalloc(sz));
-
 
414
    }
-
 
415
    q = (pointer)realloc(p,(size_t)sz);
-
 
416
    if (q == null) {
-
 
417
	    error(FATAL, "Memory reallocation error");
111
    }
418
    }
112
    if ( checker ) progname = PROGNAME_TCHK ;
-
 
113
    IGNORE fprintf ( stderr, "%s: ", progname ) ;
-
 
114
    if ( errtype ) IGNORE fprintf ( stderr, "%s: ", errtype ) ;
-
 
115
    IGNORE vfprintf ( stderr, s, args ) ;
-
 
116
    IGNORE fprintf ( stderr, ".\n" ) ;
-
 
117
    va_end ( args ) ;
-
 
118
    if ( e == FATAL ) main_end () ;
-
 
119
    return ;
419
    return (q);
120
}
420
}
121
 
421
 
122
 
422
 
123
/*
423
/*
-
 
424
 * Takes in a substitution variable as an argument, and returns its
-
 
425
 * corresponding value. This routine is used by the env substitution function
124
    PRINT A COMMENT
426
 * (see format_path) to map variables to paths.
-
 
427
 *
-
 
428
 * For example, input is "<TCCDIR_BASE>", and return value is
-
 
429
 * "/usr/local/share/". Variable lookup is prioritized:
125
 
430
 *
126
    This routine prints the comment s (a printf-style string, which
431
 *   a) command line args have highest priority,
-
 
432
 *   b) environment variables are used next,
127
    may be followed by any number of arguments) to the standard output.
433
 *   c) for a select group of variables, sane defaults are used.
128
*/
434
 */
129
 
435
 
130
void comment
436
char *
131
    PROTO_V ( ( int e, char *s, ... ) ) /* VARARGS */
437
find_path_subst(char *var)
132
{
438
{
133
    FILE *f ;
439
	char *ret;
134
    va_list args ;
440
	char **subs;
135
#if FS_STDARG
441
	int i = 0;
136
    va_start ( args, s ) ;
-
 
-
 
442
 
137
#else
443
	i = 0;
138
    int e ;
444
	subs = PATH_SUBS;
139
    char *s ;
445
	while (*subs){
140
    va_start ( args ) ;
446
		if (!strcmp(var, *subs)) {
141
    e = va_arg ( args, int ) ;
447
			if (env_paths[i] == NULL){
-
 
448
				error(FATAL, "The env variable <%s> is null.\n"
-
 
449
				      "Check your environment or edit your env"
142
    s = va_arg ( args, char * ) ;
450
				      " files", PATH_SUBS[i]);
143
#endif
451
			}
144
    f = ( e ? stdout : stderr ) ;
452
			return env_paths[i];
-
 
453
		}
-
 
454
		i++;
-
 
455
		subs++;
-
 
456
	}
145
    IGNORE fflush ( f ) ;
457
	if (!*subs) {
-
 
458
		error(WARNING, "Expected command line option -y%s=[value]; "
146
    IGNORE vfprintf ( f, s, args ) ;
459
		      "trying environment", var);
-
 
460
	}
147
    IGNORE fflush ( f ) ;
461
	ret = getenv(var);
-
 
462
 
-
 
463
	/* XXX: Perhaps this should not be fatal? */
148
    va_end ( args ) ;
464
	if (!ret) {
-
 
465
		error(FATAL, "Unknown environment variable %s", var);
-
 
466
	}
149
    return ;
467
	return ret;
150
}
468
}
151
 
469
 
152
 
470
 
153
/*
471
/*
154
    ALLOCATE A BLOCK OF MEMORY
472
 * ALLOCATE SPACE FOR A STRING
155
 
473
 *
156
    This routine allocates a block of memory of size sz and returns
474
 * This routine allocates n characters of memory for use in the string memory
157
    the result.
475
 * allocation routines.
158
*/
476
 */
159
 
477
 
160
pointer xalloc
478
static char *
161
    PROTO_N ( ( sz ) )
-
 
162
    PROTO_T ( int sz )
479
string_alloc(int n)
163
{
480
{
-
 
481
	char *r;
-
 
482
	if (n >= 1000) {
164
    pointer p = ( pointer ) malloc ( ( size_t ) sz ) ;
483
		/* Long strings are allocated space by alloc_nof */
-
 
484
		r = alloc_nof(char, n);
-
 
485
	} else {
165
    if ( p == null ) error ( FATAL, "Memory allocation error" ) ;
486
		/* Short strings are allocated space from a buffer */
-
 
487
		static int no_free = 0;
-
 
488
		static char *free_chars = null;
-
 
489
		if (n >= no_free) {
-
 
490
			no_free = 4000;
-
 
491
			free_chars = alloc_nof(char, no_free);
-
 
492
		}
-
 
493
		r = free_chars;
-
 
494
		no_free -= n;
-
 
495
		free_chars += n;
-
 
496
	}
166
    return ( p ) ;
497
	return (r);
167
}
498
}
168
 
499
 
169
 
500
 
170
/*
501
/*
171
    REALLOCATE A BLOCK OF MEMORY
502
 * COPY A STRING
172
 
503
 *
173
    This routine reallocates the block of memory p to have size sz.
504
 * This routine allocates space for a copy of the string s and copies the
174
    xrealloc ( null, sz ) is equivalent to xalloc ( sz ).
505
 * string into this space. This copy is returned.
175
 
-
 
176
*/
506
 */
177
 
507
 
178
pointer xrealloc
508
char *
179
    PROTO_N ( ( p, sz ) )
509
string_copy(char *s)
180
    PROTO_T ( pointer p X int sz )
-
 
181
{
510
{
182
    pointer q ;
511
	int n = (int)strlen(s);
183
    if ( p == null ) return ( xalloc ( sz ) ) ;
512
	char *r = string_alloc(n + 1);
184
    q = ( pointer ) realloc ( p, ( size_t ) sz ) ;
513
	IGNORE strcpy(r, s);
185
    if ( q == null ) error ( FATAL, "Memory reallocation error" ) ;
-
 
186
    return ( q ) ;
514
	return (r);
187
}
515
}
188
 
516
 
189
 
517
 
190
/*
518
/*
191
    ALLOCATE SPACE FOR A STRING
519
 * COPY TWO STRINGS
192
 
520
 *
193
    This routine allocates n characters of memory for use in the string
521
 * This routine allocates space for a copy of the string s followed by a copy
-
 
522
 * of the string t and concatenates the strings into this space. This copy is
194
    memory allocation routines.
523
 * returned.
195
*/
524
 */
196
 
525
 
197
static char *string_alloc
526
char *
198
    PROTO_N ( ( n ) )
-
 
199
    PROTO_T ( int n )
527
string_concat(char *s, char *t)
200
{
528
{
201
    char *r ;
-
 
202
    if ( n >= 1000 ) {
-
 
203
	/* Long strings are allocated space by alloc_nof */
-
 
204
	r = alloc_nof ( char, n ) ;
-
 
205
    } else {
-
 
206
	/* Short strings are allocated space from a buffer */
-
 
207
	static int no_free = 0 ;
529
	int n = (int)strlen(s);
208
	static char *free_chars = null ;
-
 
209
	if ( n >= no_free ) {
530
	int m = (int)strlen(t);
210
	    no_free = 4000 ;
-
 
211
	    free_chars = alloc_nof ( char, no_free ) ;
531
	char *r = string_alloc(n + m + 1);
212
	}
-
 
213
	r = free_chars ;
532
	IGNORE strcpy(r, s);
214
	no_free -= n ;
-
 
215
	free_chars += n ;
533
	IGNORE strcpy(r + n, t);
216
    }
-
 
217
    return ( r ) ;
534
	return (r);
218
}
535
}
219
 
536
 
220
 
537
 
221
/*
538
/*	
222
    COPY A STRING
539
 * APPEND TWO STRINGS	
223
 
540
 *   
224
    This routine allocates space for a copy of the string s and copies
541
 * This routine allocates space for a copy of the string s followed by a copy
-
 
542
 * of the string t and concatenates the strings into this space, placing the
225
    the string into this space.  This copy is returned.
543
 * delimiter character between them. The copy is returned.  E.g.,:	
-
 
544
 *   
-
 
545
 * Given:    "foo" + "bar" + ':'	
-
 
546
 * Returns:  "foo:bar"	
226
*/
547
 */	
227
 
548
 	 	
228
char *string_copy
549
char *	
229
    PROTO_N ( ( s ) )
-
 
230
    PROTO_T ( char *s )
550
string_append(char *s, char *t, char delimeter)	
231
{
551
{	
232
    int n = ( int ) strlen ( s ) ;
552
	int n = (int)strlen(s);	
-
 
553
	int m = (int)strlen(t);	
233
    char *r = string_alloc ( n + 1 ) ;
554
	char *r = string_alloc(n + m + 2);	
234
    IGNORE strcpy ( r, s ) ;
555
	IGNORE strcpy(r, s);	
-
 
556
	*(r + n) = delimeter;	
-
 
557
	IGNORE strcpy(r + n + 1, t);	
235
    return ( r ) ;
558
	return (r);
236
}
559
}
237
 
560
 
238
 
561
 
239
/*
562
/*
240
    COPY TWO STRINGS
-
 
241
 
-
 
242
    This routine allocates space for a copy of the string s followed by
-
 
243
    a copy of the string t and concatenates the strings into this space.
-
 
244
    This copy is returned.
-
 
245
*/
-
 
246
 
-
 
247
char *string_concat
-
 
248
    PROTO_N ( ( s, t ) )
-
 
249
    PROTO_T ( char *s X char *t )
-
 
250
{
-
 
251
    int n = ( int ) strlen ( s ) ;
-
 
252
    int m = ( int ) strlen ( t ) ;
-
 
253
    char *r = string_alloc ( n + m + 1 ) ;
-
 
254
    IGNORE strcpy ( r, s ) ;
-
 
255
    IGNORE strcpy ( r + n, t ) ;
-
 
256
    return ( r ) ;
-
 
257
}
-
 
258
 
-
 
259
 
-
 
260
/*
-
 
261
    TEMPORARY WORK SPACE
563
 * TEMPORARY WORK SPACE
262
 
564
 *
263
    This variable gives a temporary work space of size buffer_size
565
 * This variable gives a temporary work space of size buffer_size (see
264
    (see utility.h) which is used as a scratch work area.
566
 * utility.h) which is used as a scratch work area.
265
*/
567
 */
266
 
568
 
267
char *buffer ;
569
char *buffer;