xref: /openbsd-src/libexec/tradcpp/place.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*-
2  * Copyright (c) 2010 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by David A. Holland.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "utils.h"
37 #include "array.h"
38 #include "place.h"
39 
40 struct placefile {
41 	struct place includedfrom;
42 	char *dir;
43 	char *name;
44 	int depth;
45 	bool fromsystemdir;
46 };
47 DECLARRAY(placefile, static UNUSED);
48 DEFARRAY(placefile, static);
49 
50 static struct placefilearray placefiles;
51 static bool overall_failure;
52 
53 static const char *myprogname;
54 
55 ////////////////////////////////////////////////////////////
56 // seenfiles
57 
58 static
59 struct placefile *
60 placefile_create(const struct place *from, const char *name,
61 		 bool fromsystemdir)
62 {
63 	struct placefile *pf;
64 	const char *s;
65 	size_t len;
66 
67 	pf = domalloc(sizeof(*pf));
68 	pf->includedfrom = *from;
69 
70 	s = strrchr(name, '/');
71 	len = (s == NULL) ? 0 : s - name;
72 	pf->dir = dostrndup(name, len);
73 
74 	pf->name = dostrdup(name);
75 	pf->fromsystemdir = fromsystemdir;
76 
77 	if (from->file != NULL) {
78 		pf->depth = from->file->depth + 1;
79 	} else {
80 		pf->depth = 1;
81 	}
82 	return pf;
83 }
84 
85 static
86 void
87 placefile_destroy(struct placefile *pf)
88 {
89 	dostrfree(pf->name);
90 	dofree(pf, sizeof(*pf));
91 }
92 
93 DESTROYALL_ARRAY(placefile, );
94 
95 const char *
96 place_getparsedir(const struct place *place)
97 {
98 	if (place->file == NULL) {
99 		return ".";
100 	}
101 	return place->file->dir;
102 }
103 
104 const struct placefile *
105 place_addfile(const struct place *place, const char *file, bool issystem)
106 {
107 	struct placefile *pf;
108 
109 	pf = placefile_create(place, file, issystem);
110 	placefilearray_add(&placefiles, pf, NULL);
111 	if (pf->depth > 120) {
112 		complain(place, "Maximum include nesting depth exceeded");
113 		die();
114 	}
115 	return pf;
116 }
117 
118 ////////////////////////////////////////////////////////////
119 // places
120 
121 void
122 place_setnowhere(struct place *p)
123 {
124 	p->type = P_NOWHERE;
125 	p->file = NULL;
126 	p->line = 0;
127 	p->column = 0;
128 }
129 
130 void
131 place_setbuiltin(struct place *p, unsigned num)
132 {
133 	p->type = P_BUILTIN;
134 	p->file = NULL;
135 	p->line = num;
136 	p->column = 1;
137 }
138 
139 void
140 place_setcommandline(struct place *p, unsigned line, unsigned column)
141 {
142 	p->type = P_COMMANDLINE;
143 	p->file = NULL;
144 	p->line = line;
145 	p->column = column;
146 }
147 
148 void
149 place_setfilestart(struct place *p, const struct placefile *pf)
150 {
151 	p->type = P_FILE;
152 	p->file = pf;
153 	p->line = 1;
154 	p->column = 1;
155 }
156 
157 static
158 const char *
159 place_getname(const struct place *p)
160 {
161 	switch (p->type) {
162 	    case P_NOWHERE: return "<nowhere>";
163 	    case P_BUILTIN: return "<built-in>";
164 	    case P_COMMANDLINE: return "<command-line>";
165 	    case P_FILE: return p->file->name;
166 	}
167 	assert(0);
168 	return NULL;
169 }
170 
171 static
172 void
173 place_printfrom(const struct place *p)
174 {
175 	const struct place *from;
176 
177 	if (p->file == NULL) {
178 		return;
179 	}
180 	from = &p->file->includedfrom;
181 	if (from->type != P_NOWHERE) {
182 		place_printfrom(from);
183 		fprintf(stderr, "In file included from %s:%u:%u:\n",
184 			place_getname(from), from->line, from->column);
185 	}
186 }
187 
188 ////////////////////////////////////////////////////////////
189 // complaints
190 
191 void
192 complain_init(const char *pn)
193 {
194 	myprogname = pn;
195 }
196 
197 void
198 complain(const struct place *p, const char *fmt, ...)
199 {
200 	va_list ap;
201 
202 	if (p != NULL) {
203 		place_printfrom(p);
204 		fprintf(stderr, "%s:%u:%u: ", place_getname(p),
205 			p->line, p->column);
206 	} else {
207 		fprintf(stderr, "%s: ", myprogname);
208 	}
209 	va_start(ap, fmt);
210 	vfprintf(stderr, fmt, ap);
211 	va_end(ap);
212 	fprintf(stderr, "\n");
213 }
214 
215 void
216 complain_fail(void)
217 {
218 	overall_failure = true;
219 }
220 
221 bool
222 complain_failed(void)
223 {
224 	return overall_failure;
225 }
226 
227 ////////////////////////////////////////////////////////////
228 // module init and cleanup
229 
230 void
231 place_init(void)
232 {
233 	placefilearray_init(&placefiles);
234 }
235 
236 void
237 place_cleanup(void)
238 {
239 	placefilearray_destroyall(&placefiles);
240 	placefilearray_cleanup(&placefiles);
241 }
242