Warning: Undefined variable $n in /usr/local/www/websvn.planix.org/include/diff_util.php on line 243

Warning: Undefined variable $n in /usr/local/www/websvn.planix.org/include/diff_util.php on line 247

Warning: Undefined variable $m in /usr/local/www/websvn.planix.org/include/diff_util.php on line 251
WebSVN – tendra.SVN – Diff – /branches/tendra5/src/producers/common/parse/file.c – Rev 5 and 6

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
*/
Line 52... Line 82...
52
 
82
 
53
    These are the files from which the lexical routines read their input
83
    These are the files from which the lexical routines read their input
54
    and to which the output routines write.
84
    and to which the output routines write.
55
*/
85
*/
56
 
86
 
57
FILE *input_file = NULL ;
87
FILE *input_file = NULL;
58
FILE *output_file [ OUTPUT_FILES ] = { NULL, NULL, NULL, NULL, NULL } ;
88
FILE *output_file[OUTPUT_FILES] = { NULL, NULL, NULL, NULL, NULL };
59
 
89
 
60
 
90
 
61
/*
91
/*
62
    CURRENT FILE NAMES
92
    CURRENT FILE NAMES
63
 
93
 
Line 65... Line 95...
65
    file name.  This remains constant and is not, for example, changed by
95
    file name.  This remains constant and is not, for example, changed by
66
    #line directives.  Similarly output_name holds the names of the output
96
    #line directives.  Similarly output_name holds the names of the output
67
    files.
97
    files.
68
*/
98
*/
69
 
99
 
70
string input_name = NULL ;
100
string input_name = NULL;
71
string output_name [ OUTPUT_FILES ] = { NULL, NULL, NULL, NULL, NULL } ;
101
string output_name[OUTPUT_FILES] = { NULL, NULL, NULL, NULL, NULL };
72
 
102
 
73
 
103
 
74
/*
104
/*
75
    STANDARD FILE NAME
105
    STANDARD FILE NAME
76
 
106
 
77
    The macro std_file_name checks whether the file name A is the special
107
    The macro std_file_name checks whether the file name A is the special
78
    string "-" used to indicate the standard input or output.  The other
108
    string "-" used to indicate the standard input or output.  The other
79
    macros give the corresponding names used in error reports.
109
    macros give the corresponding names used in error reports.
80
*/
110
*/
81
 
111
 
82
#define std_file_name( A )	ustrseq ( ( A ), "-" )
112
#define std_file_name(A)	ustrseq((A), "-")
83
#define stdin_name		ustrlit ( "<stdin>" )
113
#define stdin_name		ustrlit("<stdin>")
84
#define stdout_name		ustrlit ( "<stdout>" )
114
#define stdout_name		ustrlit("<stdout>")
85
 
115
 
86
 
116
 
87
/*
117
/*
88
    INTERNAL FILE BUFFER
118
    INTERNAL FILE BUFFER
89
 
119
 
90
    This buffer is used as the internal file buffer which is used to hold
120
    This buffer is used as the internal file buffer which is used to hold
91
    any preprocessing directives arising from command-line options.  It
121
    any preprocessing directives arising from command-line options.  It
92
    has an associated dummy file and file name.
122
    has an associated dummy file and file name.
93
*/
123
*/
94
 
124
 
95
BUFFER internal_buff = NULL_buff ;
125
BUFFER internal_buff = NULL_buff;
96
static FILE *internal_file = NULL ;
126
static FILE *internal_file = NULL;
97
static string internal_name = NULL ;
127
static string internal_name = NULL;
98
 
128
 
99
 
129
 
100
/*
130
/*
101
    INCLUDE FILE BUFFER
131
    INCLUDE FILE BUFFER
102
 
132
 
103
    This buffer is used to build up file names when processing #include
133
    This buffer is used to build up file names when processing #include
104
    directives.
134
    directives.
105
*/
135
*/
106
 
136
 
107
BUFFER incl_buff = NULL_buff ;
137
BUFFER incl_buff = NULL_buff;
108
 
138
 
109
 
139
 
110
/*
140
/*
111
    INPUT FLAGS
141
    INPUT FLAGS
112
 
142
 
113
    These flags are used to record changes in the current file location.
143
    These flags are used to record changes in the current file location.
114
*/
144
*/
115
 
145
 
116
unsigned long crt_spaces = 0 ;
146
unsigned long crt_spaces = 0;
117
unsigned long tab_width = 8 ;
147
unsigned long tab_width = 8;
118
int crt_line_changed = 0 ;
148
int crt_line_changed = 0;
119
int crt_file_changed = 0 ;
149
int crt_file_changed = 0;
120
int crt_col_changed = 0 ;
150
int crt_col_changed = 0;
121
int crt_file_type = 0 ;
151
int crt_file_type = 0;
122
int bad_crt_loc = 0 ;
152
int bad_crt_loc = 0;
123
 
153
 
124
 
154
 
125
/*
155
/*
126
    INPUT BUFFERS
156
    INPUT BUFFERS
127
 
157
 
Line 133... Line 163...
133
    the end of the current buffer and the end of the last buffer.
163
    the end of the current buffer and the end of the last buffer.
134
    Characters beyond the end of the buffer hold char_end.
164
    Characters beyond the end of the buffer hold char_end.
135
*/
165
*/
136
 
166
 
137
#define NO_BUFFER		4
167
#define NO_BUFFER		4
138
#define CHAR_SZ			sizeof ( character )
168
#define CHAR_SZ			sizeof(character)
139
#define BUFF_SZ			( ( size_t ) ( BUFSIZ ) )
169
#define BUFF_SZ			((size_t)(BUFSIZ))
140
#define PENDING_SZ		16
170
#define PENDING_SZ		16
141
#define OVERFLOW_SZ		16
171
#define OVERFLOW_SZ		16
142
#define TOTAL_SZ		( PENDING_SZ + BUFF_SZ + OVERFLOW_SZ )
172
#define TOTAL_SZ		(PENDING_SZ + BUFF_SZ + OVERFLOW_SZ)
143
 
173
 
144
typedef struct {
174
typedef struct {
145
    string buff ;
175
	string buff;
146
    string posn ;
176
	string posn;
147
    string end ;
177
	string end;
148
    string eof ;
178
	string eof;
149
    long bytes ;
179
	long bytes;
150
} INPUT_BUFFER ;
180
} INPUT_BUFFER;
151
 
181
 
152
static INPUT_BUFFER input_buff [ NO_BUFFER ] = {
182
static INPUT_BUFFER input_buff[NO_BUFFER] = {
153
    { NULL, NULL, NULL, NULL, 0 },
183
	{ NULL, NULL, NULL, NULL, 0 },
154
    { NULL, NULL, NULL, NULL, 0 },
184
	{ NULL, NULL, NULL, NULL, 0 },
155
    { NULL, NULL, NULL, NULL, 0 },
185
	{ NULL, NULL, NULL, NULL, 0 },
156
    { NULL, NULL, NULL, NULL, 0 }
186
	{ NULL, NULL, NULL, NULL, 0 }
157
} ;
187
};
158
 
188
 
159
string input_start = NULL ;
189
string input_start = NULL;
160
string input_posn = NULL ;
190
string input_posn = NULL;
161
string input_end = NULL ;
191
string input_end = NULL;
162
string input_eof = NULL ;
192
string input_eof = NULL;
163
string input_crt = NULL ;
193
string input_crt = NULL;
164
static long input_bytes = 0 ;
194
static long input_bytes = 0;
165
static int input_special = 0 ;
195
static int input_special = 0;
166
static int started_buff = 0 ;
196
static int started_buff = 0;
167
unsigned long crt_buff_no = 0 ;
197
unsigned long crt_buff_no = 0;
168
 
198
 
169
 
199
 
170
/*
200
/*
171
    IS A FILE NAME A FULL PATHNAME?
201
    IS A FILE NAME A FULL PATHNAME?
172
 
202
 
173
    This routine checks whether the file name nm represents a full
203
    This routine checks whether the file name nm represents a full
174
    pathname.
204
    pathname.
175
*/
205
*/
176
 
206
 
177
int is_full_pathname
-
 
178
    PROTO_N ( ( nm ) )
-
 
179
    PROTO_T ( string nm )
-
 
180
{
-
 
181
    character c = nm [0] ;
-
 
182
    character q = ( character ) drive_sep ;
-
 
183
    if ( c == char_slash ) return ( 1 ) ;
-
 
184
    if ( c && q && nm [1] == q ) {
-
 
185
	/* Allow for DOS drive letters */
-
 
186
	return ( is_alpha_char ( ( unsigned long ) c ) ) ;
-
 
187
    }
-
 
188
    return ( 0 ) ;
-
 
189
}
-
 
190
 
-
 
191
 
-
 
192
/*
207
int
193
    CONVERT A FILE NAME TO STANDARD FORMAT
-
 
194
 
-
 
195
    This routine modifies the file name nm to the standard format with
-
 
196
    sensible forward slashes rather backslashes.
-
 
197
*/
-
 
198
 
-
 
199
string make_pathname
-
 
200
    PROTO_N ( ( nm ) )
-
 
201
    PROTO_T ( string nm )
