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