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