]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/igen/table.c
Initial creation of sourceware repository
[thirdparty/binutils-gdb.git] / sim / igen / table.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1995,1997 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
41 typedef struct _open_table open_table;
42 struct _open_table {
43 size_t size;
44 char *buffer;
45 char *pos;
46 line_ref pseudo_line;
47 line_ref real_line;
48 open_table *parent;
49 table *root;
50 };
51 struct _table {
52 open_table *current;
53 };
54
55
56 static line_ref *
57 current_line (open_table *file)
58 {
59 line_ref *entry = ZALLOC (line_ref);
60 *entry = file->pseudo_line;
61 return entry;
62 }
63
64 static table_entry *
65 new_table_entry (open_table *file,
66 table_entry_type type)
67 {
68 table_entry *entry;
69 entry = ZALLOC (table_entry);
70 entry->file = file->root;
71 entry->line = current_line (file);
72 entry->type = type;
73 return entry;
74 }
75
76 static void
77 set_nr_table_entry_fields (table_entry *entry,
78 int nr_fields)
79 {
80 entry->field = NZALLOC (char*, nr_fields + 1);
81 entry->nr_fields = nr_fields;
82 }
83
84
85 void
86 table_push (table *root,
87 line_ref *line,
88 table_include *includes,
89 const char *file_name)
90 {
91 FILE *ff;
92 open_table *file;
93 table_include dummy;
94 table_include *include = &dummy;
95
96 /* dummy up a search of this directory */
97 dummy.next = includes;
98 dummy.dir = "";
99
100 /* create a file descriptor */
101 file = ZALLOC (open_table);
102 if (file == NULL)
103 {
104 perror (file_name);
105 exit (1);
106 }
107 file->root = root;
108 file->parent = root->current;
109 root->current = file;
110
111 while (1)
112 {
113 /* save the file name */
114 char *dup_name = NZALLOC (char, strlen (include->dir) + strlen (file_name) + 2);
115 if (dup_name == NULL)
116 {
117 perror (file_name);
118 exit (1);
119 }
120 if (include->dir[0] != '\0')
121 {
122 strcat (dup_name, include->dir);
123 strcat (dup_name, "/");
124 }
125 strcat (dup_name, file_name);
126 file->real_line.file_name = dup_name;
127 file->pseudo_line.file_name = dup_name;
128 /* open the file */
129
130 ff = fopen (dup_name, "rb");
131 if (ff)
132 break;
133 /* zfree (dup_name); */
134 if (include->next == NULL)
135 {
136 if (line != NULL)
137 error (line, "Problem opening file `%s'\n", file_name);
138 perror (file_name);
139 exit (1);
140 }
141 include = include->next;
142 }
143
144
145 /* determine the size */
146 fseek (ff, 0, SEEK_END);
147 file->size = ftell (ff);
148 fseek (ff, 0, SEEK_SET);
149
150 /* allocate this much memory */
151 file->buffer = (char*) zalloc (file->size + 1);
152 if (file->buffer == NULL)
153 {
154 perror (file_name);
155 exit (1);
156 }
157 file->pos = file->buffer;
158
159 /* read it all in */
160 if (fread (file->buffer, 1, file->size, ff) < file->size) {
161 perror (file_name);
162 exit (1);
163 }
164 file->buffer[file->size] = '\0';
165
166 /* set the initial line numbering */
167 file->real_line.line_nr = 1; /* specifies current line */
168 file->pseudo_line.line_nr = 1; /* specifies current line */
169
170 /* done */
171 fclose (ff);
172 }
173
174 table *
175 table_open (const char *file_name)
176 {
177 table *root;
178
179 /* create a file descriptor */
180 root = ZALLOC (table);
181 if (root == NULL)
182 {
183 perror (file_name);
184 exit (1);
185 }
186
187 table_push (root, NULL, NULL, file_name);
188 return root;
189 }
190
191 char *
192 skip_spaces (char *chp)
193 {
194 while (1)
195 {
196 if (*chp == '\0'
197 || *chp == '\n'
198 || !isspace (*chp))
199 return chp;
200 chp++;
201 }
202 }
203
204
205 char *
206 back_spaces (char *start, char *chp)
207 {
208 while (1)
209 {
210 if (chp <= start
211 || !isspace (chp[-1]))
212 return chp;
213 chp--;
214 }
215 }
216
217 char *
218 skip_digits (char *chp)
219 {
220 while (1)
221 {
222 if (*chp == '\0'
223 || *chp == '\n'
224 || !isdigit (*chp))
225 return chp;
226 chp++;
227 }
228 }
229
230 char *
231 skip_to_separator (char *chp,
232 char *separators)
233 {
234 while (1)
235 {
236 char *sep = separators;
237 while (1)
238 {
239 if (*chp == *sep)
240 return chp;
241 if (*sep == '\0')
242 break;
243 sep++;
244 }
245 chp++;
246 }
247 }
248
249 static char *
250 skip_to_null (char *chp)
251 {
252 return skip_to_separator (chp, "");
253 }
254
255
256 static char *
257 skip_to_nl (char * chp)
258 {
259 return skip_to_separator (chp, "\n");
260 }
261
262
263 static void
264 next_line (open_table *file)
265 {
266 file->pos = skip_to_nl (file->pos);
267 if (*file->pos == '0')
268 error (&file->pseudo_line, "Missing <nl> at end of line\n");
269 *file->pos = '\0';
270 file->pos += 1;
271 file->real_line.line_nr += 1;
272 file->pseudo_line.line_nr += 1;
273 }
274
275
276 extern table_entry *
277 table_read (table *root)
278 {
279 open_table *file = root->current;
280 table_entry *entry = NULL;
281 while(1)
282 {
283
284 /* end-of-file? */
285 while (*file->pos == '\0')
286 {
287 if (file->parent != NULL)
288 {
289 file = file->parent;
290 root->current = file;
291 }
292 else
293 return NULL;
294 }
295
296 /* code_block? */
297 if (*file->pos == '{')
298 {
299 char *chp;
300 next_line (file); /* discard leading brace */
301 entry = new_table_entry (file, table_code_entry);
302 chp = file->pos;
303 /* determine how many lines are involved - look for <nl> "}" */
304 {
305 int nr_lines = 0;
306 while (*file->pos != '}')
307 {
308 next_line (file);
309 nr_lines++;
310 }
311 set_nr_table_entry_fields (entry, nr_lines);
312 }
313 /* now enter each line */
314 {
315 int line_nr;
316 for (line_nr = 0; line_nr < entry->nr_fields; line_nr++)
317 {
318 if (strncmp (chp, " ", 2) == 0)
319 entry->field[line_nr] = chp + 2;
320 else
321 entry->field[line_nr] = chp;
322 chp = skip_to_null (chp) + 1;
323 }
324 /* skip trailing brace */
325 ASSERT (*file->pos == '}');
326 next_line (file);
327 }
328 break;
329 }
330
331 /* tab block? */
332 if (*file->pos == '\t')
333 {
334 char *chp = file->pos;
335 entry = new_table_entry (file, table_code_entry);
336 /* determine how many lines are involved - look for <nl> !<tab> */
337 {
338 int nr_lines = 0;
339 int nr_blank_lines = 0;
340 while (1)
341 {
342 if (*file->pos == '\t')
343 {
344 nr_lines = nr_lines + nr_blank_lines + 1;
345 nr_blank_lines = 0;
346 next_line (file);
347 }
348 else
349 {
350 file->pos = skip_spaces (file->pos);
351 if (*file->pos != '\n')
352 break;
353 nr_blank_lines++;
354 next_line (file);
355 }
356 }
357 set_nr_table_entry_fields (entry, nr_lines);
358 }
359 /* now enter each line */
360 {
361 int line_nr;
362 for (line_nr = 0; line_nr < entry->nr_fields; line_nr++)
363 {
364 if (*chp == '\t')
365 entry->field[line_nr] = chp + 1;
366 else
367 entry->field[line_nr] = ""; /* blank */
368 chp = skip_to_null (chp) + 1;
369 }
370 }
371 break;
372 }
373
374 /* cpp directive? */
375 if (file->pos[0] == '#')
376 {
377 char *chp = skip_spaces (file->pos + 1);
378
379 /* cpp line-nr directive - # <line-nr> "<file>" */
380 if (isdigit (*chp)
381 && *skip_digits (chp) == ' '
382 && *skip_spaces (skip_digits (chp)) == '"')
383 {
384 int line_nr;
385 char *file_name;
386 file->pos = chp;
387 /* parse the number */
388 line_nr = atoi(file->pos) - 1;
389 /* skip to the file name */
390 while (file->pos[0] != '0'
391 && file->pos[0] != '"'
392 && file->pos[0] != '\0')
393 file->pos++;
394 if (file->pos[0] != '"')
395 error (&file->real_line, "Missing opening quote in cpp directive\n");
396 /* parse the file name */
397 file->pos++;
398 file_name = file->pos;
399 while (file->pos[0] != '"'
400 && file->pos[0] != '\0')
401 file->pos++;
402 if (file->pos[0] != '"')
403 error (&file->real_line, "Missing closing quote in cpp directive\n");
404 file->pos[0] = '\0';
405 file->pos++;
406 file->pos = skip_to_nl (file->pos);
407 if (file->pos[0] != '\n')
408 error (&file->real_line, "Missing newline in cpp directive\n");
409 file->pseudo_line.file_name = file_name;
410 file->pseudo_line.line_nr = line_nr;
411 next_line (file);
412 continue;
413 }
414
415 /* #define and #undef - not implemented yet */
416
417 /* Old style # comment */
418 next_line (file);
419 continue;
420 }
421
422 /* blank line or end-of-file? */
423 file->pos = skip_spaces (file->pos);
424 if (*file->pos == '\0')
425 error (&file->pseudo_line, "Missing <nl> at end of file\n");
426 if (*file->pos == '\n')
427 {
428 next_line (file);
429 continue;
430 }
431
432 /* comment - leading // or # - skip */
433 if ((file->pos[0] == '/' && file->pos[1] == '/')
434 || (file->pos[0] == '#'))
435 {
436 next_line (file);
437 continue;
438 }
439
440 /* colon field */
441 {
442 char *chp = file->pos;
443 entry = new_table_entry (file, table_colon_entry);
444 next_line (file);
445 /* figure out how many fields */
446 {
447 int nr_fields = 1;
448 char *tmpch = chp;
449 while (1)
450 {
451 tmpch = skip_to_separator (tmpch, "\\:");
452 if (*tmpch == '\\')
453 {
454 /* eat the escaped character */
455 char *cp = tmpch;
456 while (cp[1] != '\0')
457 {
458 cp[0] = cp[1];
459 cp++;
460 }
461 cp[0] = '\0';
462 tmpch++;
463 }
464 else if (*tmpch != ':')
465 break;
466 else
467 {
468 *tmpch = '\0';
469 tmpch++;
470 nr_fields++;
471 }
472 }
473 set_nr_table_entry_fields (entry, nr_fields);
474 }
475 /* now parse them */
476 {
477 int field_nr;
478 for (field_nr = 0; field_nr < entry->nr_fields; field_nr++)
479 {
480 chp = skip_spaces (chp);
481 entry->field[field_nr] = chp;
482 chp = skip_to_null (chp);
483 *back_spaces (entry->field[field_nr], chp) = '\0';
484 chp++;
485 }
486 }
487 break;
488 }
489
490 }
491
492 ASSERT (entry == NULL || entry->field[entry->nr_fields] == NULL);
493 return entry;
494 }
495
496 extern void
497 table_print_code (lf *file,
498 table_entry *entry)
499 {
500 int field_nr;
501 int nr = 0;
502 for (field_nr = 0;
503 field_nr < entry->nr_fields;
504 field_nr++)
505 {
506 char *chp = entry->field[field_nr];
507 int in_bit_field = 0;
508 if (*chp == '#')
509 lf_indent_suppress(file);
510 while (*chp != '\0')
511 {
512 if (chp[0] == '{'
513 && !isspace(chp[1])
514 && chp[1] != '\0')
515 {
516 in_bit_field = 1;
517 nr += lf_putchr(file, '_');
518 }
519 else if (in_bit_field && chp[0] == ':')
520 {
521 nr += lf_putchr(file, '_');
522 }
523 else if (in_bit_field && *chp == '}')
524 {
525 nr += lf_putchr(file, '_');
526 in_bit_field = 0;
527 }
528 else
529 {
530 nr += lf_putchr(file, *chp);
531 }
532 chp++;
533 }
534 if (in_bit_field)
535 {
536 line_ref line = *entry->line;
537 line.line_nr += field_nr;
538 error (&line, "Bit field brace miss match\n");
539 }
540 nr += lf_putchr(file, '\n');
541 }
542 }
543
544
545
546 void
547 dump_line_ref (lf *file,
548 char *prefix,
549 const line_ref *line,
550 char *suffix)
551 {
552 lf_printf (file, "%s(line_ref*) 0x%lx", prefix, (long) line);
553 if (line != NULL)
554 {
555 lf_indent (file, +1);
556 lf_printf (file, "\n(line_nr %d)", line->line_nr);
557 lf_printf (file, "\n(file_name %s)", line->file_name);
558 lf_indent (file, -1);
559 }
560 lf_printf (file, "%s", suffix);
561 }
562
563
564 static const char *
565 table_entry_type_to_str (table_entry_type type)
566 {
567 switch (type)
568 {
569 case table_code_entry: return "code-entry";
570 case table_colon_entry: return "colon-entry";
571 }
572 return "*invalid*";
573 }
574
575 void
576 dump_table_entry(lf *file,
577 char *prefix,
578 const table_entry *entry,
579 char *suffix)
580 {
581 lf_printf (file, "%s(table_entry*) 0x%lx", prefix, (long) entry);
582 if (entry != NULL)
583 {
584 int field;
585 lf_indent (file, +1);
586 dump_line_ref (file, "\n(line ", entry->line, ")");
587 lf_printf (file, "\n(type %s)", table_entry_type_to_str (entry->type));
588 lf_printf (file, "\n(nr_fields %d)", entry->nr_fields);
589 lf_printf (file, "\n(fields");
590 lf_indent (file, +1);
591 for (field = 0; field < entry->nr_fields; field++)
592 lf_printf (file, "\n\"%s\"", entry->field[field]);
593 lf_indent (file, -1);
594 lf_printf (file, ")");
595 lf_indent (file, -1);
596 }
597 lf_printf (file, "%s", suffix);
598 }
599
600
601 #ifdef MAIN
602 int
603 main(int argc, char **argv)
604 {
605 table *t;
606 table_entry *entry;
607 lf *l;
608 int line_nr;
609
610 if (argc != 2)
611 {
612 printf("Usage: table <file>\n");
613 exit (1);
614 }
615
616 t = table_open (argv[1]);
617 l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-table");
618
619 line_nr = 0;
620 do
621 {
622 char line[10];
623 entry = table_read (t);
624 line_nr ++;
625 sprintf (line, "(%d ", line_nr);
626 dump_table_entry (l, line, entry, ")\n");
627 }
628 while (entry != NULL);
629
630 return 0;
631 }
632 #endif