srcpos.c revision 204433
1/*
2 * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 *  This program is distributed in the hope that it will be useful,
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 *  General Public License for more details.
13 *
14 *  You should have received a copy of the GNU General Public License
15 *  along with this program; if not, write to the Free Software
16 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
17 *                                                                   USA
18 */
19
20#define _GNU_SOURCE
21
22#include <stdio.h>
23
24#include "dtc.h"
25#include "srcpos.h"
26
27
28/*
29 * Like yylineno, this is the current open file pos.
30 */
31struct dtc_file *srcpos_file;
32
33/*
34 * The empty source position.
35 */
36
37struct dtc_file dtc_empty_file = {
38	.dir = NULL,
39	.name = "<no file>",
40	.file = NULL
41};
42
43srcpos srcpos_empty = {
44	.first_line = 0,
45	.first_column = 0,
46	.last_line = 0,
47	.last_column = 0,
48	.file = &dtc_empty_file
49};
50
51
52static int
53dtc_open_one(struct dtc_file *file, const char *search, const char *fname)
54{
55	char *fullname;
56
57	if (search) {
58		fullname = xmalloc(strlen(search) + strlen(fname) + 2);
59
60		strcpy(fullname, search);
61		strcat(fullname, "/");
62		strcat(fullname, fname);
63	} else {
64		fullname = xstrdup(fname);
65	}
66
67	file->file = fopen(fullname, "r");
68	if (!file->file) {
69		free(fullname);
70		return 0;
71	}
72
73	file->name = fullname;
74	return 1;
75}
76
77
78struct dtc_file *
79dtc_open_file(const char *fname, const struct search_path *search)
80{
81	static const struct search_path default_search = { NULL, NULL, NULL };
82
83	struct dtc_file *file;
84	const char *slash;
85
86	file = xmalloc(sizeof(struct dtc_file));
87
88	slash = strrchr(fname, '/');
89	if (slash) {
90		char *dir = xmalloc(slash - fname + 1);
91
92		memcpy(dir, fname, slash - fname);
93		dir[slash - fname] = 0;
94		file->dir = dir;
95	} else {
96		file->dir = NULL;
97	}
98
99	if (streq(fname, "-")) {
100		file->name = "stdin";
101		file->file = stdin;
102		return file;
103	}
104
105	if (fname[0] == '/') {
106		file->file = fopen(fname, "r");
107		if (!file->file)
108			goto fail;
109
110		file->name = xstrdup(fname);
111		return file;
112	}
113
114	if (!search)
115		search = &default_search;
116
117	while (search) {
118		if (dtc_open_one(file, search->dir, fname))
119			return file;
120
121		if (errno != ENOENT)
122			goto fail;
123
124		search = search->next;
125	}
126
127fail:
128	die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
129}
130
131
132void
133dtc_close_file(struct dtc_file *file)
134{
135	if (fclose(file->file))
136		die("Error closing \"%s\": %s\n", file->name, strerror(errno));
137}
138
139
140srcpos *
141srcpos_copy(srcpos *pos)
142{
143	srcpos *pos_new;
144
145	pos_new = xmalloc(sizeof(srcpos));
146	memcpy(pos_new, pos, sizeof(srcpos));
147
148	return pos_new;
149}
150
151
152
153void
154srcpos_dump(srcpos *pos)
155{
156	printf("file        : \"%s\"\n",
157	       pos->file ? (char *) pos->file : "<no file>");
158	printf("first_line  : %d\n", pos->first_line);
159	printf("first_column: %d\n", pos->first_column);
160	printf("last_line   : %d\n", pos->last_line);
161	printf("last_column : %d\n", pos->last_column);
162	printf("file        : %s\n", pos->file->name);
163}
164
165
166char *
167srcpos_string(srcpos *pos)
168{
169	const char *fname;
170	char col_buf[100];
171	char *pos_str;
172
173	if (!pos) {
174		fname = "<no-file>";
175	} else if (pos->file->name) {
176		fname = pos->file->name;
177		if (strcmp(fname, "-") == 0)
178			fname = "stdin";
179	} else {
180		fname = "<no-file>";
181	}
182
183	if (pos->first_line == pos->last_line) {
184		if (pos->first_column == pos->last_column) {
185			snprintf(col_buf, sizeof(col_buf),
186				 "%d:%d",
187				 pos->first_line, pos->first_column);
188		} else {
189			snprintf(col_buf, sizeof(col_buf),
190				 "%d:%d-%d",
191				 pos->first_line,
192				 pos->first_column, pos->last_column);
193		}
194
195	} else {
196		snprintf(col_buf, sizeof(col_buf),
197			 "%d:%d - %d:%d",
198			 pos->first_line, pos->first_column,
199			 pos->last_line, pos->last_column);
200	}
201
202	if (asprintf(&pos_str, "%s %s", fname, col_buf) == -1)
203		return "<unknown source position?";
204
205	return pos_str;
206}
207
208
209void
210srcpos_error(srcpos *pos, char const *fmt, ...)
211{
212	const char *srcstr;
213	va_list va;
214	va_start(va, fmt);
215
216	srcstr = srcpos_string(pos);
217
218	fprintf(stderr, "Error: %s ", srcstr);
219	vfprintf(stderr, fmt, va);
220	fprintf(stderr, "\n");
221
222	va_end(va);
223}
224
225
226void
227srcpos_warn(srcpos *pos, char const *fmt, ...)
228{
229	const char *srcstr;
230	va_list va;
231	va_start(va, fmt);
232
233	srcstr = srcpos_string(pos);
234
235	fprintf(stderr, "Warning: %s ", srcstr);
236	vfprintf(stderr, fmt, va);
237	fprintf(stderr, "\n");
238
239	va_end(va);
240}
241