Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
263 dpurdie 1
/*
2
	CPP V5 -- macro symbol table routines.
3
 
4
	source:  mst.c
5
	started: September 22, 1985
6
	version: May 26, 1988
7
 
8
	Written by Edward K. Ream.
9
	This software is in the public domain.
10
 
11
	See the read.me file for disclaimer and other information.
12
*/
13
 
14
#include "cpp.h"
15
 
16
/* Declare local routines. */
17
static int mst_hash	(unsigned char *);
18
 
19
/* Define the hash table used to access macro table nodes. */
20
 
21
#define MAC_PRIME 101
22
typedef struct mst_node mactab;
23
static struct mst_node {
24
	mactab * mst_next; 	/* Pointer to next bucket.	*/
25
	int	 mst_nargs;	/* Number of args in text.	*/
26
	char *	 mst_name;    	/* Pointer to name.		*/
27
	char *	 mst_text;    	/* Pointer to replacement text. */
28
};
29
static mactab mst_ht [MAC_PRIME];
30
 
31
/*
32
	Define the "initial undef list" for
33
	arguments undefined on the command line.
34
*/
35
typedef struct u_node unode;
36
static struct u_node {
37
	unode *	u_next;
38
	char *		u_name;
39
};
40
unode undef_list;	/* list header. */
41
 
42
/*
43
	Remove ALL instances of a symbol from the symbol table.
44
	This ensures that an #undef will expose any non-macro version
45
	of a routine.
46
*/
47
void
48
mst_delete (symbol)
49
register char * symbol;
50
{
51
	register mactab *bp1, *bp2;
52
	int hash;
53
 
54
	TRACEP("mst_delete",printf("entry: symbol=<%s>\n", symbol));
55
 
56
	hash = mst_hash(symbol);
57
	bp1 = & mst_ht [hash];
58
	bp2 = bp1 -> mst_next;
59
 
60
	while(bp2 != NULL) {
61
 
62
		if(str_eq(symbol, bp2 -> mst_name)) {
63
 
64
			TRACEP("mst_delete", printf("deletes\n"));
65
			bp1 -> mst_next = bp2 -> mst_next;
66
			m_free(bp2);
67
			bp2 = bp1 -> mst_next;
68
		}
69
		else {
70
			bp1 = bp2;
71
			bp2 = bp2 -> mst_next;
72
		}
73
	}
74
}
75
 
76
/*
77
	Place a macro in the symbol table along with the number of arguments
78
	to the macro and a pointer to the macro's replacement text.
79
 
80
	Multiple entries for a symbol can exist in which case the last entry
81
	defined is active.
82
 
83
	This code conforms to the new standard.  It rejects duplicate 
84
	definitions of a macro unless the new definition is exactly the
85
	same as the old.  
86
 
87
	This code also checks the "initial undef list" to see if the first
88
	definition of a macro should be ignored.  If the macro name is
89
	found on the list, it is removed from the list and no entry is made
90
	in the macro symbol table.
91
*/
92
void
93
mst_enter (symbol, txt, nargs)
94
register char *symbol;
95
register char *txt;
96
register int nargs;
97
{
98
	register mactab *bp, *bp2;
99
	int hash;
100
	unode *up1, *up2;
101
 
102
	TRACEP("mst_enter", printf("(%s, <%s>, %d)\n",
103
		symbol, pr_str(txt), nargs));
104
 
105
	/*
106
		Search the global "initial undef list" (created by command line
107
		-u arguments) to see if the initial definition of name should
108
		be rejected.  If the name appears on the list, remove it from
109
		the list and do not enter the name in the macro table.
110
	*/
111
 
112
	if (undef_list . u_next != NULL) {
113
		up1 = &undef_list;
114
		up2 = up1 -> u_next;
115
 
116
		while (up2 != NULL) {
117
			if (str_eq(symbol, up2 -> u_name)) {
118
				/* Remove the entry from the list. */
119
				up1 -> u_next = up2 -> u_next;
120
				return;
121
			}
122
			else {
123
				up1 = up2;
124
				up2 = up2 -> u_next;
125
			}
126
		}
127
	}
128
 
129
	/* Search down the list of mst_nodes. */
130
	hash = mst_hash(symbol);
131
	bp   = & mst_ht [hash];
132
	for (bp = bp -> mst_next; bp; bp = bp -> mst_next) {
133
 
134
		/* Reject redefinitions of a macro unless identical. */
135
		if (str_eq (symbol, bp -> mst_name)) {
136
			if (nargs == bp -> mst_nargs) {
137
				if (str_eq(txt, bp -> mst_text)) {
138
					return;
139
				}
140
			}
141
			err3(	"Non-identical redefinition of ", symbol,
142
				" ignored.");
143
			return;
144
		}
145
	}
146
 
147
	/* Dynamically allocate space for node. */
148
	bp2 = m_alloc(sizeof(mactab));
149
 
150
	/* Hang node from hash table. */
151
	bp = & mst_ht [hash];
152
	bp2 -> mst_next = bp -> mst_next;
153
	bp  -> mst_next = bp2;
154
 
155
	/* Fill in the name and text fields. */
156
	bp2 -> mst_name  = str_alloc(symbol);
157
	bp2 -> mst_text  = str_alloc(txt);
158
	bp2 -> mst_nargs = nargs;
159
}
160
 
