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 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 FILE *depfile; /* = NULL */ 44 struct srcfile_state *current_srcfile; /* = NULL */ 45 46 /* Detect infinite include recursion. */ 47 #define MAX_SRCFILE_DEPTH (100) 48 static int srcfile_depth; /* = 0 */ 49 50 FILE *srcfile_relative_open(const char *fname, char **fullnamep) 51 { 52 FILE *f; 53 char *fullname; 54 55 if (streq(fname, "-")) { 56 f = stdin; 57 fullname = xstrdup("<stdin>"); 58 } else { 59 if (!current_srcfile || !current_srcfile->dir 60 || (fname[0] == '/')) 61 fullname = xstrdup(fname); 62 else 63 fullname = join_path(current_srcfile->dir, fname); 64 65 f = fopen(fullname, "r"); 66 if (!f) 67 die("Couldn't open \"%s\": %s\n", fname, 68 strerror(errno)); 69 } 70 71 if (depfile) 72 fprintf(depfile, " %s", fullname); 73 74 if (fullnamep) 75 *fullnamep = fullname; 76 else 77 free(fullname); 78 79 return f; 80 } 81 82 void srcfile_push(const char *fname) 83 { 84 struct srcfile_state *srcfile; 85 86 if (srcfile_depth++ >= MAX_SRCFILE_DEPTH) 87 die("Includes nested too deeply"); 88 89 srcfile = xmalloc(sizeof(*srcfile)); 90 91 srcfile->f = srcfile_relative_open(fname, &srcfile->name); 92 srcfile->dir = dirname(srcfile->name); 93 srcfile->prev = current_srcfile; 94 95 srcfile->lineno = 1; 96 srcfile->colno = 1; 97 98 current_srcfile = srcfile; 99 } 100 101 int srcfile_pop(void) 102 { 103 struct srcfile_state *srcfile = current_srcfile; 104 105 assert(srcfile); 106 107 current_srcfile = srcfile->prev; 108 109 if (fclose(srcfile->f)) 110 die("Error closing \"%s\": %s\n", srcfile->name, 111 strerror(errno)); 112 113 /* FIXME: We allow the srcfile_state structure to leak, 114 * because it could still be referenced from a location 115 * variable being carried through the parser somewhere. To 116 * fix this we could either allocate all the files from a 117 * table, or use a pool allocator. */ 118 119 return current_srcfile ? 1 : 0; 120 } 121 122 /* 123 * The empty source position. 124 */ 125 126 struct srcpos srcpos_empty = { 127 .first_line = 0, 128 .first_column = 0, 129 .last_line = 0, 130 .last_column = 0, 131 .file = NULL, 132 }; 133 134 #define TAB_SIZE 8 135 136 void srcpos_update(struct srcpos *pos, const char *text, int len) 137 { 138 int i; 139 140 pos->file = current_srcfile; 141 142 pos->first_line = current_srcfile->lineno; 143 pos->first_column = current_srcfile->colno; 144 145 for (i = 0; i < len; i++) 146 if (text[i] == '\n') { 147 current_srcfile->lineno++; 148 current_srcfile->colno = 1; 149 } else if (text[i] == '\t') { 150 current_srcfile->colno = 151 ALIGN(current_srcfile->colno, TAB_SIZE); 152 } else { 153 current_srcfile->colno++; 154 } 155 156 pos->last_line = current_srcfile->lineno; 157 pos->last_column = current_srcfile->colno; 158 } 159 160 struct srcpos * 161 srcpos_copy(struct srcpos *pos) 162 { 163 struct srcpos *pos_new; 164 165 pos_new = xmalloc(sizeof(struct srcpos)); 166 memcpy(pos_new, pos, sizeof(struct srcpos)); 167 168 return pos_new; 169 } 170 171 172 173 void 174 srcpos_dump(struct srcpos *pos) 175 { 176 printf("file : \"%s\"\n", 177 pos->file ? (char *) pos->file : "<no file>"); 178 printf("first_line : %d\n", pos->first_line); 179 printf("first_column: %d\n", pos->first_column); 180 printf("last_line : %d\n", pos->last_line); 181 printf("last_column : %d\n", pos->last_column); 182 printf("file : %s\n", pos->file->name); 183 } 184 185 186 char * 187 srcpos_string(struct srcpos *pos) 188 { 189 const char *fname = "<no-file>"; 190 char *pos_str; 191 int rc; 192 193 if (pos) 194 fname = pos->file->name; 195 196 197 if (pos->first_line != pos->last_line) 198 rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname, 199 pos->first_line, pos->first_column, 200 pos->last_line, pos->last_column); 201 else if (pos->first_column != pos->last_column) 202 rc = asprintf(&pos_str, "%s:%d.%d-%d", fname, 203 pos->first_line, pos->first_column, 204 pos->last_column); 205 else 206 rc = asprintf(&pos_str, "%s:%d.%d", fname, 207 pos->first_line, pos->first_column); 208 209 if (rc == -1) 210 die("Couldn't allocate in srcpos string"); 211 212 return pos_str; 213 } 214 215 void 216 srcpos_verror(struct srcpos *pos, char const *fmt, va_list va) 217 { 218 const char *srcstr; 219 220 srcstr = srcpos_string(pos); 221 222 fprintf(stdout, "Error: %s ", srcstr); 223 vfprintf(stdout, fmt, va); 224 fprintf(stdout, "\n"); 225 } 226 227 void 228 srcpos_error(struct srcpos *pos, char const *fmt, ...) 229 { 230 va_list va; 231 232 va_start(va, fmt); 233 srcpos_verror(pos, fmt, va); 234 va_end(va); 235 } 236 237 238 void 239 srcpos_warn(struct srcpos *pos, char const *fmt, ...) 240 { 241 const char *srcstr; 242 va_list va; 243 va_start(va, fmt); 244 245 srcstr = srcpos_string(pos); 246 247 fprintf(stderr, "Warning: %s ", srcstr); 248 vfprintf(stderr, fmt, va); 249 fprintf(stderr, "\n"); 250 251 va_end(va); 252 } 253