208
is_full_pathname(string nm)
202
{
209
{
-
 
210
	character c = nm[0];
203
    character q = ( character ) file_sep ;
211
	character q = (character)drive_sep;
204
    if ( q != char_slash ) {
212
	if (c == char_slash) {
205
	string s ;
213
		return(1);
-
 
214
	}
206
	nm = xustrcpy ( nm ) ;
215
	if (c && q && nm[1] == q) {
207
	for ( s = nm ; *s ; s++ ) {
216
		/* Allow for DOS drive letters */
208
	    if ( *s == q ) *s = char_slash ;
217
		return(is_alpha_char((unsigned long)c));
209
	}
218
	}
-
 
219
	return(0);
-
 
220
}
-
 
221
 
-
 
222
 
-
 
223
/*
-
 
224
    CONVERT A FILE NAME TO STANDARD FORMAT
-
 
225
 
-
 
226
    This routine modifies the file name nm to the standard format with
-
 
227
    sensible forward slashes rather backslashes.
-
 
228
*/
-
 
229
 
-
 
230
string
-
 
231
make_pathname(string nm)
-
 
232
{
-
 
233
	character q = (character)file_sep;
-
 
234
	if (q != char_slash) {
-
 
235
		string s;
-
 
236
		nm = xustrcpy(nm);
-
 
237
		for (s = nm; *s; s++) {
-
 
238
			if (*s == q) {
-
 
239
				*s = char_slash;
210
    }
240
			}
-
 
241
		}
-
 
242
	}
211
    return ( nm ) ;
243
	return(nm);
212
}
244
}
213
 
245
 
214
 
246
 
215
/*
247
/*
216
    NORMALISE A FILE NAME
248
    NORMALISE A FILE NAME
217
 
249
 
218
    This routine normalises the file name s by removing any . or ..
250
    This routine normalises the file name s by removing any . or ..
219
    components.  The result is only used in the printing of error
251
    components.  The result is only used in the printing of error
220
    messages so it doesn't matter too much if the result isn't quite
252
    messages so it doesn't matter too much if the result isn't quite
221
    right.
253
    right.
222
*/
254
*/
223
 
255
 
224
static string normalise_pathname
256
static string
225
    PROTO_N ( ( s ) )
-
 
226
    PROTO_T ( string s )
257
normalise_pathname(string s)
227
{
258
{
228
    character c ;
259
	character c;
229
    string p = s ;
260
	string p = s;
230
    int depth = 0 ;
261
	int depth = 0;
231
    int changed = 0 ;
262
	int changed = 0;
232
    BUFFER *bf = clear_buffer ( &incl_buff, NIL ( FILE ) ) ;
263
	BUFFER *bf = clear_buffer(&incl_buff, NIL(FILE));
233
    while ( c = *( p++ ), c != 0 ) {
264
	while (c = *(p++), c != 0) {
234
	if ( c == char_slash ) {
265
		if (c == char_slash) {
235
	    if ( p [0] == char_dot ) {
266
			if (p[0] == char_dot) {
236
		if ( p [1] == char_slash ) {
267
				if (p[1] == char_slash) {
237
		    /* Have '/./' */
268
					/* Have '/./' */
238
		    p++ ;
269
					p++;
239
		    changed = 1 ;
270
					changed = 1;
240
		} else if ( p [1] == char_dot && p [2] == char_slash ) {
271
				} else if (p[1] == char_dot &&
-
 
272
					   p[2] == char_slash) {
241
		    /* Have '/../' */
273
					/* Have '/../' */
242
		    string q = bf->posn ;
274
					string q = bf->posn;
243
		    if ( depth > 0 ) {
275
					if (depth > 0) {
244
			string q0 = bf->start ;
276
						string q0 = bf->start;
245
			*q = 0 ;
277
						*q = 0;
246
			q = ustrrchr ( q0, char_slash ) ;
278
						q = ustrrchr(q0, char_slash);
247
			if ( q && q != q0 ) {
279
						if (q && q != q0) {
248
			    bf->posn = q ;
280
							bf->posn = q;
249
			    p += 2 ;
281
							p += 2;
250
			    changed = 1 ;
282
							changed = 1;
251
			    c = 0 ;
283
							c = 0;
252
			}
284
						}
253
		    }
285
					}
-
 
286
					if (c) {
254
		    if ( c ) bfputc ( bf, ( int ) c ) ;
287
						bfputc(bf, (int)c);
-
 
288
					}
255
		    depth-- ;
289
					depth--;
256
		} else {
290
				} else {
257
		    bfputc ( bf, ( int ) c ) ;
291
					bfputc(bf, (int)c);
258
		    depth++ ;
292
					depth++;
259
		}
293
				}
260
	    } else if ( p [0] == char_slash ) {
294
			} else if (p[0] == char_slash) {
261
		/* Have '//' */
295
				/* Have '//' */
262
		p++ ;
-
 
263
		changed = 1 ;
296
				changed = 1;
264
	    } else {
297
			} else {
265
		bfputc ( bf, ( int ) c ) ;
298
				bfputc(bf, (int)c);
266
		depth++ ;
299
				depth++;
267
	    }
300
			}
268
	} else {
301
		} else {
269
	    bfputc ( bf, ( int ) c ) ;
302
			bfputc(bf, (int)c);
270
	}
303
		}
271
    }
304
	}
272
    bfputc ( bf, 0 ) ;
305
	bfputc(bf, 0);
-
 
306
	if (changed) {
273
    if ( changed ) s = xustrcpy ( bf->start ) ;
307
		s = xustrcpy(bf->start);
-
 
308
	}
274
    return ( s ) ;
309
	return(s);
275
}
310
}
276
 
311
 
277
 
312
 
278
/*
313
/*
279
    SET CURRENT LOCATION
314
    SET CURRENT LOCATION
280
 
315
 
281
    This routine sets the current location from the filename nm.  It returns
316
    This routine sets the current location from the filename nm.  It returns
282
    the result of applying make_pathname to nm.
317
    the result of applying make_pathname to nm.
283
*/
318
*/
284
 
319
 
285
string set_crt_loc
320
string
286
    PROTO_N ( ( nm, special ) )
-
 
287
    PROTO_T ( string nm X int special )
321
set_crt_loc(string nm, int special)
288
{
322
{
289
    string en ;
323
	string en;
290
    unsigned long date ;
324
	unsigned long date;
291
    if ( special ) {
325
	if (special) {
292
	/* Standard input */
326
		/* Standard input */
293
	en = ustrlit ( "" ) ;
327
		en = ustrlit("");
294
	date = 0 ;
328
		date = 0;
295
    } else {
329
	} else {
296
	/* Simple file */
330
		/* Simple file */
297
	STAT_TYPE *fs ;
331
		STAT_TYPE *fs;
298
	STAT_TYPE fstr ;
332
		STAT_TYPE fstr;
299
	nm = make_pathname ( nm ) ;
333
		nm = make_pathname(nm);
300
	en = nm ;
334
		en = nm;
301
	fs = stat_func ( strlit ( nm ), &fstr ) ;
335
		fs = stat_func(strlit(nm), &fstr);
302
	date = stat_date ( fs ) ;
336
		date = stat_date(fs);
303
    }
337
	}
304
    CREATE_loc ( nm, en, nm, NULL, NULL_ptr ( LOCATION ), date, crt_loc ) ;
338
	CREATE_loc(nm, en, nm, NULL, NULL_ptr(LOCATION), date, crt_loc);
305
    return ( nm ) ;
339
	return(nm);
306
}
340
}
307
 
341
 
308
 
342
 
309
/*
343
/*
310
    OPEN INPUT FILE
344
    OPEN INPUT FILE
Line 314... Line 348...
314
    is used.  The file is opened in binary mode if bin is true.  The routine
348
    is used.  The file is opened in binary mode if bin is true.  The routine
315
    also allocates space for each of the buffers above.  The routine returns
349
    also allocates space for each of the buffers above.  The routine returns
316
    1 if the file is opened successfully.
350
    1 if the file is opened successfully.
317
*/
351
*/
318
 
352
 
319
int open_input
353
int
320
    PROTO_N ( ( bin ) )
-
 
321
    PROTO_T ( int bin )
354
open_input(int bin)
322
{
355
{
323
    if ( input_file == NULL ) {
356
	if (input_file == NULL) {
324
	string nm = input_name ;
357
		string nm = input_name;
325
	if ( nm == NULL || std_file_name ( nm ) ) {
358
		if (nm == NULL || std_file_name(nm)) {
326
	    nm = set_crt_loc ( stdin_name, 1 ) ;
359
			nm = set_crt_loc(stdin_name, 1);
327
	    input_special = 1 ;
360
			input_special = 1;
-
 
361
			if (!bin) {
328
	    if ( !bin ) input_file = stdin ;
362
				input_file = stdin;
-
 
363
			}
329
	} else {
364
		} else {
330
	    CONST char *mode = ( bin ? "rb" : "r" ) ;
365
			CONST char *mode = (bin ? "rb" : "r");
331
	    nm = set_crt_loc ( nm, 0 ) ;
366
			nm = set_crt_loc(nm, 0);
332
	    input_special = 0 ;
367
			input_special = 0;
333
	    input_file = fopen ( strlit ( nm ), mode ) ;
368
			input_file = fopen(strlit(nm), mode);
334
	}
369
		}
335
	input_name = nm ;
370
		input_name = nm;
336
	if ( input_file == NULL ) return ( 0 ) ;
371
		if (input_file == NULL) {
-
 
372
			return(0);
-
 
373
		}
337
	if ( !started_buff ) {
374
		if (!started_buff) {
338
	    unsigned i ;
375
			unsigned i;
339
	    for ( i = 0 ; i < NO_BUFFER ; i++ ) {
376
			for (i = 0; i < NO_BUFFER; i++) {
340
		string buff = xmalloc_nof ( character, TOTAL_SZ ) ;
377
				string buff = xmalloc_nof(character, TOTAL_SZ);
341
		input_buff [i].buff = buff ;
378
				input_buff[i].buff = buff;
342
	    }
379
			}
343
	    started_buff = 1 ;
380
			started_buff = 1;
-
 
381
		}
-
 
382
		crt_file_changed = 1;
-
 
383
		crt_line_changed = 1;
-
 
384
		crt_spaces = 0;
344
	}
385
	}
345
	crt_file_changed = 1 ;
-
 
346
	crt_line_changed = 1 ;
-
 
347
	crt_spaces = 0 ;
-
 
348
    }
-
 
349
    return ( 1 ) ;
386
	return(1);
350
}
387
}
351
 
