1
0
mirror of https://git.savannah.gnu.org/git/gperf.git synced 2025-12-02 21:19:24 +00:00

Implement % declarations.

This commit is contained in:
Bruno Haible
2003-02-10 14:21:58 +00:00
parent ef37a53d73
commit 6202aaadb1
8 changed files with 721 additions and 90 deletions

View File

@@ -46,6 +46,187 @@ pretty_input_file_name ()
return "(standard input)";
}
/* Returns true if the given line contains a "%DECL" declaration. */
static bool
is_declaration (const char *line, const char *line_end, unsigned int lineno,
const char *decl)
{
/* Skip '%'. */
line++;
/* Skip DECL. */
for (const char *d = decl; *d; d++)
{
if (!(line < line_end))
return false;
if (!(*line == *d || (*d == '-' && *line == '_')))
return false;
line++;
}
if (line < line_end
&& ((*line >= 'A' && *line <= 'Z')
|| (*line >= 'a' && *line <= 'z')
|| *line == '-' || *line == '_'))
return false;
/* OK, found DECL. */
/* Skip whitespace. */
while (line < line_end && (*line == ' ' || *line == '\t'))
line++;
/* Expect end of line. */
if (line < line_end && *line != '\n')
{
fprintf (stderr, "%s:%u: junk after declaration\n",
pretty_input_file_name (), lineno);
exit (1);
}
return true;
}
/* Tests if the given line contains a "%DECL=ARG" declaration.
If yes, it sets *ARGP to the argument, and returns true.
Otherwise, it returns false. */
static bool
is_declaration_with_arg (const char *line, const char *line_end,
unsigned int lineno,
const char *decl, char **argp)
{
/* Skip '%'. */
line++;
/* Skip DECL. */
for (const char *d = decl; *d; d++)
{
if (!(line < line_end))
return false;
if (!(*line == *d || (*d == '-' && *line == '_')))
return false;
line++;
}
if (line < line_end
&& ((*line >= 'A' && *line <= 'Z')
|| (*line >= 'a' && *line <= 'z')
|| *line == '-' || *line == '_'))
return false;
/* OK, found DECL. */
/* Skip '='. */
if (!(line < line_end && *line == '='))
{
fprintf (stderr, "%s:%u: missing argument in %%%s=ARG declaration.\n",
pretty_input_file_name (), lineno, decl);
exit (1);
}
line++;
/* The next word is the argument. */
char *arg = new char[line_end - line + 1];
char *p = arg;
while (line < line_end && !(*line == ' ' || *line == '\t' || *line == '\n'))
*p++ = *line++;
*p = '\0';
/* Skip whitespace. */
while (line < line_end && (*line == ' ' || *line == '\t'))
line++;
/* Expect end of line. */
if (line < line_end && *line != '\n')
{
fprintf (stderr, "%s:%u: junk after declaration\n",
pretty_input_file_name (), lineno);
exit (1);
}
*argp = arg;
return true;
}
/* Tests if the given line contains a "%define DECL ARG" declaration.
If yes, it sets *ARGP to the argument, and returns true.
Otherwise, it returns false. */
static bool
is_define_declaration (const char *line, const char *line_end,
unsigned int lineno,
const char *decl, char **argp)
{
/* Skip '%'. */
line++;
/* Skip "define". */
{
for (const char *d = "define"; *d; d++)
{
if (!(line < line_end))
return false;
if (!(*line == *d))
return false;
line++;
}
if (!(line < line_end && (*line == ' ' || *line == '\t')))
return false;
}
/* Skip whitespace. */
while (line < line_end && (*line == ' ' || *line == '\t'))
line++;
/* Skip DECL. */
for (const char *d = decl; *d; d++)
{
if (!(line < line_end))
return false;
if (!(*line == *d || (*d == '-' && *line == '_')))
return false;
line++;
}
if (line < line_end
&& ((*line >= 'A' && *line <= 'Z')
|| (*line >= 'a' && *line <= 'z')
|| *line == '-' || *line == '_'))
return false;
/* OK, found DECL. */
/* Skip whitespace. */
if (!(line < line_end && (*line == ' ' || *line == '\t')))
{
fprintf (stderr, "%s:%u:"
" missing argument in %%define %s ARG declaration.\n",
pretty_input_file_name (), lineno, decl);
exit (1);
}
do
line++;
while (line < line_end && (*line == ' ' || *line == '\t'));
/* The next word is the argument. */
char *arg = new char[line_end - line + 1];
char *p = arg;
while (line < line_end && !(*line == ' ' || *line == '\t' || *line == '\n'))
*p++ = *line++;
*p = '\0';
/* Skip whitespace. */
while (line < line_end && (*line == ' ' || *line == '\t'))
line++;
/* Expect end of line. */
if (line < line_end && *line != '\n')
{
fprintf (stderr, "%s:%u: junk after declaration\n",
pretty_input_file_name (), lineno);
exit (1);
}
*argp = arg;
return true;
}
/* Reads the entire input file. */
void
Input::read_input ()
@@ -208,18 +389,18 @@ Input::read_input ()
char *struct_decl = NULL;
unsigned int *struct_decl_linenos = NULL;
unsigned int struct_decl_linecount = 0;
for (const char *p = declarations; p < declarations_end; )
for (const char *line = declarations; line < declarations_end; )
{
const char *line_end;
line_end = (const char *) memchr (p, '\n', declarations_end - p);
line_end = (const char *) memchr (line, '\n', declarations_end - line);
if (line_end != NULL)
line_end++;
else
line_end = declarations_end;
if (*p == '%')
if (*line == '%')
{
if (p[1] == '{')
if (line[1] == '{')
{
/* Handle %{. */
if (_verbatim_declarations != NULL)
@@ -231,10 +412,10 @@ Input::read_input ()
pretty_input_file_name (), lineno);
exit (1);
}
_verbatim_declarations = p + 2;
_verbatim_declarations = line + 2;
_verbatim_declarations_lineno = lineno;
}
else if (p[1] == '}')
else if (line[1] == '}')
{
/* Handle %}. */
if (_verbatim_declarations == NULL)
@@ -251,11 +432,11 @@ Input::read_input ()
pretty_input_file_name (), lineno);
exit (1);
}
_verbatim_declarations_end = p;
_verbatim_declarations_end = line;
/* Give a warning if the rest of the line is nonempty. */
bool nonempty_line = false;
const char *q;
for (q = p + 2; q < line_end; q++)
for (q = line + 2; q < line_end; q++)
{
if (*q == '\n')
{
@@ -280,9 +461,98 @@ Input::read_input ()
}
else
{
fprintf (stderr, "%s:%u: unrecognized %% directive\n",
pretty_input_file_name (), lineno);
exit (1);
char *arg;
if (is_declaration_with_arg (line, line_end, lineno,
"delimiters", &arg))
option.set_delimiters (arg);
else
if (is_declaration (line, line_end, lineno, "struct-type"))
option.set (TYPE);
else
if (is_declaration_with_arg (line, line_end, lineno,
"language", &arg))
option.set_language (arg);
else
if (is_define_declaration (line, line_end, lineno,
"slot-name", &arg))
option.set_slot_name (arg);
else
if (is_define_declaration (line, line_end, lineno,
"hash-function-name", &arg))
option.set_hash_name (arg);
else
if (is_define_declaration (line, line_end, lineno,
"lookup-function-name", &arg))
option.set_function_name (arg);
else
if (is_define_declaration (line, line_end, lineno,
"class-name", &arg))
option.set_class_name (arg);
else
if (is_declaration (line, line_end, lineno, "7bit"))
option.set (SEVENBIT);
else
if (is_declaration (line, line_end, lineno, "compare-lengths"))
option.set (LENTABLE);
else
if (is_declaration (line, line_end, lineno, "compare-strncmp"))
option.set (COMP);
else
if (is_declaration (line, line_end, lineno, "readonly-tables"))
option.set (CONST);
else
if (is_declaration (line, line_end, lineno, "enum"))
option.set (ENUM);
else
if (is_declaration (line, line_end, lineno, "includes"))
option.set (INCLUDE);
else
if (is_declaration (line, line_end, lineno, "global-table"))
option.set (GLOBAL);
else
if (is_define_declaration (line, line_end, lineno,
"word-array-name", &arg))
option.set_wordlist_name (arg);
else
if (is_declaration_with_arg (line, line_end, lineno,
"switch", &arg))
{
option.set_total_switches (atoi (arg));
if (option.get_total_switches () <= 0)
{
fprintf (stderr, "%s:%u: number of switches %s"
" must be a positive number\n",
pretty_input_file_name (), lineno, arg);
exit (1);
}
}
else
if (is_declaration (line, line_end, lineno, "omit-struct-type"))
option.set (NOTYPE);
else
{
fprintf (stderr, "%s:%u: unrecognized %% directive\n",
pretty_input_file_name (), lineno);
exit (1);
}
}
}
else if (!(_verbatim_declarations != NULL
@@ -290,12 +560,12 @@ Input::read_input ()
{
/* Append the line to struct_decl. */
size_t old_len = (struct_decl ? strlen (struct_decl) : 0);
size_t line_len = line_end - p;
size_t line_len = line_end - line;
size_t new_len = old_len + line_len + 1;
char *new_struct_decl = new char[new_len];
if (old_len > 0)
memcpy (new_struct_decl, struct_decl, old_len);
memcpy (new_struct_decl + old_len, p, line_len);
memcpy (new_struct_decl + old_len, line, line_len);
new_struct_decl[old_len + line_len] = '\0';
if (struct_decl)
delete[] struct_decl;
@@ -314,7 +584,7 @@ Input::read_input ()
struct_decl_linecount++;
}
lineno++;
p = line_end;
line = line_end;
}
if (_verbatim_declarations != NULL && _verbatim_declarations_end == NULL)
{

View File

@@ -41,10 +41,10 @@ const char *program_name;
static const int DEFAULT_JUMP_VALUE = 5;
/* Default name for generated lookup function. */
static const char *const DEFAULT_NAME = "in_word_set";
static const char *const DEFAULT_FUNCTION_NAME = "in_word_set";
/* Default name for the key component. */
static const char *const DEFAULT_KEY = "name";
static const char *const DEFAULT_SLOT_NAME = "name";
/* Default struct initializer suffix. */
static const char *const DEFAULT_INITIALIZER_SUFFIX = "";
@@ -428,14 +428,15 @@ Options::Options ()
: _option_word (C),
_input_file_name (NULL),
_output_file_name (NULL),
_language (NULL),
_iterations (0),
_jump (DEFAULT_JUMP_VALUE),
_initial_asso_value (0),
_asso_iterations (0),
_total_switches (1),
_size_multiple (1),
_function_name (DEFAULT_NAME),
_key_name (DEFAULT_KEY),
_function_name (DEFAULT_FUNCTION_NAME),
_slot_name (DEFAULT_SLOT_NAME),
_initializer_suffix (DEFAULT_INITIALIZER_SUFFIX),
_class_name (DEFAULT_CLASS_NAME),
_hash_name (DEFAULT_HASH_NAME),
@@ -476,7 +477,7 @@ Options::~Options ()
"\nlookup function name = %s"
"\nhash function name = %s"
"\nword list name = %s"
"\nkey name = %s"
"\nslot name = %s"
"\ninitializer suffix = %s"
"\nasso_values iterations = %d"
"\njump value = %d"
@@ -505,7 +506,7 @@ Options::~Options ()
_option_word & INCLUDE ? "enabled" : "disabled",
_option_word & SEVENBIT ? "enabled" : "disabled",
_iterations,
_function_name, _hash_name, _wordlist_name, _key_name,
_function_name, _hash_name, _wordlist_name, _slot_name,
_initializer_suffix, _asso_iterations, _jump, _size_multiple,
_initial_asso_value, _delimiters, _total_switches);
if (_option_word & ALLCHARS)
@@ -528,6 +529,91 @@ Options::~Options ()
}
/* Sets the output language, if not already set. */
void
Options::set_language (const char *language)
{
if (_language == NULL)
{
_language = language;
_option_word &= ~(KRC | C | ANSIC | CPLUSPLUS);
if (!strcmp (language, "KR-C"))
_option_word |= KRC;
else if (!strcmp (language, "C"))
_option_word |= C;
else if (!strcmp (language, "ANSI-C"))
_option_word |= ANSIC;
else if (!strcmp (language, "C++"))
_option_word |= CPLUSPLUS;
else
{
fprintf (stderr, "unsupported language option %s, defaulting to C\n",
language);
_option_word |= C;
}
}
}
/* Sets the total number of switch statements, if not already set. */
void
Options::set_total_switches (int total_switches)
{
if (!(_option_word & SWITCH))
{
_option_word |= SWITCH;
_total_switches = total_switches;
}
}
/* Sets the generated function name, if not already set. */
void
Options::set_function_name (const char *name)
{
if (_function_name == DEFAULT_FUNCTION_NAME)
_function_name = name;
}
/* Set the keyword key name, if not already set. */
void
Options::set_slot_name (const char *name)
{
if (_slot_name == DEFAULT_SLOT_NAME)
_slot_name = name;
}
/* Sets the generated class name, if not already set. */
void
Options::set_class_name (const char *name)
{
if (_class_name == DEFAULT_CLASS_NAME)
_class_name = name;
}
/* Sets the hash function name, if not already set. */
void
Options::set_hash_name (const char *name)
{
if (_hash_name == DEFAULT_HASH_NAME)
_hash_name = name;
}
/* Sets the hash table array name, if not already set. */
void
Options::set_wordlist_name (const char *name)
{
if (_wordlist_name == DEFAULT_WORDLIST_NAME)
_wordlist_name = name;
}
/* Sets the delimiters string, if not already set. */
void
Options::set_delimiters (const char *delimiters)
{
if (_delimiters == DEFAULT_DELIMITERS)
_delimiters = delimiters;
}
/* Parses the command line Options and sets appropriate flags in option_word. */
static const struct option long_options[] =
@@ -737,7 +823,7 @@ Options::parse_options (int argc, char *argv[])
}
case 'K': /* Make this the keyname for the keyword component field. */
{
_key_name = /*getopt*/optarg;
_slot_name = /*getopt*/optarg;
break;
}
case 'l': /* Create length table to avoid extra string compares. */
@@ -747,20 +833,8 @@ Options::parse_options (int argc, char *argv[])
}
case 'L': /* Deal with different generated languages. */
{
_option_word &= ~(KRC | C | ANSIC | CPLUSPLUS);
if (!strcmp (/*getopt*/optarg, "KR-C"))
_option_word |= KRC;
else if (!strcmp (/*getopt*/optarg, "C"))
_option_word |= C;
else if (!strcmp (/*getopt*/optarg, "ANSI-C"))
_option_word |= ANSIC;
else if (!strcmp (/*getopt*/optarg, "C++"))
_option_word |= CPLUSPLUS;
else
{
fprintf (stderr, "unsupported language option %s, defaulting to C\n", /*getopt*/optarg);
_option_word |= C;
}
_language = NULL;
set_language (/*getopt*/optarg);
break;
}
case 'm': /* Multiple iterations for finding good asso_values. */
@@ -805,7 +879,8 @@ Options::parse_options (int argc, char *argv[])
case 'S': /* Generate switch statement output, rather than lookup table. */
{
_option_word |= SWITCH;
if ((_total_switches = atoi (/*getopt*/optarg)) <= 0)
_total_switches = atoi (/*getopt*/optarg);
if (_total_switches <= 0)
{
fprintf (stderr, "number of switches %s must be a positive number\n", /*getopt*/optarg);
short_usage (stderr);

View File

@@ -180,6 +180,8 @@ public:
/* Tests a given boolean option. Returns true if set, false otherwise. */
bool operator[] (Option_Type option) const;
/* Sets a given boolean option. */
void set (Option_Type option);
/* Returns the input file name. */
const char * get_input_file_name () const;
@@ -187,6 +189,9 @@ public:
/* Returns the output file name. */
const char * get_output_file_name () const;
/* Sets the output language, if not already set. */
void set_language (const char *language);
/* Returns the iterations value. */
int get_iterations () const;
@@ -201,30 +206,44 @@ public:
/* Returns the total number of switch statements to generate. */
int get_total_switches () const;
/* Sets the total number of switch statements, if not already set. */
void set_total_switches (int total_switches);
/* Returns the factor by which to multiply the generated table's size. */
int get_size_multiple () const;
/* Returns the generated function name. */
const char * get_function_name () const;
/* Sets the generated function name, if not already set. */
void set_function_name (const char *name);
/* Returns the keyword key name. */
const char * get_key_name () const;
const char * get_slot_name () const;
/* Set the keyword key name, if not already set. */
void set_slot_name (const char *name);
/* Returns the struct initializer suffix. */
const char * get_initializer_suffix () const;
/* Returns the generated class name. */
const char * get_class_name () const;
/* Sets the generated class name, if not already set. */
void set_class_name (const char *name);
/* Returns the hash function name. */
const char * get_hash_name () const;
/* Sets the hash function name, if not already set. */
void set_hash_name (const char *name);
/* Returns the hash table array name. */
const char * get_wordlist_name () const;
/* Sets the hash table array name, if not already set. */
void set_wordlist_name (const char *name);
/* Returns the string used to delimit keywords from other attributes. */
const char * get_delimiters () const;
/* Sets the delimiters string, if not already set. */
void set_delimiters (const char *delimiters);
/* Returns key positions.
Only to be called if !options[ALLCHARS]. */
@@ -256,6 +275,9 @@ private:
/* Name of output file. */
char * _output_file_name;
/* The output language. */
const char * _language;
/* Amount to iterate when a collision occurs. */
int _iterations;
@@ -278,7 +300,7 @@ private:
const char * _function_name;
/* Name used for keyword key. */
const char * _key_name;
const char * _slot_name;
/* Suffix for empty struct initializers. */
const char * _initializer_suffix;

View File

@@ -125,6 +125,13 @@ Options::operator[] (Option_Type option) const
return _option_word & option;
}
/* Sets a given boolean option. */
INLINE void
Options::set (Option_Type option)
{
_option_word |= option;
}
/* Returns the input file name. */
INLINE const char *
Options::get_input_file_name () const
@@ -190,9 +197,9 @@ Options::get_function_name () const
/* Returns the keyword key name. */
INLINE const char *
Options::get_key_name () const
Options::get_slot_name () const
{
return _key_name;
return _slot_name;
}
/* Returns the struct initializer suffix. */

View File

@@ -1210,7 +1210,7 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const
printf ("%*s register %schar *s = ",
indent, "", const_always);
if (option[TYPE])
printf ("wordptr->%s", option.get_key_name ());
printf ("wordptr->%s", option.get_slot_name ());
else
printf ("*wordptr");
printf (";\n\n"
@@ -1241,7 +1241,7 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const
printf (" {\n"
" register %schar *s = resword->%s;\n\n"
" if (",
const_always, option.get_key_name ());
const_always, option.get_slot_name ());
comparison.output_comparison (Output_Expr1 ("str"), Output_Expr1 ("s"));
printf (")\n"
" return resword;\n"
@@ -1279,7 +1279,7 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const
indent, "",
indent, "", const_always, option.get_wordlist_name ());
if (option[TYPE])
printf (".%s", option.get_key_name ());
printf (".%s", option.get_slot_name ());
printf (";\n\n"
"%*s if (",
indent, "");
@@ -1330,7 +1330,7 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const
printf ("%*s register %schar *s = ",
indent, "", const_always);
if (option[TYPE])
printf ("wordptr->%s", option.get_key_name ());
printf ("wordptr->%s", option.get_slot_name ());
else
printf ("*wordptr");
printf (";\n\n"
@@ -1374,7 +1374,7 @@ Output::output_lookup_function_body (const Output_Compare& comparison) const
indent, "", const_always, option.get_wordlist_name ());
if (option[TYPE])
printf (".%s", option.get_key_name ());
printf (".%s", option.get_slot_name ());
printf (";\n\n"
"%*s if (",