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