Add include-file support to igen.
This commit is contained in:
parent
f45dd42b32
commit
e2880fadf3
@ -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>
|
Thu Oct 16 11:03:27 1997 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
* gen-semantics.c (print_semantic_body): Use CIA not
|
* gen-semantics.c (print_semantic_body): Use CIA not
|
||||||
|
159
sim/igen/igen.c
159
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 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 ("\t This option can now be set directly in the instruction table.\n");
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf (" -I <icache-size>\n");
|
printf (" -I <directory>\n");
|
||||||
printf ("\t Specify size of the cracking instruction cache (default %d instructions).\n",
|
printf ("\t Add <directory> to the list of directories searched when opening a file\n");
|
||||||
options.gen.icache_size);
|
|
||||||
printf ("\t Implies -G icache.\n");
|
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
printf (" -M <model-list>\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 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 ("\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");
|
||||||
printf (" -N <nr-cpus>\n");
|
printf (" -N <nr-cpus>\n");
|
||||||
printf ("\t Generate a simulator supporting <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-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-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-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-insn-in-icache - save original instruction when cracking\n");
|
||||||
printf ("\t gen-multi-sim - generate multiple simulators - one per model\n");
|
printf ("\t gen-multi-sim - generate multiple simulators - one per model\n");
|
||||||
printf ("\t By default, a single simulator that will\n");
|
printf ("\t By default, a single simulator that will\n");
|
||||||
@ -1099,8 +1098,13 @@ main (int argc,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'I':
|
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;
|
break;
|
||||||
|
|
||||||
case 'B':
|
case 'B':
|
||||||
@ -1213,130 +1217,161 @@ main (int argc,
|
|||||||
|
|
||||||
|
|
||||||
case 'G':
|
case 'G':
|
||||||
if (strcmp (optarg, "decode-duplicate") == 0)
|
|
||||||
{
|
{
|
||||||
options.decode.duplicate = 1;
|
int enable_p;
|
||||||
|
char *argp;
|
||||||
|
if (strncmp (optarg, "no-", strlen ("no-")) == 0)
|
||||||
|
{
|
||||||
|
argp = optarg + strlen ("no-");
|
||||||
|
enable_p = 0;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "decode-combine") == 0)
|
else if (strncmp (optarg, "!", strlen ("!")) == 0)
|
||||||
{
|
{
|
||||||
options.decode.combine = 1;
|
argp = optarg + strlen ("no-");
|
||||||
|
enable_p = 0;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "decode-zero-reserved") == 0)
|
else
|
||||||
{
|
{
|
||||||
options.decode.zero_reserved = 1;
|
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 (optarg, "gen-conditional-issue") == 0)
|
else if (strcmp (argp, "gen-conditional-issue") == 0)
|
||||||
{
|
{
|
||||||
options.gen.conditional_issue = 1;
|
options.gen.conditional_issue = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "conditional-issue") == 0)
|
else if (strcmp (argp, "conditional-issue") == 0)
|
||||||
{
|
{
|
||||||
options.gen.conditional_issue = 1;
|
options.gen.conditional_issue = enable_p;
|
||||||
options.warning (NULL, "Option conditional-issue replaced by gen-conditional-issue\n");
|
options.warning (NULL, "Option conditional-issue replaced by gen-conditional-issue\n");
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "gen-delayed-branch") == 0)
|
else if (strcmp (argp, "gen-delayed-branch") == 0)
|
||||||
{
|
{
|
||||||
options.gen.delayed_branch = 1;
|
options.gen.delayed_branch = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "delayed-branch") == 0)
|
else if (strcmp (argp, "delayed-branch") == 0)
|
||||||
{
|
{
|
||||||
options.gen.delayed_branch = 1;
|
options.gen.delayed_branch = enable_p;
|
||||||
options.warning (NULL, "Option delayed-branch replaced by gen-delayed-branch\n");
|
options.warning (NULL, "Option delayed-branch replaced by gen-delayed-branch\n");
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "gen-direct-access") == 0)
|
else if (strcmp (argp, "gen-direct-access") == 0)
|
||||||
{
|
{
|
||||||
options.gen.direct_access = 1;
|
options.gen.direct_access = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "direct-access") == 0)
|
else if (strcmp (argp, "direct-access") == 0)
|
||||||
{
|
{
|
||||||
options.gen.direct_access = 1;
|
options.gen.direct_access = enable_p;
|
||||||
options.warning (NULL, "Option direct-access replaced by gen-direct-access\n");
|
options.warning (NULL, "Option direct-access replaced by gen-direct-access\n");
|
||||||
}
|
}
|
||||||
else if (strncmp (optarg, "gen-zero-r", strlen ("gen-zero-r")) == 0)
|
else if (strncmp (argp, "gen-zero-r", strlen ("gen-zero-r")) == 0)
|
||||||
{
|
{
|
||||||
options.gen.zero_reg = 1;
|
options.gen.zero_reg = enable_p;
|
||||||
options.gen.zero_reg_nr = atoi (optarg + strlen ("gen-zero-r"));
|
options.gen.zero_reg_nr = atoi (argp + strlen ("gen-zero-r"));
|
||||||
}
|
}
|
||||||
else if (strncmp (optarg, "zero-r", strlen ("zero-r")) == 0)
|
else if (strncmp (argp, "zero-r", strlen ("zero-r")) == 0)
|
||||||
{
|
{
|
||||||
options.gen.zero_reg = 1;
|
options.gen.zero_reg = enable_p;
|
||||||
options.gen.zero_reg_nr = atoi (optarg + strlen ("zero-r"));
|
options.gen.zero_reg_nr = atoi (argp + strlen ("zero-r"));
|
||||||
options.warning (NULL, "Option zero-r<N> replaced by gen-zero-r<N>\n");
|
options.warning (NULL, "Option zero-r<N> replaced by gen-zero-r<N>\n");
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "gen-icache") == 0)
|
else if (strncmp (argp, "gen-icache", strlen ("gen-icache")) == 0)
|
||||||
{
|
{
|
||||||
options.gen.icache = 1;
|
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 (optarg, "gen-insn-in-icache") == 0)
|
|
||||||
{
|
|
||||||
options.gen.insn_in_icache = 1;
|
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "gen-multi-sim") == 0)
|
else if (strcmp (argp, "gen-insn-in-icache") == 0)
|
||||||
{
|
{
|
||||||
options.gen.multi_sim = 1;
|
options.gen.insn_in_icache = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "gen-multi-word") == 0)
|
else if (strcmp (argp, "gen-multi-sim") == 0)
|
||||||
{
|
{
|
||||||
options.gen.multi_word = 1;
|
options.gen.multi_sim = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "gen-semantic-icache") == 0)
|
else if (strcmp (argp, "gen-multi-word") == 0)
|
||||||
{
|
{
|
||||||
options.gen.semantic_icache = 1;
|
options.gen.multi_word = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "gen-slot-verification") == 0)
|
else if (strcmp (argp, "gen-semantic-icache") == 0)
|
||||||
{
|
{
|
||||||
options.gen.slot_verification = 1;
|
options.gen.semantic_icache = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "verify-slot") == 0)
|
else if (strcmp (argp, "gen-slot-verification") == 0)
|
||||||
{
|
{
|
||||||
options.gen.slot_verification = 1;
|
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");
|
options.warning (NULL, "Option verify-slot replaced by gen-slot-verification\n");
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "gen-nia-invalid") == 0)
|
else if (strcmp (argp, "gen-nia-invalid") == 0)
|
||||||
{
|
{
|
||||||
options.gen.nia = nia_is_invalid;
|
options.gen.nia = nia_is_invalid;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "default-nia-minus-one") == 0)
|
else if (strcmp (argp, "default-nia-minus-one") == 0)
|
||||||
{
|
{
|
||||||
options.gen.nia = nia_is_invalid;
|
options.gen.nia = nia_is_invalid;
|
||||||
options.warning (NULL, "Option default-nia-minus-one replaced by gen-nia-invalid\n");
|
options.warning (NULL, "Option default-nia-minus-one replaced by gen-nia-invalid\n");
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "gen-nia-void") == 0)
|
else if (strcmp (argp, "gen-nia-void") == 0)
|
||||||
{
|
{
|
||||||
options.gen.nia = nia_is_void;
|
options.gen.nia = nia_is_void;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "trace-combine") == 0)
|
else if (strcmp (argp, "trace-combine") == 0)
|
||||||
{
|
{
|
||||||
options.trace.combine = 1;
|
options.trace.combine = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "trace-entries") == 0)
|
else if (strcmp (argp, "trace-entries") == 0)
|
||||||
{
|
{
|
||||||
options.trace.entries = 1;
|
options.trace.entries = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "trace-rule-rejection") == 0)
|
else if (strcmp (argp, "trace-rule-rejection") == 0)
|
||||||
{
|
{
|
||||||
options.trace.rule_rejection = 1;
|
options.trace.rule_rejection = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "trace-rule-selection") == 0)
|
else if (strcmp (argp, "trace-rule-selection") == 0)
|
||||||
{
|
{
|
||||||
options.trace.rule_selection = 1;
|
options.trace.rule_selection = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "jumps") == 0)
|
else if (strcmp (argp, "jumps") == 0)
|
||||||
{
|
{
|
||||||
options.gen.code = generate_jumps;
|
options.gen.code = generate_jumps;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "field-widths") == 0)
|
else if (strcmp (argp, "field-widths") == 0)
|
||||||
{
|
{
|
||||||
options.insn_specifying_widths = 1;
|
options.insn_specifying_widths = enable_p;
|
||||||
}
|
}
|
||||||
else if (strcmp (optarg, "omit-line-numbers") == 0)
|
else if (strcmp (argp, "omit-line-numbers") == 0)
|
||||||
{
|
{
|
||||||
file_references = lf_omit_references;
|
file_references = lf_omit_references;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
error (NULL, "Unknown option %s\n", optarg);
|
error (NULL, "Unknown option %s\n", optarg);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
isa = load_insn_table (optarg, cache_rules);
|
isa = load_insn_table (optarg, cache_rules);
|
||||||
|
@ -374,6 +374,7 @@ typedef enum {
|
|||||||
function_record,
|
function_record,
|
||||||
internal_record,
|
internal_record,
|
||||||
define_record,
|
define_record,
|
||||||
|
include_record,
|
||||||
model_processor_record,
|
model_processor_record,
|
||||||
model_macro_record,
|
model_macro_record,
|
||||||
model_data_record,
|
model_data_record,
|
||||||
@ -388,6 +389,7 @@ static const name_map insn_type_map[] = {
|
|||||||
{ "compute", compute_record },
|
{ "compute", compute_record },
|
||||||
{ "scratch", scratch_record },
|
{ "scratch", scratch_record },
|
||||||
{ "define", define_record },
|
{ "define", define_record },
|
||||||
|
{ "include", include_record },
|
||||||
{ "%s", string_function_record },
|
{ "%s", string_function_record },
|
||||||
{ "function", function_record },
|
{ "function", function_record },
|
||||||
{ "internal", internal_record },
|
{ "internal", internal_record },
|
||||||
@ -744,6 +746,17 @@ load_insn_table (char *file_name,
|
|||||||
switch (record_type (record))
|
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:
|
case option_record:
|
||||||
{
|
{
|
||||||
if (isa->insns != NULL)
|
if (isa->insns != NULL)
|
||||||
@ -757,7 +770,7 @@ load_insn_table (char *file_name,
|
|||||||
/* convert a string function field into an internal function field */
|
/* convert a string function field into an internal function field */
|
||||||
char *name;
|
char *name;
|
||||||
if (record->nr_fields < nr_function_fields)
|
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,
|
name = NZALLOC (char,
|
||||||
(strlen ("str_")
|
(strlen ("str_")
|
||||||
+ strlen (record->field[function_name_field])
|
+ strlen (record->field[function_name_field])
|
||||||
@ -1017,8 +1030,12 @@ load_insn_table (char *file_name,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
case unknown_record:
|
||||||
error (record->line, "Unknown entry\n");
|
case define_record:
|
||||||
|
case code_record:
|
||||||
|
error (record->line, "Unknown or unexpected entry\n");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isa;
|
return isa;
|
||||||
|
608
sim/igen/ld-insn.h
Normal file
608
sim/igen/ld-insn.h
Normal file
@ -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);
|
798
sim/igen/table.c
798
sim/igen/table.c
@ -38,348 +38,598 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct _table {
|
typedef struct _open_table open_table;
|
||||||
|
struct _open_table {
|
||||||
size_t size;
|
size_t size;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
char *pos;
|
char *pos;
|
||||||
int nr_fields;
|
line_ref pseudo_line;
|
||||||
int nr_model_fields;
|
line_ref real_line;
|
||||||
int line_nr;
|
open_table *parent;
|
||||||
char *file_name;
|
table *root;
|
||||||
int current_file_line_offset;
|
};
|
||||||
char *current_file_name;
|
struct _table {
|
||||||
|
open_table *current;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern table *
|
|
||||||
table_open(const char *file_name,
|
static line_ref *
|
||||||
int nr_fields,
|
current_line (open_table *file)
|
||||||
int nr_model_fields)
|
{
|
||||||
|
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;
|
int fd;
|
||||||
struct stat stat_buf;
|
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 */
|
/* create a file descriptor */
|
||||||
file = ZALLOC(table);
|
file = ZALLOC (open_table);
|
||||||
ASSERT(file != NULL);
|
if (file == NULL)
|
||||||
file->nr_fields = nr_fields;
|
{
|
||||||
file->nr_model_fields = nr_model_fields;
|
perror (file_name);
|
||||||
|
|
||||||
/* 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);
|
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 */
|
/* determine the size */
|
||||||
if (fstat (fd, &stat_buf) < 0) {
|
if (fstat (fd, &stat_buf) < 0) {
|
||||||
perror("table_open.fstat");
|
perror (file_name);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
file->size = stat_buf.st_size;
|
file->size = stat_buf.st_size;
|
||||||
|
|
||||||
/* allocate this much memory */
|
/* allocate this much memory */
|
||||||
file->buffer = (char*) zalloc (file->size + 1);
|
file->buffer = (char*) zalloc (file->size + 1);
|
||||||
ASSERT(file->buffer != NULL);
|
if (file->buffer == NULL)
|
||||||
|
{
|
||||||
|
perror (file_name);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
file->pos = file->buffer;
|
file->pos = file->buffer;
|
||||||
|
|
||||||
/* read it in */
|
/* read it all in */
|
||||||
if (read (fd, file->buffer, file->size) < file->size) {
|
if (read (fd, file->buffer, file->size) < file->size) {
|
||||||
perror(file->file_name);
|
perror (file_name);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
file->buffer[file->size] = '\0';
|
file->buffer[file->size] = '\0';
|
||||||
|
|
||||||
/* set the initial line numbering */
|
/* set the initial line numbering */
|
||||||
file->line_nr = 0;
|
file->real_line.line_nr = 1; /* specifies current line */
|
||||||
file->current_file_line_offset = 0;
|
file->pseudo_line.line_nr = 1; /* specifies current line */
|
||||||
|
|
||||||
/* done */
|
/* done */
|
||||||
close (fd);
|
close (fd);
|
||||||
return file;
|
}
|
||||||
|
|
||||||
|
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 *
|
extern table_entry *
|
||||||
table_entry_read(table *file)
|
table_read (table *root)
|
||||||
|
{
|
||||||
|
open_table *file = root->current;
|
||||||
|
table_entry *entry = NULL;
|
||||||
|
while(1)
|
||||||
{
|
{
|
||||||
int field;
|
|
||||||
table_entry *entry;
|
|
||||||
|
|
||||||
/* skip comments/blanks */
|
/* end-of-file? */
|
||||||
while(1) {
|
while (*file->pos == '\0')
|
||||||
/* leading white space */
|
{
|
||||||
while (*file->pos != '\0'
|
if (file->parent != NULL)
|
||||||
&& *file->pos != '\n'
|
{
|
||||||
&& isspace(*file->pos))
|
file = file->parent;
|
||||||
file->pos++;
|
root->current = file;
|
||||||
/* cpp line nr directive - # <line-nr> "<file>" */
|
}
|
||||||
if (file->pos[0] == '#'
|
else
|
||||||
&& file->pos[1] == ' '
|
return NULL;
|
||||||
&& isdigit(file->pos[2])) {
|
}
|
||||||
file->pos += strlen("# ");
|
|
||||||
|
/* 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 */
|
/* parse the number */
|
||||||
file->current_file_line_offset = atoi(file->pos) - file->line_nr - 2;
|
line_nr = atoi(file->pos) - 1;
|
||||||
/* skip to the file name */
|
/* skip to the file name */
|
||||||
while (file->pos[0] != '0'
|
while (file->pos[0] != '0'
|
||||||
&& file->pos[0] != '"'
|
&& file->pos[0] != '"'
|
||||||
&& file->pos[0] != '\0')
|
&& file->pos[0] != '\0')
|
||||||
file->pos++;
|
file->pos++;
|
||||||
if (file->pos[0] != '"') {
|
if (file->pos[0] != '"')
|
||||||
error("%s:%d: Missing opening quote",
|
error (&file->real_line, "Missing opening quote in cpp directive\n");
|
||||||
file->file_name,
|
|
||||||
file->line_nr);
|
|
||||||
}
|
|
||||||
/* parse the file name */
|
/* parse the file name */
|
||||||
file->pos++;
|
file->pos++;
|
||||||
file->current_file_name = file->pos;
|
file_name = file->pos;
|
||||||
while (file->pos[0] != '"'
|
while (file->pos[0] != '"'
|
||||||
&& file->pos[0] != '\0')
|
&& file->pos[0] != '\0')
|
||||||
file->pos++;
|
file->pos++;
|
||||||
if (file->pos[0] != '"') {
|
if (file->pos[0] != '"')
|
||||||
error("%s:%d: Missing closing quote",
|
error (&file->real_line, "Missing closing quote in cpp directive\n");
|
||||||
file->file_name,
|
|
||||||
file->line_nr);
|
|
||||||
}
|
|
||||||
file->pos[0] = '\0';
|
file->pos[0] = '\0';
|
||||||
file->pos++;
|
file->pos++;
|
||||||
while (file->pos[0] != '\0'
|
file->pos = skip_to_nl (file->pos);
|
||||||
&& file->pos[0] != '\n')
|
|
||||||
file->pos[0]++;
|
|
||||||
if (file->pos[0] != '\n')
|
if (file->pos[0] != '\n')
|
||||||
error("%s:%d: Missing newline",
|
error (&file->real_line, "Missing newline in cpp directive\n");
|
||||||
file->file_name,
|
file->pseudo_line.file_name = file_name;
|
||||||
file->line_nr);
|
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 */
|
/* comment - leading // or # - skip */
|
||||||
else if ((file->pos[0] == '/' && file->pos[1] == '/')
|
if ((file->pos[0] == '/' && file->pos[1] == '/')
|
||||||
|| (file->pos[0] == '#')) {
|
|| (file->pos[0] == '#'))
|
||||||
do {
|
{
|
||||||
file->pos++;
|
next_line (file);
|
||||||
} while (*file->pos != '\0' && *file->pos != '\n');
|
continue;
|
||||||
}
|
}
|
||||||
/* end of line? */
|
|
||||||
if (*file->pos == '\n') {
|
/* colon field */
|
||||||
file->pos++;
|
{
|
||||||
file->line_nr++;
|
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
|
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;
|
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++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* any trailing stuff not the last field */
|
ASSERT (entry == NULL || entry->field[entry->nr_fields] == NULL);
|
||||||
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 == ':')
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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)
|
|
||||||
{
|
|
||||||
tmpchp = zalloc (strlen_condition + 1);
|
|
||||||
strncpy (tmpchp, condition, strlen_condition);
|
|
||||||
(*current)->condition = tmpchp;
|
|
||||||
}
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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++;
|
|
||||||
}
|
|
||||||
|
|
||||||
file->line_nr++;
|
|
||||||
model->line_nr = file->current_file_line_offset + file->line_nr;
|
|
||||||
}
|
|
||||||
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
if (*save_pos == '\t') {
|
|
||||||
file->pos = save_pos;
|
|
||||||
file->line_nr += extra_lines;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (*file->pos != '\0' && *file->pos == '\t');
|
|
||||||
if (file->pos[-1] == '\n')
|
|
||||||
file->pos[-1] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
entry->annex = NULL;
|
|
||||||
|
|
||||||
/* return it */
|
|
||||||
return entry;
|
return entry;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
dump_table_entry(table_entry *entry,
|
table_print_code (lf *file,
|
||||||
int indent)
|
|
||||||
{
|
|
||||||
printf("(table_entry*)%p\n", entry);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
dumpf(indent, "(file_name %s)\n", entry->file_name);
|
|
||||||
|
|
||||||
dumpf(indent, "(annex\n%s\n", entry->annex);
|
|
||||||
dumpf(indent, " )\n");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern void
|
|
||||||
table_entry_print_cpp_line_nr(lf *file,
|
|
||||||
table_entry *entry)
|
table_entry *entry)
|
||||||
{
|
{
|
||||||
lf_print__external_reference(file, entry->line_nr, entry->file_name);
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user