1 /* This file is part of the program psim. 2 3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, see <http://www.gnu.org/licenses/>. 17 18 */ 19 20 21 #include <sys/types.h> 22 #include <sys/stat.h> 23 #include <stdio.h> 24 #include <fcntl.h> 25 #include <ctype.h> 26 27 #include "build-config.h" 28 #include "misc.h" 29 #include "lf.h" 30 #include "table.h" 31 32 #ifdef HAVE_UNISTD_H 33 #include <unistd.h> 34 #endif 35 36 #ifdef HAVE_STDLIB_H 37 #include <stdlib.h> 38 #endif 39 40 typedef struct _open_table open_table; 41 struct _open_table { 42 size_t size; 43 char *buffer; 44 char *pos; 45 int line_nr; 46 int nr_fields; 47 int nr_model_fields; 48 char *file_name; 49 open_table *parent; 50 table *root; 51 }; 52 struct _table { 53 open_table *current; 54 }; 55 56 void 57 table_push (table *root, 58 table_include *includes, 59 const char *file_name, 60 int nr_fields, 61 int nr_model_fields) 62 63 { 64 int fd; 65 struct stat stat_buf; 66 open_table *file; 67 table_include dummy; 68 table_include *include = &dummy; 69 int nr; 70 71 /* dummy up a search of this directory */ 72 dummy.next = includes; 73 dummy.dir = ""; 74 75 /* create a file descriptor */ 76 file = ZALLOC (open_table); 77 ASSERT(file != NULL); 78 file->nr_fields = nr_fields; 79 file->nr_model_fields = nr_model_fields; 80 file->root = root; 81 file->parent = root->current; 82 root->current = file; 83 84 while (1) 85 { 86 /* save the file name */ 87 char *dup_name = NZALLOC (char, strlen (include->dir) + strlen (file_name) + 2); 88 if (dup_name == NULL) 89 { 90 perror (file_name); 91 exit (1); 92 } 93 if (include->dir[0] != '\0') 94 { 95 strcat (dup_name, include->dir); 96 strcat (dup_name, "/"); 97 } 98 strcat (dup_name, file_name); 99 file->file_name = dup_name; 100 /* open the file */ 101 fd = open (dup_name, O_RDONLY, 0); 102 if (fd >= 0) 103 break; 104 /* free (dup_name); */ 105 if (include->next == NULL) 106 { 107 error ("Problem opening file `%s'\n", file_name); 108 perror (file_name); 109 exit (1); 110 } 111 include = include->next; 112 } 113 114 /* determine the size */ 115 if (fstat(fd, &stat_buf) < 0) { 116 perror("table_open.fstat"); 117 exit(1); 118 } 119 file->size = stat_buf.st_size; 120 121 /* allocate this much memory */ 122 file->buffer = (char*)zalloc(file->size+1); 123 if(file->buffer == NULL) { 124 perror("table_open.calloc.file->size+1"); 125 exit(1); 126 } 127 file->pos = file->buffer; 128 129 /* read it in */ 130 #ifdef __CYGWIN32__ 131 if ((file->size) && ((nr = read(fd, file->buffer, file->size)) <= 0)) { 132 #else 133 if ((nr = read(fd, file->buffer, file->size)) < file->size) { 134 #endif 135 perror("table_open.read"); 136 exit(1); 137 } 138 file->size = nr; 139 file->buffer[file->size] = '\0'; 140 141 /* done */ 142 close(fd); 143 } 144 145 extern table * 146 table_open(const char *file_name, 147 int nr_fields, 148 int nr_model_fields) 149 { 150 table *root; 151 152 /* create a file descriptor */ 153 root = ZALLOC (table); 154 if (root == NULL) 155 { 156 perror (file_name); 157 exit (1); 158 } 159 160 table_push (root, NULL, file_name, nr_fields, nr_model_fields); 161 return root; 162 } 163 164 extern table_entry * 165 table_entry_read(table *root) 166 { 167 open_table *file = root->current; 168 int field; 169 table_entry *entry; 170 171 /* skip comments/blanks */ 172 while(1) { 173 /* end-of-file? */ 174 while (*file->pos == '\0') 175 { 176 if (file->parent != NULL) 177 { 178 file = file->parent; 179 root->current = file; 180 } 181 else 182 return NULL; 183 } 184 /* leading white space */ 185 while (*file->pos != '\0' 186 && *file->pos != '\n' 187 && isspace(*file->pos)) 188 file->pos++; 189 /* comment */ 190 if (*file->pos == '#') { 191 do { 192 file->pos++; 193 } while (*file->pos != '\0' && *file->pos != '\n'); 194 } 195 /* end of line? */ 196 if (*file->pos == '\n') { 197 file->pos++; 198 file->line_nr++; 199 } 200 else 201 break; 202 } 203 204 /* create this new entry */ 205 entry = (table_entry*)zalloc(sizeof(table_entry) 206 + (file->nr_fields + 1) * sizeof(char*)); 207 ASSERT(entry != NULL); 208 entry->file_name = file->file_name; 209 entry->nr_fields = file->nr_fields; 210 211 /* break the line into its colon delimitered fields */ 212 for (field = 0; field < file->nr_fields-1; field++) { 213 entry->fields[field] = file->pos; 214 while(*file->pos && *file->pos != ':' && *file->pos != '\n') 215 file->pos++; 216 if (*file->pos == ':') { 217 *file->pos = '\0'; 218 file->pos++; 219 } 220 } 221 222 /* any trailing stuff not the last field */ 223 ASSERT(field == file->nr_fields-1); 224 entry->fields[field] = file->pos; 225 while (*file->pos && *file->pos != '\n') { 226 file->pos++; 227 } 228 if (*file->pos == '\n') { 229 *file->pos = '\0'; 230 file->pos++; 231 } 232 file->line_nr++; 233 234 /* if following lines begin with a star, add them to the model 235 section. */ 236 while ((file->nr_model_fields > 0) && (*file->pos == '*')) { 237 table_model_entry *model = (table_model_entry*)zalloc(sizeof(table_model_entry) 238 + (file->nr_model_fields + 1) * sizeof(char*)); 239 if (entry->model_last) 240 entry->model_last->next = model; 241 else 242 entry->model_first = model; 243 entry->model_last = model; 244 245 /* break the line into its colon delimitered fields */ 246 file->pos++; 247 for (field = 0; field < file->nr_model_fields-1; field++) { 248 model->fields[field] = file->pos; 249 while(*file->pos && *file->pos != ':' && *file->pos != '\n') 250 file->pos++; 251 if (*file->pos == ':') { 252 *file->pos = '\0'; 253 file->pos++; 254 } 255 } 256 257 /* any trailing stuff not the last field */ 258 ASSERT(field == file->nr_model_fields-1); 259 model->fields[field] = file->pos; 260 while (*file->pos && *file->pos != '\n') { 261 file->pos++; 262 } 263 if (*file->pos == '\n') { 264 *file->pos = '\0'; 265 file->pos++; 266 } 267 268 file->line_nr++; 269 model->line_nr = file->line_nr; 270 } 271 272 entry->line_nr = file->line_nr; 273 274 /* if following lines are tab indented, put in the annex */ 275 if (*file->pos == '\t') { 276 entry->annex = file->pos; 277 do { 278 do { 279 file->pos++; 280 } while (*file->pos != '\0' && *file->pos != '\n'); 281 if (*file->pos == '\n') { 282 char *save_pos = ++file->pos; 283 int extra_lines = 0; 284 file->line_nr++; 285 /* Allow tab indented to have blank lines */ 286 while (*save_pos == '\n') { 287 save_pos++; 288 extra_lines++; 289 } 290 if (*save_pos == '\t') { 291 file->pos = save_pos; 292 file->line_nr += extra_lines; 293 } 294 } 295 } while (*file->pos != '\0' && *file->pos == '\t'); 296 if (file->pos[-1] == '\n') 297 file->pos[-1] = '\0'; 298 } 299 else 300 entry->annex = NULL; 301 302 /* return it */ 303 return entry; 304 305 } 306 307 308 extern void 309 dump_table_entry(table_entry *entry, 310 int indent) 311 { 312 printf("(table_entry*)%p\n", entry); 313 314 if (entry != NULL) { 315 int field; 316 char sep; 317 318 sep = ' '; 319 dumpf(indent, "(fields"); 320 for (field = 0; field < entry->nr_fields; field++) { 321 printf("%c%s", sep, entry->fields[field]); 322 sep = ':'; 323 } 324 printf(")\n"); 325 326 dumpf(indent, "(line_nr %d)\n", entry->line_nr); 327 328 dumpf(indent, "(file_name %s)\n", entry->file_name); 329 330 dumpf(indent, "(annex\n%s\n", entry->annex); 331 dumpf(indent, " )\n"); 332 333 } 334 } 335 336 337 extern void 338 table_entry_print_cpp_line_nr(lf *file, 339 table_entry *entry) 340 { 341 lf_print__external_reference(file, entry->line_nr, entry->file_name); 342 } 343 344 345