Subversion Repositories DevTools

Rev

Rev 333 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
333 dpurdie 1
/* $XConsortium: parse.c /main/31 1995/12/08 18:26:41 gildea $ */
2
/*
3
 
4
Copyright (c) 1993, 1994  X Consortium
5
 
6
Permission is hereby granted, free of charge, to any person obtaining a copy
7
of this software and associated documentation files (the "Software"), to deal
8
in the Software without restriction, including without limitation the rights
9
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
copies of the Software, and to permit persons to whom the Software is
11
furnished to do so, subject to the following conditions:
12
 
13
The above copyright notice and this permission notice shall be included in
14
all copies or substantial portions of the Software.
15
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
 
23
Except as contained in this notice, the name of the X Consortium shall not be
24
used in advertising or otherwise to promote the sale, use or other dealings
25
in this Software without prior written authorization from the X Consortium.
26
 
27
 $Source: /cvsroot/device/DEVL/UTILS/MKDEPEND/parse.c,v $
28
 $Revision: 1.2 $ $Date: 2004/05/10 03:49:20 $ $State: Exp $
29
 $Author: ayoung $ $Locker:  $
30
 
31
*/
32
 
33
#include "def.h"
34
 
35
extern const char      *directives[];
36
extern struct inclist	maininclist;
37
 
38
find_includes(filep, file, file_red, recursion, failOK)
39
	struct filepointer	*filep;
40
	struct inclist		*file, *file_red;
41
	int			recursion;
42
	boolean			failOK;
43
{
44
	register char	*line;
45
	register int	type;
46
	boolean recfailOK;
47
 
4160 dpurdie 48
	while (line = my_getline(filep)) {
333 dpurdie 49
		switch(type = deftype(line, filep, file_red, file, TRUE)) {
50
		case IF:
51
		doif:
52
			type = find_includes(filep, file,
53
				file_red, recursion+1, failOK);
54
			while ((type == ELIF) || (type == ELIFFALSE) ||
55
			       (type == ELIFGUESSFALSE))
56
				type = gobble(filep, file, file_red);
57
			if (type == ELSE)
58
				gobble(filep, file, file_red);
59
			break;
60
		case IFFALSE:
61
		case IFGUESSFALSE:
62
		    doiffalse:
63
			if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
64
			    recfailOK = TRUE;
65
			else
66
			    recfailOK = failOK;
67
			type = gobble(filep, file, file_red);
68
			if (type == ELSE)
69
			    find_includes(filep, file,
70
					  file_red, recursion+1, recfailOK);
71
			else
72
			if (type == ELIF)
73
			    goto doif;
74
			else
75
			if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
76
			    goto doiffalse;
77
			break;
78
		case IFDEF:
79
		case IFNDEF:
80
			if ((type == IFDEF && isdefined(line, file_red, NULL))
81
			 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
82
				debug(1,(type == IFNDEF ?
83
				    "line %d: %s !def'd in %s via %s%s\n" : "",
84
				    filep->f_line, line,
85
				    file->i_file, file_red->i_file, ": doit"));
86
				type = find_includes(filep, file,
87
					file_red, recursion+1, failOK);
88
				while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
89
					type = gobble(filep, file, file_red);
90
				if (type == ELSE)
91
					gobble(filep, file, file_red);
92
			}
93
			else {
94
				debug(1,(type == IFDEF ?
95
				    "line %d: %s !def'd in %s via %s%s\n" : "",
96
				    filep->f_line, line,
97
				    file->i_file, file_red->i_file, ": gobble"));
98
				type = gobble(filep, file, file_red);
99
				if (type == ELSE)
100
					find_includes(filep, file,
101
						file_red, recursion+1, failOK);
102
				else if (type == ELIF)
103
				    	goto doif;
104
				else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
105
				    	goto doiffalse;
106
			}
107
			break;
108
		case ELSE:
109
		case ELIFFALSE:
110
		case ELIFGUESSFALSE:
111
		case ELIF:
112
			if (!recursion)
113
				gobble(filep, file, file_red);
114
		case ENDIF:
115
			if (recursion)
116
				return(type);
117
		case DEFINE:
118
			define(line, file);
119
			break;
120
		case UNDEF:
121
			if (!*line) {
122
			    warning("%s, line %d: incomplete undef == \"%s\"\n",
123
				file_red->i_file, filep->f_line, line);
124
			    break;
125
			}
126
			undefine(line, file_red);
127
			break;
128
		case INCLUDE:
129
			add_include(filep, file, file_red, line, FALSE, failOK);
130
			break;
131
		case INCLUDEDOT:
132
			add_include(filep, file, file_red, line, TRUE, failOK);
133
			break;
134
		case ERROR:
135
		    	warning("%s: %d: %s\n", file_red->i_file,
136
				 filep->f_line, line);
137
		    	break;
138
 
139
		case PRAGMA:
140
		case IDENT:
141
		case SCCS:
142
		case EJECT:
143
			break;
144
		case -1:
145
			warning("%s", file_red->i_file);
146
			if (file_red != file)
147
			    warning1(" (reading %s)", file->i_file);
148
			warning1(", line %d: unknown directive == \"%s\"\n",
149
				 filep->f_line, line);
150
			break;
151
		case -2:
152
			warning("%s", file_red->i_file);
153
			if (file_red != file)
154
			    warning1(" (reading %s)", file->i_file);
155
			warning1(", line %d: incomplete include == \"%s\"\n",
156
				 filep->f_line, line);
157
			break;
158
		}
159
	}
160
	file->i_flags |= FINISHED;
161
	return(-1);
162
}
163
 
