Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
srcpos.c
Go to the documentation of this file.
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 
37 static char *dirname(const char *path)
38 {
39  const char *slash = strrchr(path, '/');
40 
41  if (slash) {
42  int len = slash - path;
43  char *dir = xmalloc(len + 1);
44 
45  memcpy(dir, path, len);
46  dir[len] = '\0';
47  return dir;
48  }
49  return NULL;
50 }
51 
52 FILE *depfile; /* = NULL */
53 struct srcfile_state *current_srcfile; /* = NULL */
54 
55 /* Detect infinite include recursion. */
56 #define MAX_SRCFILE_DEPTH (100)
57 static int srcfile_depth; /* = 0 */
58 
59 
71 static char *try_open(const char *dirname, const char *fname, FILE **fp)
72 {
73  char *fullname;
74 
75  if (!dirname || fname[0] == '/')
76  fullname = xstrdup(fname);
77  else
78  fullname = join_path(dirname, fname);
79 
80  *fp = fopen(fullname, "r");
81  if (!*fp) {
82  free(fullname);
83  fullname = NULL;
84  }
85 
86  return fullname;
87 }
88 
98 static char *fopen_any_on_path(const char *fname, FILE **fp)
99 {
100  const char *cur_dir = NULL;
101  struct search_path *node;
102  char *fullname;
103 
104  /* Try current directory first */
105  assert(fp);
106  if (current_srcfile)
107  cur_dir = current_srcfile->dir;
108  fullname = try_open(cur_dir, fname, fp);
109 
110  /* Failing that, try each search path in turn */
111  for (node = search_path_head; !*fp && node; node = node->next)
112  fullname = try_open(node->dirname, fname, fp);
113 
114  return fullname;
115 }
116 
117 FILE *srcfile_relative_open(const char *fname, char **fullnamep)
118 {
119  FILE *f;
120  char *fullname;
121 
122  if (streq(fname, "-")) {
123  f = stdin;
124  fullname = xstrdup("<stdin>");
125  } else {
126  fullname = fopen_any_on_path(fname, &f);
127  if (!f)
128  die("Couldn't open \"%s\": %s\n", fname,
129  strerror(errno));
130  }
131 
132  if (depfile)
133  fprintf(depfile, " %s", fullname);
134 
135  if (fullnamep)
136  *fullnamep = fullname;
137  else
138  free(fullname);
139 
140  return f;
141 }
142 
143 void srcfile_push(const char *fname)
144 {
145  struct srcfile_state *srcfile;
146 
147  if (srcfile_depth++ >= MAX_SRCFILE_DEPTH)
148  die("Includes nested too deeply");
149 
150  srcfile = xmalloc(sizeof(*srcfile));
151 
152  srcfile->f = srcfile_relative_open(fname, &srcfile->name);
153  srcfile->dir = dirname(srcfile->name);
154  srcfile->prev = current_srcfile;
155 
156  srcfile->lineno = 1;
157  srcfile->colno = 1;
158 
159  current_srcfile = srcfile;
160 }
161 
162 int srcfile_pop(void)
163 {
164  struct srcfile_state *srcfile = current_srcfile;
165 
166  assert(srcfile);
167 
168  current_srcfile = srcfile->prev;
169 
170  if (fclose(srcfile->f))
171  die("Error closing \"%s\": %s\n", srcfile->name,
172  strerror(errno));
173 
174  /* FIXME: We allow the srcfile_state structure to leak,
175  * because it could still be referenced from a location
176  * variable being carried through the parser somewhere. To
177  * fix this we could either allocate all the files from a
178  * table, or use a pool allocator. */
179 
180  return current_srcfile ? 1 : 0;
181 }
182 
183 void srcfile_add_search_path(const char *dirname)
184 {
185  struct search_path *node;
186 
187  /* Create the node */
188  node = xmalloc(sizeof(*node));
189  node->next = NULL;
190  node->dirname = xstrdup(dirname);
191 
192  /* Add to the end of our list */
193  if (search_path_tail)
194  *search_path_tail = node;
195  else
196  search_path_head = node;
197  search_path_tail = &node->next;
198 }
199 
200 /*
201  * The empty source position.
202  */
203 
205  .first_line = 0,
206  .first_column = 0,
207  .last_line = 0,
208  .last_column = 0,
209  .file = NULL,
210 };
211 
212 #define TAB_SIZE 8
213 
214 void srcpos_update(struct srcpos *pos, const char *text, int len)
215 {
216  int i;
217 
218  pos->file = current_srcfile;
219 
220  pos->first_line = current_srcfile->lineno;
221  pos->first_column = current_srcfile->colno;
222 
223  for (i = 0; i < len; i++)
224  if (text[i] == '\n') {
225  current_srcfile->lineno++;
226  current_srcfile->colno = 1;
227  } else if (text[i] == '\t') {
228  current_srcfile->colno =
229  ALIGN(current_srcfile->colno, TAB_SIZE);
230  } else {
231  current_srcfile->colno++;
232  }
233 
234  pos->last_line = current_srcfile->lineno;
235  pos->last_column = current_srcfile->colno;
236 }
237 
238 struct srcpos *
240 {
241  struct srcpos *pos_new;
242 
243  pos_new = xmalloc(sizeof(struct srcpos));
244  memcpy(pos_new, pos, sizeof(struct srcpos));
245 
246  return pos_new;
247 }
248 
249 
250 
251 void
253 {
254  printf("file : \"%s\"\n",
255  pos->file ? (char *) pos->file : "<no file>");
256  printf("first_line : %d\n", pos->first_line);
257  printf("first_column: %d\n", pos->first_column);
258  printf("last_line : %d\n", pos->last_line);
259  printf("last_column : %d\n", pos->last_column);
260  printf("file : %s\n", pos->file->name);
261 }
262 
263 
264 char *
266 {
267  const char *fname = "<no-file>";
268  char *pos_str;
269  int rc;
270 
271  if (pos)
272  fname = pos->file->name;
273 
274 
275  if (pos->first_line != pos->last_line)
276  rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
277  pos->first_line, pos->first_column,
278  pos->last_line, pos->last_column);
279  else if (pos->first_column != pos->last_column)
280  rc = asprintf(&pos_str, "%s:%d.%d-%d", fname,
281  pos->first_line, pos->first_column,
282  pos->last_column);
283  else
284  rc = asprintf(&pos_str, "%s:%d.%d", fname,
285  pos->first_line, pos->first_column);
286 
287  if (rc == -1)
288  die("Couldn't allocate in srcpos string");
289 
290  return pos_str;
291 }
292 
293 void
294 srcpos_verror(struct srcpos *pos, char const *fmt, va_list va)
295 {
296  const char *srcstr;
297 
298  srcstr = srcpos_string(pos);
299 
300  fprintf(stdout, "Error: %s ", srcstr);
301  vfprintf(stdout, fmt, va);
302  fprintf(stdout, "\n");
303 }
304 
305 void
306 srcpos_error(struct srcpos *pos, char const *fmt, ...)
307 {
308  va_list va;
309 
310  va_start(va, fmt);
311  srcpos_verror(pos, fmt, va);
312  va_end(va);
313 }
314 
315 
316 void
317 srcpos_warn(struct srcpos *pos, char const *fmt, ...)
318 {
319  const char *srcstr;
320  va_list va;
321  va_start(va, fmt);
322 
323  srcstr = srcpos_string(pos);
324 
325  fprintf(stderr, "Warning: %s ", srcstr);
326  vfprintf(stderr, fmt, va);
327  fprintf(stderr, "\n");
328 
329  va_end(va);
330 }
331 
332 void srcpos_set_line(char *f, int l)
333 {
334  current_srcfile->name = f;
335  current_srcfile->lineno = l;
336 }