1204431Sraj/* 2204431Sraj * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. 3204431Sraj * 4204431Sraj * This program is free software; you can redistribute it and/or 5204431Sraj * modify it under the terms of the GNU General Public License as 6204431Sraj * published by the Free Software Foundation; either version 2 of the 7204431Sraj * License, or (at your option) any later version. 8204431Sraj * 9204431Sraj * This program is distributed in the hope that it will be useful, 10204431Sraj * but WITHOUT ANY WARRANTY; without even the implied warranty of 11204431Sraj * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12204431Sraj * General Public License for more details. 13204431Sraj * 14204431Sraj * You should have received a copy of the GNU General Public License 15204431Sraj * along with this program; if not, write to the Free Software 16204431Sraj * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 17204431Sraj * USA 18204431Sraj */ 19204431Sraj 20204433Sraj#define _GNU_SOURCE 21204433Sraj 22204433Sraj#include <stdio.h> 23204433Sraj 24204431Sraj#include "dtc.h" 25204431Sraj#include "srcpos.h" 26204431Sraj 27238742Simp/* A node in our list of directories to search for source/include files */ 28238742Simpstruct search_path { 29238742Simp struct search_path *next; /* next node in list, NULL for end */ 30238742Simp const char *dirname; /* name of directory to search */ 31238742Simp}; 32204433Sraj 33238742Simp/* This is the list of directories that we search for source files */ 34238742Simpstatic struct search_path *search_path_head, **search_path_tail; 35204431Sraj 36204433Sraj 37318102Sgonzostatic char *get_dirname(const char *path) 38238742Simp{ 39238742Simp const char *slash = strrchr(path, '/'); 40204433Sraj 41238742Simp if (slash) { 42238742Simp int len = slash - path; 43238742Simp char *dir = xmalloc(len + 1); 44204433Sraj 45238742Simp memcpy(dir, path, len); 46238742Simp dir[len] = '\0'; 47238742Simp return dir; 48238742Simp } 49238742Simp return NULL; 50238742Simp} 51204433Sraj 52238742SimpFILE *depfile; /* = NULL */ 53238742Simpstruct srcfile_state *current_srcfile; /* = NULL */ 54238742Simp 55238742Simp/* Detect infinite include recursion. */ 56238742Simp#define MAX_SRCFILE_DEPTH (100) 57238742Simpstatic int srcfile_depth; /* = 0 */ 58238742Simp 59238742Simp 60238742Simp/** 61238742Simp * Try to open a file in a given directory. 62238742Simp * 63238742Simp * If the filename is an absolute path, then dirname is ignored. If it is a 64238742Simp * relative path, then we look in that directory for the file. 65238742Simp * 66238742Simp * @param dirname Directory to look in, or NULL for none 67238742Simp * @param fname Filename to look for 68238742Simp * @param fp Set to NULL if file did not open 69238742Simp * @return allocated filename on success (caller must free), NULL on failure 70238742Simp */ 71238742Simpstatic char *try_open(const char *dirname, const char *fname, FILE **fp) 72204431Sraj{ 73204431Sraj char *fullname; 74204431Sraj 75238742Simp if (!dirname || fname[0] == '/') 76204433Sraj fullname = xstrdup(fname); 77238742Simp else 78238742Simp fullname = join_path(dirname, fname); 79204431Sraj 80318102Sgonzo *fp = fopen(fullname, "rb"); 81238742Simp if (!*fp) { 82204431Sraj free(fullname); 83238742Simp fullname = NULL; 84204431Sraj } 85204431Sraj 86238742Simp return fullname; 87204431Sraj} 88204431Sraj 89238742Simp/** 90238742Simp * Open a file for read access 91238742Simp * 92238742Simp * If it is a relative filename, we search the full search path for it. 93238742Simp * 94238742Simp * @param fname Filename to open 95238742Simp * @param fp Returns pointer to opened FILE, or NULL on failure 96238742Simp * @return pointer to allocated filename, which caller must free 97238742Simp */ 98238742Simpstatic char *fopen_any_on_path(const char *fname, FILE **fp) 99204431Sraj{ 100238742Simp const char *cur_dir = NULL; 101238742Simp struct search_path *node; 102238742Simp char *fullname; 103204431Sraj 104238742Simp /* Try current directory first */ 105238742Simp assert(fp); 106238742Simp if (current_srcfile) 107238742Simp cur_dir = current_srcfile->dir; 108238742Simp fullname = try_open(cur_dir, fname, fp); 109204431Sraj 110238742Simp /* Failing that, try each search path in turn */ 111238742Simp for (node = search_path_head; !*fp && node; node = node->next) 112238742Simp fullname = try_open(node->dirname, fname, fp); 113204431Sraj 114238742Simp return fullname; 115238742Simp} 116204431Sraj 117238742SimpFILE *srcfile_relative_open(const char *fname, char **fullnamep) 118238742Simp{ 119238742Simp FILE *f; 120238742Simp char *fullname; 121204431Sraj 122204431Sraj if (streq(fname, "-")) { 123238742Simp f = stdin; 124238742Simp fullname = xstrdup("<stdin>"); 125238742Simp } else { 126238742Simp fullname = fopen_any_on_path(fname, &f); 127238742Simp if (!f) 128238742Simp die("Couldn't open \"%s\": %s\n", fname, 129238742Simp strerror(errno)); 130204431Sraj } 131204431Sraj 132238742Simp if (depfile) 133238742Simp fprintf(depfile, " %s", fullname); 134204431Sraj 135238742Simp if (fullnamep) 136238742Simp *fullnamep = fullname; 137238742Simp else 138238742Simp free(fullname); 139204431Sraj 140238742Simp return f; 141238742Simp} 142204431Sraj 143238742Simpvoid srcfile_push(const char *fname) 144238742Simp{ 145238742Simp struct srcfile_state *srcfile; 146204431Sraj 147238742Simp if (srcfile_depth++ >= MAX_SRCFILE_DEPTH) 148238742Simp die("Includes nested too deeply"); 149204431Sraj 150238742Simp srcfile = xmalloc(sizeof(*srcfile)); 151204431Sraj 152238742Simp srcfile->f = srcfile_relative_open(fname, &srcfile->name); 153318102Sgonzo srcfile->dir = get_dirname(srcfile->name); 154238742Simp srcfile->prev = current_srcfile; 155238742Simp 156238742Simp srcfile->lineno = 1; 157238742Simp srcfile->colno = 1; 158238742Simp 159238742Simp current_srcfile = srcfile; 160204431Sraj} 161204431Sraj 162261215Simpbool srcfile_pop(void) 163238742Simp{ 164238742Simp struct srcfile_state *srcfile = current_srcfile; 165204433Sraj 166238742Simp assert(srcfile); 167238742Simp 168238742Simp current_srcfile = srcfile->prev; 169238742Simp 170238742Simp if (fclose(srcfile->f)) 171238742Simp die("Error closing \"%s\": %s\n", srcfile->name, 172238742Simp strerror(errno)); 173238742Simp 174238742Simp /* FIXME: We allow the srcfile_state structure to leak, 175238742Simp * because it could still be referenced from a location 176238742Simp * variable being carried through the parser somewhere. To 177238742Simp * fix this we could either allocate all the files from a 178238742Simp * table, or use a pool allocator. */ 179238742Simp 180261215Simp return current_srcfile ? true : false; 181238742Simp} 182238742Simp 183238742Simpvoid srcfile_add_search_path(const char *dirname) 184204431Sraj{ 185238742Simp struct search_path *node; 186238742Simp 187238742Simp /* Create the node */ 188238742Simp node = xmalloc(sizeof(*node)); 189238742Simp node->next = NULL; 190238742Simp node->dirname = xstrdup(dirname); 191238742Simp 192238742Simp /* Add to the end of our list */ 193238742Simp if (search_path_tail) 194238742Simp *search_path_tail = node; 195238742Simp else 196238742Simp search_path_head = node; 197238742Simp search_path_tail = &node->next; 198204433Sraj} 199204431Sraj 200238742Simp/* 201238742Simp * The empty source position. 202238742Simp */ 203204433Sraj 204238742Simpstruct srcpos srcpos_empty = { 205238742Simp .first_line = 0, 206238742Simp .first_column = 0, 207238742Simp .last_line = 0, 208238742Simp .last_column = 0, 209238742Simp .file = NULL, 210238742Simp}; 211238742Simp 212238742Simp#define TAB_SIZE 8 213238742Simp 214238742Simpvoid srcpos_update(struct srcpos *pos, const char *text, int len) 215204433Sraj{ 216238742Simp int i; 217204433Sraj 218238742Simp pos->file = current_srcfile; 219204433Sraj 220238742Simp pos->first_line = current_srcfile->lineno; 221238742Simp pos->first_column = current_srcfile->colno; 222238742Simp 223238742Simp for (i = 0; i < len; i++) 224238742Simp if (text[i] == '\n') { 225238742Simp current_srcfile->lineno++; 226238742Simp current_srcfile->colno = 1; 227238742Simp } else if (text[i] == '\t') { 228238742Simp current_srcfile->colno = 229238742Simp ALIGN(current_srcfile->colno, TAB_SIZE); 230238742Simp } else { 231238742Simp current_srcfile->colno++; 232238742Simp } 233238742Simp 234238742Simp pos->last_line = current_srcfile->lineno; 235238742Simp pos->last_column = current_srcfile->colno; 236238742Simp} 237238742Simp 238238742Simpstruct srcpos * 239238742Simpsrcpos_copy(struct srcpos *pos) 240238742Simp{ 241238742Simp struct srcpos *pos_new; 242238742Simp 243238742Simp pos_new = xmalloc(sizeof(struct srcpos)); 244238742Simp memcpy(pos_new, pos, sizeof(struct srcpos)); 245238742Simp 246204433Sraj return pos_new; 247204431Sraj} 248204433Sraj 249204433Srajchar * 250238742Simpsrcpos_string(struct srcpos *pos) 251204433Sraj{ 252238742Simp const char *fname = "<no-file>"; 253204433Sraj char *pos_str; 254204433Sraj 255318102Sgonzo if (pos->file && pos->file->name) 256204433Sraj fname = pos->file->name; 257204433Sraj 258204433Sraj 259238742Simp if (pos->first_line != pos->last_line) 260318102Sgonzo xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname, 261318102Sgonzo pos->first_line, pos->first_column, 262318102Sgonzo pos->last_line, pos->last_column); 263238742Simp else if (pos->first_column != pos->last_column) 264318102Sgonzo xasprintf(&pos_str, "%s:%d.%d-%d", fname, 265318102Sgonzo pos->first_line, pos->first_column, 266318102Sgonzo pos->last_column); 267238742Simp else 268318102Sgonzo xasprintf(&pos_str, "%s:%d.%d", fname, 269318102Sgonzo pos->first_line, pos->first_column); 270204433Sraj 271204433Sraj return pos_str; 272204433Sraj} 273204433Sraj 274261215Simpvoid srcpos_verror(struct srcpos *pos, const char *prefix, 275261215Simp const char *fmt, va_list va) 276238742Simp{ 277261215Simp char *srcstr; 278204433Sraj 279261215Simp srcstr = srcpos_string(pos); 280238742Simp 281261215Simp fprintf(stderr, "%s: %s ", prefix, srcstr); 282261215Simp vfprintf(stderr, fmt, va); 283261215Simp fprintf(stderr, "\n"); 284261215Simp 285261215Simp free(srcstr); 286238742Simp} 287238742Simp 288261215Simpvoid srcpos_error(struct srcpos *pos, const char *prefix, 289261215Simp const char *fmt, ...) 290204433Sraj{ 291204433Sraj va_list va; 292238742Simp 293204433Sraj va_start(va, fmt); 294261215Simp srcpos_verror(pos, prefix, fmt, va); 295204433Sraj va_end(va); 296204433Sraj} 297204433Sraj 298261215Simpvoid srcpos_set_line(char *f, int l) 299204433Sraj{ 300261215Simp current_srcfile->name = f; 301261215Simp current_srcfile->lineno = l; 302204433Sraj} 303