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:
14
ChangeLog
14
ChangeLog
@@ -1,3 +1,17 @@
|
|||||||
|
2003-01-01 Bruno Haible <bruno@clisp.org>
|
||||||
|
|
||||||
|
* src/output.c (Output_Compare::output_firstchar_comparison): New
|
||||||
|
method.
|
||||||
|
(Output_Compare_Strcmp::output_comparison,
|
||||||
|
Output_Compare_Strncmp::output_comparison,
|
||||||
|
Output_Compare_Memcmp::output_comparison): Use it.
|
||||||
|
* tests/permutc2.exp: Update.
|
||||||
|
|
||||||
|
* tests/smtp.gperf: New file, based on a contribution by Bruce Lilly.
|
||||||
|
* tests/Makefile.in (check-smtp): New rule.
|
||||||
|
(check): Depend on it.
|
||||||
|
(clean): Update.
|
||||||
|
|
||||||
2002-12-12 Bruno Haible <bruno@clisp.org>
|
2002-12-12 Bruno Haible <bruno@clisp.org>
|
||||||
|
|
||||||
* src/search.h (Search::init_selchars_tuple,
|
* src/search.h (Search::init_selchars_tuple,
|
||||||
|
|||||||
188
src/output.cc
188
src/output.cc
@@ -1,5 +1,5 @@
|
|||||||
/* Output routines.
|
/* 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>
|
Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
|
||||||
and Bruno Haible <bruno@clisp.org>.
|
and Bruno Haible <bruno@clisp.org>.
|
||||||
|
|
||||||
@@ -144,22 +144,22 @@ Output::num_hash_values () const
|
|||||||
|
|
||||||
struct Output_Constants
|
struct Output_Constants
|
||||||
{
|
{
|
||||||
virtual void output_start () = 0;
|
virtual void output_start () = 0;
|
||||||
virtual void output_item (const char *name, int value) = 0;
|
virtual void output_item (const char *name, int value) = 0;
|
||||||
virtual void output_end () = 0;
|
virtual void output_end () = 0;
|
||||||
Output_Constants () {}
|
Output_Constants () {}
|
||||||
virtual ~Output_Constants () {}
|
virtual ~Output_Constants () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This class outputs an enumeration in #define syntax. */
|
/* This class outputs an enumeration in #define syntax. */
|
||||||
|
|
||||||
struct Output_Defines : public Output_Constants
|
struct Output_Defines : public Output_Constants
|
||||||
{
|
{
|
||||||
virtual void output_start ();
|
virtual void output_start ();
|
||||||
virtual void output_item (const char *name, int value);
|
virtual void output_item (const char *name, int value);
|
||||||
virtual void output_end ();
|
virtual void output_end ();
|
||||||
Output_Defines () {}
|
Output_Defines () {}
|
||||||
virtual ~Output_Defines () {}
|
virtual ~Output_Defines () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Output_Defines::output_start ()
|
void Output_Defines::output_start ()
|
||||||
@@ -180,11 +180,12 @@ void Output_Defines::output_end ()
|
|||||||
|
|
||||||
struct Output_Enum : public Output_Constants
|
struct Output_Enum : public Output_Constants
|
||||||
{
|
{
|
||||||
virtual void output_start ();
|
virtual void output_start ();
|
||||||
virtual void output_item (const char *name, int value);
|
virtual void output_item (const char *name, int value);
|
||||||
virtual void output_end ();
|
virtual void output_end ();
|
||||||
Output_Enum (const char *indent) : _indentation (indent) {}
|
Output_Enum (const char *indent)
|
||||||
virtual ~Output_Enum () {}
|
: _indentation (indent) {}
|
||||||
|
virtual ~Output_Enum () {}
|
||||||
private:
|
private:
|
||||||
const char *_indentation;
|
const char *_indentation;
|
||||||
bool _pending_comma;
|
bool _pending_comma;
|
||||||
@@ -407,18 +408,18 @@ output_const_type (const char *const_string, const char *type_string)
|
|||||||
|
|
||||||
struct Output_Expr
|
struct Output_Expr
|
||||||
{
|
{
|
||||||
virtual void output_expr () const = 0;
|
virtual void output_expr () const = 0;
|
||||||
Output_Expr () {}
|
Output_Expr () {}
|
||||||
virtual ~Output_Expr () {}
|
virtual ~Output_Expr () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This class outputs an expression formed by a single string. */
|
/* This class outputs an expression formed by a single string. */
|
||||||
|
|
||||||
struct Output_Expr1 : public Output_Expr
|
struct Output_Expr1 : public Output_Expr
|
||||||
{
|
{
|
||||||
virtual void output_expr () const;
|
virtual void output_expr () const;
|
||||||
Output_Expr1 (const char *piece1) : _p1 (piece1) {}
|
Output_Expr1 (const char *piece1) : _p1 (piece1) {}
|
||||||
virtual ~Output_Expr1 () {}
|
virtual ~Output_Expr1 () {}
|
||||||
private:
|
private:
|
||||||
const char *_p1;
|
const char *_p1;
|
||||||
};
|
};
|
||||||
@@ -435,10 +436,10 @@ void Output_Expr1::output_expr () const
|
|||||||
|
|
||||||
struct Output_Expr2 : public Output_Expr
|
struct Output_Expr2 : public Output_Expr
|
||||||
{
|
{
|
||||||
virtual void output_expr () const;
|
virtual void output_expr () const;
|
||||||
Output_Expr2 (const char *piece1, const char *piece2)
|
Output_Expr2 (const char *piece1, const char *piece2)
|
||||||
: _p1 (piece1), _p2 (piece2) {}
|
: _p1 (piece1), _p2 (piece2) {}
|
||||||
virtual ~Output_Expr2 () {}
|
virtual ~Output_Expr2 () {}
|
||||||
private:
|
private:
|
||||||
const char *_p1;
|
const char *_p1;
|
||||||
const char *_p2;
|
const char *_p2;
|
||||||
@@ -462,37 +463,76 @@ struct Output_Compare
|
|||||||
the string being looked up. expr2 outputs a simple expression of type
|
the string being looked up. expr2 outputs a simple expression of type
|
||||||
'const char *' referring to the constant string stored in the gperf
|
'const char *' referring to the constant string stored in the gperf
|
||||||
generated hash table. */
|
generated hash table. */
|
||||||
virtual void output_comparison (const Output_Expr& expr1,
|
virtual void output_comparison (const Output_Expr& expr1,
|
||||||
const Output_Expr& expr2) const = 0;
|
const Output_Expr& expr2) const = 0;
|
||||||
Output_Compare () {}
|
/* Outputs the comparison expression for the first byte.
|
||||||
virtual ~Output_Compare () {}
|
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. */
|
/* This class outputs a comparison using strcmp. */
|
||||||
|
|
||||||
struct Output_Compare_Strcmp : public Output_Compare
|
struct Output_Compare_Strcmp : public Output_Compare
|
||||||
{
|
{
|
||||||
virtual void output_comparison (const Output_Expr& expr1,
|
virtual void output_comparison (const Output_Expr& expr1,
|
||||||
const Output_Expr& expr2) const;
|
const Output_Expr& expr2) const;
|
||||||
Output_Compare_Strcmp () {}
|
Output_Compare_Strcmp () {}
|
||||||
virtual ~Output_Compare_Strcmp () {}
|
virtual ~Output_Compare_Strcmp () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Output_Compare_Strcmp::output_comparison (const Output_Expr& expr1,
|
void Output_Compare_Strcmp::output_comparison (const Output_Expr& expr1,
|
||||||
const Output_Expr& expr2) const
|
const Output_Expr& expr2) const
|
||||||
{
|
{
|
||||||
printf ("*");
|
bool firstchar_done = output_firstchar_comparison (expr1, expr2);
|
||||||
expr1.output_expr ();
|
|
||||||
printf (" == *");
|
|
||||||
expr2.output_expr ();
|
|
||||||
printf (" && !");
|
printf (" && !");
|
||||||
if (option[UPPERLOWER])
|
if (option[UPPERLOWER])
|
||||||
printf ("gperf_case_");
|
printf ("gperf_case_");
|
||||||
printf ("strcmp (");
|
printf ("strcmp (");
|
||||||
expr1.output_expr ();
|
if (firstchar_done)
|
||||||
printf (" + 1, ");
|
{
|
||||||
expr2.output_expr ();
|
expr1.output_expr ();
|
||||||
printf (" + 1)");
|
printf (" + 1, ");
|
||||||
|
expr2.output_expr ();
|
||||||
|
printf (" + 1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expr1.output_expr ();
|
||||||
|
printf (", ");
|
||||||
|
expr2.output_expr ();
|
||||||
|
}
|
||||||
|
printf (")");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This class outputs a comparison using strncmp.
|
/* 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
|
struct Output_Compare_Strncmp : public Output_Compare
|
||||||
{
|
{
|
||||||
virtual void output_comparison (const Output_Expr& expr1,
|
virtual void output_comparison (const Output_Expr& expr1,
|
||||||
const Output_Expr& expr2) const;
|
const Output_Expr& expr2) const;
|
||||||
Output_Compare_Strncmp () {}
|
Output_Compare_Strncmp () {}
|
||||||
virtual ~Output_Compare_Strncmp () {}
|
virtual ~Output_Compare_Strncmp () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Output_Compare_Strncmp::output_comparison (const Output_Expr& expr1,
|
void Output_Compare_Strncmp::output_comparison (const Output_Expr& expr1,
|
||||||
const Output_Expr& expr2) const
|
const Output_Expr& expr2) const
|
||||||
{
|
{
|
||||||
printf ("*");
|
bool firstchar_done = output_firstchar_comparison (expr1, expr2);
|
||||||
expr1.output_expr ();
|
|
||||||
printf (" == *");
|
|
||||||
expr2.output_expr ();
|
|
||||||
printf (" && !");
|
printf (" && !");
|
||||||
if (option[UPPERLOWER])
|
if (option[UPPERLOWER])
|
||||||
printf ("gperf_case_");
|
printf ("gperf_case_");
|
||||||
printf ("strncmp (");
|
printf ("strncmp (");
|
||||||
expr1.output_expr ();
|
if (firstchar_done)
|
||||||
printf (" + 1, ");
|
{
|
||||||
expr2.output_expr ();
|
expr1.output_expr ();
|
||||||
printf (" + 1, len - 1) && ");
|
printf (" + 1, ");
|
||||||
|
expr2.output_expr ();
|
||||||
|
printf (" + 1, len - 1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expr1.output_expr ();
|
||||||
|
printf (", ");
|
||||||
|
expr2.output_expr ();
|
||||||
|
printf (", len");
|
||||||
|
}
|
||||||
|
printf (") && ");
|
||||||
expr2.output_expr ();
|
expr2.output_expr ();
|
||||||
printf ("[len] == '\\0'");
|
printf ("[len] == '\\0'");
|
||||||
}
|
}
|
||||||
@@ -533,27 +581,35 @@ void Output_Compare_Strncmp::output_comparison (const Output_Expr& expr1,
|
|||||||
|
|
||||||
struct Output_Compare_Memcmp : public Output_Compare
|
struct Output_Compare_Memcmp : public Output_Compare
|
||||||
{
|
{
|
||||||
virtual void output_comparison (const Output_Expr& expr1,
|
virtual void output_comparison (const Output_Expr& expr1,
|
||||||
const Output_Expr& expr2) const;
|
const Output_Expr& expr2) const;
|
||||||
Output_Compare_Memcmp () {}
|
Output_Compare_Memcmp () {}
|
||||||
virtual ~Output_Compare_Memcmp () {}
|
virtual ~Output_Compare_Memcmp () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
void Output_Compare_Memcmp::output_comparison (const Output_Expr& expr1,
|
void Output_Compare_Memcmp::output_comparison (const Output_Expr& expr1,
|
||||||
const Output_Expr& expr2) const
|
const Output_Expr& expr2) const
|
||||||
{
|
{
|
||||||
printf ("*");
|
bool firstchar_done = output_firstchar_comparison (expr1, expr2);
|
||||||
expr1.output_expr ();
|
|
||||||
printf (" == *");
|
|
||||||
expr2.output_expr ();
|
|
||||||
printf (" && !");
|
printf (" && !");
|
||||||
if (option[UPPERLOWER])
|
if (option[UPPERLOWER])
|
||||||
printf ("gperf_case_");
|
printf ("gperf_case_");
|
||||||
printf ("memcmp (");
|
printf ("memcmp (");
|
||||||
expr1.output_expr ();
|
if (firstchar_done)
|
||||||
printf (" + 1, ");
|
{
|
||||||
expr2.output_expr ();
|
expr1.output_expr ();
|
||||||
printf (" + 1, len - 1)");
|
printf (" + 1, ");
|
||||||
|
expr2.output_expr ();
|
||||||
|
printf (" + 1, len - 1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expr1.output_expr ();
|
||||||
|
printf (", ");
|
||||||
|
expr2.output_expr ();
|
||||||
|
printf (", len");
|
||||||
|
}
|
||||||
|
printf (")");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Makefile for gperf/tests
|
# Makefile for gperf/tests
|
||||||
|
|
||||||
# Copyright (C) 1989, 1992, 1993, 1995, 1998, 2000, 2002 Free Software Foundation, Inc.
|
# Copyright (C) 1989, 1992, 1993, 1995, 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
|
||||||
# Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
|
# Written by Douglas C. Schmidt <schmidt@ics.uci.edu>
|
||||||
# and Bruno Haible <bruno@clisp.org>.
|
# and Bruno Haible <bruno@clisp.org>.
|
||||||
#
|
#
|
||||||
@@ -58,7 +58,7 @@ installdirs :
|
|||||||
|
|
||||||
uninstall :
|
uninstall :
|
||||||
|
|
||||||
check : check-link-c check-link-c++ check-c check-ada check-modula3 check-pascal check-lang-utf8 check-lang-ucs2 check-test
|
check : check-link-c check-link-c++ check-c check-ada check-modula3 check-pascal check-lang-utf8 check-lang-ucs2 check-smtp check-test
|
||||||
@true
|
@true
|
||||||
|
|
||||||
extracheck : @CHECK_LANG_SYNTAX@
|
extracheck : @CHECK_LANG_SYNTAX@
|
||||||
@@ -121,6 +121,19 @@ check-lang-ucs2:
|
|||||||
./lu2out -v < $(srcdir)/lang-ucs2.in > lang-ucs2.out
|
./lu2out -v < $(srcdir)/lang-ucs2.in > lang-ucs2.out
|
||||||
diff $(srcdir)/lang-ucs2.exp lang-ucs2.out
|
diff $(srcdir)/lang-ucs2.exp lang-ucs2.out
|
||||||
|
|
||||||
|
# check case-insensitive lookup
|
||||||
|
check-smtp:
|
||||||
|
@echo "testing SMTP keywords, case-insensitive"
|
||||||
|
$(GPERF) --struct-type --readonly-table --enum --global -K field_name -N header_entry --ignore-case $(srcdir)/smtp.gperf > smtp.c
|
||||||
|
$(CC) $(CFLAGS) -o smtp smtp.c
|
||||||
|
./smtp
|
||||||
|
$(GPERF) --struct-type --readonly-table --enum --global -K field_name -N header_entry --ignore-case --compare-strncmp $(srcdir)/smtp.gperf > smtp.c
|
||||||
|
$(CC) $(CFLAGS) -o smtp smtp.c
|
||||||
|
./smtp
|
||||||
|
$(GPERF) --struct-type --readonly-table --enum --global -K field_name -N header_entry --ignore-case --compare-lengths $(srcdir)/smtp.gperf > smtp.c
|
||||||
|
$(CC) $(CFLAGS) -o smtp smtp.c
|
||||||
|
./smtp
|
||||||
|
|
||||||
# these next 5 are demos that show off the generated code
|
# these next 5 are demos that show off the generated code
|
||||||
check-test:
|
check-test:
|
||||||
$(GPERF) -L C -F ', 0, 0' -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,'$$' < $(srcdir)/c-parse.gperf > c-parse.out
|
$(GPERF) -L C -F ', 0, 0' -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,'$$' < $(srcdir)/c-parse.gperf > c-parse.out
|
||||||
@@ -273,7 +286,7 @@ check-lang-syntax : force
|
|||||||
mostlyclean : clean
|
mostlyclean : clean
|
||||||
|
|
||||||
clean : force
|
clean : force
|
||||||
$(RM) *.o core *inset.c output.* *.out aout cout lu2out lu8out m3out pout preout tmp-* valitest*
|
$(RM) *.o core *inset.c output.* *.out aout cout lu2out lu8out m3out pout preout smtp.c smtp tmp-* valitest*
|
||||||
|
|
||||||
distclean : clean
|
distclean : clean
|
||||||
$(RM) config.status config.log config.cache Makefile
|
$(RM) config.status config.log config.cache Makefile
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ in_word_set (str, len)
|
|||||||
{
|
{
|
||||||
register const char *s = wordlist[key];
|
register const char *s = wordlist[key];
|
||||||
|
|
||||||
if (*str == *s && !gperf_case_strcmp (str + 1, s + 1))
|
if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_strcmp (str, s))
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
206
tests/smtp.gperf
Normal file
206
tests/smtp.gperf
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
%{
|
||||||
|
/* gperf --struct-type --readonly-table --enum --global -K field_name -N header_entry --ignore-case */
|
||||||
|
/* Contributed by Bruce Lilly
|
||||||
|
derived from http://users.erols.com/blilly/mailparse/fields.gperf */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
%}
|
||||||
|
struct header_state { const char *field_name; };
|
||||||
|
%%
|
||||||
|
Accept-Language
|
||||||
|
Action
|
||||||
|
Alternate-Recipient
|
||||||
|
Approved
|
||||||
|
Archive
|
||||||
|
Arrival-Date
|
||||||
|
Autoforwarded
|
||||||
|
Autosubmitted
|
||||||
|
Bcc
|
||||||
|
Cc
|
||||||
|
Comments
|
||||||
|
Complaints-To
|
||||||
|
Content-alternative
|
||||||
|
Content-Base
|
||||||
|
Content-Description
|
||||||
|
Content-Disposition
|
||||||
|
Content-Duration
|
||||||
|
Content-Features
|
||||||
|
Content-ID
|
||||||
|
Content-Language
|
||||||
|
Content-Location
|
||||||
|
Content-MD5
|
||||||
|
Content-Transfer-Encoding
|
||||||
|
Content-Type
|
||||||
|
Control
|
||||||
|
Conversion
|
||||||
|
Conversion-With-Loss
|
||||||
|
DL-Expansion-History
|
||||||
|
DSN-Gateway
|
||||||
|
Date
|
||||||
|
Deferred-Delivery
|
||||||
|
Delivery-Date
|
||||||
|
Diagnostic-Code
|
||||||
|
Discarded-X400-IPMS-Extensions
|
||||||
|
Discarded-X400-MTS-Extensions
|
||||||
|
Disclose-Recipients
|
||||||
|
Disposition
|
||||||
|
Disposition-Notification-Options
|
||||||
|
Disposition-Notification-To
|
||||||
|
Distribution
|
||||||
|
Encrypted
|
||||||
|
Error
|
||||||
|
Expires
|
||||||
|
Failure
|
||||||
|
Final-Log-ID
|
||||||
|
Final-Recipient
|
||||||
|
Followup-To
|
||||||
|
From
|
||||||
|
Generate-Delivery-Report
|
||||||
|
Importance
|
||||||
|
In-Reply-To
|
||||||
|
Incomplete-Copy
|
||||||
|
Injector-Info
|
||||||
|
Keywords
|
||||||
|
Last-Attempt-Date
|
||||||
|
Latest-Delivery-Time
|
||||||
|
Lines
|
||||||
|
List-Archive
|
||||||
|
List-Help
|
||||||
|
List-ID
|
||||||
|
List-Post
|
||||||
|
List-Owner
|
||||||
|
List-Subscribe
|
||||||
|
List-Unsubscribe
|
||||||
|
MDN-Gateway
|
||||||
|
Media-Accept-Features
|
||||||
|
MIME-Version
|
||||||
|
Mail-Copies-To
|
||||||
|
Message-ID
|
||||||
|
Message-Type
|
||||||
|
Newsgroups
|
||||||
|
Organization
|
||||||
|
Original-Encoded-Information-Types
|
||||||
|
Original-Envelope-ID
|
||||||
|
Original-Message-ID
|
||||||
|
Original-Recipient
|
||||||
|
Originator-Return-Address
|
||||||
|
Path
|
||||||
|
Posted-And-Mailed
|
||||||
|
Prevent-Nondelivery-Report
|
||||||
|
Priority
|
||||||
|
Received
|
||||||
|
Received-content-MIC
|
||||||
|
Received-From-MTA
|
||||||
|
References
|
||||||
|
Remote-MTA
|
||||||
|
Reply-By
|
||||||
|
Reply-To
|
||||||
|
Reporting-MTA
|
||||||
|
Reporting-UA
|
||||||
|
Return-Path
|
||||||
|
Sender
|
||||||
|
Sensitivity
|
||||||
|
Status
|
||||||
|
Subject
|
||||||
|
Summary
|
||||||
|
Supersedes
|
||||||
|
To
|
||||||
|
User-Agent
|
||||||
|
Warning
|
||||||
|
Will-Retry-Until
|
||||||
|
X400-Content-Identifier
|
||||||
|
X400-Content-Return
|
||||||
|
X400-Content-Type
|
||||||
|
X400-MTS-Identifier
|
||||||
|
X400-Originator
|
||||||
|
X400-Received
|
||||||
|
X400-Recipients
|
||||||
|
Xref
|
||||||
|
%%
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
my_case_strcmp (s1, s2)
|
||||||
|
register const char *s1;
|
||||||
|
register const char *s2;
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
unsigned char c1 = *s1++;
|
||||||
|
unsigned char c2 = *s2++;
|
||||||
|
if (c1 >= 'A' && c1 <= 'Z')
|
||||||
|
c1 += 'a' - 'A';
|
||||||
|
if (c2 >= 'A' && c2 <= 'Z')
|
||||||
|
c2 += 'a' - 'A';
|
||||||
|
if (c1 != 0 && c1 == c2)
|
||||||
|
continue;
|
||||||
|
return (int)c1 - (int)c2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (argc, argv)
|
||||||
|
int argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
int i, j, k, n, exitcode;
|
||||||
|
unsigned int len;
|
||||||
|
const struct header_state *hs;
|
||||||
|
|
||||||
|
n = 1;
|
||||||
|
if (argc > 1)
|
||||||
|
n = atoi (argv[1]);
|
||||||
|
if (n < 1)
|
||||||
|
n = 1;
|
||||||
|
|
||||||
|
exitcode = 0;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j <= MAX_HASH_VALUE; j++)
|
||||||
|
{
|
||||||
|
const char *s = wordlist[j].field_name;
|
||||||
|
len = strlen (s);
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
hs = header_entry (s, len);
|
||||||
|
if (!(hs && strcmp (hs->field_name, s) == 0))
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s != %s\n", s, hs ? hs->field_name : "(null)");
|
||||||
|
exitcode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (j = 0; j <= MAX_HASH_VALUE; j++)
|
||||||
|
{
|
||||||
|
char s[MAX_WORD_LENGTH+1];
|
||||||
|
/* expensive copy with case conversion (for testing) */
|
||||||
|
strcpy (s, wordlist[j].field_name);
|
||||||
|
len = strlen (s);
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
for (k = 0; k < len; k++)
|
||||||
|
if (isupper (s[k]))
|
||||||
|
s[k] = tolower (s[k]);
|
||||||
|
else if (islower (s[k]))
|
||||||
|
s[k] = toupper (s[k]);
|
||||||
|
hs = header_entry (s, len);
|
||||||
|
if (!(hs && my_case_strcmp (hs->field_name, s) == 0))
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s != %s\n", s, hs ? hs->field_name : "(null)");
|
||||||
|
exitcode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hs = header_entry ("Dave", 4);
|
||||||
|
if (hs)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Dave == %s\n", hs->field_name);
|
||||||
|
exitcode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exitcode;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user