xref: /netbsd-src/external/bsd/tradcpp/dist/place.c (revision 31615c9617fab4df7f5e221552df7da87f14320d)
1*31615c96Sdholland /*-
2*31615c96Sdholland  * Copyright (c) 2010 The NetBSD Foundation, Inc.
3*31615c96Sdholland  * All rights reserved.
4*31615c96Sdholland  *
5*31615c96Sdholland  * This code is derived from software contributed to The NetBSD Foundation
6*31615c96Sdholland  * by David A. Holland.
7*31615c96Sdholland  *
8*31615c96Sdholland  * Redistribution and use in source and binary forms, with or without
9*31615c96Sdholland  * modification, are permitted provided that the following conditions
10*31615c96Sdholland  * are met:
11*31615c96Sdholland  * 1. Redistributions of source code must retain the above copyright
12*31615c96Sdholland  *    notice, this list of conditions and the following disclaimer.
13*31615c96Sdholland  * 2. Redistributions in binary form must reproduce the above copyright
14*31615c96Sdholland  *    notice, this list of conditions and the following disclaimer in the
15*31615c96Sdholland  *    documentation and/or other materials provided with the distribution.
16*31615c96Sdholland  *
17*31615c96Sdholland  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18*31615c96Sdholland  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19*31615c96Sdholland  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20*31615c96Sdholland  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21*31615c96Sdholland  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*31615c96Sdholland  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*31615c96Sdholland  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*31615c96Sdholland  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*31615c96Sdholland  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*31615c96Sdholland  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*31615c96Sdholland  * POSSIBILITY OF SUCH DAMAGE.
28*31615c96Sdholland  */
29*31615c96Sdholland 
30*31615c96Sdholland #include <assert.h>
31*31615c96Sdholland #include <stdarg.h>
32*31615c96Sdholland #include <stdio.h>
33*31615c96Sdholland #include <stdlib.h>
34*31615c96Sdholland #include <string.h>
35*31615c96Sdholland #include <errno.h>
36*31615c96Sdholland 
37*31615c96Sdholland #include "utils.h"
38*31615c96Sdholland #include "array.h"
39*31615c96Sdholland #include "place.h"
40*31615c96Sdholland 
41*31615c96Sdholland struct placefile {
42*31615c96Sdholland 	struct place includedfrom;
43*31615c96Sdholland 	char *dir;
44*31615c96Sdholland 	char *name;
45*31615c96Sdholland 	int depth;
46*31615c96Sdholland 	bool fromsystemdir;
47*31615c96Sdholland };
48*31615c96Sdholland DECLARRAY(placefile, static UNUSED);
49*31615c96Sdholland DEFARRAY(placefile, static);
50*31615c96Sdholland 
51*31615c96Sdholland static struct placefilearray placefiles;
52*31615c96Sdholland static bool overall_failure;
53*31615c96Sdholland 
54*31615c96Sdholland static const char *myprogname;
55*31615c96Sdholland 
56*31615c96Sdholland static FILE *debuglogfile;
57*31615c96Sdholland 
58*31615c96Sdholland ////////////////////////////////////////////////////////////
59*31615c96Sdholland // placefiles
60*31615c96Sdholland 
61*31615c96Sdholland static
62*31615c96Sdholland struct placefile *
placefile_create(const struct place * from,const char * name,bool fromsystemdir)63*31615c96Sdholland placefile_create(const struct place *from, const char *name,
64*31615c96Sdholland 		 bool fromsystemdir)
65*31615c96Sdholland {
66*31615c96Sdholland 	struct placefile *pf;
67*31615c96Sdholland 	const char *s;
68*31615c96Sdholland 	size_t len;
69*31615c96Sdholland 
70*31615c96Sdholland 	pf = domalloc(sizeof(*pf));
71*31615c96Sdholland 	pf->includedfrom = *from;
72*31615c96Sdholland 
73*31615c96Sdholland 	s = strrchr(name, '/');
74*31615c96Sdholland 	len = (s == NULL) ? 0 : s - name;
75*31615c96Sdholland 	pf->dir = dostrndup(name, len);
76*31615c96Sdholland 
77*31615c96Sdholland 	pf->name = dostrdup(name);
78*31615c96Sdholland 	pf->fromsystemdir = fromsystemdir;
79*31615c96Sdholland 
80*31615c96Sdholland 	if (from->file != NULL) {
81*31615c96Sdholland 		pf->depth = from->file->depth + 1;
82*31615c96Sdholland 	} else {
83*31615c96Sdholland 		pf->depth = 1;
84*31615c96Sdholland 	}
85*31615c96Sdholland 	return pf;
86*31615c96Sdholland }
87*31615c96Sdholland 
88*31615c96Sdholland static
89*31615c96Sdholland void
placefile_destroy(struct placefile * pf)90*31615c96Sdholland placefile_destroy(struct placefile *pf)
91*31615c96Sdholland {
92*31615c96Sdholland 	dostrfree(pf->name);
93*31615c96Sdholland 	dofree(pf, sizeof(*pf));
94*31615c96Sdholland }
95*31615c96Sdholland 
96*31615c96Sdholland DESTROYALL_ARRAY(placefile, );
97*31615c96Sdholland 
98*31615c96Sdholland const char *
place_getparsedir(const struct place * place)99*31615c96Sdholland place_getparsedir(const struct place *place)
100*31615c96Sdholland {
101*31615c96Sdholland 	if (place->file == NULL) {
102*31615c96Sdholland 		return ".";
103*31615c96Sdholland 	}
104*31615c96Sdholland 	return place->file->dir;
105*31615c96Sdholland }
106*31615c96Sdholland 
107*31615c96Sdholland static
108*31615c96Sdholland struct placefile *
placefile_find(const struct place * incfrom,const char * name)109*31615c96Sdholland placefile_find(const struct place *incfrom, const char *name)
110*31615c96Sdholland {
111*31615c96Sdholland 	unsigned i, num;
112*31615c96Sdholland 	struct placefile *pf;
113*31615c96Sdholland 
114*31615c96Sdholland 	num = placefilearray_num(&placefiles);
115*31615c96Sdholland 	for (i=0; i<num; i++) {
116*31615c96Sdholland 		pf = placefilearray_get(&placefiles, i);
117*31615c96Sdholland 		if (place_eq(incfrom, &pf->includedfrom) &&
118*31615c96Sdholland 		    !strcmp(name, pf->name)) {
119*31615c96Sdholland 			return pf;
120*31615c96Sdholland 		}
121*31615c96Sdholland 	}
122*31615c96Sdholland 	return NULL;
123*31615c96Sdholland }
124*31615c96Sdholland 
125*31615c96Sdholland void
place_changefile(struct place * p,const char * name)126*31615c96Sdholland place_changefile(struct place *p, const char *name)
127*31615c96Sdholland {
128*31615c96Sdholland 	struct placefile *pf;
129*31615c96Sdholland 
130*31615c96Sdholland 	assert(p->type == P_FILE);
131*31615c96Sdholland 	if (!strcmp(name, p->file->name)) {
132*31615c96Sdholland 		return;
133*31615c96Sdholland 	}
134*31615c96Sdholland 	pf = placefile_find(&p->file->includedfrom, name);
135*31615c96Sdholland 	if (pf == NULL) {
136*31615c96Sdholland 		pf = placefile_create(&p->file->includedfrom, name,
137*31615c96Sdholland 				      p->file->fromsystemdir);
138*31615c96Sdholland 		placefilearray_add(&placefiles, pf, NULL);
139*31615c96Sdholland 	}
140*31615c96Sdholland 	p->file = pf;
141*31615c96Sdholland }
142*31615c96Sdholland 
143*31615c96Sdholland const struct placefile *
place_addfile(const struct place * place,const char * file,bool issystem)144*31615c96Sdholland place_addfile(const struct place *place, const char *file, bool issystem)
145*31615c96Sdholland {
146*31615c96Sdholland 	struct placefile *pf;
147*31615c96Sdholland 
148*31615c96Sdholland 	pf = placefile_create(place, file, issystem);
149*31615c96Sdholland 	placefilearray_add(&placefiles, pf, NULL);
150*31615c96Sdholland 	if (pf->depth > 120) {
151*31615c96Sdholland 		complain(place, "Maximum include nesting depth exceeded");
152*31615c96Sdholland 		die();
153*31615c96Sdholland 	}
154*31615c96Sdholland 	return pf;
155*31615c96Sdholland }
156*31615c96Sdholland 
157*31615c96Sdholland ////////////////////////////////////////////////////////////
158*31615c96Sdholland // places
159*31615c96Sdholland 
160*31615c96Sdholland void
place_setnowhere(struct place * p)161*31615c96Sdholland place_setnowhere(struct place *p)
162*31615c96Sdholland {
163*31615c96Sdholland 	p->type = P_NOWHERE;
164*31615c96Sdholland 	p->file = NULL;
165*31615c96Sdholland 	p->line = 0;
166*31615c96Sdholland 	p->column = 0;
167*31615c96Sdholland }
168*31615c96Sdholland 
169*31615c96Sdholland void
place_setbuiltin(struct place * p,unsigned num)170*31615c96Sdholland place_setbuiltin(struct place *p, unsigned num)
171*31615c96Sdholland {
172*31615c96Sdholland 	p->type = P_BUILTIN;
173*31615c96Sdholland 	p->file = NULL;
174*31615c96Sdholland 	p->line = num;
175*31615c96Sdholland 	p->column = 1;
176*31615c96Sdholland }
177*31615c96Sdholland 
178*31615c96Sdholland void
place_setcommandline(struct place * p,unsigned line,unsigned column)179*31615c96Sdholland place_setcommandline(struct place *p, unsigned line, unsigned column)
180*31615c96Sdholland {
181*31615c96Sdholland 	p->type = P_COMMANDLINE;
182*31615c96Sdholland 	p->file = NULL;
183*31615c96Sdholland 	p->line = line;
184*31615c96Sdholland 	p->column = column;
185*31615c96Sdholland }
186*31615c96Sdholland 
187*31615c96Sdholland void
place_setfilestart(struct place * p,const struct placefile * pf)188*31615c96Sdholland place_setfilestart(struct place *p, const struct placefile *pf)
189*31615c96Sdholland {
190*31615c96Sdholland 	p->type = P_FILE;
191*31615c96Sdholland 	p->file = pf;
192*31615c96Sdholland 	p->line = 1;
193*31615c96Sdholland 	p->column = 1;
194*31615c96Sdholland }
195*31615c96Sdholland 
196*31615c96Sdholland void
place_addcolumns(struct place * p,unsigned cols)197*31615c96Sdholland place_addcolumns(struct place *p, unsigned cols)
198*31615c96Sdholland {
199*31615c96Sdholland 	unsigned newcol;
200*31615c96Sdholland 
201*31615c96Sdholland 	newcol = p->column + cols;
202*31615c96Sdholland 	if (newcol < p->column) {
203*31615c96Sdholland 		/* overflow (use the old place to complain) */
204*31615c96Sdholland 		complain(p, "Column numbering overflow");
205*31615c96Sdholland 		die();
206*31615c96Sdholland 	}
207*31615c96Sdholland 	p->column = newcol;
208*31615c96Sdholland }
209*31615c96Sdholland 
210*31615c96Sdholland void
place_addlines(struct place * p,unsigned lines)211*31615c96Sdholland place_addlines(struct place *p, unsigned lines)
212*31615c96Sdholland {
213*31615c96Sdholland 	unsigned nextline;
214*31615c96Sdholland 
215*31615c96Sdholland 	nextline = p->line + lines;
216*31615c96Sdholland 	if (nextline < p->line) {
217*31615c96Sdholland 		/* overflow (use the old place to complain) */
218*31615c96Sdholland 		complain(p, "Line numbering overflow");
219*31615c96Sdholland 		die();
220*31615c96Sdholland 	}
221*31615c96Sdholland 	p->line = nextline;
222*31615c96Sdholland }
223*31615c96Sdholland 
224*31615c96Sdholland const char *
place_getname(const struct place * p)225*31615c96Sdholland place_getname(const struct place *p)
226*31615c96Sdholland {
227*31615c96Sdholland 	switch (p->type) {
228*31615c96Sdholland 	    case P_NOWHERE: return "<nowhere>";
229*31615c96Sdholland 	    case P_BUILTIN: return "<built-in>";
230*31615c96Sdholland 	    case P_COMMANDLINE: return "<command-line>";
231*31615c96Sdholland 	    case P_FILE: return p->file->name;
232*31615c96Sdholland 	}
233*31615c96Sdholland 	assert(0);
234*31615c96Sdholland 	return NULL;
235*31615c96Sdholland }
236*31615c96Sdholland 
237*31615c96Sdholland bool
place_samefile(const struct place * a,const struct place * b)238*31615c96Sdholland place_samefile(const struct place *a, const struct place *b)
239*31615c96Sdholland {
240*31615c96Sdholland 	if (a->type != b->type) {
241*31615c96Sdholland 		return false;
242*31615c96Sdholland 	}
243*31615c96Sdholland 	if (a->file != b->file) {
244*31615c96Sdholland 		return false;
245*31615c96Sdholland 	}
246*31615c96Sdholland 	return true;
247*31615c96Sdholland }
248*31615c96Sdholland 
249*31615c96Sdholland bool
place_eq(const struct place * a,const struct place * b)250*31615c96Sdholland place_eq(const struct place *a, const struct place *b)
251*31615c96Sdholland {
252*31615c96Sdholland 	if (!place_samefile(a, b)) {
253*31615c96Sdholland 		return false;
254*31615c96Sdholland 	}
255*31615c96Sdholland 	if (a->line != b->line || a->column != b->column) {
256*31615c96Sdholland 		return false;
257*31615c96Sdholland 	}
258*31615c96Sdholland 	return true;
259*31615c96Sdholland }
260*31615c96Sdholland 
261*31615c96Sdholland static
262*31615c96Sdholland void
place_printfrom(const struct place * p)263*31615c96Sdholland place_printfrom(const struct place *p)
264*31615c96Sdholland {
265*31615c96Sdholland 	const struct place *from;
266*31615c96Sdholland 
267*31615c96Sdholland 	if (p->file == NULL) {
268*31615c96Sdholland 		return;
269*31615c96Sdholland 	}
270*31615c96Sdholland 	from = &p->file->includedfrom;
271*31615c96Sdholland 	if (from->type != P_NOWHERE) {
272*31615c96Sdholland 		place_printfrom(from);
273*31615c96Sdholland 		fprintf(stderr, "In file included from %s:%u:%u:\n",
274*31615c96Sdholland 			place_getname(from), from->line, from->column);
275*31615c96Sdholland 	}
276*31615c96Sdholland }
277*31615c96Sdholland 
278*31615c96Sdholland ////////////////////////////////////////////////////////////
279*31615c96Sdholland // complaints
280*31615c96Sdholland 
281*31615c96Sdholland void
complain_init(const char * pn)282*31615c96Sdholland complain_init(const char *pn)
283*31615c96Sdholland {
284*31615c96Sdholland 	myprogname = pn;
285*31615c96Sdholland }
286*31615c96Sdholland 
287*31615c96Sdholland void
complain(const struct place * p,const char * fmt,...)288*31615c96Sdholland complain(const struct place *p, const char *fmt, ...)
289*31615c96Sdholland {
290*31615c96Sdholland 	va_list ap;
291*31615c96Sdholland 
292*31615c96Sdholland 	if (p != NULL) {
293*31615c96Sdholland 		place_printfrom(p);
294*31615c96Sdholland 		fprintf(stderr, "%s:%u:%u: ", place_getname(p),
295*31615c96Sdholland 			p->line, p->column);
296*31615c96Sdholland 	} else {
297*31615c96Sdholland 		fprintf(stderr, "%s: ", myprogname);
298*31615c96Sdholland 	}
299*31615c96Sdholland 	va_start(ap, fmt);
300*31615c96Sdholland 	vfprintf(stderr, fmt, ap);
301*31615c96Sdholland 	va_end(ap);
302*31615c96Sdholland 	fprintf(stderr, "\n");
303*31615c96Sdholland }
304*31615c96Sdholland 
305*31615c96Sdholland void
complain_fail(void)306*31615c96Sdholland complain_fail(void)
307*31615c96Sdholland {
308*31615c96Sdholland 	overall_failure = true;
309*31615c96Sdholland }
310*31615c96Sdholland 
311*31615c96Sdholland bool
complain_failed(void)312*31615c96Sdholland complain_failed(void)
313*31615c96Sdholland {
314*31615c96Sdholland 	return overall_failure;
315*31615c96Sdholland }
316*31615c96Sdholland 
317*31615c96Sdholland ////////////////////////////////////////////////////////////
318*31615c96Sdholland // debug logging
319*31615c96Sdholland 
320*31615c96Sdholland void
debuglog_open(const struct place * p,char * file)321*31615c96Sdholland debuglog_open(const struct place *p, /*const*/ char *file)
322*31615c96Sdholland {
323*31615c96Sdholland 	assert(debuglogfile == NULL);
324*31615c96Sdholland 	debuglogfile = fopen(file, "w");
325*31615c96Sdholland 	if (debuglogfile == NULL) {
326*31615c96Sdholland 		complain(p, "%s: %s", file, strerror(errno));
327*31615c96Sdholland 		die();
328*31615c96Sdholland 	}
329*31615c96Sdholland }
330*31615c96Sdholland 
331*31615c96Sdholland void
debuglog_close(void)332*31615c96Sdholland debuglog_close(void)
333*31615c96Sdholland {
334*31615c96Sdholland 	if (debuglogfile != NULL) {
335*31615c96Sdholland 		fclose(debuglogfile);
336*31615c96Sdholland 		debuglogfile = NULL;
337*31615c96Sdholland 	}
338*31615c96Sdholland }
339*31615c96Sdholland 
340*31615c96Sdholland PF(2, 3) void
debuglog(const struct place * p,const char * fmt,...)341*31615c96Sdholland debuglog(const struct place *p, const char *fmt, ...)
342*31615c96Sdholland {
343*31615c96Sdholland 	va_list ap;
344*31615c96Sdholland 
345*31615c96Sdholland 	if (debuglogfile == NULL) {
346*31615c96Sdholland 		return;
347*31615c96Sdholland 	}
348*31615c96Sdholland 
349*31615c96Sdholland 	fprintf(debuglogfile, "%s:%u: ", place_getname(p), p->line);
350*31615c96Sdholland 	va_start(ap, fmt);
351*31615c96Sdholland 	vfprintf(debuglogfile, fmt, ap);
352*31615c96Sdholland 	va_end(ap);
353*31615c96Sdholland 	fprintf(debuglogfile, "\n");
354*31615c96Sdholland 	fflush(debuglogfile);
355*31615c96Sdholland }
356*31615c96Sdholland 
357*31615c96Sdholland PF(3, 4) void
debuglog2(const struct place * p,const struct place * p2,const char * fmt,...)358*31615c96Sdholland debuglog2(const struct place *p, const struct place *p2, const char *fmt, ...)
359*31615c96Sdholland {
360*31615c96Sdholland 	va_list ap;
361*31615c96Sdholland 
362*31615c96Sdholland 	if (debuglogfile == NULL) {
363*31615c96Sdholland 		return;
364*31615c96Sdholland 	}
365*31615c96Sdholland 
366*31615c96Sdholland 	fprintf(debuglogfile, "%s:%u: ", place_getname(p), p->line);
367*31615c96Sdholland 	if (place_samefile(p, p2)) {
368*31615c96Sdholland 		fprintf(debuglogfile, "(block began at line %u) ",
369*31615c96Sdholland 			p2->line);
370*31615c96Sdholland 	} else {
371*31615c96Sdholland 		fprintf(debuglogfile, "(block began at %s:%u)",
372*31615c96Sdholland 			place_getname(p2), p2->line);
373*31615c96Sdholland 	}
374*31615c96Sdholland 	va_start(ap, fmt);
375*31615c96Sdholland 	vfprintf(debuglogfile, fmt, ap);
376*31615c96Sdholland 	va_end(ap);
377*31615c96Sdholland 	fprintf(debuglogfile, "\n");
378*31615c96Sdholland 	fflush(debuglogfile);
379*31615c96Sdholland }
380*31615c96Sdholland 
381*31615c96Sdholland ////////////////////////////////////////////////////////////
382*31615c96Sdholland // module init and cleanup
383*31615c96Sdholland 
384*31615c96Sdholland void
place_init(void)385*31615c96Sdholland place_init(void)
386*31615c96Sdholland {
387*31615c96Sdholland 	placefilearray_init(&placefiles);
388*31615c96Sdholland }
389*31615c96Sdholland 
390*31615c96Sdholland void
place_cleanup(void)391*31615c96Sdholland place_cleanup(void)
392*31615c96Sdholland {
393*31615c96Sdholland 	placefilearray_destroyall(&placefiles);
394*31615c96Sdholland 	placefilearray_cleanup(&placefiles);
395*31615c96Sdholland }
396