diff options
Diffstat (limited to 'scripts/dtc/srcpos.c')
-rw-r--r-- | scripts/dtc/srcpos.c | 258 |
1 files changed, 195 insertions, 63 deletions
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c index 9641b7628b4..2dbc874288c 100644 --- a/scripts/dtc/srcpos.c +++ b/scripts/dtc/srcpos.c | |||
@@ -17,100 +17,232 @@ | |||
17 | * USA | 17 | * USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #define _GNU_SOURCE | ||
21 | |||
22 | #include <stdio.h> | ||
23 | |||
20 | #include "dtc.h" | 24 | #include "dtc.h" |
21 | #include "srcpos.h" | 25 | #include "srcpos.h" |
22 | 26 | ||
23 | /* | ||
24 | * Like yylineno, this is the current open file pos. | ||
25 | */ | ||
26 | 27 | ||
27 | struct dtc_file *srcpos_file; | 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 */ | ||
28 | 44 | ||
29 | static int dtc_open_one(struct dtc_file *file, | 45 | /* Detect infinite include recursion. */ |
30 | const char *search, | 46 | #define MAX_SRCFILE_DEPTH (100) |
31 | const char *fname) | 47 | static int srcfile_depth; /* = 0 */ |
48 | |||
49 | FILE *srcfile_relative_open(const char *fname, char **fullnamep) | ||
32 | { | 50 | { |
51 | FILE *f; | ||
33 | char *fullname; | 52 | char *fullname; |
34 | 53 | ||
35 | if (search) { | 54 | if (streq(fname, "-")) { |
36 | fullname = xmalloc(strlen(search) + strlen(fname) + 2); | 55 | f = stdin; |
37 | 56 | fullname = xstrdup("<stdin>"); | |
38 | strcpy(fullname, search); | ||
39 | strcat(fullname, "/"); | ||
40 | strcat(fullname, fname); | ||
41 | } else { | 57 | } else { |
42 | fullname = strdup(fname); | 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)); | ||
43 | } | 68 | } |
44 | 69 | ||
45 | file->file = fopen(fullname, "r"); | 70 | if (fullnamep) |
46 | if (!file->file) { | 71 | *fullnamep = fullname; |
72 | else | ||
47 | free(fullname); | 73 | free(fullname); |
48 | return 0; | ||
49 | } | ||
50 | 74 | ||
51 | file->name = fullname; | 75 | return f; |
52 | return 1; | ||
53 | } | 76 | } |
54 | 77 | ||
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 | } | ||
55 | 96 | ||
56 | struct dtc_file *dtc_open_file(const char *fname, | 97 | int srcfile_pop(void) |
57 | const struct search_path *search) | ||
58 | { | 98 | { |
59 | static const struct search_path default_search = { NULL, NULL, NULL }; | 99 | struct srcfile_state *srcfile = current_srcfile; |
60 | 100 | ||
61 | struct dtc_file *file; | 101 | assert(srcfile); |
62 | const char *slash; | ||
63 | 102 | ||
64 | file = xmalloc(sizeof(struct dtc_file)); | 103 | current_srcfile = srcfile->prev; |
65 | 104 | ||
66 | slash = strrchr(fname, '/'); | 105 | if (fclose(srcfile->f)) |
67 | if (slash) { | 106 | die("Error closing \"%s\": %s\n", srcfile->name, |
68 | char *dir = xmalloc(slash - fname + 1); | 107 | strerror(errno)); |
69 | 108 | ||
70 | memcpy(dir, fname, slash - fname); | 109 | /* FIXME: We allow the srcfile_state structure to leak, |
71 | dir[slash - fname] = 0; | 110 | * because it could still be referenced from a location |
72 | file->dir = dir; | 111 | * variable being carried through the parser somewhere. To |
73 | } else { | 112 | * fix this we could either allocate all the files from a |
74 | file->dir = NULL; | 113 | * table, or use a pool allocator. */ |
75 | } | ||
76 | 114 | ||
77 | if (streq(fname, "-")) { | 115 | return current_srcfile ? 1 : 0; |
78 | file->name = "stdin"; | 116 | } |
79 | file->file = stdin; | ||
80 | return file; | ||
81 | } | ||
82 | 117 | ||
83 | if (fname[0] == '/') { | 118 | /* |
84 | file->file = fopen(fname, "r"); | 119 | * The empty source position. |
85 | if (!file->file) | 120 | */ |
86 | goto fail; | ||
87 | 121 | ||
88 | file->name = strdup(fname); | 122 | struct srcpos srcpos_empty = { |
89 | return file; | 123 | .first_line = 0, |
90 | } | 124 | .first_column = 0, |
125 | .last_line = 0, | ||
126 | .last_column = 0, | ||
127 | .file = NULL, | ||
128 | }; | ||
91 | 129 | ||
92 | if (!search) | 130 | #define TAB_SIZE 8 |
93 | search = &default_search; | ||
94 | 131 | ||
95 | while (search) { | 132 | void srcpos_update(struct srcpos *pos, const char *text, int len) |
96 | if (dtc_open_one(file, search->dir, fname)) | 133 | { |
97 | return file; | 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 | } | ||
98 | 155 | ||
99 | if (errno != ENOENT) | 156 | struct srcpos * |
100 | goto fail; | 157 | srcpos_copy(struct srcpos *pos) |
158 | { | ||
159 | struct srcpos *pos_new; | ||
101 | 160 | ||
102 | search = search->next; | 161 | pos_new = xmalloc(sizeof(struct srcpos)); |
103 | } | 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 | } | ||
104 | 180 | ||
105 | fail: | 181 | |
106 | die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); | 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"); | ||
107 | } | 221 | } |
108 | 222 | ||
109 | void dtc_close_file(struct dtc_file *file) | 223 | void |
224 | srcpos_error(struct srcpos *pos, char const *fmt, ...) | ||
110 | { | 225 | { |
111 | if (fclose(file->file)) | 226 | va_list va; |
112 | die("Error closing \"%s\": %s\n", file->name, strerror(errno)); | 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"); | ||
113 | 246 | ||
114 | free(file->dir); | 247 | va_end(va); |
115 | free(file); | ||
116 | } | 248 | } |