File: parse.c

package info (click to toggle)
xview 3.2p1.4-4
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 20,068 kB
  • ctags: 24,304
  • sloc: ansic: 241,105; yacc: 1,392; sh: 1,140; makefile: 273; lex: 76; perl: 54; asm: 50; cpp: 15
file content (357 lines) | stat: -rw-r--r-- 8,918 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
#ifndef	lint
#ifdef sccs
static char     sccsid[] = "@(#)parse.c 20.13 93/06/28 Copyr 1985 Sun Micro";
#endif
#endif

/*
 *	(c) Copyright 1989 Sun Microsystems, Inc. Sun design patents 
 *	pending in the U.S. and foreign countries. See LEGAL NOTICE 
 *	file for terms of the license.
 */

/*
 * This package contains routines for parsing numbers and strings from a
 * standard I/O stream.
 */

#include <view2/sun.h>		/* True, False, ... */
#include <stdio.h>		/* Standard I/O Library */
#include <view2/xv_error.h>
#include <view2_private/parse.h>/* Exported routine definitions */

#define	STRING_SIZE	255	/* Maximum string size */

/* If character at a time debugging is needed, remove these two defines. */
#define	getchr(fp)	((int)getc(fp))	/* Get next character */
#define	ungetchr	ungetc	/* Unget next character */

extern char    *hash_get_memory();

/*
 * Locally defined procedures in alphabetical order:
 */

int             parse_octal();
int             parse_backslash_chr();

/*
 * parse_comments(in_file) will skip over a C-style comment from In_File.
 */
void
parse_comments(in_file)
    register FILE  *in_file;	/* Input file */
{
    register int    chr;	/* Temporary character */

    chr = parse_whitespace(in_file);
    if (chr == ';')
	(void) parse_eol(in_file);
    else if (chr == '/') {
	if (getchr(in_file) != '*') {
	    (void) ungetchr('*', in_file);
	    (void) ungetchr('/', in_file);
	    return;
	}
	while (True) {
	    chr = getchr(in_file);
	    if ((chr == '*') && (getchr(in_file) == '/'))
		break;
	    if (chr == EOF)
		break;
	}
	(void) parse_whitespace(in_file);
    } else
	(void) ungetchr(chr, in_file);
}


/*
 * parse_string(in_file, text, max_size) will parse a C-style string from
 * In_File and return the result into Text.  If Text is NULL, a string will
 * be malloc'ed and returned.  If Text is non-NULL, Max_Size specifies the
 * maximum size string that can be read into Text.  If any error occurs, NULL
 * will be returned.
 */
char           *
parse_string(in_file, text, max_size)
    register FILE  *in_file;	/* Input file */
    char           *text;	/* Place to store string */
    int             max_size;	/* Maximum size */
{
    register int    chr;	/* Temporary character */
    register char  *pointer;	/* Pointer into string */
    register int    size;	/* String size */
    char            temp[STRING_SIZE];	/* Temporary string */

    size = 0;
    if (text == NULL) {
	pointer = temp;
	max_size = STRING_SIZE;
    } else
	pointer = text;
    max_size--;			/* Just in case */
    chr = parse_whitespace(in_file);
    if (chr != '"') {
	(void) ungetchr(chr, in_file);
	return NULL;
    }
    getchr(in_file);
    while (size < max_size) {
	chr = getchr(in_file);
	if (chr == '"')
	    break;
	if (chr == '\n') {
	    (void) ungetchr(chr, in_file);
	    return NULL;
	}
	if (chr == EOF)
	    return NULL;
	if (chr == '\\') {
	    (void) ungetchr(chr, in_file);
	    chr = parse_backslash_chr(in_file);
	    if (chr == -1)
		return NULL;
	}
	*pointer++ = chr;
	size++;
	if (size >= max_size)
	    return NULL;
    }
    if (size == max_size)
	return NULL;
    *pointer = '\0';
    if (text == NULL) {
	text = hash_get_memory(size + 1);
	(void) strcpy(text, temp);
    }
    return text;
}

/*
 * parse_chr(in_file) will parse a single C-style character from In_File and
 * return the result.  -1 will be returned on any errors.
 */
int
parse_chr(in_file)
    register FILE  *in_file;	/* Input file */
{
    register int    chr;	/* Temporary character */
    int             temp_chr;	/* Yet another temporary character */

    chr = getchr(in_file);
    if (chr != '\'')
	return -1;
    chr = parse_backslash_chr(in_file);
    if (chr < 0)
	return -1;
    temp_chr = getchr(in_file);
    if (temp_chr == '\'')
	return chr;
    else
	return -1;
}

/*
 * parse_backslash_chr(infile) will parse a C-style backslash character.
 */
