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