about summary refs log tree commit diff stats
path: root/WWW/Library/Implementation/HTLex.c
blob: 5a0df9173d87a88d1954d50707fcd0d04bd65c85 (plain) (blame)
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
/* MODULE							HTLex.c
 *		LEXICAL ANALYSOR
 *
 * AUTHORS:
 *	AL	Ari Luotonen	luotonen@dxcern.cern.ch
 *
 * HISTORY:
 *
 *
 * BUGS:
 *
 *
 */

#include <HTUtils.h>

#include <HTLex.h>		/* Implemented here */

#include <LYLeaks.h>

/*
 * Global variables
 */
char HTlex_buffer[40];		/* Read lexical string          */
int HTlex_line = 1;		/* Line number in source file   */

/*
 * Module-wide variables
 */
static int lex_cnt;
static BOOL lex_template;
static LexItem lex_pushed_back = LEX_NONE;
static FILE *cache = NULL;

void unlex(LexItem lex_item)
{
    lex_pushed_back = lex_item;
}

LexItem lex(FILE *fp)
{
    int ch = 0;

    if (fp != cache) {		/* This cache doesn't work ok because the system  */
	cache = fp;		/* often assign same FILE structure the next open */
	HTlex_line = 1;		/* file.  So, if there are syntax errors in setup *
				   files it may confuse things later on.      */
    }
    if (lex_pushed_back != LEX_NONE) {
	LexItem ret = lex_pushed_back;

	lex_pushed_back = LEX_NONE;
	return ret;
    }

    lex_cnt = 0;
    lex_template = NO;

    for (;;) {
	switch (ch = getc(fp)) {
	case EOF:
	case ' ':
	case '\t':
	case '\r':
	case '\n':
	case ':':
	case ',':
	case '(':
	case ')':
	case '@':
	    if (lex_cnt > 0) {
		if (ch != EOF)
		    ungetc(ch, fp);
		if (lex_template)
		    return LEX_TMPL_STR;
		else
		    return LEX_ALPH_STR;
	    } else
		switch (ch) {
		case EOF:
		    return LEX_EOF;
		case '\n':
		    HTlex_line++;
		    return LEX_REC_SEP;
		case ':':
		    return LEX_FIELD_SEP;
		case ',':
		    return LEX_ITEM_SEP;
		case '(':
		    return LEX_OPEN_PAREN;
		case ')':
		    return LEX_CLOSE_PAREN;
		case '@':
		    return LEX_AT_SIGN;
		default:	/* Leading white space ignored (SP,TAB,CR) */
		    break;
		}
	    break;
	default:
	    if (lex_cnt < (int) (sizeof(HTlex_buffer) - 1))
		HTlex_buffer[lex_cnt++] = (char) ch;
	    HTlex_buffer[lex_cnt] = '\0';
	    if ('*' == ch)
		lex_template = YES;
	}			/* switch ch */
    }				/* forever */
}

const char *lex_verbose(LexItem lex_item)
{
    static char msg[sizeof(HTlex_buffer) + 30];		/* @@@@@@@@ */

    switch (lex_item) {
    case LEX_NONE:		/* Internally used      */
	return "NO-LEX-ITEM";
    case LEX_EOF:		/* End of file          */
	return "end-of-file";
    case LEX_REC_SEP:		/* Record separator     */
	return "record separator (newline)";
    case LEX_FIELD_SEP:	/* Field separator      */
	return "field separator ':'";
    case LEX_ITEM_SEP:		/* List item separator  */
	return "item separator ','";
    case LEX_OPEN_PAREN:	/* Group start tag      */
	return "'('";
    case LEX_CLOSE_PAREN:	/* Group end tag        */
	return "')'";
    case LEX_AT_SIGN:		/* Address qualifier    */
	return "address qualifier '@'";
    case LEX_ALPH_STR:		/* Alphanumeric string  */
	sprintf(msg, "alphanumeric string '%.*s'",
		(int) sizeof(HTlex_buffer), HTlex_buffer);
	return msg;
    case LEX_TMPL_STR:		/* Template string      */
	sprintf(msg, "template string '%.*s'",
		(int) sizeof(HTlex_buffer), HTlex_buffer);
	return msg;
    default:
	return "UNKNOWN-LEX-ITEM";
    }
}