164
gobble(filep, file, file_red)
165
	register struct filepointer *filep;
166
	struct inclist		*file, *file_red;
167
{
168
	register char	*line;
169
	register int	type;
170
 
4160 dpurdie 171
	while (line = my_getline(filep)) {
333 dpurdie 172
		switch(type = deftype(line, filep, file_red, file, FALSE)) {
173
		case IF:
174
		case IFFALSE:
175
		case IFGUESSFALSE:
176
		case IFDEF:
177
		case IFNDEF:
178
			type = gobble(filep, file, file_red);
179
			while ((type == ELIF) || (type == ELIFFALSE) ||
180
			       (type == ELIFGUESSFALSE))
181
			    type = gobble(filep, file, file_red);
182
			if (type == ELSE)
183
			        (void)gobble(filep, file, file_red);
184
			break;
185
		case ELSE:
186
		case ENDIF:
187
			debug(0,("%s, line %d: #%s\n",
188
				file->i_file, filep->f_line,
189
				directives[type]));
190
			return(type);
191
		case DEFINE:
192
		case UNDEF:
193
		case INCLUDE:
194
		case INCLUDEDOT:
195
		case PRAGMA:
196
		case ERROR:
197
		case IDENT:
198
		case SCCS:
199
		case EJECT:
200
			break;
201
		case ELIF:
202
		case ELIFFALSE:
203
		case ELIFGUESSFALSE:
204
			return(type);
205
		case -1:
206
			warning("%s, line %d: unknown directive == \"%s\"\n",
207
				file_red->i_file, filep->f_line, line);
208
			break;
209
		}
210
	}
211
	return(-1);
212
}
213
 
214
/*
215
 * Decide what type of # directive this line is.
216
 */
217
int deftype (line, filep, file_red, file, parse_it)
218
	register char	*line;
219
	register struct filepointer *filep;
220
	register struct inclist *file_red, *file;
221
	int	parse_it;
