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