]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/igen/table.c
Update copyright year range in all GDB files
[thirdparty/binutils-gdb.git] / sim / igen / table.c
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2
3 Copyright 2002-2021 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 3 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, see <http://www.gnu.org/licenses/>. */
21
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
43 typedef struct _open_table open_table;
44 struct _open_table
45 {
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 };
54 struct _table
55 {
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, table_entry_type type)
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
79 static void
80 set_nr_table_entry_fields (table_entry *entry, int nr_fields)
81 {
82 entry->field = NZALLOC (char *, nr_fields + 1);
83 entry->nr_fields = nr_fields;
84 }
85
86
87 void
88 table_push (table *root,
89 line_ref *line, table_include *includes, 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 =
115 NZALLOC (char, strlen (include->dir) + strlen (file_name) + 2);
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 /* free (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;
143 }
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 */
152 file->buffer = (char *) zalloc (file->size + 1);
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 */
161 if (fread (file->buffer, 1, file->size, ff) < file->size)
162 {
163 perror (file_name);
164 exit (1);
165 }
166 file->buffer[file->size] = '\0';
167
168 /* set the initial line numbering */
169 file->real_line.line_nr = 1; /* specifies current line */
170 file->pseudo_line.line_nr = 1; /* specifies current line */
171
172 /* done */
173 fclose (ff);
174 }
175
176 table *
177 table_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
193 char *
194 skip_spaces (char *chp)
195 {
196 while (1)
197 {
198 if (*chp == '\0' || *chp == '\n' || !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 || !isspace (chp[-1]))
211 return chp;
212 chp--;
213 }
214 }
215
216 char *
217 skip_digits (char *chp)
218 {
219 while (1)
220 {
221 if (*chp == '\0' || *chp == '\n' || !isdigit (*chp))
222 return chp;
223 chp++;
224 }
225 }
226
227 char *
228 skip_to_separator (char *chp, char *separators)
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
245 static char *
246 skip_to_null (char *chp)
247 {
248 return skip_to_separator (chp, "");
249 }
250
251
252 static char *
253 skip_to_nl (char *chp)
254 {
255 return skip_to_separator (chp, "\n");
256 }
257
258
259 static void
260 next_line (open_table * file)
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
272 extern table_entry *
273 table_read (table *root)
274 {
275 open_table *file = root->current;
276 table_entry *entry = NULL;
277 while (1)
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;
296 next_line (file); /* discard leading brace */
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
363 entry->field[line_nr] = ""; /* blank */
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 */
384 line_nr = atoi (file->pos) - 1;
385 /* skip to the file name */
386 while (file->pos[0] != '0'
387 && file->pos[0] != '"' && file->pos[0] != '\0')
388 file->pos++;
389 if (file->pos[0] != '"')
390 error (&file->real_line,
391 "Missing opening quote in cpp directive\n");
392 /* parse the file name */
393 file->pos++;
394 file_name = file->pos;
395 while (file->pos[0] != '"' && file->pos[0] != '\0')
396 file->pos++;
397 if (file->pos[0] != '"')
398 error (&file->real_line,
399 "Missing closing quote in cpp directive\n");
400 file->pos[0] = '\0';
401 file->pos++;
402 file->pos = skip_to_nl (file->pos);
403 if (file->pos[0] != '\n')
404 error (&file->real_line,
405 "Missing newline in cpp directive\n");
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
493 extern void
494 table_print_code (lf *file, table_entry *entry)
495 {
496 int field_nr;
497 int nr = 0;
498 for (field_nr = 0; field_nr < entry->nr_fields; field_nr++)
499 {
500 char *chp = entry->field[field_nr];
501 int in_bit_field = 0;
502 if (*chp == '#')
503 lf_indent_suppress (file);
504 while (*chp != '\0')
505 {
506 if (chp[0] == '{' && !isspace (chp[1]) && chp[1] != '\0')
507 {
508 in_bit_field = 1;
509 nr += lf_putchr (file, '_');
510 }
511 else if (in_bit_field && chp[0] == ':')
512 {
513 nr += lf_putchr (file, '_');
514 }
515 else if (in_bit_field && *chp == '}')
516 {
517 nr += lf_putchr (file, '_');
518 in_bit_field = 0;
519 }
520 else
521 {
522 nr += lf_putchr (file, *chp);
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 }
532 nr += lf_putchr (file, '\n');
533 }
534 }
535
536
537
538 void
539 dump_line_ref (lf *file, char *prefix, const line_ref *line, char *suffix)
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
553 static const char *
554 table_entry_type_to_str (table_entry_type type)
555 {
556 switch (type)
557 {
558 case table_code_entry:
559 return "code-entry";
560 case table_colon_entry:
561 return "colon-entry";
562 }
563 return "*invalid*";
564 }
565
566 void
567 dump_table_entry (lf *file,
568 char *prefix, const table_entry *entry, char *suffix)
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
591 int
592 main (int argc, char **argv)
593 {
594 table *t;
595 table_entry *entry;
596 lf *l;
597 int line_nr;
598
599 if (argc != 2)
600 {
601 printf ("Usage: table <file>\n");
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);
613 line_nr++;
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