]>
Commit | Line | Data |
---|---|---|
a4da2e3e DG |
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 | ||
658f29a5 JB |
20 | #define _GNU_SOURCE |
21 | ||
22 | #include <stdio.h> | |
23 | ||
a4da2e3e DG |
24 | #include "dtc.h" |
25 | #include "srcpos.h" | |
26 | ||
a4da2e3e | 27 | |
658f29a5 JB |
28 | static char *dirname(const char *path) |
29 | { | |
30 | const char *slash = strrchr(path, '/'); | |
31 | ||
32 | if (slash) { | |
33 | int len = slash - path; | |
34 | char *dir = xmalloc(len + 1); | |
35 | ||
36 | memcpy(dir, path, len); | |
37 | dir[len] = '\0'; | |
38 | return dir; | |
39 | } | |
40 | return NULL; | |
41 | } | |
42 | ||
43 | struct srcfile_state *current_srcfile; /* = NULL */ | |
a4da2e3e | 44 | |
658f29a5 JB |
45 | /* Detect infinite include recursion. */ |
46 | #define MAX_SRCFILE_DEPTH (100) | |
47 | static int srcfile_depth; /* = 0 */ | |
48 | ||
49 | FILE *srcfile_relative_open(const char *fname, char **fullnamep) | |
a4da2e3e | 50 | { |
658f29a5 | 51 | FILE *f; |
ed95d745 | 52 | char *fullname; |
a4da2e3e | 53 | |
658f29a5 JB |
54 | if (streq(fname, "-")) { |
55 | f = stdin; | |
56 | fullname = xstrdup("<stdin>"); | |
ed95d745 | 57 | } else { |
658f29a5 JB |
58 | if (!current_srcfile || !current_srcfile->dir |
59 | || (fname[0] == '/')) | |
60 | fullname = xstrdup(fname); | |
61 | else | |
62 | fullname = join_path(current_srcfile->dir, fname); | |
63 | ||
64 | f = fopen(fullname, "r"); | |
65 | if (!f) | |
66 | die("Couldn't open \"%s\": %s\n", fname, | |
67 | strerror(errno)); | |
ed95d745 | 68 | } |
a4da2e3e | 69 | |
658f29a5 JB |
70 | if (fullnamep) |
71 | *fullnamep = fullname; | |
72 | else | |
ed95d745 | 73 | free(fullname); |
a4da2e3e | 74 | |
658f29a5 | 75 | return f; |
a4da2e3e DG |
76 | } |
77 | ||
658f29a5 JB |
78 | void srcfile_push(const char *fname) |
79 | { | |
80 | struct srcfile_state *srcfile; | |
81 | ||
82 | if (srcfile_depth++ >= MAX_SRCFILE_DEPTH) | |
83 | die("Includes nested too deeply"); | |
84 | ||
85 | srcfile = xmalloc(sizeof(*srcfile)); | |
86 | ||
87 | srcfile->f = srcfile_relative_open(fname, &srcfile->name); | |
88 | srcfile->dir = dirname(srcfile->name); | |
89 | srcfile->prev = current_srcfile; | |
90 | ||
91 | srcfile->lineno = 1; | |
92 | srcfile->colno = 1; | |
93 | ||
94 | current_srcfile = srcfile; | |
95 | } | |
a4da2e3e | 96 | |
658f29a5 | 97 | int srcfile_pop(void) |
ed95d745 | 98 | { |
658f29a5 | 99 | struct srcfile_state *srcfile = current_srcfile; |
a4da2e3e | 100 | |
658f29a5 | 101 | assert(srcfile); |
a4da2e3e | 102 | |
658f29a5 | 103 | current_srcfile = srcfile->prev; |
a4da2e3e | 104 | |
658f29a5 JB |
105 | if (fclose(srcfile->f)) |
106 | die("Error closing \"%s\": %s\n", srcfile->name, | |
107 | strerror(errno)); | |
ed95d745 | 108 | |
658f29a5 JB |
109 | /* FIXME: We allow the srcfile_state structure to leak, |
110 | * because it could still be referenced from a location | |
111 | * variable being carried through the parser somewhere. To | |
112 | * fix this we could either allocate all the files from a | |
113 | * table, or use a pool allocator. */ | |
a4da2e3e | 114 | |
658f29a5 JB |
115 | return current_srcfile ? 1 : 0; |
116 | } | |
a4da2e3e | 117 | |
658f29a5 JB |
118 | /* |
119 | * The empty source position. | |
120 | */ | |
ed95d745 | 121 | |
658f29a5 JB |
122 | struct srcpos srcpos_empty = { |
123 | .first_line = 0, | |
124 | .first_column = 0, | |
125 | .last_line = 0, | |
126 | .last_column = 0, | |
127 | .file = NULL, | |
128 | }; | |
a4da2e3e | 129 | |
658f29a5 | 130 | #define TAB_SIZE 8 |
a4da2e3e | 131 | |
658f29a5 JB |
132 | void srcpos_update(struct srcpos *pos, const char *text, int len) |
133 | { | |
134 | int i; | |
135 | ||
136 | pos->file = current_srcfile; | |
137 | ||
138 | pos->first_line = current_srcfile->lineno; | |
139 | pos->first_column = current_srcfile->colno; | |
140 | ||
141 | for (i = 0; i < len; i++) | |
142 | if (text[i] == '\n') { | |
143 | current_srcfile->lineno++; | |
144 | current_srcfile->colno = 1; | |
145 | } else if (text[i] == '\t') { | |
146 | current_srcfile->colno = | |
147 | ALIGN(current_srcfile->colno, TAB_SIZE); | |
148 | } else { | |
149 | current_srcfile->colno++; | |
150 | } | |
151 | ||
152 | pos->last_line = current_srcfile->lineno; | |
153 | pos->last_column = current_srcfile->colno; | |
154 | } | |
ed95d745 | 155 | |
658f29a5 JB |
156 | struct srcpos * |
157 | srcpos_copy(struct srcpos *pos) | |
158 | { | |
159 | struct srcpos *pos_new; | |
ed95d745 | 160 | |
658f29a5 JB |
161 | pos_new = xmalloc(sizeof(struct srcpos)); |
162 | memcpy(pos_new, pos, sizeof(struct srcpos)); | |
163 | ||
164 | return pos_new; | |
165 | } | |
166 | ||
167 | ||
168 | ||
169 | void | |
170 | srcpos_dump(struct srcpos *pos) | |
171 | { | |
172 | printf("file : \"%s\"\n", | |
173 | pos->file ? (char *) pos->file : "<no file>"); | |
174 | printf("first_line : %d\n", pos->first_line); | |
175 | printf("first_column: %d\n", pos->first_column); | |
176 | printf("last_line : %d\n", pos->last_line); | |
177 | printf("last_column : %d\n", pos->last_column); | |
178 | printf("file : %s\n", pos->file->name); | |
179 | } | |
a4da2e3e | 180 | |
658f29a5 JB |
181 | |
182 | char * | |
183 | srcpos_string(struct srcpos *pos) | |
184 | { | |
185 | const char *fname = "<no-file>"; | |
186 | char *pos_str; | |
187 | int rc; | |
188 | ||
189 | if (pos) | |
190 | fname = pos->file->name; | |
191 | ||
192 | ||
193 | if (pos->first_line != pos->last_line) | |
194 | rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname, | |
195 | pos->first_line, pos->first_column, | |
196 | pos->last_line, pos->last_column); | |
197 | else if (pos->first_column != pos->last_column) | |
198 | rc = asprintf(&pos_str, "%s:%d.%d-%d", fname, | |
199 | pos->first_line, pos->first_column, | |
200 | pos->last_column); | |
201 | else | |
202 | rc = asprintf(&pos_str, "%s:%d.%d", fname, | |
203 | pos->first_line, pos->first_column); | |
204 | ||
205 | if (rc == -1) | |
206 | die("Couldn't allocate in srcpos string"); | |
207 | ||
208 | return pos_str; | |
209 | } | |
210 | ||
211 | void | |
212 | srcpos_verror(struct srcpos *pos, char const *fmt, va_list va) | |
213 | { | |
214 | const char *srcstr; | |
215 | ||
216 | srcstr = srcpos_string(pos); | |
217 | ||
218 | fprintf(stdout, "Error: %s ", srcstr); | |
219 | vfprintf(stdout, fmt, va); | |
220 | fprintf(stdout, "\n"); | |
a4da2e3e DG |
221 | } |
222 | ||
658f29a5 JB |
223 | void |
224 | srcpos_error(struct srcpos *pos, char const *fmt, ...) | |
a4da2e3e | 225 | { |
658f29a5 JB |
226 | va_list va; |
227 | ||
228 | va_start(va, fmt); | |
229 | srcpos_verror(pos, fmt, va); | |
230 | va_end(va); | |
231 | } | |
232 | ||
233 | ||
234 | void | |
235 | srcpos_warn(struct srcpos *pos, char const *fmt, ...) | |
236 | { | |
237 | const char *srcstr; | |
238 | va_list va; | |
239 | va_start(va, fmt); | |
240 | ||
241 | srcstr = srcpos_string(pos); | |
242 | ||
243 | fprintf(stderr, "Warning: %s ", srcstr); | |
244 | vfprintf(stderr, fmt, va); | |
245 | fprintf(stderr, "\n"); | |
ed95d745 | 246 | |
658f29a5 | 247 | va_end(va); |
a4da2e3e | 248 | } |