222
{
223
	register char	*p;
224
	char	*directive, savechar;
225
	register int	ret;
226
 
227
	/*
228
	 * Parse the directive...
229
	 */
230
	directive=line+1;
231
	while (*directive == ' ' || *directive == '\t')
232
		directive++;
233
 
234
	p = directive;
235
	while (*p >= 'a' && *p <= 'z')
236
		p++;
237
	savechar = *p;
238
	*p = '\0';
239
	ret = match(directive, directives);
240
	*p = savechar;
241
 
242
	/* If we don't recognize this compiler directive or we happen to just
243
	 * be gobbling up text while waiting for an #endif or #elif or #else
244
	 * in the case of an #elif we must check the zero_value and return an
245
	 * ELIF or an ELIFFALSE.
246
	 */
247
 
248
	if (ret == ELIF && !parse_it)
249
	{
250
	    while (*p == ' ' || *p == '\t')
251
		p++;
252
	    /*
253
	     * parse an expression.
254
	     */
255
	    debug(0,("%s, line %d: #elif %s ",
256
		   file->i_file, filep->f_line, p));
257
	    ret = zero_value(p, filep, file_red);
258
	    if (ret != IF)
259
	    {
260
		debug(0,("false...\n"));
261
		if (ret == IFFALSE)
262
		    return(ELIFFALSE);
263
		else
264
		    return(ELIFGUESSFALSE);
265
	    }
266
	    else
267
	    {
268
		debug(0,("true...\n"));
269
		return(ELIF);
270
	    }
271
	}
272
 
273
	if (ret < 0 || ! parse_it)
274
		return(ret);
275
 
276
	/*
277
	 * now decide how to parse the directive, and do it.
278
	 */
279
	while (*p == ' ' || *p == '\t')
280
		p++;
281
	switch (ret) {
282
	case IF:
283
		/*
284
		 * parse an expression.
285
		 */
286
		ret = zero_value(p, filep, file_red);
287
		debug(0,("%s, line %d: %s #if %s\n",
288
			 file->i_file, filep->f_line, ret?"false":"true", p));
289
		break;
290
	case IFDEF:
291
	case IFNDEF:
292
		debug(0,("%s, line %d: #%s %s\n",
293
			file->i_file, filep->f_line, directives[ret], p));
294
	case UNDEF:
295
		/*
296
		 * separate the name of a single symbol.
297
		 */
298
		while (isalnum(*p) || *p == '_')
299
			*line++ = *p++;
300
		*line = '\0';
301
		break;
302
	case INCLUDE:
303
		debug(2,("%s, line %d: #include %s\n",
304
			file->i_file, filep->f_line, p));
305
 
306
		/* Support ANSI macro substitution */
307
		{
308
		    struct symtab **sym = isdefined(p, file_red, NULL);
309
		    while (sym) {
310
			p = (*sym)->s_value;
311
			debug(3,("%s : #includes SYMBOL %s = %s\n",
312
			       file->i_incstring,
313
			       (*sym) -> s_name,
314
			       (*sym) -> s_value));
315
			/* mark file as having included a 'soft include' */
316
		    debug(1,("Setting INCLUDED_SYM\n"));
317
			file->i_flags |= INCLUDED_SYM; 
318
			sym = isdefined(p, file_red, NULL);
319
		    }
320
		}
321
 
322
		/*
323
		 * Separate the name of the include file.
324
		 */
325
		while (*p && *p != '"' && *p != '<')
326
			p++;
327
		if (! *p)
328
			return(-2);
329
		if (*p++ == '"') {
330
			ret = INCLUDEDOT;
331
			while (*p && *p != '"')
332
				*line++ = *p++;
333
		} else
334
			while (*p && *p != '>')
335
				*line++ = *p++;
336
		*line = '\0';
337
		break;
338
	case DEFINE:
339
		/*
340
		 * copy the definition back to the beginning of the line.
341
		 */
342
		strcpy (line, p);
343
		break;
344
	case ELSE:
345
	case ENDIF:
346
	case ELIF:
347
	case PRAGMA:
348
	case ERROR:
349
	case IDENT:
350
	case SCCS:
351
	case EJECT:
352
    case WARNING:
353
		debug(0,("%s, line %d: #%s\n",
354
			file->i_file, filep->f_line, directives[ret]));
355
		/*
356
		 * nothing to do.
357
		 */
358
		break;
359
	}
360
	return(ret);
361
}
362
 
363
struct symtab **isdefined(symbol, file, srcfile)
364
	register char	*symbol;
365
	struct inclist	*file;
366
	struct inclist	**srcfile;
367
{
368
	register struct symtab	**val;
369
 
370
	if (val = slookup(symbol, &maininclist)) {
371
		debug(1,("%s defined on command line\n", symbol));
372
		if (srcfile != NULL) *srcfile = &maininclist;
373
		return(val);
374
	}
375
	if (val = fdefined(symbol, file, srcfile))
376
		return(val);
377
	debug(1,("%s not defined in %s\n", symbol, file->i_file));
378
	return(NULL);
379
}
380
 
