dt-bindings: reset: imx7: Fix the spelling of 'indices'
[sfrench/cifs-2.6.git] / scripts / dtc / srcpos.c
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 /* A node in our list of directories to search for source/include files */
28 struct search_path {
29         struct search_path *next;       /* next node in list, NULL for end */
30         const char *dirname;            /* name of directory to search */
31 };
32
33 /* This is the list of directories that we search for source files */
34 static struct search_path *search_path_head, **search_path_tail;
35
36 /* Detect infinite include recursion. */
37 #define MAX_SRCFILE_DEPTH     (100)
38 static int srcfile_depth; /* = 0 */
39
40 static char *get_dirname(const char *path)
41 {
42         const char *slash = strrchr(path, '/');
43
44         if (slash) {
45                 int len = slash - path;
46                 char *dir = xmalloc(len + 1);
47
48                 memcpy(dir, path, len);
49                 dir[len] = '\0';
50                 return dir;
51         }
52         return NULL;
53 }
54
55 FILE *depfile; /* = NULL */
56 struct srcfile_state *current_srcfile; /* = NULL */
57 static char *initial_path; /* = NULL */
58 static int initial_pathlen; /* = 0 */
59 static bool initial_cpp = true;
60
61 static void set_initial_path(char *fname)
62 {
63         int i, len = strlen(fname);
64
65         xasprintf(&initial_path, "%s", fname);
66         initial_pathlen = 0;
67         for (i = 0; i != len; i++)
68                 if (initial_path[i] == '/')
69                         initial_pathlen++;
70 }
71
72 static char *shorten_to_initial_path(char *fname)
73 {
74         char *p1, *p2, *prevslash1 = NULL;
75         int slashes = 0;
76
77         for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) {
78                 if (*p1 != *p2)
79                         break;
80                 if (*p1 == '/') {
81                         prevslash1 = p1;
82                         slashes++;
83                 }
84         }
85         p1 = prevslash1 + 1;
86         if (prevslash1) {
87                 int diff = initial_pathlen - slashes, i, j;
88                 int restlen = strlen(fname) - (p1 - fname);
89                 char *res;
90
91                 res = xmalloc((3 * diff) + restlen + 1);
92                 for (i = 0, j = 0; i != diff; i++) {
93                         res[j++] = '.';
94                         res[j++] = '.';
95                         res[j++] = '/';
96                 }
97                 strcpy(res + j, p1);
98                 return res;
99         }
100         return NULL;
101 }
102
103 /**
104  * Try to open a file in a given directory.
105  *
106  * If the filename is an absolute path, then dirname is ignored. If it is a
107  * relative path, then we look in that directory for the file.
108  *
109  * @param dirname       Directory to look in, or NULL for none
110  * @param fname         Filename to look for
111  * @param fp            Set to NULL if file did not open
112  * @return allocated filename on success (caller must free), NULL on failure
113  */
114 static char *try_open(const char *dirname, const char *fname, FILE **fp)
115 {
116         char *fullname;
117
118         if (!dirname || fname[0] == '/')
119                 fullname = xstrdup(fname);
120         else
121                 fullname = join_path(dirname, fname);
122
123         *fp = fopen(fullname, "rb");
124         if (!*fp) {
125                 free(fullname);
126                 fullname = NULL;
127         }
128
129         return fullname;
130 }
131
132 /**
133  * Open a file for read access
134  *
135  * If it is a relative filename, we search the full search path for it.
136  *
137  * @param fname Filename to open
138  * @param fp    Returns pointer to opened FILE, or NULL on failure
139  * @return pointer to allocated filename, which caller must free
140  */
141 static char *fopen_any_on_path(const char *fname, FILE **fp)
142 {
143         const char *cur_dir = NULL;
144         struct search_path *node;
145         char *fullname;
146
147         /* Try current directory first */
148         assert(fp);
149         if (current_srcfile)
150                 cur_dir = current_srcfile->dir;
151         fullname = try_open(cur_dir, fname, fp);
152
153         /* Failing that, try each search path in turn */
154         for (node = search_path_head; !*fp && node; node = node->next)
155                 fullname = try_open(node->dirname, fname, fp);
156
157         return fullname;
158 }
159
160 FILE *srcfile_relative_open(const char *fname, char **fullnamep)
161 {
162         FILE *f;
163         char *fullname;
164
165         if (streq(fname, "-")) {
166                 f = stdin;
167                 fullname = xstrdup("<stdin>");
168         } else {
169                 fullname = fopen_any_on_path(fname, &f);
170                 if (!f)
171                         die("Couldn't open \"%s\": %s\n", fname,
172                             strerror(errno));
173         }
174
175         if (depfile)
176                 fprintf(depfile, " %s", fullname);
177
178         if (fullnamep)
179                 *fullnamep = fullname;
180         else
181                 free(fullname);
182
183         return f;
184 }
185
186 void srcfile_push(const char *fname)
187 {
188         struct srcfile_state *srcfile;
189
190         if (srcfile_depth++ >= MAX_SRCFILE_DEPTH)
191                 die("Includes nested too deeply");
192
193         srcfile = xmalloc(sizeof(*srcfile));
194
195         srcfile->f = srcfile_relative_open(fname, &srcfile->name);
196         srcfile->dir = get_dirname(srcfile->name);
197         srcfile->prev = current_srcfile;
198
199         srcfile->lineno = 1;
200         srcfile->colno = 1;
201
202         current_srcfile = srcfile;
203
204         if (srcfile_depth == 1)
205                 set_initial_path(srcfile->name);
206 }
207
208 bool srcfile_pop(void)
209 {
210         struct srcfile_state *srcfile = current_srcfile;
211
212         assert(srcfile);
213
214         current_srcfile = srcfile->prev;
215
216         if (fclose(srcfile->f))
217                 die("Error closing \"%s\": %s\n", srcfile->name,
218                     strerror(errno));
219
220         /* FIXME: We allow the srcfile_state structure to leak,
221          * because it could still be referenced from a location
222          * variable being carried through the parser somewhere.  To
223          * fix this we could either allocate all the files from a
224          * table, or use a pool allocator. */
225
226         return current_srcfile ? true : false;
227 }
228
229 void srcfile_add_search_path(const char *dirname)
230 {
231         struct search_path *node;
232
233         /* Create the node */
234         node = xmalloc(sizeof(*node));
235         node->next = NULL;
236         node->dirname = xstrdup(dirname);
237
238         /* Add to the end of our list */
239         if (search_path_tail)
240                 *search_path_tail = node;
241         else
242                 search_path_head = node;
243         search_path_tail = &node->next;
244 }
245
246 void srcpos_update(struct srcpos *pos, const char *text, int len)
247 {
248         int i;
249
250         pos->file = current_srcfile;
251
252         pos->first_line = current_srcfile->lineno;
253         pos->first_column = current_srcfile->colno;
254
255         for (i = 0; i < len; i++)
256                 if (text[i] == '\n') {
257                         current_srcfile->lineno++;
258                         current_srcfile->colno = 1;
259                 } else {
260                         current_srcfile->colno++;
261                 }
262
263         pos->last_line = current_srcfile->lineno;
264         pos->last_column = current_srcfile->colno;
265 }
266
267 struct srcpos *
268 srcpos_copy(struct srcpos *pos)
269 {
270         struct srcpos *pos_new;
271         struct srcfile_state *srcfile_state;
272
273         if (!pos)
274                 return NULL;
275
276         pos_new = xmalloc(sizeof(struct srcpos));
277         assert(pos->next == NULL);
278         memcpy(pos_new, pos, sizeof(struct srcpos));
279
280         /* allocate without free */
281         srcfile_state = xmalloc(sizeof(struct srcfile_state));
282         memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state));
283         pos_new->file = srcfile_state;
284
285         return pos_new;
286 }
287
288 struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
289 {
290         struct srcpos *p;
291
292         if (!pos)
293                 return newtail;
294
295         for (p = pos; p->next != NULL; p = p->next);
296         p->next = newtail;
297         return pos;
298 }
299
300 char *
301 srcpos_string(struct srcpos *pos)
302 {
303         const char *fname = "<no-file>";
304         char *pos_str;
305
306         if (pos->file && pos->file->name)
307                 fname = pos->file->name;
308
309
310         if (pos->first_line != pos->last_line)
311                 xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
312                           pos->first_line, pos->first_column,
313                           pos->last_line, pos->last_column);
314         else if (pos->first_column != pos->last_column)
315                 xasprintf(&pos_str, "%s:%d.%d-%d", fname,
316                           pos->first_line, pos->first_column,
317                           pos->last_column);
318         else
319                 xasprintf(&pos_str, "%s:%d.%d", fname,
320                           pos->first_line, pos->first_column);
321
322         return pos_str;
323 }
324
325 static char *
326 srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
327 {
328         char *pos_str, *fname, *first, *rest;
329         bool fresh_fname = false;
330
331         if (!pos) {
332                 if (level > 1) {
333                         xasprintf(&pos_str, "<no-file>:<no-line>");
334                         return pos_str;
335                 } else {
336                         return NULL;
337                 }
338         }
339
340         if (!pos->file)
341                 fname = "<no-file>";
342         else if (!pos->file->name)
343                 fname = "<no-filename>";
344         else if (level > 1)
345                 fname = pos->file->name;
346         else {
347                 fname = shorten_to_initial_path(pos->file->name);
348                 if (fname)
349                         fresh_fname = true;
350                 else
351                         fname = pos->file->name;
352         }
353
354         if (level > 1)
355                 xasprintf(&first, "%s:%d:%d-%d:%d", fname,
356                           pos->first_line, pos->first_column,
357                           pos->last_line, pos->last_column);
358         else
359                 xasprintf(&first, "%s:%d", fname,
360                           first_line ? pos->first_line : pos->last_line);
361
362         if (fresh_fname)
363                 free(fname);
364
365         if (pos->next != NULL) {
366                 rest = srcpos_string_comment(pos->next, first_line, level);
367                 xasprintf(&pos_str, "%s, %s", first, rest);
368                 free(first);
369                 free(rest);
370         } else {
371                 pos_str = first;
372         }
373
374         return pos_str;
375 }
376
377 char *srcpos_string_first(struct srcpos *pos, int level)
378 {
379         return srcpos_string_comment(pos, true, level);
380 }
381
382 char *srcpos_string_last(struct srcpos *pos, int level)
383 {
384         return srcpos_string_comment(pos, false, level);
385 }
386
387 void srcpos_verror(struct srcpos *pos, const char *prefix,
388                    const char *fmt, va_list va)
389 {
390         char *srcstr;
391
392         srcstr = srcpos_string(pos);
393
394         fprintf(stderr, "%s: %s ", prefix, srcstr);
395         vfprintf(stderr, fmt, va);
396         fprintf(stderr, "\n");
397
398         free(srcstr);
399 }
400
401 void srcpos_error(struct srcpos *pos, const char *prefix,
402                   const char *fmt, ...)
403 {
404         va_list va;
405
406         va_start(va, fmt);
407         srcpos_verror(pos, prefix, fmt, va);
408         va_end(va);
409 }
410
411 void srcpos_set_line(char *f, int l)
412 {
413         current_srcfile->name = f;
414         current_srcfile->lineno = l;
415
416         if (initial_cpp) {
417                 initial_cpp = false;
418                 set_initial_path(f);
419         }
420 }