diff --git a/Makefile.in b/Makefile.in index acef67ec7..2304cda5b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -267,7 +267,7 @@ lexor.cc: $(srcdir)/lexor.lex lexor_keyword.o: lexor_keyword.cc parse.h lexor_keyword.cc: $(srcdir)/lexor_keyword.gperf - gperf -o -i 7 -C -k 1-4,6,9,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false) + gperf -o -i 7 -C -k 1-4,6,9,$$ -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false) iverilog-vpi.man: $(srcdir)/iverilog-vpi.man.in version.exe ./version.exe `head -1 $(srcdir)/iverilog-vpi.man.in`'\n' > $@ diff --git a/autoconf.sh b/autoconf.sh index 0840ac287..8eee0af8e 100644 --- a/autoconf.sh +++ b/autoconf.sh @@ -10,7 +10,7 @@ echo "Autoconf in root..." autoconf -f echo "Precompiling lexor_keyword.gperf" -gperf -o -i 7 -C -k 1-4,6,9,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc +gperf -o -i 7 -C -k 1-4,6,9,\$ -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc echo "Precompiling vhdlpp/lexor_keyword.gperf" -(cd vhdlpp ; gperf -o -i 7 --ignore-case -C -k 1-4,6,9,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc ) +(cd vhdlpp ; gperf -o -i 7 --ignore-case -C -k 1-4,6,9,\$ -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc ) diff --git a/elab_scope.cc b/elab_scope.cc index 5428a803d..815167b45 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -168,7 +168,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, assert(enum_type->range->size() == 1); pform_range_t&range = enum_type->range->front(); NetExpr*msb_ex = elab_and_eval(des, scope, range.first, -1); - NetExpr*lsb_ex = elab_and_eval(des, scope, range.second, -1); + NetExpr*lsb_ex = elab_and_eval(des, scope, range.second, -1); long msb = 0; rc_flag = eval_as_long(msb, msb_ex); @@ -180,7 +180,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, netenum_t*use_enum = new netenum_t(enum_type->base_type, enum_type->signed_flag, enum_type->integer_flag, msb, lsb, - enum_type->names->size()); + enum_type->names->size(), + enum_type); use_enum->set_line(enum_type->li); if (scope) @@ -188,14 +189,18 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, else des->add_enumeration_set(enum_type, use_enum); - verinum cur_value (0); - verinum one_value (1); size_t name_idx = 0; // Find the enumeration width. long raw_width = use_enum->packed_width(); assert(raw_width > 0); unsigned enum_width = (unsigned)raw_width; - // Find the minimum and maximum allowed enumeration values. + // Define the default start value and the increment value to be the + // correct type for this enumeration. + verinum cur_value ((uint64_t)0, enum_width); + cur_value.has_sign(enum_type->signed_flag); + verinum one_value ((uint64_t)1, enum_width); + one_value.has_sign(enum_type->signed_flag); + // Find the maximum allowed enumeration value. verinum min_value (0); verinum max_value (0); if (enum_type->signed_flag) { @@ -206,10 +211,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, } min_value.has_sign(true); max_value.has_sign(enum_type->signed_flag); + // Process the enumeration definition. for (list::const_iterator cur = enum_type->names->begin() ; cur != enum_type->names->end() ; ++ cur, name_idx += 1) { - - + // Check to see if the enumeration name has a value given. if (cur->parm) { // There is an explicit value. elaborate/evaluate // the value and assign it to the enumeration name. @@ -217,26 +222,115 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, NetEConst*val_const = dynamic_cast (val); if (val_const == 0) { cerr << use_enum->get_fileline() - << ": error: Enumeration expression is not " - "constant." << endl; + << ": error: Enumeration expression for " + << cur->name <<" is not an integer constant." + << endl; des->errors += 1; continue; } cur_value = val_const->value(); + // A 2-state value can not have a constant with X/Z bits. if (enum_type->base_type==IVL_VT_BOOL && ! cur_value.is_defined()) { cerr << use_enum->get_fileline() << ": error: Enumeration name " << cur->name - << " cannot have an undefined value." << endl; + << " can not have an undefined value." << endl; des->errors += 1; - continue; } + // If this is a literal constant and it has a defined + // width then the width must match the enumeration width. + if (PENumber *tmp = dynamic_cast(cur->parm)) { + if (tmp->value().has_len() && + (tmp->value().len() != enum_width)) { + cerr << use_enum->get_fileline() + << ": error: Enumeration name " << cur->name + << " has an incorrectly sized constant." + << endl; + des->errors += 1; + } + } + + // If we are padding/truncating a negative value for an + // unsigned enumeration that is an error or if the new + // value does not have a defined width. + if (((cur_value.len() != enum_width) || + ! cur_value.has_len()) && + ! enum_type->signed_flag && cur_value.is_negative()) { + cerr << use_enum->get_fileline() + << ": error: Enumeration name " << cur->name + << " has a negative value." << endl; + des->errors += 1; + } + + // Narrower values need to be padded to the width of the + // enumeration and defined to have the specified width. + if (cur_value.len() < enum_width) { + cur_value = pad_to_width(cur_value, enum_width); + } + + // Some wider values can be truncated. + if (cur_value.len() > enum_width) { + unsigned check_width = enum_width - 1; + // Check that the upper bits match the MSB + for (unsigned idx = enum_width; + idx < cur_value.len(); + idx += 1) { + if (cur_value[idx] != cur_value[check_width]) { + // If this is an unsigned enumeration + // then zero padding is okay. + if (! enum_type->signed_flag && + (idx == enum_width) && + (cur_value[idx] == verinum::V0)) { + check_width += 1; + continue; + } + if (cur_value.is_defined()) { + cerr << use_enum->get_fileline() + << ": error: Enumeration name " + << cur->name + << " has a value that is too " + << ((cur_value > max_value) ? + "large" : "small") + << " " << cur_value << "." + << endl; + } else { + cerr << use_enum->get_fileline() + << ": error: Enumeration name " + << cur->name + << " has trimmed bits that do " + << "not match the enumeration " + << "MSB: " << cur_value << "." + << endl; + } + des->errors += 1; + break; + } + } + // If this is an unsigned value then make sure + // The upper bits are not 1. + if (! cur_value.has_sign() && + (cur_value[enum_width] == verinum::V1)) { + cerr << use_enum->get_fileline() + << ": error: Enumeration name " + << cur->name + << " has a value that is too large: " + << cur_value << "." << endl; + des->errors += 1; + break; + } + cur_value = verinum(cur_value, enum_width); + } + + // At this point the value has the correct size and needs + // to have the correct sign attribute set. + cur_value.has_len(true); + cur_value.has_sign(enum_type->signed_flag); } else if (! cur_value.is_defined()) { cerr << use_enum->get_fileline() << ": error: Enumeration name " << cur->name - << " cannot have an undefined inferred value." << endl; + << " has an undefined inferred value." << endl; des->errors += 1; continue; } @@ -258,10 +352,10 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, } else if ((two_state_value > max_value) || (cur_value.has_sign() && (two_state_value < min_value))) { + cerr << use_enum->get_fileline() << ": error: Enumeration name " << cur->name - << " cannot have an out of range value " << cur_value - << "." << endl; + << " has an inferred value that overflowed." << endl; des->errors += 1; } @@ -275,38 +369,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, des->errors += 1; } - // The values are explicitly sized to the width of the - // base type of the enumeration. - verinum tmp_val (0); - if (cur_value.len() < enum_width) { - // Pad the current value if it is narrower than the final - // width of the enum. - tmp_val = pad_to_width (cur_value, enum_width); - tmp_val.has_len(true); - } else { - // Truncate an oversized value. We report out of bound - // defined values above. Undefined values need to be - // checked here. This may create duplicates. - tmp_val = verinum(cur_value, enum_width); - // For an undefined value verify that all the trimmed bits - // match the MSB of the final enumeration value. - if (! cur_value.is_defined()) for (unsigned idx = enum_width; - idx < cur_value.len(); - idx += 1) { - if (cur_value[idx] != tmp_val[enum_width-1]) { - cerr << use_enum->get_fileline() - << ": error: Enumeration name " << cur->name - << " cannot have trimmed bits that do not " - << "match the enumeration MSB " << cur_value - << "." << endl; - des->errors += 1; - break; - } - } - } - tmp_val.has_sign(enum_type->signed_flag); - - rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val); + rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value); if (scope) rc_flag &= scope->add_enumeration_name(use_enum, cur->name); else @@ -321,8 +384,9 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, // In case the next name has an implicit value, // increment the current value by one. - if (cur_value.is_defined()) + if (cur_value.is_defined()) { cur_value = cur_value + one_value; + } } use_enum->insert_name_close(); @@ -852,7 +916,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, delete[]attr; // Generate schemes need to have their scopes elaborated, but - // we cannot do that until defparams are run, so push it off + // we can not do that until defparams are run, so push it off // into an elaborate work item. if (debug_scopes) cerr << get_fileline() << ": debug: " @@ -1594,7 +1658,7 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const continue; } - cerr << get_fileline() << ": error: You cannot instantiate " + cerr << get_fileline() << ": error: You can not instantiate " << "module " << mod->mod_name() << " within itself." << endl; cerr << get_fileline() << ": : The offending instance is " << get_name() << " within " << scope_path(scn) << "." << endl; diff --git a/elaborate.cc b/elaborate.cc index 3095394b6..95005c140 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -38,6 +38,7 @@ # include "PPackage.h" # include "PSpec.h" # include "netlist.h" +# include "netenum.h" # include "netvector.h" # include "netdarray.h" # include "netparray.h" @@ -2668,7 +2669,8 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const return bl; } - if (lv->enumeration() && (lv->enumeration() != rv->enumeration())) { + if (lv->enumeration() && + ! lv->enumeration()->matches(rv->enumeration())) { cerr << get_fileline() << ": error: " << "Enumeration type mismatch in assignment." << endl; des->errors += 1; @@ -3003,10 +3005,10 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const context_width = 1; context_unsigned = false; - } else if (context_mode > PExpr::SIZED) { + } else if (context_mode >= PExpr::LOSSLESS) { /* Expressions may choose a different size if they are - in an unsized context, so we need to run through the + in a lossless context, so we need to run through the process again to get the final expression width. */ context_width = test_case_width(des, scope, expr_, context_mode); @@ -3069,7 +3071,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const /* Iterate over all the case items (guard/statement pairs) elaborating them. If the guard has no expression, then this - is a "default" cause. Otherwise, the guard has one or more + is a "default" case. Otherwise, the guard has one or more expressions, and each guard is a case. */ unsigned inum = 0; for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) { @@ -3110,6 +3112,8 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const } } + res->prune(); + return res; } diff --git a/lexor_keyword.gperf b/lexor_keyword.gperf index 34e994e4a..4bb8d0629 100644 --- a/lexor_keyword.gperf +++ b/lexor_keyword.gperf @@ -3,9 +3,11 @@ * tokenType values are not initialized for the empty table entries. */ %define initializer-suffix ,0,0 +%language=C++ +%define class-name Lkwd %{ -/* Command-line: gperf -o -i 1 -C -k 1-3,$ -L C -H keyword_hash -N check_identifier -tT lexor_keyword.gperf */ +/* Command-line: gperf -o -i 7 -C -k '1-4,6,9,$' -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf */ #include "config.h" #include "parse_misc.h" @@ -362,7 +364,7 @@ int lexor_keyword_mask = 0; int lexor_keyword_code(const char*str, unsigned nstr) { - const struct lexor_keyword*rc = check_identifier(str, nstr); + const struct lexor_keyword*rc = Lkwd::check_identifier(str, nstr); if (rc == 0) return IDENTIFIER; else if ((rc->mask & lexor_keyword_mask) == 0) diff --git a/net_proc.cc b/net_proc.cc index 93c746b6d..2aedec7c2 100644 --- a/net_proc.cc +++ b/net_proc.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -19,8 +19,10 @@ # include "config.h" +# include "compiler.h" # include "netlist.h" -# include +# include "netmisc.h" +# include "ivl_assert.h" NetBlock::NetBlock(Type t, NetScope*ss) : type_(t), subscope_(ss), last_(0) @@ -73,7 +75,7 @@ const NetProc* NetBlock::proc_next(const NetProc*cur) const NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt) : type_(c), expr_(ex), items_(cnt) { - assert(expr_); + ivl_assert(*this, expr_); } NetCase::~NetCase() @@ -92,11 +94,73 @@ NetCase::TYPE NetCase::type() const void NetCase::set_case(unsigned idx, NetExpr*e, NetProc*p) { - assert(idx < items_.size()); + ivl_assert(*this, idx < items_.size()); items_[idx].guard = e; items_[idx].statement = p; } +void NetCase::prune() +{ + // Test whether the case expression has been padded out + NetESelect*padded_expr = dynamic_cast(expr_); + if ((padded_expr == 0) || (padded_expr->select() != 0)) + return; + + // If so, run through the case item expressions to find + // the minimum number of bits needed to unambiguously + // select the correct case item. + const NetExpr*unpadded_expr = padded_expr->sub_expr(); + unsigned padded_width = padded_expr->expr_width(); + unsigned prune_width = unpadded_expr->expr_width(); + for (unsigned idx = 0; idx < items_.size(); idx += 1) { + // If there is no guard expression, this is the default + // case, so skip it. + if (items_[idx].guard == 0) + continue; + + // If the guard expression is not constant, assume + // all bits are needed, so no pruning can be done. + NetEConst*gc = dynamic_cast(items_[idx].guard); + if (gc == 0) + return; + + unsigned sig_bits = gc->value().significant_bits(); + if (sig_bits > prune_width) + prune_width = sig_bits; + + // If all the padding bits are needed, no pruning + // can be done. + if (prune_width >= padded_width) + return; + } + ivl_assert(*this, prune_width < padded_width); + + if (debug_elaborate) { + cerr << get_fileline() << ": debug: pruning case expressions to " + << prune_width << " bits." << endl; + } + + // Prune the case expression + expr_ = pad_to_width(unpadded_expr->dup_expr(), prune_width, *expr_); + delete padded_expr; + + // Prune the case item expressions + for (unsigned idx = 0; idx < items_.size(); idx += 1) { + if (items_[idx].guard == 0) + continue; + + NetEConst*gc = dynamic_cast(items_[idx].guard); + ivl_assert(*this, gc); + + verinum value(gc->value(), prune_width); + NetEConst*tmp = new NetEConst(value); + tmp->set_line(*gc); + delete gc; + + items_[idx].guard = tmp; + } +} + NetDisable::NetDisable(NetScope*tgt) : target_(tgt) { @@ -175,7 +239,7 @@ NetPDelay::~NetPDelay() uint64_t NetPDelay::delay() const { - assert(expr_ == 0); + ivl_assert(*this, expr_ == 0); return delay_; } diff --git a/netenum.cc b/netenum.cc index cab73a55c..0ec7ca33d 100644 --- a/netenum.cc +++ b/netenum.cc @@ -24,9 +24,11 @@ using namespace std; netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag, - bool integer_flag, long msb, long lsb, size_t name_count) -: base_type_(btype), signed_flag_(signed_flag), integer_flag_(integer_flag), - msb_(msb), lsb_(lsb), names_(name_count), bits_(name_count) + bool integer_flag, long msb, long lsb, size_t name_count, + enum_type_t*enum_type) +: base_type_(btype), enum_type_(enum_type), signed_flag_(signed_flag), + integer_flag_(integer_flag), msb_(msb), lsb_(lsb), + names_(name_count), bits_(name_count) { } @@ -161,3 +163,8 @@ perm_string netenum_t::bits_at(size_t idx) const { return bits_[idx]; } + +bool netenum_t::matches(const netenum_t*other) const +{ + return enum_type_ == other->enum_type_; +} diff --git a/netenum.h b/netenum.h index 64c2aac6a..8ff8a9063 100644 --- a/netenum.h +++ b/netenum.h @@ -29,12 +29,14 @@ class NetScope; +struct enum_type_t; + class netenum_t : public LineInfo, public ivl_type_s { public: explicit netenum_t(ivl_variable_type_t base_type, bool signed_flag, bool isint_flag, long msb, long lsb, - size_t name_count); + size_t name_count, enum_type_t*enum_type); ~netenum_t(); virtual ivl_variable_type_t base_type() const; @@ -67,8 +69,12 @@ class netenum_t : public LineInfo, public ivl_type_s { perm_string name_at(size_t idx) const; perm_string bits_at(size_t idx) const; + // Check if two enumerations have the same definition. + bool matches(const netenum_t*other) const; + private: ivl_variable_type_t base_type_; + enum_type_t*enum_type_; bool signed_flag_; bool integer_flag_; long msb_, lsb_; diff --git a/netlist.h b/netlist.h index 19cf46bc7..3d44016d8 100644 --- a/netlist.h +++ b/netlist.h @@ -2939,6 +2939,8 @@ class NetCase : public NetProc { void set_case(unsigned idx, NetExpr*ex, NetProc*st); + void prune(); + TYPE type() const; const NetExpr*expr() const { return expr_; } inline unsigned nitems() const { return items_.size(); } diff --git a/synth2.cc b/synth2.cc index 89e93f931..7d3b39267 100644 --- a/synth2.cc +++ b/synth2.cc @@ -502,16 +502,33 @@ bool NetCase::synth_async(Design*des, NetScope*scope, } NetEConst*ge = dynamic_cast(items_[item].guard); + if (ge == 0) { + cerr << items_[item].guard->get_fileline() << ": sorry: " + << "variable case item expressions with a variable " + << "case select expression are not supported in " + << "synthesis. " << endl; + des->errors += 1; + return false; + } ivl_assert(*this, ge); verinum gval = ge->value(); - unsigned sel_idx = gval.as_ulong(); + unsigned long sel_idx = gval.as_ulong(); - assert(items_[item].statement); - statement_map[sel_idx] = items_[item].statement; + if (statement_map[sel_idx]) { + cerr << ge->get_fileline() << ": warning: duplicate case " + << "value '" << sel_idx << "' detected. This case is " + << "unreachable." << endl; + delete items_[item].statement; + items_[item].statement = 0; + continue; + } if (sel_idx > max_guard_value) max_guard_value = sel_idx; + + ivl_assert(*this, items_[item].statement); + statement_map[sel_idx] = items_[item].statement; } // The mux_size is the number of inputs that are selected. @@ -544,6 +561,14 @@ bool NetCase::synth_async(Design*des, NetScope*scope, esig = mux_selector_reduce_width(des, scope, *this, esig, sel_need); } + if (!statement_default && (statement_map.size() != ((size_t)1 << sel_width))) { + cerr << get_fileline() << ": sorry: Latch inferred from " + << "incomplete case statement. This is not supported " + << "in synthesis." << endl; + des->errors += 1; + return false; + } + /* If there is a default clause, synthesize it once and we'll link it in wherever it is needed. */ NetBus default_bus (scope, nex_map.size()); @@ -607,12 +632,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, continue; } - if (stmt == 0) { - cerr << get_fileline() << ": error: case " << idx - << " is not accounted for in asynchronous mux." << endl; - des->errors += 1; - continue; - } + ivl_assert(*this, stmt); NetBus accumulated_tmp (scope, nex_map.size()); for (unsigned pin = 0 ; pin < nex_map.size() ; pin += 1) @@ -1911,9 +1931,9 @@ void synth2_f::process(Design*des, NetProcTop*top) } if (! top->synth_async(des)) { - cerr << top->get_fileline() << ": internal error: " - << "is_asynchronous does not match " - << "sync_async results." << endl; + cerr << top->get_fileline() << ": error: " + << "failed to synthesize asynchronous " + << "logic for this process." << endl; des->errors += 1; return; } diff --git a/verinum.cc b/verinum.cc index 250df8293..3c889311a 100644 --- a/verinum.cc +++ b/verinum.cc @@ -587,6 +587,21 @@ bool verinum::is_negative() const return (bits_[nbits_-1] == V1) && has_sign(); } +unsigned verinum::significant_bits() const +{ + unsigned sbits = nbits_; + + if (has_sign_) { + V sign_bit = bits_[sbits-1]; + while ((sbits > 1) && (bits_[sbits-2] == sign_bit)) + sbits -= 1; + } else { + while ((sbits > 1) && (bits_[sbits-1] == verinum::V0)) + sbits -= 1; + } + return sbits; +} + void verinum::cast_to_int2() { for (unsigned idx = 0 ; idx < nbits_ ; idx += 1) { @@ -765,7 +780,7 @@ ostream& operator<< (ostream&o, const verinum&v) /* If the number is fully defined (no x or z) then print it out as a decimal number. */ - if (v.is_defined() && v.len() < 8*sizeof(long)) { + if (v.is_defined() && v.len() <= 8*sizeof(long)) { if (v.has_sign()) o << "'sd" << v.as_long(); else diff --git a/verinum.h b/verinum.h index e7f311920..dfae90958 100644 --- a/verinum.h +++ b/verinum.h @@ -59,7 +59,7 @@ class verinum { ~verinum(); verinum& operator= (const verinum&); - // Number of significant bits in this number. + // Number of stored bits in this number. unsigned len() const { return nbits_; } // A number "has a length" if the length was specified fixed @@ -86,6 +86,9 @@ class verinum { // Comparison for use in sorting algorithms. bool is_before(const verinum&that) const; + // Number of significant bits in this number. + unsigned significant_bits() const; + // Convert 4-state to 2-state void cast_to_int2(); diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index e3622a7c3..ce796c588 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -124,7 +124,7 @@ parse.h: parse.cc lexor_keyword.o: lexor_keyword.cc parse.h lexor_keyword.cc: $(srcdir)/lexor_keyword.gperf - gperf -o -i 7 --ignore-case -C -k 1-4,6,9,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false) + gperf -o -i 7 --ignore-case -C -k 1-4,6,9,$$ -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false) install: all installdirs $(libdir)/ivl$(suffix)/vhdlpp@EXEEXT@ diff --git a/vhdlpp/lexor_keyword.gperf b/vhdlpp/lexor_keyword.gperf index 647798f27..42fd1bc0d 100644 --- a/vhdlpp/lexor_keyword.gperf +++ b/vhdlpp/lexor_keyword.gperf @@ -3,9 +3,10 @@ * tokenType values are not initialized for the empty table entries. */ %define initializer-suffix ,0,0 - +%language=C++ +%define class-name Lkwd %{ -/* Command-line: gperf -o -i 1 --ignore-case -C -k 1-3,$ -L C -H keyword_hash -N check_identifier -tT lexor_keyword.gperf */ +/* Command-line: gperf -o -i 7 --ignore-case -C -k '1-4,6,9,$' -H keyword_hash -N check_identifier -t lexor_keyword.gperf */ #include "vhdlpp_config.h" #include @@ -134,7 +135,7 @@ int lexor_keyword_mask = GN_KEYWORD_2008; int lexor_keyword_code(const char*str, unsigned nstr) { - const struct lexor_keyword*rc = check_identifier(str, nstr); + const struct lexor_keyword*rc = Lkwd::check_identifier(str, nstr); if (rc == 0) return IDENTIFIER; else if ((rc->mask & lexor_keyword_mask) == 0)