"Das U-Boot" Source Tree
at master 294 lines 6.9 kB view raw
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 */ 28struct 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 */ 34static struct search_path *search_path_head, **search_path_tail; 35 36static char *get_dirname(const char *path) 37{ 38 const char *slash = strrchr(path, '/'); 39 40 if (slash) { 41 int len = slash - path; 42 char *dir = xmalloc(len + 1); 43 44 memcpy(dir, path, len); 45 dir[len] = '\0'; 46 return dir; 47 } 48 return NULL; 49} 50 51FILE *depfile; /* = NULL */ 52struct srcfile_state *current_srcfile; /* = NULL */ 53 54/* Detect infinite include recursion. */ 55#define MAX_SRCFILE_DEPTH (100) 56static int srcfile_depth; /* = 0 */ 57 58/** 59 * Try to open a file in a given directory. 60 * 61 * If the filename is an absolute path, then dirname is ignored. If it is a 62 * relative path, then we look in that directory for the file. 63 * 64 * @param dirname Directory to look in, or NULL for none 65 * @param fname Filename to look for 66 * @param fp Set to NULL if file did not open 67 * Return: allocated filename on success (caller must free), NULL on failure 68 */ 69static char *try_open(const char *dirname, const char *fname, FILE **fp) 70{ 71 char *fullname; 72 73 if (!dirname || fname[0] == '/') 74 fullname = xstrdup(fname); 75 else 76 fullname = join_path(dirname, fname); 77 78 *fp = fopen(fullname, "rb"); 79 if (!*fp) { 80 free(fullname); 81 fullname = NULL; 82 } 83 84 return fullname; 85} 86 87/** 88 * Open a file for read access 89 * 90 * If it is a relative filename, we search the full search path for it. 91 * 92 * @param fname Filename to open 93 * @param fp Returns pointer to opened FILE, or NULL on failure 94 * Return: pointer to allocated filename, which caller must free 95 */ 96static char *fopen_any_on_path(const char *fname, FILE **fp) 97{ 98 const char *cur_dir = NULL; 99 struct search_path *node; 100 char *fullname; 101 102 /* Try current directory first */ 103 assert(fp); 104 if (current_srcfile) 105 cur_dir = current_srcfile->dir; 106 fullname = try_open(cur_dir, fname, fp); 107 108 /* Failing that, try each search path in turn */ 109 for (node = search_path_head; !*fp && node; node = node->next) 110 fullname = try_open(node->dirname, fname, fp); 111 112 return fullname; 113} 114 115FILE *srcfile_relative_open(const char *fname, char **fullnamep) 116{ 117 FILE *f; 118 char *fullname; 119 120 if (streq(fname, "-")) { 121 f = stdin; 122 fullname = xstrdup("<stdin>"); 123 } else { 124 fullname = fopen_any_on_path(fname, &f); 125 if (!f) 126 die("Couldn't open \"%s\": %s\n", fname, 127 strerror(errno)); 128 } 129 130 if (depfile) 131 fprintf(depfile, " %s", fullname); 132 133 if (fullnamep) 134 *fullnamep = fullname; 135 else 136 free(fullname); 137 138 return f; 139} 140 141void srcfile_push(const char *fname) 142{ 143 struct srcfile_state *srcfile; 144 145 if (srcfile_depth++ >= MAX_SRCFILE_DEPTH) 146 die("Includes nested too deeply"); 147 148 srcfile = xmalloc(sizeof(*srcfile)); 149 150 srcfile->f = srcfile_relative_open(fname, &srcfile->name); 151 srcfile->dir = get_dirname(srcfile->name); 152 srcfile->prev = current_srcfile; 153 154 srcfile->lineno = 1; 155 srcfile->colno = 1; 156 157 current_srcfile = srcfile; 158} 159 160bool srcfile_pop(void) 161{ 162 struct srcfile_state *srcfile = current_srcfile; 163 164 assert(srcfile); 165 166 current_srcfile = srcfile->prev; 167 168 if (fclose(srcfile->f)) 169 die("Error closing \"%s\": %s\n", srcfile->name, 170 strerror(errno)); 171 172 /* FIXME: We allow the srcfile_state structure to leak, 173 * because it could still be referenced from a location 174 * variable being carried through the parser somewhere. To 175 * fix this we could either allocate all the files from a 176 * table, or use a pool allocator. */ 177 178 return current_srcfile ? true : false; 179} 180 181void srcfile_add_search_path(const char *dirname) 182{ 183 struct search_path *node; 184 185 /* Create the node */ 186 node = xmalloc(sizeof(*node)); 187 node->next = NULL; 188 node->dirname = xstrdup(dirname); 189 190 /* Add to the end of our list */ 191 if (search_path_tail) 192 *search_path_tail = node; 193 else 194 search_path_head = node; 195 search_path_tail = &node->next; 196} 197 198/* 199 * The empty source position. 200 */ 201 202struct srcpos srcpos_empty = { 203 .first_line = 0, 204 .first_column = 0, 205 .last_line = 0, 206 .last_column = 0, 207 .file = NULL, 208}; 209 210void srcpos_update(struct srcpos *pos, const char *text, int len) 211{ 212 int i; 213 214 pos->file = current_srcfile; 215 216 pos->first_line = current_srcfile->lineno; 217 pos->first_column = current_srcfile->colno; 218 219 for (i = 0; i < len; i++) 220 if (text[i] == '\n') { 221 current_srcfile->lineno++; 222 current_srcfile->colno = 1; 223 } else { 224 current_srcfile->colno++; 225 } 226 227 pos->last_line = current_srcfile->lineno; 228 pos->last_column = current_srcfile->colno; 229} 230 231struct srcpos * 232srcpos_copy(struct srcpos *pos) 233{ 234 struct srcpos *pos_new; 235 236 pos_new = xmalloc(sizeof(struct srcpos)); 237 memcpy(pos_new, pos, sizeof(struct srcpos)); 238 239 return pos_new; 240} 241 242char * 243srcpos_string(struct srcpos *pos) 244{ 245 const char *fname = "<no-file>"; 246 char *pos_str; 247 248 if (pos->file && pos->file->name) 249 fname = pos->file->name; 250 251 if (pos->first_line != pos->last_line) 252 xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname, 253 pos->first_line, pos->first_column, 254 pos->last_line, pos->last_column); 255 else if (pos->first_column != pos->last_column) 256 xasprintf(&pos_str, "%s:%d.%d-%d", fname, 257 pos->first_line, pos->first_column, 258 pos->last_column); 259 else 260 xasprintf(&pos_str, "%s:%d.%d", fname, 261 pos->first_line, pos->first_column); 262 263 return pos_str; 264} 265 266void srcpos_verror(struct srcpos *pos, const char *prefix, 267 const char *fmt, va_list va) 268{ 269 char *srcstr; 270 271 srcstr = srcpos_string(pos); 272 273 fprintf(stderr, "%s: %s ", prefix, srcstr); 274 vfprintf(stderr, fmt, va); 275 fprintf(stderr, "\n"); 276 277 free(srcstr); 278} 279 280void srcpos_error(struct srcpos *pos, const char *prefix, 281 const char *fmt, ...) 282{ 283 va_list va; 284 285 va_start(va, fmt); 286 srcpos_verror(pos, prefix, fmt, va); 287 va_end(va); 288} 289 290void srcpos_set_line(char *f, int l) 291{ 292 current_srcfile->name = f; 293 current_srcfile->lineno = l; 294}