388
 
352
 
389
 
353
/*
390
/*
354
    FREE SPACE ALLOCATED FOR INPUT BUFFERS
391
    FREE SPACE ALLOCATED FOR INPUT BUFFERS
355
 
392
 
356
    This routine frees the memory allocated for the input buffers.
393
    This routine frees the memory allocated for the input buffers.
357
*/
394
*/
358
 
395
 
359
void term_input
396
void
360
    PROTO_Z ()
397
term_input(void)
361
{
398
{
362
    free_buffer ( &incl_buff ) ;
399
	free_buffer(&incl_buff);
363
    free_buffer ( &internal_buff ) ;
400
	free_buffer(&internal_buff);
364
    if ( started_buff ) {
401
	if (started_buff) {
365
	unsigned i ;
402
		unsigned i;
366
	for ( i = 0 ; i < NO_BUFFER ; i++ ) {
403
		for (i = 0; i < NO_BUFFER; i++) {
367
	    xfree_nof ( input_buff [i].buff ) ;
404
			xfree_nof(input_buff[i].buff);
368
	    input_buff [i].buff = NULL ;
405
			input_buff[i].buff = NULL;
-
 
406
		}
-
 
407
		started_buff = 0;
369
	}
408
	}
370
	started_buff = 0 ;
-
 
371
    }
-
 
372
    input_start = NULL ;
409
	input_start = NULL;
373
    input_bytes = 0 ;
410
	input_bytes = 0;
374
    return ;
411
	return;
375
}
412
}
376
 
413
 
377
 
414
 
378
/*
415
/*
379
    OPEN OUTPUT FILE
416
    OPEN OUTPUT FILE
380
 
417
 
381
    This routine opens the nth output file, using output_name as the name
418
    This routine opens the nth output file, using output_name as the name
382
    of the file to be opened.  If this is the null string then the standard
419
    of the file to be opened.  If this is the null string then the standard
383
    output is used.  The file is opened in binary mode if bin is true.  The
420
    output is used.  The file is opened in binary mode if bin is true.  The
384
    routine returns 1 if the file is opened successfully.
421
    routine returns 1 if the file is opened successfully.
385
*/
422
*/
386
 
423
 
387
int open_output
424
int
388
    PROTO_N ( ( n, bin ) )
-
 
389
    PROTO_T ( int n X int bin )
425
open_output(int n, int bin)
390
{
426
{
391
    if ( output_file [n] == NULL ) {
427
	if (output_file[n] == NULL) {
392
	string nm = output_name [n] ;
428
		string nm = output_name[n];
393
	if ( nm == NULL || std_file_name ( nm ) ) {
429
		if (nm == NULL || std_file_name(nm)) {
394
	    nm = stdout_name ;
430
			nm = stdout_name;
395
	    output_name [n] = nm ;
431
			output_name[n] = nm;
396
	    output_file [n] = stdout ;
432
			output_file[n] = stdout;
-
 
433
			if (bin) {
397
	    if ( bin ) return ( 0 ) ;
434
				return(0);
-
 
435
			}
398
	} else {
436
		} else {
399
	    CONST char *mode = ( bin ? "wb" : "w" ) ;
437
			CONST char *mode = (bin ? "wb" : "w");
400
	    nm = make_pathname ( nm ) ;
438
			nm = make_pathname(nm);
401
	    output_name [n] = nm ;
439
			output_name[n] = nm;
402
	    output_file [n] = fopen ( strlit ( nm ), mode ) ;
440
			output_file[n] = fopen(strlit(nm), mode);
403
	    if ( output_file [n] == NULL ) return ( 0 ) ;
441
			if (output_file[n] == NULL) {
-
 
442
				return(0);
-
 
443
			}
404
	}
444
		}
405
    }
445
	}
406
    return ( 1 ) ;
446
	return(1);
407
}
447
}
408
 
448
 
409
 
449
 
410
/*
450
/*
411
    CLOSE INPUT FILE
451
    CLOSE INPUT FILE
412
 
452
 
413
    This routine closes the input file.
453
    This routine closes the input file.
414
*/
454
*/
415
 
455
 
416
void close_input
456
void
417
    PROTO_Z ()
457
close_input(void)
418
{
458
{
419
    FILE *fin = input_file ;
459
	FILE *fin = input_file;
420
    if ( fin && !input_special ) {
460
	if (fin && !input_special) {
421
	if ( ferror ( fin ) || fclose ( fin ) ) {
461
		if (ferror(fin) || fclose(fin)) {
422
	    char *nm = strlit ( input_name ) ;
462
			char *nm = strlit(input_name);
423
	    error ( ERROR_INTERNAL, "Reading error in '%s'", nm ) ;
463
			error(ERROR_INTERNAL, "Reading error in '%s'", nm);
-
 
464
		}
424
	}
465
	}
425
    }
-
 
426
    input_file = NULL ;
466
	input_file = NULL;
427
    return ;
467
	return;
428
}
468
}
429
 
469
 
430
 
470
 
431
/*
471
/*
432
    CLOSE OUTPUT FILE
472
    CLOSE OUTPUT FILE
433
 
473
 
434
    This routine closes the nth output file.
474
    This routine closes the nth output file.
435
*/
475
*/
436
 
476
 
437
void close_output
477
void
438
    PROTO_N ( ( n ) )
-
 
439
    PROTO_T ( int n )
478
close_output(int n)
440
{
479
{
441
    FILE *fout = output_file [n] ;
480
	FILE *fout = output_file[n];
442
    if ( fout && fout != stdout && fout != stderr ) {
481
	if (fout && fout != stdout && fout != stderr) {
443
	if ( ferror ( fout ) || fclose ( fout ) ) {
482
		if (ferror(fout) || fclose(fout)) {
444
	    char *nm = strlit ( output_name [n] ) ;
483
			char *nm = strlit(output_name[n]);
445
	    error ( ERROR_INTERNAL, "Writing error in '%s'", nm ) ;
484
			error(ERROR_INTERNAL, "Writing error in '%s'", nm);
-
 
485
		}
446
	}
486
	}
447
    }
-
 
448
    output_file [n] = NULL ;
487
	output_file[n] = NULL;
449
    return ;
488
	return;
450
}
489
}
451
 
490
 
452
 
491
 
453
/*
492
/*
454
    FILL THE INPUT BUFFER
493
    FILL THE INPUT BUFFER
455
 
494
 
456
    This routine fills the current input buffer from the input file, setting
495
    This routine fills the current input buffer from the input file, setting
457
    up the associated buffer pointers.  It returns NULL to indicate that no
496
    up the associated buffer pointers.  It returns NULL to indicate that no
458
    bytes were read.
497
    bytes were read.
459
*/
498
*/
460
 
499
 
461
static string fill_buffer
500
static string
462
    PROTO_Z ()
501
fill_buffer(void)
463
{
502
{
464
    size_t i, n ;
503
	size_t i, n;
465
    size_t m = TOTAL_SZ ;
504
	size_t m = TOTAL_SZ;
466
    FILE *f = input_file ;
505
	FILE *f = input_file;
467
    string p = input_start ;
506
	string p = input_start;
468
 
507
 
469
    /* Fill the buffer from the input file */
508
	/* Fill the buffer from the input file */
470
    if ( f == internal_file ) {
509
	if (f == internal_file) {
471
	n = ( size_t ) bfread ( &internal_buff, p, ( gen_size ) BUFF_SZ ) ;
510
		n = (size_t)bfread(&internal_buff, p, (gen_size)BUFF_SZ);
472
	if ( n < BUFF_SZ ) m = n ;
511
		if (n < BUFF_SZ)m = n;
473
    } else if ( f ) {
512
	} else if (f) {
474
	n = fread ( ( gen_ptr ) p, CHAR_SZ, BUFF_SZ, f ) ;
513
		n = fread((gen_ptr)p, CHAR_SZ, BUFF_SZ, f);
475
	if ( n < BUFF_SZ ) m = n ;
514
		if (n < BUFF_SZ)m = n;
476
    } else {
515
	} else {
477
	n = 0 ;
516
		n = 0;
478
	m = 0 ;
517
		m = 0;
479
    }
518
	}
480
    input_posn = p ;
519
	input_posn = p;
481
    input_end = p + n ;
520
	input_end = p + n;
482
    input_eof = p + m ;
521
	input_eof = p + m;
483
    input_crt = p ;
522
	input_crt = p;
484
    input_bytes += ( long ) n ;
523
	input_bytes += (long)n;
485
 
524
 
486
    /* Fill the overflow area with char_end's */
525
	/* Fill the overflow area with char_end's */
487
    for ( i = n ; i < n + OVERFLOW_SZ ; i++ ) p [i] = char_end ;
526
	for (i = n; i < n + OVERFLOW_SZ; i++) {
-
 
527
		p[i] = char_end;
-
 
528
	}
488
    if ( n == 0 ) p = NULL ;
529
	if (n == 0) {
-
 
530
		p = NULL;
-
 
531
	}
489
    return ( p ) ;
532
	return(p);
490
}
533
}
491
 
534
 
492
 
535
 
493
/*
536
/*
494
    INITIALISE BUFFER
537
    INITIALISE BUFFER
495
 
538
 
496
    This routine initialises buffer number i and makes it into the current
539
    This routine initialises buffer number i and makes it into the current
497
    buffer.  It returns NULL to indicate an empty file.
540
    buffer.  It returns NULL to indicate an empty file.
498
*/
541
*/
499
 
