2021-10-11 18:37:13 -03:00

350 lines
7.9 KiB
C

#ifndef lint
#ifdef sccs
static char sccsid[] = "@(#)parse.c 1.1 94/10/31";
#endif
#endif
/*
* Copyright (c) 1985, 1988 by Sun Microsystems, Inc.
*/
/*
* This package contains routines for parsing numbers and strings from a
* standard I/O stream.
*/
#include <sunwindow/sun.h> /* True, False, ... */
#include <stdio.h> /* Standard I/O Library */
#include <sunwindow/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){
(void)fprintf(stderr, "PARSE_INT: No integer\n");
exit(1);
}
} 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); */
/*
}
*/