Milán Major

netscape-revival

1 branch
Code

lib/libparse/pa_hash.template

@! This file is used to generate pa_hash.c.  A perl script merges this
@! file  with the output of gperf to produce the hash functions for
@! tag lookup.   Lines starting with @! are comments.  Lines which do
@! not being with @! are copied straight to the output file. "@begin NAME
@! /REGEX1/ /REGEX2/" means to  skip lines in the input until REGEX1 is
@! matched, and then begin  saving output under name NAME, and stop when
@! REGEX2 is matched. "@include NAME" inserts the data saved as "NAME".
@! "@SUB NAME SUBREGEX" performs a substitution on the data saved in NAME.
@!
@! Comments and compaints about this poop go to Michael Toy.
@!
@! The following goop extracts the parts we need from the generated output
@! of gperf.  We later merge that goop with custom code to generate
@! the tag lookup function.
@!
@begin MACROS /#define/ /^$/
@begin HASH_TABLE /static unsigned [a-z]+ (asso_values|hash_table)/ /};/
@begin HASH_FUNC /register int hval = len;/ /return hval/
@sub HASH_FUNC /return hval \+/hval +=/
@sub HASH_FUNC /str\[/MYLOWER(str[/
@sub HASH_FUNC /]]/])]/
@begin LENGTH_TABLE /static unsigned char lengthtable/ /};/
@begin TAG_TABLE /static struct pa_TagTable *wordlist/ /};/
@!
/*
** This is a generated file, do not edit it.  If you need to make changes,
** edit the file pa_hash.template and re-build pa_hash.c on a UNIX machine.
** This whole hacky pile of poop was done by Michael Toy.
*/

#include "pa_parse.h"
@include MACROS
#define MYLOWER(x) TOLOWER(((x) & 0x7f))

/*************************************
 * Function: pa_tokenize_tag
 *
 * Description: This function maps the passed in string
 * 		to one of the valid tag element tokens, or to
 *		the UNKNOWN token.
 *
 * Params: Takes a \0 terminated string.
 *
 * Returns: a 32 bit token to describe this tag element.  On error,
 * 	    which means it was not passed an unknown tag element string,
 * 	    it returns the token P_UNKNOWN.
 *
 * Performance Notes:
 * Profiling on mac revealed this routine as a big (5%) time sink.
 * This function was stolen from pa_mdl.c and merged with the perfect
 * hashing code and the tag comparison code so it would be flatter (fewer
 * function calls) since those are still expensive on 68K and x86 machines.
 *************************************/

intn
pa_tokenize_tag(char *str)
{
@include HASH_TABLE
@include LENGTH_TABLE
@include TAG_TABLE

  if (str != NULL)
  {
    int len = strlen(str);
    if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
    {
@include HASH_FUNC
@! "hval" now contains hash value
      if (hval <= MAX_HASH_VALUE && hval >= MIN_HASH_VALUE)
      {
	if (len == lengthtable[hval])
	{
	  register char *tag = wordlist[hval].name;
	  /*
	  ** The following code was stolen from pa_TagEqual,
	  ** again to make this function flatter.
	  */

	  /*
	  ** While not at the end of the string, if they ever differ
	  ** they are not equal.  We know "tag" is already lower case.
	  */
	  while ((*tag != '\0')&&(*str != '\0'))
	  {
	    if (*tag != (char) TOLOWER(*str))
	      return(P_UNKNOWN);
	    tag++;
	    str++;
	  }
	  /*
	  ** One of the strings has ended, if they are both ended, then they
	  ** are equal, otherwise not.
	  */
	  if ((*tag == '\0')&&(*str == '\0'))
	    return wordlist[hval].id;
	}
      }
    }
  }
  return(P_UNKNOWN);
}