161
/*
162
	Return the hash value for symbol.
163
*/
164
static int
165
mst_hash (symbol)
166
register unsigned char * symbol;
167
{
168
	register int hash;
169
 
170
	STAT("mst_hash");
171
 
172
	for (hash = 0; *symbol; ) {
173
		hash *= 3;
174
		hash += (int) *symbol++;
175
		hash %= MAC_PRIME;
176
	}
177
	return hash;
178
}
179
 
180
/*
181
	Initialize the macro module.
182
	This must be done BEFORE command line arguments are processed.
183
*/
184
void
185
mst_init()
186
{
187
	register int i;
188
 
189
	TICK("mst_init");
190
 
191
	/* Clear the hash table. */
192
	for (i = 0; i < MAC_PRIME; i++) {
193
		mst_ht [i] . mst_next = NULL;
194
		mst_ht [i] . mst_name = "<NAME>";
195
		mst_ht [i] . mst_text = "<TEXT>";
196
		mst_ht [i] . mst_nargs = 0;
197
	}
198
 
199
	/* Clear the "initial undef list." */
200
	undef_list . u_next = NULL;
201
}
202
 
203
/*
204
	Enter the predefined macros into the table.
205
	Do nothing if the initial definitions have been
206
	suppressed with -u options.
207
 
208
	This must be done AFTER command line options have been processed.
209
*/
210
void
211
mst2_init()
212
{
213
	mst_enter("__LINE__", "", -3);
214
	mst_enter("__FILE__", "", -3);
215
	mst_enter("__STDC__", "", -3);
216
	mst_enter("__TIME__", "", -3);
217
	mst_enter("__DATE__", "", -3);
218
}
219
 
220
/*
221
	Look up a symbol in the macro table.
222
	Return TRUE if found, and set text and nargs.
223
*/
224
bool
225
mst_lookup(symbol, text, nargs)
226
register char * symbol;
227
char ** text;
228
int *nargs;
229
{
230
	register mactab *bp;
231
	char buffer [100];
232
	int hash;
233
 
234
	TRACEP("mst_lookup", printf("(%s)\n", symbol));
235
 
236
	/* Calculate the hash value of the symbol. */
237
	hash = mst_hash(symbol);
238
	bp = & mst_ht [hash];
239
 
240
	/* Search down the list of mst_nodes. */
241
	for (bp = bp -> mst_next; bp; bp = bp -> mst_next) {
242
 
243
		if (str_eq(symbol, bp -> mst_name)) {
244
 
245
			/* Special case for __line__ and __file__. */
246
			if (bp -> mst_nargs == -3) {
247
				if (str_eq(bp -> mst_name, "__LINE__")) {
248
					/* Set current line number. */
249
					conv2s(t_line, buffer);
250
					bp -> mst_text = str_alloc(buffer);
251
				}
252
				else if (str_eq(bp -> mst_name, "__FILE__")) {
253
 
254
					/* Set current file name. */
255
					strcpy(buffer, "\"");
256
					strcat(buffer, t_file);
257
					strcat(buffer, "\"");
258
					bp -> mst_text = str_alloc(buffer);
259
				}
260
				else if (str_eq(bp -> mst_name, "__TIME__")) {
261
					/* Set current file name. */
262
					bp -> mst_text = systime();
263
				}
264
				else if (str_eq(bp -> mst_name, "__DATE__")) {
265
					bp -> mst_text = sysdate();
266
				}
267
				else if (str_eq(bp -> mst_name, "__STDC__")) {
268
					bp -> mst_text = "1";
269
				}
270
			}
271
 
272
			/* Return success. */
273
			*nargs = max(-1, bp -> mst_nargs);
274
			*text  = bp -> mst_text;
275
 
276
			TRACEP("mst_lookup", printf("found:\n"));
277
			return TRUE;
278
		}
279
	}
280
 
281
	TRACEP("mst_lookup", printf("not found\n"));
282
 
283
	/* Return failure. */
284
	return FALSE;
285
}
286
 
287
/*
288
	Add an argument to the "initial undef list."
289
*/
290
void
291
mst_unarg(arg)
292
char * arg;
293
{
294
	unode * p;
295
 
296
	TICK("mst_unarg");
297
 
298
	p = m_alloc(sizeof(unode));
299
	p -> u_name		= arg;
300
	p -> u_next		= undef_list . u_next;
301
	undef_list . u_next	= p;
302
}