diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:35:26 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:35:26 +0000 |
commit | c906108c21474dfb4ed285bcc0ac6fe02cd400cc (patch) | |
tree | a0015aa5cedc19ccbab307251353a41722a3ae13 /sim/igen/table.c | |
parent | cd946cff9ede3f30935803403f06f6ed30cad136 (diff) | |
download | fsf-binutils-gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.zip fsf-binutils-gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.gz fsf-binutils-gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.bz2 |
Initial creation of sourceware repositorygdb-4_18-branchpoint
Diffstat (limited to 'sim/igen/table.c')
-rw-r--r-- | sim/igen/table.c | 632 |
1 files changed, 632 insertions, 0 deletions
diff --git a/sim/igen/table.c b/sim/igen/table.c new file mode 100644 index 0000000..f6a9e9b --- /dev/null +++ b/sim/igen/table.c @@ -0,0 +1,632 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995,1997 Andrew Cagney <cagney@highland.com.au> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> + +#include "config.h" +#include "misc.h" +#include "lf.h" +#include "table.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +typedef struct _open_table open_table; +struct _open_table { + size_t size; + char *buffer; + char *pos; + line_ref pseudo_line; + line_ref real_line; + open_table *parent; + table *root; +}; +struct _table { + open_table *current; +}; + + +static line_ref * +current_line (open_table *file) +{ + line_ref *entry = ZALLOC (line_ref); + *entry = file->pseudo_line; + return entry; +} + +static table_entry * +new_table_entry (open_table *file, + table_entry_type type) +{ + table_entry *entry; + entry = ZALLOC (table_entry); + entry->file = file->root; + entry->line = current_line (file); + entry->type = type; + return entry; +} + +static void +set_nr_table_entry_fields (table_entry *entry, + int nr_fields) +{ + entry->field = NZALLOC (char*, nr_fields + 1); + entry->nr_fields = nr_fields; +} + + +void +table_push (table *root, + line_ref *line, + table_include *includes, + const char *file_name) +{ + FILE *ff; + open_table *file; + table_include dummy; + table_include *include = &dummy; + + /* dummy up a search of this directory */ + dummy.next = includes; + dummy.dir = ""; + + /* create a file descriptor */ + file = ZALLOC (open_table); + if (file == NULL) + { + perror (file_name); + exit (1); + } + file->root = root; + file->parent = root->current; + root->current = file; + + while (1) + { + /* save the file name */ + char *dup_name = NZALLOC (char, strlen (include->dir) + strlen (file_name) + 2); + if (dup_name == NULL) + { + perror (file_name); + exit (1); + } + if (include->dir[0] != '\0') + { + strcat (dup_name, include->dir); + strcat (dup_name, "/"); + } + strcat (dup_name, file_name); + file->real_line.file_name = dup_name; + file->pseudo_line.file_name = dup_name; + /* open the file */ + + ff = fopen (dup_name, "rb"); + if (ff) + break; + /* zfree (dup_name); */ + if (include->next == NULL) + { + if (line != NULL) + error (line, "Problem opening file `%s'\n", file_name); + perror (file_name); + exit (1); + } + include = include->next; + } + + + /* determine the size */ + fseek (ff, 0, SEEK_END); + file->size = ftell (ff); + fseek (ff, 0, SEEK_SET); + + /* allocate this much memory */ + file->buffer = (char*) zalloc (file->size + 1); + if (file->buffer == NULL) + { + perror (file_name); + exit (1); + } + file->pos = file->buffer; + + /* read it all in */ + if (fread (file->buffer, 1, file->size, ff) < file->size) { + perror (file_name); + exit (1); + } + file->buffer[file->size] = '\0'; + + /* set the initial line numbering */ + file->real_line.line_nr = 1; /* specifies current line */ + file->pseudo_line.line_nr = 1; /* specifies current line */ + + /* done */ + fclose (ff); +} + +table * +table_open (const char *file_name) +{ + table *root; + + /* create a file descriptor */ + root = ZALLOC (table); + if (root == NULL) + { + perror (file_name); + exit (1); + } + + table_push (root, NULL, NULL, file_name); + return root; +} + +char * +skip_spaces (char *chp) +{ + while (1) + { + if (*chp == '\0' + || *chp == '\n' + || !isspace (*chp)) + return chp; + chp++; + } +} + + +char * +back_spaces (char *start, char *chp) +{ + while (1) + { + if (chp <= start + || !isspace (chp[-1])) + return chp; + chp--; + } +} + +char * +skip_digits (char *chp) +{ + while (1) + { + if (*chp == '\0' + || *chp == '\n' + || !isdigit (*chp)) + return chp; + chp++; + } +} + +char * +skip_to_separator (char *chp, + char *separators) +{ + while (1) + { + char *sep = separators; + while (1) + { + if (*chp == *sep) + return chp; + if (*sep == '\0') + break; + sep++; + } + chp++; + } +} + +static char * +skip_to_null (char *chp) +{ + return skip_to_separator (chp, ""); +} + + +static char * +skip_to_nl (char * chp) +{ + return skip_to_separator (chp, "\n"); +} + + +static void +next_line (open_table *file) +{ + file->pos = skip_to_nl (file->pos); + if (*file->pos == '0') + error (&file->pseudo_line, "Missing <nl> at end of line\n"); + *file->pos = '\0'; + file->pos += 1; + file->real_line.line_nr += 1; + file->pseudo_line.line_nr += 1; +} + + +extern table_entry * +table_read (table *root) +{ + open_table *file = root->current; + table_entry *entry = NULL; + while(1) + { + + /* end-of-file? */ + while (*file->pos == '\0') + { + if (file->parent != NULL) + { + file = file->parent; + root->current = file; + } + else + return NULL; + } + + /* code_block? */ + if (*file->pos == '{') + { + char *chp; + next_line (file); /* discard leading brace */ + entry = new_table_entry (file, table_code_entry); + chp = file->pos; + /* determine how many lines are involved - look for <nl> "}" */ + { + int nr_lines = 0; + while (*file->pos != '}') + { + next_line (file); + nr_lines++; + } + set_nr_table_entry_fields (entry, nr_lines); + } + /* now enter each line */ + { + int line_nr; + for (line_nr = 0; line_nr < entry->nr_fields; line_nr++) + { + if (strncmp (chp, " ", 2) == 0) + entry->field[line_nr] = chp + 2; + else + entry->field[line_nr] = chp; + chp = skip_to_null (chp) + 1; + } + /* skip trailing brace */ + ASSERT (*file->pos == '}'); + next_line (file); + } + break; + } + + /* tab block? */ + if (*file->pos == '\t') + { + char *chp = file->pos; + entry = new_table_entry (file, table_code_entry); + /* determine how many lines are involved - look for <nl> !<tab> */ + { + int nr_lines = 0; + int nr_blank_lines = 0; + while (1) + { + if (*file->pos == '\t') + { + nr_lines = nr_lines + nr_blank_lines + 1; + nr_blank_lines = 0; + next_line (file); + } + else + { + file->pos = skip_spaces (file->pos); + if (*file->pos != '\n') + break; + nr_blank_lines++; + next_line (file); + } + } + set_nr_table_entry_fields (entry, nr_lines); + } + /* now enter each line */ + { + int line_nr; + for (line_nr = 0; line_nr < entry->nr_fields; line_nr++) + { + if (*chp == '\t') + entry->field[line_nr] = chp + 1; + else + entry->field[line_nr] = ""; /* blank */ + chp = skip_to_null (chp) + 1; + } + } + break; + } + + /* cpp directive? */ + if (file->pos[0] == '#') + { + char *chp = skip_spaces (file->pos + 1); + + /* cpp line-nr directive - # <line-nr> "<file>" */ + if (isdigit (*chp) + && *skip_digits (chp) == ' ' + && *skip_spaces (skip_digits (chp)) == '"') + { + int line_nr; + char *file_name; + file->pos = chp; + /* parse the number */ + line_nr = atoi(file->pos) - 1; + /* skip to the file name */ + while (file->pos[0] != '0' + && file->pos[0] != '"' + && file->pos[0] != '\0') + file->pos++; + if (file->pos[0] != '"') + error (&file->real_line, "Missing opening quote in cpp directive\n"); + /* parse the file name */ + file->pos++; + file_name = file->pos; + while (file->pos[0] != '"' + && file->pos[0] != '\0') + file->pos++; + if (file->pos[0] != '"') + error (&file->real_line, "Missing closing quote in cpp directive\n"); + file->pos[0] = '\0'; + file->pos++; + file->pos = skip_to_nl (file->pos); + if (file->pos[0] != '\n') + error (&file->real_line, "Missing newline in cpp directive\n"); + file->pseudo_line.file_name = file_name; + file->pseudo_line.line_nr = line_nr; + next_line (file); + continue; + } + + /* #define and #undef - not implemented yet */ + + /* Old style # comment */ + next_line (file); + continue; + } + + /* blank line or end-of-file? */ + file->pos = skip_spaces (file->pos); + if (*file->pos == '\0') + error (&file->pseudo_line, "Missing <nl> at end of file\n"); + if (*file->pos == '\n') + { + next_line (file); + continue; + } + + /* comment - leading // or # - skip */ + if ((file->pos[0] == '/' && file->pos[1] == '/') + || (file->pos[0] == '#')) + { + next_line (file); + continue; + } + + /* colon field */ + { + char *chp = file->pos; + entry = new_table_entry (file, table_colon_entry); + next_line (file); + /* figure out how many fields */ + { + int nr_fields = 1; + char *tmpch = chp; + while (1) + { + tmpch = skip_to_separator (tmpch, "\\:"); + if (*tmpch == '\\') + { + /* eat the escaped character */ + char *cp = tmpch; + while (cp[1] != '\0') + { + cp[0] = cp[1]; + cp++; + } + cp[0] = '\0'; + tmpch++; + } + else if (*tmpch != ':') + break; + else + { + *tmpch = '\0'; + tmpch++; + nr_fields++; + } + } + set_nr_table_entry_fields (entry, nr_fields); + } + /* now parse them */ + { + int field_nr; + for (field_nr = 0; field_nr < entry->nr_fields; field_nr++) + { + chp = skip_spaces (chp); + entry->field[field_nr] = chp; + chp = skip_to_null (chp); + *back_spaces (entry->field[field_nr], chp) = '\0'; + chp++; + } + } + break; + } + + } + + ASSERT (entry == NULL || entry->field[entry->nr_fields] == NULL); + return entry; +} + +extern void +table_print_code (lf *file, + table_entry *entry) +{ + int field_nr; + int nr = 0; + for (field_nr = 0; + field_nr < entry->nr_fields; + field_nr++) + { + char *chp = entry->field[field_nr]; + int in_bit_field = 0; + if (*chp == '#') + lf_indent_suppress(file); + while (*chp != '\0') + { + if (chp[0] == '{' + && !isspace(chp[1]) + && chp[1] != '\0') + { + in_bit_field = 1; + nr += lf_putchr(file, '_'); + } + else if (in_bit_field && chp[0] == ':') + { + nr += lf_putchr(file, '_'); + } + else if (in_bit_field && *chp == '}') + { + nr += lf_putchr(file, '_'); + in_bit_field = 0; + } + else + { + nr += lf_putchr(file, *chp); + } + chp++; + } + if (in_bit_field) + { + line_ref line = *entry->line; + line.line_nr += field_nr; + error (&line, "Bit field brace miss match\n"); + } + nr += lf_putchr(file, '\n'); + } +} + + + +void +dump_line_ref (lf *file, + char *prefix, + const line_ref *line, + char *suffix) +{ + lf_printf (file, "%s(line_ref*) 0x%lx", prefix, (long) line); + if (line != NULL) + { + lf_indent (file, +1); + lf_printf (file, "\n(line_nr %d)", line->line_nr); + lf_printf (file, "\n(file_name %s)", line->file_name); + lf_indent (file, -1); + } + lf_printf (file, "%s", suffix); +} + + +static const char * +table_entry_type_to_str (table_entry_type type) +{ + switch (type) + { + case table_code_entry: return "code-entry"; + case table_colon_entry: return "colon-entry"; + } + return "*invalid*"; +} + +void +dump_table_entry(lf *file, + char *prefix, + const table_entry *entry, + char *suffix) +{ + lf_printf (file, "%s(table_entry*) 0x%lx", prefix, (long) entry); + if (entry != NULL) + { + int field; + lf_indent (file, +1); + dump_line_ref (file, "\n(line ", entry->line, ")"); + lf_printf (file, "\n(type %s)", table_entry_type_to_str (entry->type)); + lf_printf (file, "\n(nr_fields %d)", entry->nr_fields); + lf_printf (file, "\n(fields"); + lf_indent (file, +1); + for (field = 0; field < entry->nr_fields; field++) + lf_printf (file, "\n\"%s\"", entry->field[field]); + lf_indent (file, -1); + lf_printf (file, ")"); + lf_indent (file, -1); + } + lf_printf (file, "%s", suffix); +} + + +#ifdef MAIN +int +main(int argc, char **argv) +{ + table *t; + table_entry *entry; + lf *l; + int line_nr; + + if (argc != 2) + { + printf("Usage: table <file>\n"); + exit (1); + } + + t = table_open (argv[1]); + l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-table"); + + line_nr = 0; + do + { + char line[10]; + entry = table_read (t); + line_nr ++; + sprintf (line, "(%d ", line_nr); + dump_table_entry (l, line, entry, ")\n"); + } + while (entry != NULL); + + return 0; +} +#endif |