1 /* The IGEN simulator generator for GDB, the GNU Debugger.
3 Copyright 2002-2021 Free Software Foundation, Inc.
5 Contributed by Andrew Cagney.
7 This file is part of GDB.
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.
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.
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/>. */
24 #include <sys/types.h>
40 typedef struct _open_table open_table
;
58 current_line (open_table
* file
)
60 line_ref
*entry
= ZALLOC (line_ref
);
61 *entry
= file
->pseudo_line
;
66 new_table_entry (open_table
* file
, table_entry_type type
)
69 entry
= ZALLOC (table_entry
);
70 entry
->file
= file
->root
;
71 entry
->line
= current_line (file
);
77 set_nr_table_entry_fields (table_entry
*entry
, int nr_fields
)
79 entry
->field
= NZALLOC (char *, nr_fields
+ 1);
80 entry
->nr_fields
= nr_fields
;
85 table_push (table
*root
,
86 line_ref
*line
, table_include
*includes
, const char *file_name
)
91 table_include
*include
= &dummy
;
93 /* dummy up a search of this directory */
94 dummy
.next
= includes
;
97 /* create a file descriptor */
98 file
= ZALLOC (open_table
);
105 file
->parent
= root
->current
;
106 root
->current
= file
;
110 /* save the file name */
112 NZALLOC (char, strlen (include
->dir
) + strlen (file_name
) + 2);
113 if (dup_name
== NULL
)
118 if (include
->dir
[0] != '\0')
120 strcat (dup_name
, include
->dir
);
121 strcat (dup_name
, "/");
123 strcat (dup_name
, file_name
);
124 file
->real_line
.file_name
= dup_name
;
125 file
->pseudo_line
.file_name
= dup_name
;
128 ff
= fopen (dup_name
, "rb");
131 /* free (dup_name); */
132 if (include
->next
== NULL
)
135 error (line
, "Problem opening file `%s'\n", file_name
);
139 include
= include
->next
;
143 /* determine the size */
144 fseek (ff
, 0, SEEK_END
);
145 file
->size
= ftell (ff
);
146 fseek (ff
, 0, SEEK_SET
);
148 /* allocate this much memory */
149 file
->buffer
= (char *) zalloc (file
->size
+ 1);
150 if (file
->buffer
== NULL
)
155 file
->pos
= file
->buffer
;
158 if (fread (file
->buffer
, 1, file
->size
, ff
) < file
->size
)
163 file
->buffer
[file
->size
] = '\0';
165 /* set the initial line numbering */
166 file
->real_line
.line_nr
= 1; /* specifies current line */
167 file
->pseudo_line
.line_nr
= 1; /* specifies current line */
174 table_open (const char *file_name
)
178 /* create a file descriptor */
179 root
= ZALLOC (table
);
186 table_push (root
, NULL
, NULL
, file_name
);
191 skip_spaces (char *chp
)
195 if (*chp
== '\0' || *chp
== '\n' || !isspace (*chp
))
203 back_spaces (char *start
, char *chp
)
207 if (chp
<= start
|| !isspace (chp
[-1]))
214 skip_digits (char *chp
)
218 if (*chp
== '\0' || *chp
== '\n' || !isdigit (*chp
))
225 skip_to_separator (char *chp
, char *separators
)
229 char *sep
= separators
;
243 skip_to_null (char *chp
)
245 return skip_to_separator (chp
, "");
250 skip_to_nl (char *chp
)
252 return skip_to_separator (chp
, "\n");
257 next_line (open_table
* file
)
259 file
->pos
= skip_to_nl (file
->pos
);
260 if (*file
->pos
== '0')
261 error (&file
->pseudo_line
, "Missing <nl> at end of line\n");
264 file
->real_line
.line_nr
+= 1;
265 file
->pseudo_line
.line_nr
+= 1;
270 table_read (table
*root
)
272 open_table
*file
= root
->current
;
273 table_entry
*entry
= NULL
;
278 while (*file
->pos
== '\0')
280 if (file
->parent
!= NULL
)
283 root
->current
= file
;
290 if (*file
->pos
== '{')
293 next_line (file
); /* discard leading brace */
294 entry
= new_table_entry (file
, table_code_entry
);
296 /* determine how many lines are involved - look for <nl> "}" */
299 while (*file
->pos
!= '}')
304 set_nr_table_entry_fields (entry
, nr_lines
);
306 /* now enter each line */
309 for (line_nr
= 0; line_nr
< entry
->nr_fields
; line_nr
++)
311 if (strncmp (chp
, " ", 2) == 0)
312 entry
->field
[line_nr
] = chp
+ 2;
314 entry
->field
[line_nr
] = chp
;
315 chp
= skip_to_null (chp
) + 1;
317 /* skip trailing brace */
318 ASSERT (*file
->pos
== '}');
325 if (*file
->pos
== '\t')
327 char *chp
= file
->pos
;
328 entry
= new_table_entry (file
, table_code_entry
);
329 /* determine how many lines are involved - look for <nl> !<tab> */
332 int nr_blank_lines
= 0;
335 if (*file
->pos
== '\t')
337 nr_lines
= nr_lines
+ nr_blank_lines
+ 1;
343 file
->pos
= skip_spaces (file
->pos
);
344 if (*file
->pos
!= '\n')
350 set_nr_table_entry_fields (entry
, nr_lines
);
352 /* now enter each line */
355 for (line_nr
= 0; line_nr
< entry
->nr_fields
; line_nr
++)
358 entry
->field
[line_nr
] = chp
+ 1;
360 entry
->field
[line_nr
] = ""; /* blank */
361 chp
= skip_to_null (chp
) + 1;
368 if (file
->pos
[0] == '#')
370 char *chp
= skip_spaces (file
->pos
+ 1);
372 /* cpp line-nr directive - # <line-nr> "<file>" */
374 && *skip_digits (chp
) == ' '
375 && *skip_spaces (skip_digits (chp
)) == '"')
380 /* parse the number */
381 line_nr
= atoi (file
->pos
) - 1;
382 /* skip to the file name */
383 while (file
->pos
[0] != '0'
384 && file
->pos
[0] != '"' && file
->pos
[0] != '\0')
386 if (file
->pos
[0] != '"')
387 error (&file
->real_line
,
388 "Missing opening quote in cpp directive\n");
389 /* parse the file name */
391 file_name
= file
->pos
;
392 while (file
->pos
[0] != '"' && file
->pos
[0] != '\0')
394 if (file
->pos
[0] != '"')
395 error (&file
->real_line
,
396 "Missing closing quote in cpp directive\n");
399 file
->pos
= skip_to_nl (file
->pos
);
400 if (file
->pos
[0] != '\n')
401 error (&file
->real_line
,
402 "Missing newline in cpp directive\n");
403 file
->pseudo_line
.file_name
= file_name
;
404 file
->pseudo_line
.line_nr
= line_nr
;
409 /* #define and #undef - not implemented yet */
411 /* Old style # comment */
416 /* blank line or end-of-file? */
417 file
->pos
= skip_spaces (file
->pos
);
418 if (*file
->pos
== '\0')
419 error (&file
->pseudo_line
, "Missing <nl> at end of file\n");
420 if (*file
->pos
== '\n')
426 /* comment - leading // or # - skip */
427 if ((file
->pos
[0] == '/' && file
->pos
[1] == '/')
428 || (file
->pos
[0] == '#'))
436 char *chp
= file
->pos
;
437 entry
= new_table_entry (file
, table_colon_entry
);
439 /* figure out how many fields */
445 tmpch
= skip_to_separator (tmpch
, "\\:");
448 /* eat the escaped character */
450 while (cp
[1] != '\0')
458 else if (*tmpch
!= ':')
467 set_nr_table_entry_fields (entry
, nr_fields
);
472 for (field_nr
= 0; field_nr
< entry
->nr_fields
; field_nr
++)
474 chp
= skip_spaces (chp
);
475 entry
->field
[field_nr
] = chp
;
476 chp
= skip_to_null (chp
);
477 *back_spaces (entry
->field
[field_nr
], chp
) = '\0';
486 ASSERT (entry
== NULL
|| entry
->field
[entry
->nr_fields
] == NULL
);
491 table_print_code (lf
*file
, table_entry
*entry
)
495 for (field_nr
= 0; field_nr
< entry
->nr_fields
; field_nr
++)
497 char *chp
= entry
->field
[field_nr
];
498 int in_bit_field
= 0;
500 lf_indent_suppress (file
);
503 if (chp
[0] == '{' && !isspace (chp
[1]) && chp
[1] != '\0')
506 nr
+= lf_putchr (file
, '_');
508 else if (in_bit_field
&& chp
[0] == ':')
510 nr
+= lf_putchr (file
, '_');
512 else if (in_bit_field
&& *chp
== '}')
514 nr
+= lf_putchr (file
, '_');
519 nr
+= lf_putchr (file
, *chp
);
525 line_ref line
= *entry
->line
;
526 line
.line_nr
+= field_nr
;
527 error (&line
, "Bit field brace miss match\n");
529 nr
+= lf_putchr (file
, '\n');
536 dump_line_ref (lf
*file
, char *prefix
, const line_ref
*line
, char *suffix
)
538 lf_printf (file
, "%s(line_ref*) 0x%lx", prefix
, (long) line
);
541 lf_indent (file
, +1);
542 lf_printf (file
, "\n(line_nr %d)", line
->line_nr
);
543 lf_printf (file
, "\n(file_name %s)", line
->file_name
);
544 lf_indent (file
, -1);
546 lf_printf (file
, "%s", suffix
);
551 table_entry_type_to_str (table_entry_type type
)
555 case table_code_entry
:
557 case table_colon_entry
:
558 return "colon-entry";
564 dump_table_entry (lf
*file
,
565 char *prefix
, const table_entry
*entry
, char *suffix
)
567 lf_printf (file
, "%s(table_entry*) 0x%lx", prefix
, (long) entry
);
571 lf_indent (file
, +1);
572 dump_line_ref (file
, "\n(line ", entry
->line
, ")");
573 lf_printf (file
, "\n(type %s)", table_entry_type_to_str (entry
->type
));
574 lf_printf (file
, "\n(nr_fields %d)", entry
->nr_fields
);
575 lf_printf (file
, "\n(fields");
576 lf_indent (file
, +1);
577 for (field
= 0; field
< entry
->nr_fields
; field
++)
578 lf_printf (file
, "\n\"%s\"", entry
->field
[field
]);
579 lf_indent (file
, -1);
580 lf_printf (file
, ")");
581 lf_indent (file
, -1);
583 lf_printf (file
, "%s", suffix
);
589 main (int argc
, char **argv
)
598 printf ("Usage: table <file>\n");
602 t
= table_open (argv
[1]);
603 l
= lf_open ("-", "stdout", lf_omit_references
, lf_is_text
, "tmp-table");
609 entry
= table_read (t
);
611 sprintf (line
, "(%d ", line_nr
);
612 dump_table_entry (l
, line
, entry
, ")\n");
614 while (entry
!= NULL
);