381
struct symtab **fdefined(symbol, file, srcfile)
382
	register char	*symbol;
383
	struct inclist	*file;
384
	struct inclist	**srcfile;
385
{
386
	register struct inclist	**ip;
387
	register struct symtab	**val;
388
	register int	i;
389
	static int	recurse_lvl = 0;
390
 
391
	if (file->i_flags & DEFCHECKED)
392
		return(NULL);
393
	file->i_flags |= DEFCHECKED;
394
	if (val = slookup(symbol, file))
395
		debug(1,("%s defined in %s as %s\n",
396
			 symbol, file->i_file, (*val)->s_value));
397
	if (val == NULL && file->i_list)
398
		{
399
		for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
400
			if (file->i_merged[i]==FALSE) {
401
				val = fdefined(symbol, *ip, srcfile);
402
				if ((*ip)->i_flags & FINISHED) {
403
					merge2defines(file,*ip);
404
					file->i_merged[i]=TRUE;
405
				    }
406
				if (val!=NULL) break;
407
			}
408
		}
409
	else if (val != NULL && srcfile != NULL) *srcfile = file;
410
	recurse_lvl--;
411
	file->i_flags &= ~DEFCHECKED;
412
 
413
	return(val);
414
}
415
 
416
/*
417
 * Return type based on if the #if expression evaluates to 0
418
 */
419
zero_value(exp, filep, file_red)
420
	register char	*exp;
421
	register struct filepointer *filep;
422
	register struct inclist *file_red;
423
{
424
	if (cppsetup(exp, filep, file_red))
425
	    return(IFFALSE);
426
	else
427
	    return(IF);
428
}
429
 
430
void
431
define(def, file)
432
	char	*def;
433
	struct inclist	*file;
434
{
435
    char *val;
436
 
437
    /* Separate symbol name and its value */
438
    val = def;
439
    while (isalnum(*val) || *val == '_')
440
	val++;
441
    if (*val)
442
	*val++ = '\0';
443
    while (*val == ' ' || *val == '\t')
444
	val++;
445
 
446
    if (!*val)
447
	val = "1";
448
    define2(def, val, file);
449
}
450
 
451
 
452
void
453
define2(name, val, file)
454
	char	*name, *val;
455
	struct inclist	*file;