static int
parse_backslash_chr(in_file)
    register FILE  *in_file;	/* Input file */
{
    register char   chr;	/* Temporary character */
    int             count;	/* Number of octal digits */
    int             number;	/* Number associated with character */

    chr = getchr(in_file);
    if (chr != '\\')
	return -1;
    chr = getchr(in_file);
    switch (chr) {
      case 't':
	return '\t';
      case 'n':
	return '\n';
      case 'b':
	return '\b';
      case 'r':
	return '\r';
      case '\\':
	return '\\';
      case 'f':
	return '\f';
      case '\'':
	return '\'';
      case '"':
	return '"';
    }
    number = 0;
    count = 0;
    while (count < 3) {
	if (('0' <= chr) && (chr <= '7')) {
	    number = number * 8 + chr - '0';
	    chr = getchr(in_file);
	    count++;
	} else {
	    break;
	}
    }
    (void) ungetchr(chr, in_file);
    return (count == 0) ? -1 : number;
}

/*
 * parse_symbol(infile, symbol) will read in symbol from In_File and store
 * the result into Symbol.  A symbol contains an alphanumeric or an
 * underscore.  Storage will be malloc'ed if Symbol is NULL.  If an error
 * occurs, NULL will be returned.
 */
char           *
parse_symbol(in_file, symbol)
    register FILE  *in_file;	/* Input file */
    char           *symbol;	/* Optional place to store symbol */
{
    register int    chr;	/* Temporary character */
    Bool            got_chr;	/* True => got a character */
    char           *pointer;	/* Pointer into string */
    int             size;	/* String size */
    char            temp[STRING_SIZE];	/* Temporary string */

    got_chr = False;
    pointer = (symbol == NULL) ? &temp[0] : symbol;
    size = 0;
    chr = parse_whitespace(in_file);
    chr = getchr(in_file);
    while ((' ' < chr) && (chr <= '~') && (chr != '/')) {
	got_chr = True;
	*pointer++ = chr;
	size++;
	chr = getchr(in_file);
    }
    (void) ungetchr(chr, in_file);
    if (!got_chr)
	return NULL;
    *pointer = '\0';
    if (symbol == NULL) {
	symbol = hash_get_memory(size + 1);
	(void) strcpy(symbol, &temp[0]);
    }
    return symbol;
}

/*
 * parse_int(in_file, error) will parse an integer from In_File.  *Error will
 * be set to True if any error occurs.  If Error is NULL, an error message
 * will be printed and the program will be terminated.
 */
int
parse_int(in_file, error)
    register FILE  *in_file;	/* Input file */
    Bool           *error;	/* Error flag; NULL => halt on error */
{
    register int    chr;	/* Temporary character */
    Bool            have_error;	/* True => have an error */
    Bool            negative;	/* True => negative number */
    int             number;	/* Resultant number */

    have_error = True;		/* True until first digit is read */
    negative = False;
    number = 0;
    (void) parse_whitespace(in_file);
    chr = getchr(in_file);
    if (chr == '-') {
	negative = True;
	chr = getchr(in_file);
    }
    while (('0' <= chr) && (chr <= '9')) {
	have_error = False;
	number = number * 10 - '0' + chr;
	chr = getchr(in_file);
    }
    (void) ungetchr(chr, in_file);
    if (error == NULL) {
	if (have_error) {
	    xv_error(NULL, XV_ERROR_NON_RECOVERABLE, XV_ERROR_INTERNAL,
		     XV_ERROR_STRING, "parse_int(): No integer", 0);
	}
    } else
	*error = have_error;
    if (negative)
	number = -number;
    return number;
}

/*
 * parse_eol(in_file) will read characters from In_File until a new-line is
 * encountered.  True will be returned when an end-of-file is encountered.
 */
Bool
parse_eol(in_file)
    register FILE  *in_file;	/* Input file */
{
    register int    chr;	/* Temporary character */

    do
	chr = getchr(in_file);
    while ((chr != '\n') && (chr != EOF));
    return (Bool) (chr == EOF);
}

/*
 * parse_whitespace(in_file) will skip over any spaces and tabs from In_File.
 * The character that terminated the whitespace is returned.
 */
int
parse_whitespace(in_file)
    register FILE  *in_file;	/* Input file */
{
    register int    chr;	/* Temporary character */

    do
	chr = getchr(in_file);
    while ((chr == ' ') || (chr == '\t'));
    (void) ungetchr(chr, in_file);
    return chr;
}

/*
 * getchar(in_file) will return the next character from In_File.  This
 * routine is used instead of getc so that it will be easier to debug this
 * package.
 */
/*
 * static int xgetchr(in_file) register FILE	*in_file;
 *//* Input file */
/*
 * { register int	chr;
 *//* Temporary character */
/*
 * chr = getc(in_file);
 */
/*
 * if ((' ' <= chr) && (chr <= '~')) printf("%c", chr); else printf("\\%3o",
 * chr);
 */
/*
 * return chr; }
 */

/*
 * ungetchr(chr, in_file) will push Chr back onto the In_File stream.  This
 * routine is used instead of ungetc so that it will be easier to debug this
 * package.
 */
/*
 * static void xungetchr(chr, in_file) register int	chr;
 *//* Character to push back */
/* register FILE	*in_file; *//* Input file */
/*
 * { (void)ungetc(chr, in_file);
 */
/*
 * if ((' ' <= chr) && (chr <= '~')) printf("<%c>", chr); else
 * printf("<\\%3o>", chr);
 */
/*
 * }
 */