542
 
500
string init_buffer
543
string
501
    PROTO_N ( ( i ) )
-
 
502
    PROTO_T ( unsigned long i )
544
init_buffer(unsigned long i)
503
{
545
{
504
    crt_buff_no = i ;
546
	crt_buff_no = i;
505
    input_start = input_buff [i].buff + PENDING_SZ ;
547
	input_start = input_buff[i].buff + PENDING_SZ;
506
    input_bytes = 0 ;
548
	input_bytes = 0;
507
    return ( fill_buffer () ) ;
549
	return(fill_buffer());
508
}
550
}
509
 
551
 
510
 
552
 
511
/*
553
/*
512
    RESUME BUFFER
554
    RESUME BUFFER
513
 
555
 
514
    This routine makes buffer number i into the current buffer by restoring
556
    This routine makes buffer number i into the current buffer by restoring
515
    the main values from those stored in the buffer.
557
    the main values from those stored in the buffer.
516
*/
558
*/
517
 
559
 
518
static void resume_buffer
560
static void
519
    PROTO_N ( ( i ) )
-
 
520
    PROTO_T ( unsigned long i )
561
resume_buffer(unsigned long i)
521
{
562
{
522
    INPUT_BUFFER *p = input_buff + i ;
563
	INPUT_BUFFER *p = input_buff + i;
523
    input_start = p->buff + PENDING_SZ ;
564
	input_start = p->buff + PENDING_SZ;
524
    input_posn = p->posn ;
565
	input_posn = p->posn;
525
    input_end = p->end ;
566
	input_end = p->end;
526
    input_eof = p->eof ;
567
	input_eof = p->eof;
527
    input_crt = p->posn ;
568
	input_crt = p->posn;
528
    input_bytes = p->bytes ;
569
	input_bytes = p->bytes;
529
    return ;
570
	return;
530
}
571
}
531
 
572
 
532
 
573
 
533
/*
574
/*
534
    FIND CURRENT FILE POSITION
575
    FIND CURRENT FILE POSITION
535
 
576
 
536
    This routine finds the current file position and updates the pointers
577
    This routine finds the current file position and updates the pointers
537
    in buffer i (which should be the current buffer number).
578
    in buffer i (which should be the current buffer number).
538
*/
579
*/
539
 
580
 
540
long tell_buffer
581
long
541
    PROTO_N ( ( i ) )
-
 
542
    PROTO_T ( unsigned long i )
582
tell_buffer(unsigned long i)
543
{
583
{
544
    long bytes_left ;
584
	long bytes_left;
545
    INPUT_BUFFER *p = input_buff + i ;
585
	INPUT_BUFFER *p = input_buff + i;
546
    p->posn = input_posn ;
586
	p->posn = input_posn;
547
    p->end = input_end ;
587
	p->end = input_end;
548
    p->eof = input_eof ;
588
	p->eof = input_eof;
549
    p->bytes = input_bytes ;
589
	p->bytes = input_bytes;
550
    bytes_left = ( long ) ( input_end - input_posn ) ;
590
	bytes_left = (long)(input_end - input_posn);
551
    if ( bytes_left < 0 ) bytes_left = 0 ;
591
	if (bytes_left < 0) {
-
 
592
		bytes_left = 0;
-
 
593
	}
552
    return ( input_bytes - bytes_left ) ;
594
	return(input_bytes - bytes_left);
553
}
595
}
554
 
596
 
555
 
597
 
556
/*
598
/*
557
    SET CURRENT FILE POSITION
599
    SET CURRENT FILE POSITION
558
 
600
 
559
    This routine sets the current file position to n and the current buffer
601
    This routine sets the current file position to n and the current buffer
560
    to number i.  started is false if the file has just been opened.
602
    to number i.  started is false if the file has just been opened.
561
*/
603
*/
562
 
604
 
563
void seek_buffer
605
void
564
    PROTO_N ( ( i, n, started ) )
-
 
565
    PROTO_T ( unsigned long i X long n X int started )
606
seek_buffer(unsigned long i, long n, int started)
566
{
607
{
567
    int s ;
608
	int s;
568
    FILE *f = input_file ;
609
	FILE *f = input_file;
569
    if ( f == NULL ) return ;
610
	if (f == NULL) {
-
 
611
		return;
-
 
612
	}
570
    if ( f == internal_file ) {
613
	if (f == internal_file) {
571
	if ( started ) {
614
		if (started) {
572
	    /* Reset position to start of buffer */
615
			/* Reset position to start of buffer */
573
	    internal_buff.posn = internal_buff.start ;
616
			internal_buff.posn = internal_buff.start;
574
	    started = 0 ;
617
			started = 0;
575
	}
618
		}
576
	s = 0 ;
619
		s = 0;
577
    } else {
620
	} else {
578
	s = file_seek ( f, n ) ;
621
		s = file_seek(f, n);
579
    }
622
	}
580
    if ( s == 0 ) {
623
	if (s == 0) {
581
	/* Perform seek by hand */
624
		/* Perform seek by hand */
582
	string p ;
625
		string p;
583
	if ( started ) {
626
		if (started) {
584
	    /* Rewind to start of file */
627
			/* Rewind to start of file */
585
	    IGNORE file_seek ( f, ( long ) 0 ) ;
628
			IGNORE file_seek(f, (long)0);
586
	}
629
		}
587
	p = init_buffer ( i ) ;
630
		p = init_buffer(i);
588
	while ( input_bytes < n ) {
631
		while (input_bytes < n) {
589
	    if ( p == NULL ) {
632
			if (p == NULL) {
590
		char *nm = strlit ( input_name ) ;
633
				char *nm = strlit(input_name);
591
		CONST char *msg = "Internal seek error in '%s'" ;
634
				CONST char *msg = "Internal seek error in '%s'";
592
		error ( ERROR_INTERNAL, msg, nm ) ;
635
				error(ERROR_INTERNAL, msg, nm);
593
		return ;
636
				return;
594
	    }
637
			}
595
	    p = fill_buffer () ;
638
			p = fill_buffer();
596
	}
639
		}
597
	input_posn = input_end - ( input_bytes - n ) ;
640
		input_posn = input_end - (input_bytes - n);
598
	input_crt = input_posn ;
641
		input_crt = input_posn;
599
    } else {
642
	} else {
600
	if ( s == -1 ) {
643
		if (s == -1) {
601
	    char *nm = strlit ( input_name ) ;
644
			char *nm = strlit(input_name);
602
	    CONST char *msg = "Internal seek error in '%s'" ;
645
			CONST char *msg = "Internal seek error in '%s'";
603
	    error ( ERROR_INTERNAL, msg, nm ) ;
646
			error(ERROR_INTERNAL, msg, nm);
604
	}
647
		}
605
	input_start = input_buff [i].buff + PENDING_SZ ;
648
		input_start = input_buff[i].buff + PENDING_SZ;
606
	input_bytes = n ;
649
		input_bytes = n;
607
	IGNORE fill_buffer () ;
650
		IGNORE fill_buffer();
608
    }
651
	}
609
    return ;
652
	return;
610
}
653
}
611
 
654
 
612
 
655
 
613
/*
656
/*
614
    UPDATE THE CURRENT COLUMN POSITION
657
    UPDATE THE CURRENT COLUMN POSITION
615
 
658
 
616
    The current column position is only updated at convenient junctures.
659
    The current column position is only updated at convenient junctures.
617
    The variable input_crt is used to keep track of the last such location.
660
    The variable input_crt is used to keep track of the last such location.
618
*/
661
*/
619
 
662
 
620
void update_column
663
void
621
    PROTO_Z ()
664
update_column(void)
622
{
665
{
623
    string p = input_posn ;
666
	string p = input_posn;
624
    if ( p ) {
667
	if (p) {
625
	unsigned long n = ( unsigned long ) ( p - input_crt ) ;
668
		unsigned long n = (unsigned long)(p - input_crt);
626
	if ( n ) {
669
		if (n) {
627
	    crt_loc.column += n ;
670
			crt_loc.column += n;
628
	    input_crt = p ;
671
			input_crt = p;
629
	}
672
		}
630
    }
673
	}
631
    return ;
674
	return;
632
}
675
}
633
 
676
 
634
 
677
 
635
/*
678
/*
636
    REFILL THE INPUT BUFFER
679
    REFILL THE INPUT BUFFER
637
 
680
 
638
    This routine refills the input buffer, returning the first character.
681
    This routine refills the input buffer, returning the first character.
639
    It is called whenever the next character in the buffer is char_end.
682
    It is called whenever the next character in the buffer is char_end.
640
    It is possible that the character is really char_end, in which case
683
    It is possible that the character is really char_end, in which case
641
    this is returned.  Otherwise the buffer is refilled.  Note that in order
684
    this is returned.  Otherwise the buffer is refilled.  Note that in order
642
    for unread_char to work correctly with char_eof, ( char_eof & 0xff )
685
    for unread_char to work correctly with char_eof, ( char_eof & 0xff )
643
    must equal char_end.
686
    must equal char_end.
644
*/
687
*/
645
 
688
 
646
int refill_char
689
int
647
    PROTO_Z ()
690
refill_char(void)
648
{
691
{
649
    int c ;
692
	int c;
650
    update_column () ;
693
	update_column();
651
    do {
694
	do {
652
	string p = input_posn ;
695
		string p = input_posn;
653
	if ( p <= input_end ) return ( char_end ) ;
696
		if (p <= input_end) {
-
 
697
			return(char_end);
-
 
698
		}
654
	if ( p > input_eof ) return ( char_eof ) ;
699
		if (p > input_eof) {
-
 
700
			return(char_eof);
-
 
701
		}
655
	crt_loc.column += ( unsigned long ) ( p - input_crt ) ;
702
		crt_loc.column += (unsigned long)(p - input_crt);
656
	IGNORE fill_buffer () ;
703
		IGNORE fill_buffer();
657
	c = next_char () ;
704
		c = next_char();
658
    } while ( c == char_end ) ;
705
	} while (c == char_end);
659
    input_crt = input_posn ;
706
	input_crt = input_posn;
660
    return ( c ) ;
707
	return(c);
661
}
708
}
662
 
