1
0
mirror of https://git.savannah.gnu.org/git/gperf.git synced 2025-12-02 13:09:22 +00:00

Fix the comparison of the first byte when using gperf_case_strcmp.

This commit is contained in:
Bruno Haible
2003-04-12 00:41:03 +00:00
parent ab6f0966b7
commit 6bbdde4f5f
5 changed files with 359 additions and 70 deletions

View File

@@ -1,5 +1,5 @@
/* Output routines.
Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc.
Copyright (C) 1989-1998, 2000, 2002-2003 Free Software Foundation, Inc.
Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
and Bruno Haible <bruno@clisp.org>.
@@ -144,22 +144,22 @@ Output::num_hash_values () const
struct Output_Constants
{
virtual void output_start () = 0;
virtual void output_item (const char *name, int value) = 0;
virtual void output_end () = 0;
Output_Constants () {}
virtual ~Output_Constants () {}
virtual void output_start () = 0;
virtual void output_item (const char *name, int value) = 0;
virtual void output_end () = 0;
Output_Constants () {}
virtual ~Output_Constants () {}
};
/* This class outputs an enumeration in #define syntax. */
struct Output_Defines : public Output_Constants
{
virtual void output_start ();
virtual void output_item (const char *name, int value);
virtual void output_end ();
Output_Defines () {}
virtual ~Output_Defines () {}
virtual void output_start ();
virtual void output_item (const char *name, int value);
virtual void output_end ();
Output_Defines () {}
virtual ~Output_Defines () {}
};
void Output_Defines::output_start ()
@@ -180,11 +180,12 @@ void Output_Defines::output_end ()
struct Output_Enum : public Output_Constants
{
virtual void output_start ();
virtual void output_item (const char *name, int value);
virtual void output_end ();
Output_Enum (const char *indent) : _indentation (indent) {}
virtual ~Output_Enum () {}
virtual void output_start ();
virtual void output_item (const char *name, int value);
virtual void output_end ();
Output_Enum (const char *indent)
: _indentation (indent) {}
virtual ~Output_Enum () {}
private:
const char *_indentation;
bool _pending_comma;
@@ -407,18 +408,18 @@ output_const_type (const char *const_string, const char *type_string)
struct Output_Expr
{
virtual void output_expr () const = 0;
Output_Expr () {}
virtual ~Output_Expr () {}
virtual void output_expr () const = 0;
Output_Expr () {}
virtual ~Output_Expr () {}
};
/* This class outputs an expression formed by a single string. */
struct Output_Expr1 : public Output_Expr
{
virtual void output_expr () const;
Output_Expr1 (const char *piece1) : _p1 (piece1) {}
virtual ~Output_Expr1 () {}
virtual void output_expr () const;
Output_Expr1 (const char *piece1) : _p1 (piece1) {}
virtual ~Output_Expr1 () {}
private:
const char *_p1;
};
@@ -435,10 +436,10 @@ void Output_Expr1::output_expr () const
struct Output_Expr2 : public Output_Expr
{
virtual void output_expr () const;
Output_Expr2 (const char *piece1, const char *piece2)
: _p1 (piece1), _p2 (piece2) {}
virtual ~Output_Expr2 () {}
virtual void output_expr () const;
Output_Expr2 (const char *piece1, const char *piece2)
: _p1 (piece1), _p2 (piece2) {}
virtual ~Output_Expr2 () {}
private:
const char *_p1;
const char *_p2;
@@ -462,37 +463,76 @@ struct Output_Compare
the string being looked up. expr2 outputs a simple expression of type
'const char *' referring to the constant string stored in the gperf
generated hash table. */
virtual void output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const = 0;
Output_Compare () {}
virtual ~Output_Compare () {}
virtual void output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const = 0;
/* Outputs the comparison expression for the first byte.
Returns true if the this comparison is complete. */
bool output_firstchar_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const;
Output_Compare () {}
virtual ~Output_Compare () {}
};
bool Output_Compare::output_firstchar_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const
{
/* First, we emit a comparison of the first byte of the two strings.
This catches most cases where the string being looked up is not in the
hash table but happens to have the same hash code as an element of the
hash table. */
if (option[UPPERLOWER])
{
/* Incomplete comparison, just for speedup. */
printf ("(((unsigned char)*");
expr1.output_expr ();
printf (" ^ (unsigned char)*");
expr2.output_expr ();
printf (") & ~32) == 0");
return false;
}
else
{
/* Complete comparison. */
printf ("*");
expr1.output_expr ();
printf (" == *");
expr2.output_expr ();
return true;
}
}
/* This class outputs a comparison using strcmp. */
struct Output_Compare_Strcmp : public Output_Compare
{
virtual void output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const;
Output_Compare_Strcmp () {}
virtual ~Output_Compare_Strcmp () {}
virtual void output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const;
Output_Compare_Strcmp () {}
virtual ~Output_Compare_Strcmp () {}
};
void Output_Compare_Strcmp::output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const
{
printf ("*");
expr1.output_expr ();
printf (" == *");
expr2.output_expr ();
bool firstchar_done = output_firstchar_comparison (expr1, expr2);
printf (" && !");
if (option[UPPERLOWER])
printf ("gperf_case_");
printf ("strcmp (");
expr1.output_expr ();
printf (" + 1, ");
expr2.output_expr ();
printf (" + 1)");
if (firstchar_done)
{
expr1.output_expr ();
printf (" + 1, ");
expr2.output_expr ();
printf (" + 1");
}
else
{
expr1.output_expr ();
printf (", ");
expr2.output_expr ();
}
printf (")");
}
/* This class outputs a comparison using strncmp.
@@ -501,27 +541,35 @@ void Output_Compare_Strcmp::output_comparison (const Output_Expr& expr1,
struct Output_Compare_Strncmp : public Output_Compare
{
virtual void output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const;
Output_Compare_Strncmp () {}
virtual ~Output_Compare_Strncmp () {}
virtual void output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const;
Output_Compare_Strncmp () {}
virtual ~Output_Compare_Strncmp () {}
};
void Output_Compare_Strncmp::output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const
{
printf ("*");
expr1.output_expr ();
printf (" == *");
expr2.output_expr ();
bool firstchar_done = output_firstchar_comparison (expr1, expr2);
printf (" && !");
if (option[UPPERLOWER])
printf ("gperf_case_");
printf ("strncmp (");
expr1.output_expr ();
printf (" + 1, ");
expr2.output_expr ();
printf (" + 1, len - 1) && ");
if (firstchar_done)
{
expr1.output_expr ();
printf (" + 1, ");
expr2.output_expr ();
printf (" + 1, len - 1");
}
else
{
expr1.output_expr ();
printf (", ");
expr2.output_expr ();
printf (", len");
}
printf (") && ");
expr2.output_expr ();
printf ("[len] == '\\0'");
}
@@ -533,27 +581,35 @@ void Output_Compare_Strncmp::output_comparison (const Output_Expr& expr1,
struct Output_Compare_Memcmp : public Output_Compare
{
virtual void output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const;
Output_Compare_Memcmp () {}
virtual ~Output_Compare_Memcmp () {}
virtual void output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const;
Output_Compare_Memcmp () {}
virtual ~Output_Compare_Memcmp () {}
};
void Output_Compare_Memcmp::output_comparison (const Output_Expr& expr1,
const Output_Expr& expr2) const
{
printf ("*");
expr1.output_expr ();
printf (" == *");
expr2.output_expr ();
bool firstchar_done = output_firstchar_comparison (expr1, expr2);
printf (" && !");
if (option[UPPERLOWER])
printf ("gperf_case_");
printf ("memcmp (");
expr1.output_expr ();
printf (" + 1, ");
expr2.output_expr ();
printf (" + 1, len - 1)");
if (firstchar_done)
{
expr1.output_expr ();
printf (" + 1, ");
expr2.output_expr ();
printf (" + 1, len - 1");
}
else
{
expr1.output_expr ();
printf (", ");
expr2.output_expr ();
printf (", len");
}
printf (")");
}
/* ------------------------------------------------------------------------- */