Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / sim / igen / table.c
1 /* The IGEN simulator generator for GDB, the GNU Debugger.
2
3 Copyright 2002-2022 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 "misc.h"
31 #include "lf.h"
32 #include "table.h"
33
34 #include <unistd.h>
35 #include <stdlib.h>
36
37 typedef struct _open_table open_table;
38 struct _open_table
39 {
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 };
48 struct _table
49 {
50 open_table *current;
51 };
52
53
54 static line_ref *
55 current_line (open_table * file)
56 {
57 line_ref *entry = ZALLOC (line_ref);
58 *entry = file->pseudo_line;
59 return entry;
60 }
61
62 static table_entry *
63 new_table_entry (open_table * file, table_entry_type type)
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
73 static void
74 set_nr_table_entry_fields (table_entry *entry, int nr_fields)
75 {
76 entry->field = NZALLOC (char *, nr_fields + 1);
77 entry->nr_fields = nr_fields;
78 }
79
80
81 void
82 table_push (table *root,
83 line_ref *line, table_include *includes, const char *file_name)
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 */
108 char *dup_name =
109 NZALLOC (char, strlen (include->dir) + strlen (file_name) + 2);
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;
128 /* free (dup_name); */
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;
137 }
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 */
146 file->buffer = (char *) zalloc (file->size + 1);
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 */
155 if (fread (file->buffer, 1, file->size, ff) < file->size)
156 {
157 perror (file_name);
158 exit (1);
159 }
160 file->buffer[file->size] = '\0';
161
162 /* set the initial line numbering */
163 file->real_line.line_nr = 1; /* specifies current line */
164 file->pseudo_line.line_nr = 1; /* specifies current line */
165
166 /* done */
167 fclose (ff);
168 }
169
170 table *
171 table_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
187 char *
188 skip_spaces (char *chp)
189 {
190 while (1)
191 {
192 if (*chp == '\0' || *chp == '\n' || !isspace (*chp))
193 return chp;
194 chp++;
195 }
196 }
197
198
199 char *
200 back_spaces (char *start, char *chp)
201 {
202 while (1)
203 {
204 if (chp <= start || !isspace (chp[-1]))
205 return chp;
206 chp--;
207 }
208 }
209
210 char *
211 skip_digits (char *chp)
212 {
213 while (1)
214 {
215 if (*chp == '\0' || *chp == '\n' || !isdigit (*chp))
216 return chp;
217 chp++;
218 }
219 }
220
221 char *
222 skip_to_separator (char *chp, char *separators)
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
239 static char *
240 skip_to_null (char *chp)
241 {
242 return skip_to_separator (chp, "");
243 }
244
245
246 static char *
247 skip_to_nl (char *chp)
248 {
249 return skip_to_separator (chp, "\n");
250 }
251
252
253 static void
254 next_line (open_table * file)
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
266 extern table_entry *
267 table_read (table *root)
268 {
269 open_table *file = root->current;
270 table_entry *entry = NULL;
271 while (1)
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;
290 next_line (file); /* discard leading brace */
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
357 entry->field[line_nr] = ""; /* blank */
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 */
378 line_nr = atoi (file->pos) - 1;
379 /* skip to the file name */
380 while (file->pos[0] != '0'
381 && file->pos[0] != '"' && file->pos[0] != '\0')
382 file->pos++;
383 if (file->pos[0] != '"')
384 error (&file->real_line,
385 "Missing opening quote in cpp directive\n");
386 /* parse the file name */
387 file->pos++;
388 file_name = file->pos;
389 while (file->pos[0] != '"' && file->pos[0] != '\0')
390 file->pos++;
391 if (file->pos[0] != '"')
392 error (&file->real_line,
393 "Missing closing quote in cpp directive\n");
394 file->pos[0] = '\0';
395 file->pos++;
396 file->pos = skip_to_nl (file->pos);
397 if (file->pos[0] != '\n')
398 error (&file->real_line,
399 "Missing newline in cpp directive\n");
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
487 extern void
488 table_print_code (lf *file, table_entry *entry)
489 {
490 int field_nr;
491 int nr = 0;
492 for (field_nr = 0; field_nr < entry->nr_fields; field_nr++)
493 {
494 char *chp = entry->field[field_nr];
495 int in_bit_field = 0;
496 if (*chp == '#')
497 lf_indent_suppress (file);
498 while (*chp != '\0')
499 {
500 if (chp[0] == '{' && !isspace (chp[1]) && chp[1] != '\0')
501 {
502 in_bit_field = 1;
503 nr += lf_putchr (file, '_');
504 }
505 else if (in_bit_field && chp[0] == ':')
506 {
507 nr += lf_putchr (file, '_');
508 }
509 else if (in_bit_field && *chp == '}')
510 {
511 nr += lf_putchr (file, '_');
512 in_bit_field = 0;
513 }
514 else
515 {
516 nr += lf_putchr (file, *chp);
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 }
526 nr += lf_putchr (file, '\n');
527 }
528 }
529
530
531
532 void
533 dump_line_ref (lf *file, char *prefix, const line_ref *line, char *suffix)
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
547 static const char *
548 table_entry_type_to_str (table_entry_type type)
549 {
550 switch (type)
551 {
552 case table_code_entry:
553 return "code-entry";
554 case table_colon_entry:
555 return "colon-entry";
556 }
557 return "*invalid*";
558 }
559
560 void
561 dump_table_entry (lf *file,
562 char *prefix, const table_entry *entry, char *suffix)
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
585 int
586 main (int argc, char **argv)
587 {
588 table *t;
589 table_entry *entry;
590 lf *l;
591 int line_nr;
592
593 if (argc != 2)
594 {
595 printf ("Usage: table <file>\n");
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);
607 line_nr++;
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 0.041467 seconds and 4 git commands to generate.