709
 
663
 
710
 
664
/*
711
/*
665
    INCLUDE FILE SEARCH PATH
712
    INCLUDE FILE SEARCH PATH
Line 668... Line 715...
668
    #include'd files.  The variable crt_dir_path is set after each #include
715
    #include'd files.  The variable crt_dir_path is set after each #include
669
    directive to the position in the path after that at which the included
716
    directive to the position in the path after that at which the included
670
    file was found.
717
    file was found.
671
*/
718
*/
672
 
719
 
673
INCL_DIR *dir_path = NULL ;
720
INCL_DIR *dir_path = NULL;
674
static INCL_DIR *crt_dir_path = NULL ;
721
static INCL_DIR *crt_dir_path = NULL;
675
static INCL_DIR *crt_found_path = NULL ;
722
static INCL_DIR *crt_found_path = NULL;
676
 
723
 
677
 
724
 
678
/*
725
/*
679
    FIND A NAMED DIRECTORY
726
    FIND A NAMED DIRECTORY
680
 
727
 
681
    This routine looks up a named directory called nm.  It returns the
728
    This routine looks up a named directory called nm.  It returns the
682
    corresponding directory structure, or the null pointer if nm is not
729
    corresponding directory structure, or the null pointer if nm is not
683
    defined.
730
    defined.
684
*/
731
*/
685
 
732
 
686
static INCL_DIR *find_directory
733
static INCL_DIR *
687
    PROTO_N ( ( nm ) )
-
 
688
    PROTO_T ( string nm )
734
find_directory(string nm)
689
{
735
{
690
    INCL_DIR *p = dir_path ;
736
	INCL_DIR *p = dir_path;
691
    while ( p != NULL ) {
737
	while (p != NULL) {
692
	string s = p->name ;
738
		string s = p->name;
693
	if ( s && ustreq ( s, nm ) ) return ( p ) ;
739
		if (s && ustreq(s, nm)) {
-
 
740
			return(p);
-
 
741
		}
694
	p = p->next ;
742
		p = p->next;
695
    }
743
	}
696
    return ( NULL ) ;
744
	return(NULL);
697
}
745
}
698
 
746
 
699
 
747
 
700
/*
748
/*
701
    ADD A DIRECTORY TO THE SEARCH PATH
749
    ADD A DIRECTORY TO THE SEARCH PATH
702
 
750
 
703
    This routine adds the directory dir with associated name nm to the
751
    This routine adds the directory dir with associated name nm to the
704
    include file search path.
752
    include file search path.
705
*/
753
*/
706
 
754
 
707
void add_directory
755
void
708
    PROTO_N ( ( dir, nm ) )
-
 
709
    PROTO_T ( string dir X string nm )
756
add_directory(string dir, string nm)
710
{
757
{
711
    INCL_DIR *p = dir_path ;
758
	INCL_DIR *p = dir_path;
712
    INCL_DIR *q = xmalloc_one ( INCL_DIR ) ;
759
	INCL_DIR *q = xmalloc_one(INCL_DIR);
713
    if ( nm && find_directory ( nm ) ) {
760
	if (nm && find_directory(nm)) {
714
	char *s = strlit ( nm ) ;
761
		char *s = strlit(nm);
715
	error ( ERROR_WARNING, "Directory '%s' already defined", s ) ;
762
		error(ERROR_WARNING, "Directory '%s' already defined", s);
716
	nm = NULL ;
763
		nm = NULL;
717
    }
764
	}
718
    q->path = make_pathname ( dir ) ;
765
	q->path = make_pathname(dir);
719
    q->name = nm ;
766
	q->name = nm;
720
    q->mode = NULL ;
767
	q->mode = NULL;
721
    q->no = LINK_NONE ;
768
	q->no = LINK_NONE;
722
    q->next = NULL ;
769
	q->next = NULL;
723
    if ( p == NULL ) {
770
	if (p == NULL) {
724
	dir_path = q ;
771
		dir_path = q;
725
	crt_dir_path = q ;
772
		crt_dir_path = q;
726
    } else {
773
	} else {
727
	while ( p->next ) p = p->next ;
774
		while (p->next) {
-
 
775
			p = p->next;
-
 
776
		}
728
	p->next = q ;
777
		p->next = q;
729
    }
778
	}
730
    return ;
779
	return;
731
}
780
}
732
 
781
 
733
 
782
 
734
/*
783
/*
735
    SET A DIRECTORY COMPILATION MODE
784
    SET A DIRECTORY COMPILATION MODE
736
 
785
 
737
    This routine sets the compilation mode for the directory named nm
786
    This routine sets the compilation mode for the directory named nm
738
    to be p.
787
    to be p.
739
*/
788
*/
740
 
789
 
741
void directory_mode
790
void
742
    PROTO_N ( ( nm, p ) )
-
 
743
    PROTO_T ( string nm X OPTIONS *p )
791
directory_mode(string nm, OPTIONS *p)
744
{
792
{
745
    INCL_DIR *q = find_directory ( nm ) ;
793
	INCL_DIR *q = find_directory(nm);
746
    if ( q ) {
794
	if (q) {
747
	if ( q->mode ) {
795
		if (q->mode) {
748
	    report ( preproc_loc, ERR_pragma_dir_mode ( nm ) ) ;
796
			report(preproc_loc, ERR_pragma_dir_mode(nm));
-
 
797
		}
-
 
798
		if (p) {
-
 
799
			q->mode = p;
-
 
800
		}
-
 
801
	} else {
-
 
802
		report(preproc_loc, ERR_pragma_dir_undef(nm));
749
	}
803
	}
750
	if ( p ) q->mode = p ;
-
 
751
    } else {
-
 
752
	report ( preproc_loc, ERR_pragma_dir_undef ( nm ) ) ;
-
 
753
    }
-
 
754
    return ;
804
	return;
755
}
805
}
756
 
806
 
757
 
807
 
758
/*
808
/*
759
    LISTS OF START-UP AND END-UP FILES
809
    LISTS OF START-UP AND END-UP FILES
760
 
810
 
761
    These variables give the lists of start-up and end-up files.  These
811
    These variables give the lists of start-up and end-up files.  These
762
    are equivalent to #include "file" directives at respectively the start
812
    are equivalent to #include "file" directives at respectively the start
763
    and the end of the main include file.
813
    and the end of the main include file.
764
*/
814
*/
765
 
815
 
766
LIST ( string ) startup_files = NULL_list ( string ) ;
816
LIST(string)startup_files = NULL_list(string);
767
LIST ( string ) endup_files = NULL_list ( string ) ;
817
LIST(string)endup_files = NULL_list(string);
768
 
818
 
769
 
819
 
770
/*
820
/*
771
    SET UP INTERNAL START-UP FILE
821
    SET UP INTERNAL START-UP FILE
772
 
822
 
773
    This routine sets up the built-in internal start-up file.
823
    This routine sets up the built-in internal start-up file.
774
*/
824
*/
775
 
825
 
-
 
826
void
776
void builtin_startup
827
builtin_startup(void)
777
    PROTO_Z ()
-
 
778
{
828
{
779
    BUFFER *bf = &internal_buff ;
829
	BUFFER *bf = &internal_buff;
780
    internal_name = DEREF_string ( posn_file ( crt_loc.posn ) ) ;
830
	internal_name = DEREF_string(posn_file(crt_loc.posn));
781
    internal_file = xmalloc_one ( FILE ) ;
831
	internal_file = xmalloc_one(FILE *);
782
    if ( bf->posn != bf->start ) {
832
	if (bf->posn != bf->start) {
783
	/* Add to list of start-up files if necessary */
833
		/* Add to list of start-up files if necessary */
784
	CONS_string ( internal_name, startup_files, startup_files ) ;
834
		CONS_string(internal_name, startup_files, startup_files);
785
	bf->end = bf->posn ;
835
		bf->end = bf->posn;
786
	bf->posn = bf->start ;
836
		bf->posn = bf->start;
787
    }
837
	}
788
    return ;
838
	return;
789
}
839
}
790
 
840
 
791
 
841
 
792
/*
842
/*
793
    OPEN NEXT START-UP FILE
843
    OPEN NEXT START-UP FILE
794
 
844
 
795
    This routine opens the next start-up file.  It continues trying until
845
    This routine opens the next start-up file.  It continues trying until
796
    a start-up file is successfully opened or there are no start-up files
846
    a start-up file is successfully opened or there are no start-up files
797
    left.
847
    left.
798
*/
848
*/
799
 
849
 
800
void open_startup
850
void
801
    PROTO_Z ()
851
open_startup(void)
802
{
852
{
803
    LIST ( string ) p = startup_files ;
853
	LIST(string)p = startup_files;
804
    while ( !IS_NULL_list ( p ) ) {
854
	while (!IS_NULL_list(p)) {
805
	string fn = DEREF_string ( HEAD_list ( p ) ) ;
855
		string fn = DEREF_string(HEAD_list(p));
806
	p = TAIL_list ( p ) ;
856
		p = TAIL_list(p);
807
	startup_files = p ;
857
		startup_files = p;
808
	preproc_loc = crt_loc ;
858
		preproc_loc = crt_loc;
809
	crt_file_type = 1 ;
859
		crt_file_type = 1;
810
	if ( start_include ( fn, char_quote, 2, 0 ) ) return ;
860
		if (start_include(fn, char_quote, 2, 0)) {
-
 
861
			return;
811
    }
862
		}
-
 
863
	}
812
    crt_file_type = 0 ;
864
	crt_file_type = 0;
813
    return ;
865
	return;
814
}
866
}
815
 
