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