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