867
 
816
 
868
 
817
/*
869
/*
818
    LIST OF INCLUDED FILES
870
    LIST OF INCLUDED FILES
Line 820... Line 872...
820
    This list is used to record all the files included plus the position
872
    This list is used to record all the files included plus the position
821
    of the current file within this list.
873
    of the current file within this list.
822
*/
874
*/
823
 
875
 
824
typedef struct incl_file_tag {
876
typedef struct incl_file_tag {
825
    string name ;
877
	string name;
826
    int imported ;
878
	int imported;
827
    HASHID macro ;
879
	HASHID macro;
828
    unsigned test ;
880
	unsigned test;
829
    int state ;
881
	int state;
830
    PTR ( LOCATION ) from ;
882
	PTR(LOCATION)from;
831
    STAT_TYPE *data ;
883
	STAT_TYPE *data;
832
    STAT_TYPE data_ref ;
884
	STAT_TYPE data_ref;
833
    struct incl_file_tag *next ;
885
	struct incl_file_tag *next;
834
} INCL_FILE ;
886
} INCL_FILE;
835
 
887
 
836
static INCL_FILE *included_files = NULL ;
888
static INCL_FILE *included_files = NULL;
837
static INCL_FILE *crt_included_file = NULL ;
889
static INCL_FILE *crt_included_file = NULL;
838
 
890
 
839
 
891
 
840
/*
892
/*
841
    TABLE OF INCLUSIONS
893
    TABLE OF INCLUSIONS
842
 
894
 
843
    This table is used to hold the file positions for all the currently
895
    This table is used to hold the file positions for all the currently
844
    active #include directives.  Note that this is done as a finite
896
    active #include directives.  Note that this is done as a finite
845
    (but hopefully sufficiently large) array to detect recursive
897
    (but hopefully sufficiently large) array to detect recursive
846
    inclusions.
898
    inclusions.
847
*/
899
*/
848
 
900
 
849
typedef struct {
901
typedef struct {
850
    string name ;
902
	string name;
851
    FILE *fileptr ;
903
	FILE *fileptr;
852
    long offset ;
904
	long offset;
853
    int special ;
905
	int special;
854
    int startup ;
906
	int startup;
855
    int interface ;
907
	int interface;
856
    OPTIONS *mode ;
908
	OPTIONS *mode;
857
    INCL_DIR *path ;
909
	INCL_DIR *path;
858
    INCL_DIR *found ;
910
	INCL_DIR *found;
859
    INCL_FILE *incl ;
911
	INCL_FILE *incl;
860
} INCL_BUFF ;
912
} INCL_BUFF;
861
 
913
 
862
#define MAX_INCL_DEPTH		256
914
#define MAX_INCL_DEPTH		256
863
 
915
 
864
static INCL_BUFF position_array [ MAX_INCL_DEPTH ] ;
916
static INCL_BUFF position_array[MAX_INCL_DEPTH];
865
static INCL_BUFF *position = position_array ;
917
static INCL_BUFF *position = position_array;
866
static unsigned long position_size = MAX_INCL_DEPTH ;
918
static unsigned long position_size = MAX_INCL_DEPTH;
867
 
919
 
868
 
920
 
869
/*
921
/*
870
    SIMPLE INCLUSION DEPTH
922
    SIMPLE INCLUSION DEPTH
871
 
923
 
872
    There are two approaches to suspending the current file - either
924
    There are two approaches to suspending the current file - either
873
    leaving the file open or closing it and reopening it later.  The
925
    leaving the file open or closing it and reopening it later.  The
874
    latter is more efficient, but is limited by the maximum number of
926
    latter is more efficient, but is limited by the maximum number of
875
    files which can be opened at one time (FOPEN_MAX).  Therefore this
927
    files which can be opened at one time (FOPEN_MAX).  Therefore this
876
    strategy is only used for this number of files.  Note that FOPEN_MAX
928
    strategy is only used for this number of files.  Note that FOPEN_MAX
877
    is at least 8 (including the 3 standard files).
929
    is at least 8 (including the 3 standard files).
878
*/
930
*/
879
 
931
 
880
#define LAST_BUFFER_NO		( ( unsigned long ) ( NO_BUFFER - 1 ) )
932
#define LAST_BUFFER_NO		((unsigned long)(NO_BUFFER - 1))
881
#define SIMPLE_INCL_DEPTH	LAST_BUFFER_NO
933
#define SIMPLE_INCL_DEPTH	LAST_BUFFER_NO
882
 
934
 
883
 
935
 
884
/*
936
/*
885
    SET MAXIMUM INCLUDE DEPTH
937
    SET MAXIMUM INCLUDE DEPTH
886
 
938
 
887
    This routine sets the maximum include file depth to n.
939
    This routine sets the maximum include file depth to n.
888
*/
940
*/
889
 
941
 
890
void set_incl_depth
942
void
891
    PROTO_N ( ( n ) )
-
 
892
    PROTO_T ( unsigned long n )
943
set_incl_depth(unsigned long n)
893
{
944
{
894
    if ( n > 10000 ) n = 10000 ;
945
	if (n > 10000) {
-
 
946
		n = 10000;
-
 
947
	}
895
    if ( n > position_size ) {
948
	if (n > position_size) {
896
	/* Allocate more space if necessary */
949
		/* Allocate more space if necessary */
897
	unsigned long i, m ;
950
		unsigned long i, m;
898
	INCL_BUFF *p = xmalloc_nof ( INCL_BUFF, n ) ;
951
		INCL_BUFF *p = xmalloc_nof(INCL_BUFF, n);
899
	INCL_BUFF *q = position ;
952
		INCL_BUFF *q = position;
900
	m = crt_option_value ( OPT_VAL_include_depth ) ;
953
		m = crt_option_value(OPT_VAL_include_depth);
901
	for ( i = 0 ; i < m ; i++ ) p [i] = q [i] ;
954
		for (i = 0; i < m; i++) {
-
 
955
			p[i] = q[i];
-
 
956
		}
902
	position_size = n ;
957
		position_size = n;
903
	position = p ;
958
		position = p;
904
	if ( q != position_array ) xfree_nof ( q ) ;
959
		if (q != position_array) {
-
 
960
			xfree_nof(q);
905
    }
961
		}
-
 
962
	}
906
    option_value ( OPT_VAL_include_depth ) = n ;
963
	option_value(OPT_VAL_include_depth) = n;
907
    return ;
964
	return;
908
}
965
}
909
 
966
 
910
 
967
 
911
/*
968
/*
912
    CHECK WHETHER A FILE HAS ALREADY BEEN INCLUDED
969
    CHECK WHETHER A FILE HAS ALREADY BEEN INCLUDED
Line 915... Line 972...
915
    statistics fs has already been included and does not need to be
972
    statistics fs has already been included and does not need to be
916
    included again.  It also sets crt_included_file.  st is as in
973
    included again.  It also sets crt_included_file.  st is as in
917
    start_include.
974
    start_include.
918
*/
975
*/
919
 
976
 
920
int already_included
977
int
921
    PROTO_N ( ( nm, fs, st ) )
-
 
922
    PROTO_T ( string nm X STAT_TYPE *fs X int st )