456
{
457
    int first, last, below;
458
    register struct symtab **sp = NULL, **dest;
459
    struct symtab *stab;
460
 
461
    /* Make space if it's needed */
462
    if (file->i_defs == NULL)
463
    {
464
	file->i_defs = (struct symtab **)
465
			malloc(sizeof (struct symtab*) * SYMTABINC);
466
	file->i_ndefs = 0;
467
    }
468
    else if (!(file->i_ndefs % SYMTABINC))
469
	file->i_defs = (struct symtab **)
470
			realloc(file->i_defs,
471
			   sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
472
 
473
    if (file->i_defs == NULL)
474
	fatalerr("malloc()/realloc() failure in insert_defn()\n");
475
 
476
    below = first = 0;
477
    last = file->i_ndefs - 1;
478
    while (last >= first)
479
    {
480
	/* Fast inline binary search */
481
	register char *s1;
482
	register char *s2;
483
	register int middle = (first + last) / 2;
484
 
485
	/* Fast inline strchr() */
486
	s1 = name;
487
	s2 = file->i_defs[middle]->s_name;
488
	while (*s1++ == *s2++)
489
	    if (s2[-1] == '\0') break;
490
 
491
	/* If exact match, set sp and break */
492
	if (*--s1 == *--s2) 
493
	{
494
	    sp = file->i_defs + middle;
495
	    break;
496
	}
497
 
498
	/* If name > i_defs[middle] ... */
499
	if (*s1 > *s2) 
500
	{
501
	    below = first;
502
	    first = middle + 1;
503
	}
504
	/* else ... */
505
	else
506
	{
507
	    below = last = middle - 1;
508
	}
509
    }
510
 
511
    /* Search is done.  If we found an exact match to the symbol name,
512
       just replace its s_value */
513
    if (sp != NULL)
514
    {
515
	free((*sp)->s_value);
516
	(*sp)->s_value = copy(val);
517
	return;
518
    }
519
 
520
    sp = file->i_defs + file->i_ndefs++;
521
    dest = file->i_defs + below + 1;
522
    while (sp > dest)
523
    {
524
	*sp = sp[-1];
525
	sp--;
526
    }
527
    stab = (struct symtab *) malloc(sizeof (struct symtab));
528
    if (stab == NULL)
529
	fatalerr("malloc()/realloc() failure in insert_defn()\n");
530
 
531
    stab->s_name = copy(name);
532
    stab->s_value = copy(val);
533
    *sp = stab;
534
}
535
 
536
struct symtab **slookup(symbol, file)
537
	register char	*symbol;
538
	register struct inclist	*file;
539
{
540
	register int first = 0;
541
	register int last = file->i_ndefs - 1;
542
 
543
	if (file) while (last >= first)
544
	{
545
	    /* Fast inline binary search */
546
	    register char *s1;
547
	    register char *s2;
548
	    register int middle = (first + last) / 2;
549
 
550
	    /* Fast inline strchr() */
551
	    s1 = symbol;
552
	    s2 = file->i_defs[middle]->s_name;
553
	    while (*s1++ == *s2++)
554
	        if (s2[-1] == '\0') break;
555
 
556
	    /* If exact match, we're done */
557
	    if (*--s1 == *--s2) 
558
	    {
559
	        return file->i_defs + middle;
560
	    }
561
 
562
	    /* If symbol > i_defs[middle] ... */
563
	    if (*s1 > *s2) 
564
	    {
565
	        first = middle + 1;
566
	    }
567
	    /* else ... */
568
	    else
569
	    {
570
	        last = middle - 1;
571
	    }
572
	}
573
	return(NULL);
574
}
575
 
576
int merge2defines(file1, file2)
577
	struct inclist	*file1;
578
	struct inclist	*file2;
579
{
580
	if ((file1!=NULL) && (file2!=NULL)) 
581
        {
582
		int first1 = 0;
583
		int last1 = file1->i_ndefs - 1;
584
 
585
		int first2 = 0;
586
		int last2 = file2->i_ndefs - 1;
587
 
588
                int first=0;
589
                struct symtab** i_defs = NULL;
590
		int deflen=file1->i_ndefs+file2->i_ndefs;
591
 
592
                if (deflen>0)
593
                { 
594
                	/* make sure deflen % SYMTABINC == 0 is still true */
595
                	deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
596
                	i_defs=(struct symtab**)
597
			    malloc(deflen*sizeof(struct symtab*));
598
                	if (i_defs==NULL) return 0;
599
        	}
600
 
601
        	while ((last1 >= first1) && (last2 >= first2))
602
        	{
603
	    		char *s1=file1->i_defs[first1]->s_name;
604
	    		char *s2=file2->i_defs[first2]->s_name;
605
 
606
     			if (strcmp(s1,s2) < 0)
607
                        	i_defs[first++]=file1->i_defs[first1++];
608
     			else if (strcmp(s1,s2) > 0)
609
                        	i_defs[first++]=file2->i_defs[first2++];
610
                        else /* equal */
611
                        {
612
                        	i_defs[first++]=file2->i_defs[first2++];
613
                                first1++;
614
                        }
615
        	}
616
        	while (last1 >= first1)
617
        	{
618
                        i_defs[first++]=file1->i_defs[first1++];
619
        	}
620
        	while (last2 >= first2)
621
        	{
622
                        i_defs[first++]=file2->i_defs[first2++];
623
        	}
624
 
625
                if (file1->i_defs) free(file1->i_defs);
626
                file1->i_defs=i_defs;
627
                file1->i_ndefs=first;
628
 
629
		return 1;
630
  	}
631
	return 0;
632
}
633
 
634
 
635
void
636
undefine(symbol, file)
637
	char	*symbol;
638
	register struct inclist	*file;
639
{
640
	register struct symtab **ptr;
641
	struct inclist *srcfile;
642
	while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
643
	{
644
	    srcfile->i_ndefs--;
645
	    for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
646
		*ptr = ptr[1];
647
	}
648
}
649