aboutsummaryrefslogtreecommitdiff
path: root/sim/igen
diff options
context:
space:
mode:
Diffstat (limited to 'sim/igen')
-rw-r--r--sim/igen/ChangeLog21
-rw-r--r--sim/igen/igen.c301
-rw-r--r--sim/igen/ld-insn.c23
-rw-r--r--sim/igen/ld-insn.h608
-rw-r--r--sim/igen/table.c812
5 files changed, 1348 insertions, 417 deletions
diff --git a/sim/igen/ChangeLog b/sim/igen/ChangeLog
index aba94cb..b535133 100644
--- a/sim/igen/ChangeLog
+++ b/sim/igen/ChangeLog
@@ -1,3 +1,24 @@
+Mon Oct 27 15:14:26 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * igen.c (main): Change -I option to -I<directory>. Add optional
+ size to -Ggen-icache option. Add -Gno-... support.
+
+ * igen.h (struct _igen_options): Add include field.
+
+ * ld-insn.c (enum insn_record_type, insn_type_map): Add
+ include_record.
+ (load_insn_table): Call table_push when include record.
+
+ * table.c (struct _open table, struct table): Make table object an
+ indirect ptr to the current table file.
+ (current_line, new_table_entry, next_line): Make file arg type
+ open_table.
+ (table_open): Use table_push.
+ (table_read): Point variable file at current table, at eof, pop
+ last open table.
+
+ * table.h, table.c (table_push): New function.
+
Thu Oct 16 11:03:27 1997 Andrew Cagney <cagney@b1.cygnus.com>
* gen-semantics.c (print_semantic_body): Use CIA not
diff --git a/sim/igen/igen.c b/sim/igen/igen.c
index 0fbe8e5..afd2904 100644
--- a/sim/igen/igen.c
+++ b/sim/igen/igen.c
@@ -979,15 +979,13 @@ main (int argc,
printf ("\t Set the number of the high (most significant) instruction bit (depreciated).\n");
printf ("\t This option can now be set directly in the instruction table.\n");
printf ("\n");
- printf (" -I <icache-size>\n");
- printf ("\t Specify size of the cracking instruction cache (default %d instructions).\n",
- options.gen.icache_size);
- printf ("\t Implies -G icache.\n");
+ printf (" -I <directory>\n");
+ printf ("\t Add <directory> to the list of directories searched when opening a file\n");
printf ("\n");
printf (" -M <model-list>\n");
printf ("\t Filter out any instructions that do not support at least one of the listed\n");
printf ("\t models (An instructions with no model information is considered to support\n");
- printf ("\n all models.).\n");
+ printf ("\t all models.).\n");
printf ("\n");
printf (" -N <nr-cpus>\n");
printf ("\t Generate a simulator supporting <nr-cpus>\n");
@@ -1020,7 +1018,8 @@ main (int argc,
printf ("\t gen-delayed-branch - need both cia and nia passed around\n");
printf ("\t gen-direct-access - use #defines to directly access values\n");
printf ("\t gen-zero-r<N> - arch assumes GPR(<N>) == 0, keep it that way\n");
- printf ("\t gen-icache - generate an instruction cracking cache\n");
+ printf ("\t gen-icache[=<N> - generate an instruction cracking cache of size <N>\n");
+ printf ("\t Default size is %d\n", options.gen.icache_size);
printf ("\t gen-insn-in-icache - save original instruction when cracking\n");
printf ("\t gen-multi-sim - generate multiple simulators - one per model\n");
printf ("\t By default, a single simulator that will\n");
@@ -1099,8 +1098,13 @@ main (int argc,
break;
case 'I':
- options.gen.icache_size = a2i (optarg);
- options.gen.icache = 1;
+ {
+ table_include **dir = &options.include;
+ while ((*dir) != NULL)
+ dir = &(*dir)->next;
+ (*dir) = ZALLOC (table_include);
+ (*dir)->dir = strdup (optarg);
+ }
break;
case 'B':
@@ -1213,131 +1217,162 @@ main (int argc,
case 'G':
- if (strcmp (optarg, "decode-duplicate") == 0)
- {
- options.decode.duplicate = 1;
- }
- else if (strcmp (optarg, "decode-combine") == 0)
- {
- options.decode.combine = 1;
- }
- else if (strcmp (optarg, "decode-zero-reserved") == 0)
- {
- options.decode.zero_reserved = 1;
- }
-
- else if (strcmp (optarg, "gen-conditional-issue") == 0)
- {
- options.gen.conditional_issue = 1;
- }
- else if (strcmp (optarg, "conditional-issue") == 0)
- {
- options.gen.conditional_issue = 1;
- options.warning (NULL, "Option conditional-issue replaced by gen-conditional-issue\n");
- }
- else if (strcmp (optarg, "gen-delayed-branch") == 0)
- {
- options.gen.delayed_branch = 1;
- }
- else if (strcmp (optarg, "delayed-branch") == 0)
- {
- options.gen.delayed_branch = 1;
- options.warning (NULL, "Option delayed-branch replaced by gen-delayed-branch\n");
- }
- else if (strcmp (optarg, "gen-direct-access") == 0)
- {
- options.gen.direct_access = 1;
- }
- else if (strcmp (optarg, "direct-access") == 0)
- {
- options.gen.direct_access = 1;
- options.warning (NULL, "Option direct-access replaced by gen-direct-access\n");
- }
- else if (strncmp (optarg, "gen-zero-r", strlen ("gen-zero-r")) == 0)
- {
- options.gen.zero_reg = 1;
- options.gen.zero_reg_nr = atoi (optarg + strlen ("gen-zero-r"));
- }
- else if (strncmp (optarg, "zero-r", strlen ("zero-r")) == 0)
- {
- options.gen.zero_reg = 1;
- options.gen.zero_reg_nr = atoi (optarg + strlen ("zero-r"));
- options.warning (NULL, "Option zero-r<N> replaced by gen-zero-r<N>\n");
- }
- else if (strcmp (optarg, "gen-icache") == 0)
- {
- options.gen.icache = 1;
- }
- else if (strcmp (optarg, "gen-insn-in-icache") == 0)
- {
- options.gen.insn_in_icache = 1;
- }
- else if (strcmp (optarg, "gen-multi-sim") == 0)
- {
- options.gen.multi_sim = 1;
- }
- else if (strcmp (optarg, "gen-multi-word") == 0)
- {
- options.gen.multi_word = 1;
- }
- else if (strcmp (optarg, "gen-semantic-icache") == 0)
- {
- options.gen.semantic_icache = 1;
- }
- else if (strcmp (optarg, "gen-slot-verification") == 0)
- {
- options.gen.slot_verification = 1;
- }
- else if (strcmp (optarg, "verify-slot") == 0)
- {
- options.gen.slot_verification = 1;
- options.warning (NULL, "Option verify-slot replaced by gen-slot-verification\n");
- }
- else if (strcmp (optarg, "gen-nia-invalid") == 0)
- {
- options.gen.nia = nia_is_invalid;
- }
- else if (strcmp (optarg, "default-nia-minus-one") == 0)
- {
- options.gen.nia = nia_is_invalid;
- options.warning (NULL, "Option default-nia-minus-one replaced by gen-nia-invalid\n");
- }
- else if (strcmp (optarg, "gen-nia-void") == 0)
- {
- options.gen.nia = nia_is_void;
- }
- else if (strcmp (optarg, "trace-combine") == 0)
- {
- options.trace.combine = 1;
- }
- else if (strcmp (optarg, "trace-entries") == 0)
- {
- options.trace.entries = 1;
- }
- else if (strcmp (optarg, "trace-rule-rejection") == 0)
- {
- options.trace.rule_rejection = 1;
- }
- else if (strcmp (optarg, "trace-rule-selection") == 0)
- {
- options.trace.rule_selection = 1;
- }
- else if (strcmp (optarg, "jumps") == 0)
- {
- options.gen.code = generate_jumps;
- }
- else if (strcmp (optarg, "field-widths") == 0)
- {
- options.insn_specifying_widths = 1;
- }
- else if (strcmp (optarg, "omit-line-numbers") == 0)
- {
- file_references = lf_omit_references;
- }
- else
- error (NULL, "Unknown option %s\n", optarg);
- break;
-
+ {
+ int enable_p;
+ char *argp;
+ if (strncmp (optarg, "no-", strlen ("no-")) == 0)
+ {
+ argp = optarg + strlen ("no-");
+ enable_p = 0;
+ }
+ else if (strncmp (optarg, "!", strlen ("!")) == 0)
+ {
+ argp = optarg + strlen ("no-");
+ enable_p = 0;
+ }
+ else
+ {
+ argp = optarg;
+ enable_p = 1;
+ }
+ if (strcmp (argp, "decode-duplicate") == 0)
+ {
+ options.decode.duplicate = enable_p;
+ }
+ else if (strcmp (argp, "decode-combine") == 0)
+ {
+ options.decode.combine = enable_p;
+ }
+ else if (strcmp (argp, "decode-zero-reserved") == 0)
+ {
+ options.decode.zero_reserved = enable_p;
+ }
+
+ else if (strcmp (argp, "gen-conditional-issue") == 0)
+ {
+ options.gen.conditional_issue = enable_p;
+ }
+ else if (strcmp (argp, "conditional-issue") == 0)
+ {
+ options.gen.conditional_issue = enable_p;
+ options.warning (NULL, "Option conditional-issue replaced by gen-conditional-issue\n");
+ }
+ else if (strcmp (argp, "gen-delayed-branch") == 0)
+ {
+ options.gen.delayed_branch = enable_p;
+ }
+ else if (strcmp (argp, "delayed-branch") == 0)
+ {
+ options.gen.delayed_branch = enable_p;
+ options.warning (NULL, "Option delayed-branch replaced by gen-delayed-branch\n");
+ }
+ else if (strcmp (argp, "gen-direct-access") == 0)
+ {
+ options.gen.direct_access = enable_p;
+ }
+ else if (strcmp (argp, "direct-access") == 0)
+ {
+ options.gen.direct_access = enable_p;
+ options.warning (NULL, "Option direct-access replaced by gen-direct-access\n");
+ }
+ else if (strncmp (argp, "gen-zero-r", strlen ("gen-zero-r")) == 0)
+ {
+ options.gen.zero_reg = enable_p;
+ options.gen.zero_reg_nr = atoi (argp + strlen ("gen-zero-r"));
+ }
+ else if (strncmp (argp, "zero-r", strlen ("zero-r")) == 0)
+ {
+ options.gen.zero_reg = enable_p;
+ options.gen.zero_reg_nr = atoi (argp + strlen ("zero-r"));
+ options.warning (NULL, "Option zero-r<N> replaced by gen-zero-r<N>\n");
+ }
+ else if (strncmp (argp, "gen-icache", strlen ("gen-icache")) == 0)
+ {
+ switch (argp[strlen ("gen-icache")])
+ {
+ case '=':
+ options.gen.icache_size = atoi (argp + strlen ("gen-icache") + 1);
+ /* fall through */
+ case '\0':
+ options.gen.icache = enable_p;
+ break;
+ default:
+ error (NULL, "Expecting -Ggen-icache or -Ggen-icache=<N>\n");
+ }
+ }
+ else if (strcmp (argp, "gen-insn-in-icache") == 0)
+ {
+ options.gen.insn_in_icache = enable_p;
+ }
+ else if (strcmp (argp, "gen-multi-sim") == 0)
+ {
+ options.gen.multi_sim = enable_p;
+ }
+ else if (strcmp (argp, "gen-multi-word") == 0)
+ {
+ options.gen.multi_word = enable_p;
+ }
+ else if (strcmp (argp, "gen-semantic-icache") == 0)
+ {
+ options.gen.semantic_icache = enable_p;
+ }
+ else if (strcmp (argp, "gen-slot-verification") == 0)
+ {
+ options.gen.slot_verification = enable_p;
+ }
+ else if (strcmp (argp, "verify-slot") == 0)
+ {
+ options.gen.slot_verification = enable_p;
+ options.warning (NULL, "Option verify-slot replaced by gen-slot-verification\n");
+ }
+ else if (strcmp (argp, "gen-nia-invalid") == 0)
+ {
+ options.gen.nia = nia_is_invalid;
+ }
+ else if (strcmp (argp, "default-nia-minus-one") == 0)
+ {
+ options.gen.nia = nia_is_invalid;
+ options.warning (NULL, "Option default-nia-minus-one replaced by gen-nia-invalid\n");
+ }
+ else if (strcmp (argp, "gen-nia-void") == 0)
+ {
+ options.gen.nia = nia_is_void;
+ }
+ else if (strcmp (argp, "trace-combine") == 0)
+ {
+ options.trace.combine = enable_p;
+ }
+ else if (strcmp (argp, "trace-entries") == 0)
+ {
+ options.trace.entries = enable_p;
+ }
+ else if (strcmp (argp, "trace-rule-rejection") == 0)
+ {
+ options.trace.rule_rejection = enable_p;
+ }
+ else if (strcmp (argp, "trace-rule-selection") == 0)
+ {
+ options.trace.rule_selection = enable_p;
+ }
+ else if (strcmp (argp, "jumps") == 0)
+ {
+ options.gen.code = generate_jumps;
+ }
+ else if (strcmp (argp, "field-widths") == 0)
+ {
+ options.insn_specifying_widths = enable_p;
+ }
+ else if (strcmp (argp, "omit-line-numbers") == 0)
+ {
+ file_references = lf_omit_references;
+ }
+ else
+ {
+ error (NULL, "Unknown option %s\n", optarg);
+ }
+ break;
+ }
+
case 'i':
isa = load_insn_table (optarg, cache_rules);
if (isa->illegal_insn == NULL)
diff --git a/sim/igen/ld-insn.c b/sim/igen/ld-insn.c
index eaa7eca..c5c3679 100644
--- a/sim/igen/ld-insn.c
+++ b/sim/igen/ld-insn.c
@@ -374,6 +374,7 @@ typedef enum {
function_record,
internal_record,
define_record,
+ include_record,
model_processor_record,
model_macro_record,
model_data_record,
@@ -388,6 +389,7 @@ static const name_map insn_type_map[] = {
{ "compute", compute_record },
{ "scratch", scratch_record },
{ "define", define_record },
+ { "include", include_record },
{ "%s", string_function_record },
{ "function", function_record },
{ "internal", internal_record },
@@ -744,6 +746,17 @@ load_insn_table (char *file_name,
switch (record_type (record))
{
+ case include_record:
+ {
+ if (record->nr_fields < nr_include_record_fields)
+ error (record->line,
+ "Incorrect nr of fields for include record\n");
+ table_push (file, record->line, options.include,
+ record->field[include_record_filename_field]);
+ record = table_read (file);
+ break;
+ }
+
case option_record:
{
if (isa->insns != NULL)
@@ -757,7 +770,7 @@ load_insn_table (char *file_name,
/* convert a string function field into an internal function field */
char *name;
if (record->nr_fields < nr_function_fields)
- error (record->line, "Incorrect nr of fields for %s record\n");
+ error (record->line, "Incorrect nr of fields for %%s record\n");
name = NZALLOC (char,
(strlen ("str_")
+ strlen (record->field[function_name_field])
@@ -1017,8 +1030,12 @@ load_insn_table (char *file_name,
break;
}
- default:
- error (record->line, "Unknown entry\n");
+ case unknown_record:
+ case define_record:
+ case code_record:
+ error (record->line, "Unknown or unexpected entry\n");
+
+
}
}
return isa;
diff --git a/sim/igen/ld-insn.h b/sim/igen/ld-insn.h
new file mode 100644
index 0000000..be6f4be
--- /dev/null
+++ b/sim/igen/ld-insn.h
@@ -0,0 +1,608 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 1994,1995,1996,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.
+
+ */
+
+
+
+typedef unsigned64 insn_uint;
+
+
+/* Common among most entries:
+
+ */
+
+enum {
+ record_type_field = 1,
+ old_record_type_field = 2,
+ record_filter_flags_field = 2,
+};
+
+
+/* Include:
+
+ Include the specified file.
+
+ <include> ::=
+ ":" "include"
+ ":" <filter-flags>
+ ":" <filename>
+ <nl>
+ ;
+
+ */
+
+enum {
+ include_record_filename_field = 3,
+ nr_include_record_fields = 4,
+};
+
+
+
+/* Options:
+
+ Valid options are: hi-bit-nr (default 0), insn-bit-size (default
+ 32), insn-specifying-widths (default true), multi-sim (default false).
+
+ <option> ::=
+ ":" "option"
+ ":" <filter-flags>
+ ":" <option-name>
+ ":" <option-value>
+ <nl>
+ ;
+
+ <option-name> ::=
+ "insn-bit-size"
+ | "insn-specifying-widths"
+ | "hi-bit-nr"
+ | "flags-filter"
+ | "model-filter"
+ | "multi-sim"
+ | "format-names"
+ ;
+
+ <option-value> ::=
+ "true"
+ | "false"
+ | <integer>
+ | <list>
+ ;
+
+
+ These update the global options structure. */
+
+
+enum {
+ option_name_field = 3,
+ option_value_field = 4,
+ nr_option_fields = 5,
+};
+
+
+
+/* Macro definitions:
+
+ <insn-macro> ::=
+ <expression>
+ ":" "define"
+ ":" <filter-flags>
+ ":"
+ ":" <name>
+ <nl>
+ ;
+
+ Macro define/undef is currently unimplemented. */
+
+
+/* Functions and internal routins:
+
+ <function> ::=
+ ":" "function"
+ <function-spec>
+ ;
+
+ <internal> ::=
+ ":" "internal"
+ <function-spec>
+ ;
+
+ <function-spec> ::=
+ ":" <filter-flags>
+ ":" <typedef>
+ ":" <name>
+ [ ":" <parameter-list> ]
+ <nl>
+ <code-block>
+ ;
+
+ */
+
+enum {
+ function_typedef_field = 3,
+ function_name_field = 4,
+ function_param_field = 5,
+ nr_function_fields = 5,
+};
+
+enum {
+ old_function_typedef_field = 0,
+ old_function_type_field = 2,
+ old_function_name_field = 4,
+ old_function_param_field = 5,
+ nr_old_function_fields = 6,
+};
+
+
+typedef struct _function_entry function_entry;
+struct _function_entry {
+ line_ref *line;
+ filter *flags;
+ char *type;
+ char *name;
+ char *param;
+ table_entry *code;
+ int is_internal;
+ function_entry *next;
+};
+
+
+typedef void function_entry_handler
+(lf *file,
+ function_entry *function,
+ void *data);
+
+extern void function_entry_traverse
+(lf *file,
+ function_entry *functions,
+ function_entry_handler *handler,
+ void *data);
+
+
+/* cache-macro:
+
+ <cache-macro> ::=
+ ":" <macro-type>
+ ":" <filter-flags>
+ ":" <type>
+ ":" <name>
+ ":" <field-name> { "," <field-name> }
+ ":" <expression>
+ <nl>
+ ;
+
+ <cache-macro-type> ::=
+ "scratch"
+ | "cache"
+ | "compute"
+ ;
+
+ <name> ::=
+ <ident>
+ | <ident> "_is_" <integer>
+ ;
+
+ A cache entry is defined (for an instruction) when all
+ <field-name>s are present as named opcode fields within the
+ instructions format.
+
+ SCRATCH and CACHE macros are defined during the cache fill stage
+ while CACHE and COMPUTE macros are defined during the instruction
+ execution stage.
+
+ */
+
+enum {
+ cache_type_field = 3,
+ cache_name_field = 4,
+ cache_original_fields_field = 5,
+ cache_expression_field = 6,
+ nr_cache_fields = 7,
+};
+
+typedef enum {
+ scratch_value,
+ cache_value,
+ compute_value,
+} cache_entry_type;
+
+typedef struct _cache_entry cache_entry;
+struct _cache_entry {
+ line_ref *line;
+ filter *flags;
+ cache_entry_type entry_type;
+ char *name;
+ filter *original_fields;
+ char *type;
+ char *expression;
+ cache_entry *next;
+};
+
+
+
+/* Model specs:
+
+ <model-processor> ::=
+ ":" "model"
+ ":" <filter-flags>
+ ":" <processor>
+ ":" <long-processor>
+ ":" <function-unit-data>
+ <nl>
+ ;
+
+ <model-macro> ::=
+ ":" "model-macro"
+ ":" <filter-flags>
+ <nl>
+ <code-block>
+ ;
+
+ <model-data> ::=
+ ":" "model-data"
+ ":" <filter-flags>
+ <nl>
+ <code-block>
+ ;
+
+ <model-static> ::=
+ ":" "model-static"
+ <function-spec>
+ ;
+
+ <model-internal> ::=
+ ":" "model-internal"
+ <function-spec>
+ ;
+
+ <model-function> ::=
+ ":" "model-internal"
+ <function-spec>
+ ;
+
+ */
+
+enum {
+ nr_model_macro_fields = 3,
+ nr_model_data_fields = 3,
+ nr_model_static_fields = 6,
+ nr_model_internal_fields = 6,
+ nr_model_function_fields = 6,
+};
+
+typedef struct _model_data model_data;
+struct _model_data {
+ line_ref *line;
+ filter *flags;
+ table_entry *entry;
+ table_entry *code;
+ model_data *next;
+};
+
+enum {
+ model_name_field = 3,
+ model_full_name_field = 4,
+ model_unit_data_field = 5,
+ nr_model_processor_fields = 6,
+};
+
+typedef struct _model_entry model_entry;
+struct _model_entry {
+ line_ref *line;
+ filter *flags;
+ char *name;
+ char *full_name;
+ char *unit_data;
+ model_entry *next;
+};
+
+
+typedef struct _model_table model_table;
+struct _model_table {
+ filter *processors;
+ int nr_models;
+ model_entry *models;
+ model_data *macros;
+ model_data *data;
+ function_entry *statics;
+ function_entry *internals;
+ function_entry *functions;
+};
+
+
+
+/* Instruction format:
+
+ An instruction is composed of a sequence of N bit instruction
+ words. Each word broken into a number of instruction fields.
+ Those fields being constant (ex. an opcode) or variable (register
+ spec).
+
+ <insn-word> ::=
+ <insn-field> { "," <insn-field> } ;
+
+ <insn-word> ::=
+ ( <binary-value-implying-width>
+ | <field-name-implying-width>
+ | [ <start-or-width> "." ] <field>
+ )
+ { "!" <excluded-value> }
+ ;
+
+ <field> ::=
+ "*" +
+ | "/" +
+ | <field-name>
+ | "0x" <hex-value>
+ | "0b" <binary-value>
+ | "0" <octal-value>
+ | <integer-value> ;
+
+*/
+
+typedef struct _insn_field_exclusion insn_field_exclusion;
+struct _insn_field_exclusion {
+ char *string;
+ insn_uint value;
+ insn_field_exclusion *next;
+};
+
+typedef enum {
+ insn_field_int,
+ insn_field_reserved,
+ insn_field_wild,
+ insn_field_string,
+} insn_field_type;
+
+typedef struct _insn_field_entry insn_field_entry;
+struct _insn_field_entry {
+ int first;
+ int last;
+ int width;
+ int word_nr;
+ insn_field_type type;
+ insn_uint val_int;
+ char *pos_string;
+ char *val_string;
+ insn_field_exclusion *exclusions;
+ insn_field_entry *next;
+ insn_field_entry *prev;
+};
+
+typedef struct _insn_bit_entry insn_bit_entry;
+struct _insn_bit_entry {
+ int value;
+ int mask;
+ insn_field_entry *field;
+};
+
+
+
+
+typedef struct _insn_entry insn_entry; /* forward */
+
+typedef struct _insn_word_entry insn_word_entry;
+struct _insn_word_entry {
+ /* list of sub-fields making up the instruction. bit provides
+ faster access to the field data for bit N. */
+ insn_field_entry *first;
+ insn_field_entry *last;
+ insn_bit_entry *bit[max_insn_bit_size];
+ /* set of all the string fields */
+ filter *field_names;
+ /* For multi-word instructions, The Nth word (from zero). */
+ insn_word_entry *next;
+};
+
+
+
+/* Instruction model:
+
+ Provides scheduling data for the code modeling the instruction unit.
+
+ <insn-model> ::=
+ "*" [ <processor> ]
+ ":" <function-unit-data>
+ <nl>
+ ;
+
+ If <processor> is NULL, the model is made the default for this
+ instruction.
+
+ */
+
+enum {
+ insn_model_name_field = 0,
+ insn_model_unit_data_field = 1,
+ nr_insn_model_fields = 1,
+};
+
+typedef struct _insn_model_entry insn_model_entry;
+struct _insn_model_entry {
+ line_ref *line;
+ insn_entry *insn;
+ char *name;
+ char *full_name;
+ char *unit_data;
+ insn_model_entry *next;
+};
+
+
+
+/* Instruction mnemonic:
+
+ List of assembler mnemonics for the instruction.
+
+ <insn-mnenonic> ::=
+ "\"" <assembler-mnemonic> "\""
+ [ ":" <conditional-expression> ]
+ <nl>
+ ;
+
+ */
+
+enum {
+ insn_mnemonic_format_field = 0,
+ insn_mnemonic_condition_field = 1,
+ nr_insn_mnemonic_fields = 1,
+};
+
+typedef struct _insn_mnemonic_entry insn_mnemonic_entry;
+struct _insn_mnemonic_entry {
+ line_ref *line;
+ insn_entry *insn;
+ char *format;
+ char *condition;
+ insn_mnemonic_entry *next;
+};
+
+
+
+/* Instruction:
+
+ <insn> ::=
+ <insn-word> { "+" <insn-word> }
+ ":" <format-name>
+ ":" <filter-flags>
+ ":" <options>
+ ":" <name>
+ <nl>
+ { <insn-model> }
+ { <insn-mnemonic> }
+ <code-block>
+
+ */
+
+enum {
+ insn_word_field = 0,
+ insn_format_name_field = 1,
+ insn_filter_flags_field = 2,
+ insn_options_field = 3,
+ insn_name_field = 4,
+ nr_insn_fields = 5,
+};
+
+
+/* typedef struct _insn_entry insn_entry; */
+struct _insn_entry {
+ line_ref *line;
+ filter *flags; /* filtered by options.filters */
+ char *format_name;
+ filter *options;
+ char *name;
+ /* the words that make up the instruction. Word provides direct
+ access to word N. Pseudo instructions can be identified by
+ nr_words == 0. */
+ int nr_words;
+ insn_word_entry *words;
+ insn_word_entry **word;
+ /* a set of all the fields from all the words */
+ filter *field_names;
+ /* an array of processor models, missing models are NULL! */
+ int nr_models;
+ insn_model_entry *models;
+ insn_model_entry **model;
+ filter *processors;
+ /* list of assember formats */
+ int nr_mnemonics;
+ insn_mnemonic_entry *mnemonics;
+ /* code body */
+ table_entry *code;
+ insn_entry *next;
+};
+
+
+/* Instruction table:
+
+ */
+
+typedef struct _insn_table insn_table;
+struct _insn_table {
+ cache_entry *caches;
+ int max_nr_words;
+ int nr_insns;
+ insn_entry *insns;
+ function_entry *functions;
+ insn_entry *illegal_insn;
+ model_table *model;
+ filter *options;
+ filter *flags;
+};
+
+extern insn_table *load_insn_table
+(char *file_name,
+ cache_entry *cache);
+
+typedef void insn_entry_handler
+(lf *file,
+ insn_table *isa,
+ insn_entry *insn,
+ void *data);
+
+extern void insn_table_traverse_insn
+(lf *file,
+ insn_table *isa,
+ insn_entry_handler *handler,
+ void *data);
+
+
+
+/* Printing */
+
+extern void print_insn_words
+(lf *file,
+ insn_entry *insn);
+
+
+
+/* Debugging */
+
+void
+dump_insn_field
+(lf *file,
+ char *prefix,
+ insn_field_entry *field,
+ char *suffix);
+
+void
+dump_insn_word_entry
+(lf *file,
+ char *prefix,
+ insn_word_entry *word,
+ char *suffix);
+
+void
+dump_insn_entry
+(lf *file,
+ char *prefix,
+ insn_entry *insn,
+ char *suffix);
+
+void
+dump_cache_entries
+(lf *file,
+ char *prefix,
+ cache_entry *entry,
+ char *suffix);
+
+void
+dump_insn_table
+(lf *file,
+ char *prefix,
+ insn_table *isa,
+ char *suffix);
diff --git a/sim/igen/table.c b/sim/igen/table.c
index 461a632..71be438 100644
--- a/sim/igen/table.c
+++ b/sim/igen/table.c
@@ -38,348 +38,598 @@
#include <stdlib.h>
#endif
-struct _table {
+typedef struct _open_table open_table;
+struct _open_table {
size_t size;
char *buffer;
char *pos;
- int nr_fields;
- int nr_model_fields;
- int line_nr;
- char *file_name;
- int current_file_line_offset;
- char *current_file_name;
+ line_ref pseudo_line;
+ line_ref real_line;
+ open_table *parent;
+ table *root;
+};
+struct _table {
+ open_table *current;
};
-extern table *
-table_open(const char *file_name,
- int nr_fields,
- int nr_model_fields)
+
+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)
{
int fd;
struct stat stat_buf;
- table *file;
+ 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(table);
- ASSERT(file != NULL);
- file->nr_fields = nr_fields;
- file->nr_model_fields = nr_model_fields;
-
- /* save the file name */
- file->file_name = (char*)zalloc(strlen(file_name) + 1);
- ASSERT(file->file_name != NULL);
- strcpy(file->file_name, file_name);
- file->current_file_name = file->file_name;
-
- /* open the file */
- fd = open(file->file_name, O_RDONLY, 0);
- if (fd < 0) {
- perror(file->file_name);
- exit (1);
+ 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;
+printf ("Trying `%s'\n", dup_name);
+ /* open the file */
+ fd = open (dup_name, O_RDONLY, 0);
+ if (fd >= 0)
+ 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 */
- if (fstat(fd, &stat_buf) < 0) {
- perror("table_open.fstat");
- exit(1);
+ if (fstat (fd, &stat_buf) < 0) {
+ perror (file_name);
+ exit (1);
}
file->size = stat_buf.st_size;
/* allocate this much memory */
- file->buffer = (char*)zalloc(file->size+1);
- ASSERT(file->buffer != NULL);
+ file->buffer = (char*) zalloc (file->size + 1);
+ if (file->buffer == NULL)
+ {
+ perror (file_name);
+ exit (1);
+ }
file->pos = file->buffer;
- /* read it in */
- if (read(fd, file->buffer, file->size) < file->size) {
- perror(file->file_name);
- exit(1);
+ /* read it all in */
+ if (read (fd, file->buffer, file->size) < file->size) {
+ perror (file_name);
+ exit (1);
}
file->buffer[file->size] = '\0';
/* set the initial line numbering */
- file->line_nr = 0;
- file->current_file_line_offset = 0;
+ file->real_line.line_nr = 1; /* specifies current line */
+ file->pseudo_line.line_nr = 1; /* specifies current line */
/* done */
- close(fd);
- return file;
+ close (fd);
}
-
-extern table_entry *
-table_entry_read(table *file)
+table *
+table_open (const char *file_name)
{
- int field;
- table_entry *entry;
+ table *root;
- /* skip comments/blanks */
- while(1) {
- /* leading white space */
- while (*file->pos != '\0'
- && *file->pos != '\n'
- && isspace(*file->pos))
- file->pos++;
- /* cpp line nr directive - # <line-nr> "<file>" */
- if (file->pos[0] == '#'
- && file->pos[1] == ' '
- && isdigit(file->pos[2])) {
- file->pos += strlen("# ");
- /* parse the number */
- file->current_file_line_offset = atoi(file->pos) - file->line_nr - 2;
- /* skip to the file name */
- while (file->pos[0] != '0'
- && file->pos[0] != '"'
- && file->pos[0] != '\0')
- file->pos++;
- if (file->pos[0] != '"') {
- error("%s:%d: Missing opening quote",
- file->file_name,
- file->line_nr);
- }
- /* parse the file name */
- file->pos++;
- file->current_file_name = file->pos;
- while (file->pos[0] != '"'
- && file->pos[0] != '\0')
- file->pos++;
- if (file->pos[0] != '"') {
- error("%s:%d: Missing closing quote",
- file->file_name,
- file->line_nr);
- }
- file->pos[0] = '\0';
- file->pos ++;
- while (file->pos[0] != '\0'
- && file->pos[0] != '\n')
- file->pos[0]++;
- if (file->pos[0] != '\n')
- error("%s:%d: Missing newline",
- file->file_name,
- file->line_nr);
+ /* create a file descriptor */
+ root = ZALLOC (table);
+ if (root == NULL)
+ {
+ perror (file_name);
+ exit (1);
}
- /* comment - leading // or # - skip */
- else if ((file->pos[0] == '/' && file->pos[1] == '/')
- || (file->pos[0] == '#')) {
- do {
- file->pos++;
- } while (*file->pos != '\0' && *file->pos != '\n');
+
+ 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++;
}
- /* end of line? */
- if (*file->pos == '\n') {
- file->pos++;
- file->line_nr++;
+}
+
+
+char *
+back_spaces (char *start, char *chp)
+{
+ while (1)
+ {
+ if (chp <= start
+ || !isspace (chp[-1]))
+ return chp;
+ chp--;
}
- else
- break;
- }
- if (*file->pos == '\0')
- return NULL;
-
- /* create this new entry */
- entry = (table_entry*)zalloc(sizeof(table_entry)
- + (file->nr_fields + 1) * sizeof(char*));
- ASSERT(entry != NULL);
- entry->file_name = file->current_file_name;
- entry->nr_fields = file->nr_fields;
-
- /* break the line into its colon delimitered fields */
- for (field = 0; field < file->nr_fields-1; field++) {
- entry->fields[field] = file->pos;
- while(*file->pos && *file->pos != ':' && *file->pos != '\n')
- file->pos++;
- if (*file->pos == ':') {
- *file->pos = '\0';
- file->pos++;
+}
+
+char *
+skip_digits (char *chp)
+{
+ while (1)
+ {
+ if (*chp == '\0'
+ || *chp == '\n'
+ || !isdigit (*chp))
+ return chp;
+ chp++;
}
- }
+}
- /* any trailing stuff not the last field */
- ASSERT(field == file->nr_fields-1);
- entry->fields[field] = file->pos;
- while (*file->pos && *file->pos != '\n') {
- file->pos++;
- }
- if (*file->pos == '\n') {
- *file->pos = '\0';
- file->pos++;
- }
- file->line_nr++;
-
- /* If following lines being with a double quote ("), add them to the
- list of assembler lines */
- {
- table_assembler_entry **current = &entry->assembler;
- while (*file->pos == '"') {
- char *tmpchp;
- const char *format;
- int strlen_format;
- const char *condition;
- int strlen_condition;
-
- /* skip over the format string */
- format = file->pos;
- strlen_format = 0;
- do {
- if (file->pos[0] == '\\' && file->pos[1] == '"')
- file->pos += 2;
- else
- file->pos += 1;
- } while (*file->pos != '\0' && *file->pos != '\n' && *file->pos != '"');
- if (*file->pos != '"')
- error ("%s:%d: Missing closing quote in assembler line",
- file->file_name,
- file->line_nr);
- file->pos++;
- strlen_format = file->pos - format;
-
- /* skip over the boolean condition */
- condition = NULL;
- strlen_condition = 0;
- if (*file->pos == ':')
+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')
{
- file->pos++;
- while (isspace(*file->pos) && *file->pos != '\0' && *file->pos != '\n')
- file->pos++;
- condition = file->pos;
- while (*file->pos != '\0' && *file->pos != '\n')
- file->pos++;
- strlen_condition = file->pos - condition;
+ if (file->parent != NULL)
+ {
+ file = file->parent;
+ root->current = file;
+ }
+ else
+ return NULL;
}
- /* create the new assembler entry */
- *current = ZALLOC (table_assembler_entry);
- tmpchp = zalloc (strlen_format + 1);
- strncpy (tmpchp, format, strlen_format);
- (*current)->format = tmpchp;
- (*current)->file_name = file->file_name;
- (*current)->line_nr = file->line_nr;
- if (condition != NULL && strlen_condition > 0)
+ /* code_block? */
+ if (*file->pos == '{')
{
- tmpchp = zalloc (strlen_condition + 1);
- strncpy (tmpchp, condition, strlen_condition);
- (*current)->condition = tmpchp;
+ 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;
}
- current = &(*current)->next;
-
- /* end of line? */
- if (*file->pos != '\n')
- error ("%s:%d: Missing eoln in assembler line",
- file->file_name,
- file->line_nr);
- file->pos++;
- file->line_nr++;
- }
- }
- /* if following lines begin with a star, add them to the model
- section. */
- while ((file->nr_model_fields > 0) && (*file->pos == '*')) {
- table_model_entry *model = (table_model_entry*)zalloc(sizeof(table_model_entry)
- + (file->nr_model_fields + 1) * sizeof(char*));
- if (entry->model_last)
- entry->model_last->next = model;
- else
- entry->model_first = model;
- entry->model_last = model;
-
- /* break the line into its colon delimitered fields */
- file->pos++;
- for (field = 0; field < file->nr_model_fields-1; field++) {
- model->fields[field] = file->pos;
- while(*file->pos && *file->pos != ':' && *file->pos != '\n')
- file->pos++;
- if (*file->pos == ':') {
- *file->pos = '\0';
- file->pos++;
- }
- }
+ /* 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;
+ }
- /* any trailing stuff not the last field */
- ASSERT(field == file->nr_model_fields-1);
- model->fields[field] = file->pos;
- while (*file->pos && *file->pos != '\n') {
- file->pos++;
- }
- if (*file->pos == '\n') {
- *file->pos = '\0';
- file->pos++;
- }
+ /* 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;
+ }
- file->line_nr++;
- model->line_nr = file->current_file_line_offset + file->line_nr;
- }
+ /* 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;
+ }
- entry->line_nr = file->current_file_line_offset + file->line_nr;
-
- /* if following lines are tab indented, put in the annex */
- if (*file->pos == '\t') {
- entry->annex = file->pos;
- do {
- do {
- file->pos++;
- } while (*file->pos != '\0' && *file->pos != '\n');
- if (*file->pos == '\n') {
- char *save_pos = ++file->pos;
- int extra_lines = 0;
- file->line_nr++;
- /* Allow tab indented to have blank lines */
- while (*save_pos == '\n') {
- save_pos++;
- extra_lines++;
+ /* comment - leading // or # - skip */
+ if ((file->pos[0] == '/' && file->pos[1] == '/')
+ || (file->pos[0] == '#'))
+ {
+ next_line (file);
+ continue;
}
- if (*save_pos == '\t') {
- file->pos = save_pos;
- file->line_nr += extra_lines;
+
+ /* 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;
}
- } while (*file->pos != '\0' && *file->pos == '\t');
- if (file->pos[-1] == '\n')
- file->pos[-1] = '\0';
- }
- else
- entry->annex = NULL;
- /* return it */
- return entry;
+ }
+ ASSERT (entry == NULL || entry->field[entry->nr_fields] == NULL);
+ return entry;
}
-
extern void
-dump_table_entry(table_entry *entry,
- int indent)
+table_print_code (lf *file,
+ table_entry *entry)
{
- printf("(table_entry*)%p\n", 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');
+ }
+}
- if (entry != NULL) {
- int field;
- char sep;
- sep = ' ';
- dumpf(indent, "(fields");
- for (field = 0; field < entry->nr_fields; field++) {
- printf("%c%s", sep, entry->fields[field]);
- sep = ':';
- }
- printf(")\n");
- dumpf(indent, "(line_nr %d)\n", entry->line_nr);
+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);
+}
- dumpf(indent, "(file_name %s)\n", entry->file_name);
- dumpf(indent, "(annex\n%s\n", entry->annex);
- dumpf(indent, " )\n");
+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);
}
-extern void
-table_entry_print_cpp_line_nr(lf *file,
- table_entry *entry)
+#ifdef MAIN
+int
+main(int argc, char **argv)
{
- lf_print__external_reference(file, entry->line_nr, entry->file_name);
-}
+ 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