978
already_included(string nm, STAT_TYPE *fs, int st)
923
{
979
{
924
    INCL_FILE *p = included_files ;
980
	INCL_FILE *p = included_files;
925
    while ( p != NULL ) {
981
	while (p != NULL) {
926
	int ok ;
982
		int ok;
927
	if ( ustreq ( nm, p->name ) && st != 4 ) {
983
		if (ustreq(nm, p->name) && st != 4) {
928
	    /* Check file names */
984
			/* Check file names */
929
	    ok = 1 ;
985
			ok = 1;
-
 
986
		} else {
-
 
987
			/* Check file statistics */
-
 
988
			ok = stat_equal(fs, p->data);
-
 
989
		}
-
 
990
		if (ok) {
-
 
991
			/* Check matching file */
-
 
992
			if (st == 4) {
-
 
993
				/* Simple enquiry */
-
 
994
				return(1);
-
 
995
			}
-
 
996
			crt_included_file = p;
-
 
997
			if (st == 1) {
-
 
998
				/* Imported file */
-
 
999
				if (p->imported == 1) {
-
 
1000
					return(1);
-
 
1001
				}
-
 
1002
				p->imported = 1;
-
 
1003
			}
-
 
1004
			if (p->state == 2) {
-
 
1005
				/* Check protection macro */
-
 
1006
				unsigned def = check_macro(p->macro, 0);
-
 
1007
				def &= PP_COND_MASK;
-
 
1008
				if (def == p->test) {
-
 
1009
					return(1);
-
 
1010
				}
-
 
1011
			}
-
 
1012
			return(0);
-
 
1013
		}
-
 
1014
		p = p->next;
-
 
1015
	}
-
 
1016
 
-
 
1017
	/* Create new imported file structure */
-
 
1018
	p = xmalloc_one(INCL_FILE);
-
 
1019
	if (st != 4) {
-
 
1020
		crt_included_file = p;
-
 
1021
	}
-
 
1022
	p->name = nm;
-
 
1023
	p->imported = st;
-
 
1024
	p->macro = NULL_hashid;
-
 
1025
	p->state = 0;
-
 
1026
	p->test = PP_TRUE;
-
 
1027
	p->from = NULL_ptr(LOCATION);
-
 
1028
	if (fs) {
-
 
1029
		/* File system information available */
-
 
1030
		p->data = & (p->data_ref);
-
 
1031
		p->data_ref = *fs;
930
	} else {
1032
	} else {
931
	    /* Check file statistics */
-
 
932
	    ok = stat_equal ( fs, p->data ) ;
1033
		p->data = NULL;
933
	}
1034
	}
934
	if ( ok ) {
-
 
935
	    /* Check matching file */
-
 
936
	    if ( st == 4 ) {
-
 
937
		/* Simple enquiry */
-
 
938
		return ( 1 ) ;
-
 
939
	    }
-
 
940
	    crt_included_file = p ;
-
 
941
	    if ( st == 1 ) {
-
 
942
		/* Imported file */
-
 
943
		if ( p->imported == 1 ) return ( 1 ) ;
-
 
944
		p->imported = 1 ;
-
 
945
	    }
-
 
946
	    if ( p->state == 2 ) {
-
 
947
		/* Check protection macro */
-
 
948
		unsigned def = check_macro ( p->macro, 0 ) ;
-
 
949
		def &= PP_COND_MASK ;
-
 
950
		if ( def == p->test ) return ( 1 ) ;
-
 
951
	    }
-
 
952
	    return ( 0 ) ;
-
 
953
	}
-
 
954
	p = p->next ;
-
 
955
    }
-
 
956
 
-
 
957
    /* Create new imported file structure */
-
 
958
    p = xmalloc_one ( INCL_FILE ) ;
-
 
959
    if ( st != 4 ) crt_included_file = p ;
-
 
960
    p->name = nm ;
-
 
961
    p->imported = st ;
-
 
962
    p->macro = NULL_hashid ;
-
 
963
    p->state = 0 ;
-
 
964
    p->test = PP_TRUE ;
-
 
965
    p->from = NULL_ptr ( LOCATION ) ;
-
 
966
    if ( fs ) {
-
 
967
	/* File system information available */
-
 
968
	p->data = &( p->data_ref ) ;
-
 
969
	p->data_ref = *fs ;
-
 
970
    } else {
-
 
971
	p->data = NULL ;
-
 
972
    }
-
 
973
    p->next = included_files ;
1035
	p->next = included_files;
974
    included_files = p ;
1036
	included_files = p;
975
    return ( 0 ) ;
1037
	return(0);
976
}
1038
}
977
 
1039
 
978
 
1040
 
979
/*
1041
/*
980
    CHECK A FILE PROTECTION MACRO
1042
    CHECK A FILE PROTECTION MACRO
981
 
1043
 
982
    This routine checks whether the given macro identifier is a file
1044
    This routine checks whether the given macro identifier is a file
983
    protection macro for the current file, that is to say, whether the
1045
    protection macro for the current file, that is to say, whether the
984
    file has the form:
1046
    file has the form:
985
 
1047
 
986
		#ifndef macro
1048
		#ifndef macro
987
		....
1049
		....
988
		#endif
1050
		#endif
989
 
1051
 
990
    prev gives the previous preprocessing directive and dir gives the
1052
    prev gives the previous preprocessing directive and dir gives the
991
    current preprocessing directive.
1053
    current preprocessing directive.
992
*/
1054
*/
993
 
1055
 
994
void protection_macro
1056
void
995
    PROTO_N ( ( macro, prev, dir ) )
-
 
996
    PROTO_T ( HASHID macro X int prev X int dir )
1057
protection_macro(HASHID macro, int prev, int dir)
997
{
1058
{
998
    INCL_FILE *incl = crt_included_file ;
1059
	INCL_FILE *incl = crt_included_file;
999
    if ( incl ) {
1060
	if (incl) {
1000
	if ( prev == lex_included ) {
1061
		if (prev == lex_included) {
1001
	    if ( incl->state == 0 ) {
1062
			if (incl->state == 0) {
1002
		if ( dir == lex_ifndef ) {
1063
				if (dir == lex_ifndef) {
1003
		    /* Have '#ifndef macro' at start of file */
1064
					/* Have '#ifndef macro' at start of
-
 
1065
					 * file */
1004
		    incl->macro = macro ;
1066
					incl->macro = macro;
1005
		    incl->test = PP_TRUE ;
1067
					incl->test = PP_TRUE;
1006
		    incl->state = 1 ;
1068
					incl->state = 1;
1007
		    return ;
1069
					return;
1008
		}
1070
				}
1009
		if ( dir == lex_ifdef ) {
1071
				if (dir == lex_ifdef) {
1010
		    /* Have '#ifdef macro' at start of file */
1072
					/* Have '#ifdef macro' at start of
-
 
1073
					 * file */
1011
		    incl->macro = macro ;
1074
					incl->macro = macro;
1012
		    incl->test = PP_FALSE ;
1075
					incl->test = PP_FALSE;
1013
		    incl->state = 1 ;
1076
					incl->state = 1;
1014
		    return ;
1077
					return;
1015
		}
1078
				}
1016
		if ( dir == lex_eof ) {
1079
				if (dir == lex_eof) {
1017
		    /* Start and end of file coincide */
1080
					/* Start and end of file coincide */
1018
		    incl->macro = NULL_hashid ;
1081
					incl->macro = NULL_hashid;
1019
		    incl->test = PP_TRUE ;
1082
					incl->test = PP_TRUE;
1020
		    incl->state = 2 ;
1083
					incl->state = 2;
1021
		    return ;
1084
					return;
1022
		}
1085
				}
1023
	    }
1086
			}
1024
	}
1087
		}
1025
	if ( prev == lex_end_condition ) {
1088
		if (prev == lex_end_condition) {
1026
	    if ( incl->state == 1 ) {
1089
			if (incl->state == 1) {
1027
		if ( dir == lex_eof ) {
1090
				if (dir == lex_eof) {
1028
		    /* Have '#endif' at end of file */
1091
					/* Have '#endif' at end of file */
1029
		    incl->state = 2 ;
1092
					incl->state = 2;
1030
		    return ;
1093
					return;
1031
		}
1094
				}
1032
	    }
1095
			}
1033
	}
1096
		}
1034
	incl->state = 0 ;
1097
		incl->state = 0;
1035
    }
1098
	}
1036
    return ;
1099
	return;
1037
}
1100
}
1038
 
1101
 
1039
 
1102
 
1040
/*
1103
/*
1041
    CREATE A FILE NAME
1104
    CREATE A FILE NAME
1042
 
1105
 
1043
    This routine forms a composite file name consisting of a directory
1106
    This routine forms a composite file name consisting of a directory
1044
    component d and a file component f.  The up argument is true if the
1107
    component d and a file component f.  The up argument is true if the
1045
    existing file component is to be removed from d.
1108
    existing file component is to be removed from d.
1046
*/
1109
*/
1047
 
1110
 
1048
static string add_pathname
1111
static string
1049
    PROTO_N ( ( d, f, up ) )
-
 
1050
    PROTO_T ( string d X string f X int up )
1112
add_pathname(string d, string f, int up)
1051
{
1113
{
1052
    if ( d ) {
1114
	if (d) {
1053
	BUFFER *bf = clear_buffer ( &incl_buff, NIL ( FILE ) ) ;
1115
		BUFFER *bf = clear_buffer(&incl_buff, NIL(FILE));
1054
	bfputs ( bf, d ) ;
1116
		bfputs(bf, d);
1055
	if ( up ) {
1117
		if (up) {
1056
	    /* Remove file component */
1118
			/* Remove file component */
1057
	    string s = ustrrchr ( bf->start, char_slash ) ;
1119
			string s = ustrrchr(bf->start, char_slash);
1058
	    if ( s == NULL ) return ( f ) ;
1120
			if (s == NULL) {
-
 
1121
				return(f);
-
 
1122
			}
1059
	    bf->posn = s ;
1123
			bf->posn = s;
-
 
1124
		}
-
 
1125
		bfputc(bf, char_slash);
-
 
1126
		bfputs(bf, f);
-
 
1127
		return(bf->start);
1060
	}
1128
	}
1061
	bfputc ( bf, char_slash ) ;
-
 
1062
	bfputs ( bf, f ) ;
-
 
1063
	return ( bf->start ) ;
-
 
1064
    }
-
 
1065
    return ( f ) ;
1129
	return(f);
1066
}
1130
}
1067
 
1131
 
1068
 
1132
 
1069
/*
1133
/*
1070
    FIND AN INCLUDE FILE
1134
    FIND AN INCLUDE FILE
Line 1074... Line 1138...
1074
    directive.  The argument st is 0 for normal inclusions, 1 for imported
1138
    directive.  The argument st is 0 for normal inclusions, 1 for imported
1075
    inclusions, 2 for start-up files and 3 for end-up files.  A value of
1139
    inclusions, 2 for start-up files and 3 for end-up files.  A value of
1076
    4 is used for checking inclusion.  next is true if the search is to
1140
    4 is used for checking inclusion.  next is true if the search is to
1077
    restart at the current position in the directory path.  The routine
1141
    restart at the current position in the directory path.  The routine
1078
    returns 1 to indicate that the file was opened successfully.
1142
    returns 1 to indicate that the file was opened successfully.
1255
 
1326
 
1256
 
1327
 
1257
/*
1328
/*
1258
    END AN INCLUDE FILE
1329
    END AN INCLUDE FILE
1259
 
1330
 
Line 1264... Line 1335...
1264
    spotted during this process (except the first start-up file which is
1335
    spotted during this process (except the first start-up file which is
1265
    dealt with in process_file).  Start-up files are at depth 1, whereas
1336
    dealt with in process_file).  Start-up files are at depth 1, whereas
1266
    end-up files are at depth 0.
1337
    end-up files are at depth 0.
1267
*/
1338
*/
1268
 
1339
 
1269
int end_include
1340
int
1270
    PROTO_N ( ( prev ) )
-
 
1271
    PROTO_T ( int prev )
1341
end_include(int prev)
1272
{
1342
{
1273
    unsigned long c ;
1343
	unsigned long c;
1274
    PTR ( LOCATION ) loc ;
1344
	PTR(LOCATION)loc;
1275
    FILE *f = input_file ;
1345
	FILE *f = input_file;
1276
    string nm = input_name ;
1346
	string nm = input_name;
1277
 
1347
 
1278
    /* Check for protection macros */
1348
	/* Check for protection macros */
1279
    if ( !clear_preproc_if () ) prev = lex_end_condition ;
1349
	if (!clear_preproc_if ())prev = lex_end_condition;
1280
    protection_macro ( NULL_hashid, prev, lex_eof ) ;
1350
	protection_macro(NULL_hashid, prev, lex_eof);
1281
 
1351
 
1282
    /* Tidy up the current file */
1352
	/* Tidy up the current file */
1283
    if ( f != NULL ) {
1353
	if (f != NULL) {
1284
	if ( input_special ) {
1354
		if (input_special) {
1285
	    if ( f == internal_file ) {
1355
			if (f == internal_file) {
1286
		free_buffer ( &internal_buff ) ;
1356
				free_buffer(&internal_buff);
-
 
1357
			}
-
 
1358
		} else {
-
 
1359
			if (ferror(f) || fclose(f)) {
-
 
1360
				char *fnm = strlit(nm);
-
 
1361
				error(ERROR_INTERNAL, "Reading error in '%s'",
-
 
1362
				      fnm);
-
 
1363
			}
-
 
1364
		}
-
 
1365
		input_file = NULL;
-
 
1366
		if (do_header)dump_end(&crt_loc);
-
 
1367
	}
-
 
1368
 
-
 
1369
	/* Check for previous file */
-
 
1370
	c = crt_option_value(OPT_VAL_include_depth);
-
 
1371
	if (c == 0) {
-
 
1372
		/* End of main file - deal with end-up files */
-
 
1373
		LIST(string)p = endup_files;
-
 
1374
		while (!IS_NULL_list(p)) {
-
 
1375
			string fn = DEREF_string(HEAD_list(p));
-
 
1376
			p = TAIL_list(p);
-
 
1377
			endup_files = p;
-
 
1378
			preproc_loc = crt_loc;
-
 
1379
			crt_file_type = 1;
-
 
1380
			if (start_include(fn, char_quote, 3, 0)) {
-
 
1381
				return(1);
-
 
1382
			}
-
 
1383
		}
-
 
1384
		crt_file_type = 0;
-
 
1385
		return(0);
-
 
1386
	}
-
 
1387
	decr_value(OPT_VAL_include_depth);
-
 
1388
	c--;
-
 
1389
 
-
 
1390
	/* End checking scope if necessary */
-
 
1391
	if (position[c].mode)end_option(0);
-
 
1392
 
-
 
1393
	/* Restore previous file position (don't destroy old value) */
-
 
1394
	loc = DEREF_ptr(posn_from(crt_loc.posn));
-
 
1395
	DEREF_loc(loc, crt_loc);
-
 
1396
	crt_file_changed = 2;
-
 
1397
	crt_line_changed = 1;
-
 
1398
	crt_spaces = 0;
-
 
1399
 
-
 
1400
	/* Reopen the previous buffer */
-
 
1401
	input_name = position[c].name;
-
 
1402
	input_file = position[c].fileptr;
-
 
1403
	input_special = position[c].special;
-
 
1404
	crt_dir_path = position[c].path;
-
 
1405
	crt_found_path = position[c].found;
-
 
1406
	crt_included_file = position[c].incl;
-
 
1407
	crt_interface = position[c].interface;
-
 
1408
	if (input_file == NULL) {
-
 
1409
		/* Reopen old file */
-
 
1410
		char *str = strlit(input_name);
-
 
1411
		if (str) {
-
 
1412
			input_file = fopen(str, "r");
-
 
1413
			if (input_file == NULL) {
-
 
1414
				CONST char *msg = "Internal file error in '%s'";
-
 
1415
				error(ERROR_INTERNAL, msg, str);
-
 
1416
				crt_loc.line++;
-
 
1417
				crt_loc.column = 0;
-
 
1418
				input_crt = input_posn;
-
 
1419
				return(end_include(lex_ignore_token));
1287
	    }
1420
			}
-
 
1421
			seek_buffer(LAST_BUFFER_NO, position[c].offset, 0);
-
 
1422
		}
1288
	} else {
1423
	} else {
1289
	    if ( ferror ( f ) || fclose ( f ) ) {
1424
		/* Resume old file position */
1290
		char *fnm = strlit ( nm ) ;
1425
		resume_buffer(c);
1291
		error ( ERROR_INTERNAL, "Reading error in '%s'", fnm ) ;
-
 
1292
	    }
-
 
1293
	}
1426
	}
1294
	input_file = NULL ;
-
 
1295
	if ( do_header ) dump_end ( &crt_loc ) ;
-
 
1296
    }
-
 
1297
 
-
 
1298
    /* Check for previous file */
-
 
1299
    c = crt_option_value ( OPT_VAL_include_depth ) ;
1427
	if (option(OPT_include_verbose)) {
1300
    if ( c == 0 ) {
1428
		LOCATION ploc;
1301
	/* End of main file - deal with end-up files */
-
 
1302
	LIST ( string ) p = endup_files ;
1429
		int st = position[c].startup;
1303
	while ( !IS_NULL_list ( p ) ) {
1430
		ploc = crt_loc;
1304
	    string fn = DEREF_string ( HEAD_list ( p ) ) ;
-
 
1305
	    p = TAIL_list ( p ) ;
1431
		if (st >= 2) {
1306
	    endup_files = p ;
1432
			ploc.line++;
-
 
1433
		}
1307
	    preproc_loc = crt_loc ;
1434
		report(ploc, ERR_cpp_include_close(nm));
-
 
1435
	}
1308
	    crt_file_type = 1 ;
1436
	if (do_header) {
1309
	    if ( start_include ( fn, char_quote, 3, 0 ) ) return ( 1 ) ;
1437
		dump_include(&crt_loc, NULL_string, 4, 0);
1310
	}
1438
	}
1311
	crt_file_type = 0 ;
1439
	crt_loc.line++;
1312
	return ( 0 ) ;
-
 
1313
    }
-
 
1314
    decr_value ( OPT_VAL_include_depth ) ;
-
 
1315
    c-- ;
-
 
1316
 
-
 
1317
    /* End checking scope if necessary */
-
 
1318
    if ( position [c].mode ) end_option ( 0 ) ;
-
 
1319
 
-
 
1320
    /* Restore previous file position (don't destroy old value) */
-
 
1321
    loc = DEREF_ptr ( posn_from ( crt_loc.posn ) ) ;
-
 
1322
    DEREF_loc ( loc, crt_loc ) ;
-
 
1323
    crt_file_changed = 2 ;
-
 
1324
    crt_line_changed = 1 ;
1440
	crt_loc.column = 0;
1325
    crt_spaces = 0 ;
1441
	input_crt = input_posn;
1326
 
1442
 
1327
    /* Reopen the previous buffer */
-
 
1328
    input_name = position [c].name ;
-
 
1329
    input_file = position [c].fileptr ;
-
 
1330
    input_special = position [c].special ;
-
 
1331
    crt_dir_path = position [c].path ;
-
 
1332
    crt_found_path = position [c].found ;
-
 
1333
    crt_included_file = position [c].incl ;
-
 
1334
    crt_interface = position [c].interface ;
1443
	/* Could be the end of a start-up file - try the next one */
1335
    if ( input_file == NULL ) {
-
 
1336
	/* Reopen old file */
-
 
1337
	char *str = strlit ( input_name ) ;
-
 
1338
	if ( str ) {
1444
	if (c == 0) {
1339
	    input_file = fopen ( str, "r" ) ;
-
 
1340
	    if ( input_file == NULL ) {
-
 
1341
		CONST char *msg = "Internal file error in '%s'" ;
-
 
1342
		error ( ERROR_INTERNAL, msg, str ) ;
-
 
1343
		crt_loc.line++ ;
-
 
1344
		crt_loc.column = 0 ;
-
 
1345
		input_crt = input_posn ;
1445
		open_startup();
1346
		return ( end_include ( lex_ignore_token ) ) ;
-
 
1347
	    }
-
 
1348
	    seek_buffer ( LAST_BUFFER_NO, position [c].offset, 0 ) ;
-
 
1349
	}
1446
	}
1350
    } else {
-
 
1351
	/* Resume old file position */
-
 
1352
	resume_buffer ( c ) ;
-
 
1353
    }
-
 
1354
    if ( option ( OPT_include_verbose ) ) {
-
 
1355
	LOCATION ploc ;
-
 
1356
	int st = position [c].startup ;
-
 
1357
	ploc = crt_loc ;
-
 
1358
	if ( st >= 2 ) ploc.line++ ;
-
 
1359
	report ( ploc, ERR_cpp_include_close ( nm ) ) ;
-
 
1360
    }
-
 
1361
    if ( do_header ) dump_include ( &crt_loc, NULL_string, 4, 0 ) ;
-
 
1362
    crt_loc.line++ ;
-
 
1363
    crt_loc.column = 0 ;
-
 
1364
    input_crt = input_posn ;
-
 
1365
 
-
 
1366
    /* Could be the end of a start-up file - try the next one */
-
 
1367
    if ( c == 0 ) open_startup () ;
-
 
1368
    return ( 1 ) ;
1447
	return(1);
1369
}
1448
}