1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-12 09:58:36 +00:00

Move the hash function for directives into its own file and add

a Makefile target to re-created this file. Note, that there is no
explicite dependency to automatically re-create the file, because this
is needed only when the directive table changes and it requires the
(yet to come) devel/mph port.

Submitted by:	Max Okumoto <okumoto@ucsd.edu> (first version)
This commit is contained in:
Hartmut Brandt 2005-04-28 07:55:55 +00:00
parent 61d596a8ff
commit 2274441da6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=145612
4 changed files with 160 additions and 67 deletions

View File

@ -4,8 +4,9 @@
PROG= make
CFLAGS+=-I${.CURDIR}
SRCS= arch.c buf.c compat.c cond.c dir.c for.c hash.c job.c lst.c main.c \
make.c parse.c str.c suff.c targ.c util.c var.c var_modify.c
SRCS= arch.c buf.c compat.c cond.c dir.c directive_hash.c for.c \
hash.c job.c lst.c main.c make.c parse.c str.c suff.c targ.c \
util.c var.c var_modify.c
NO_WERROR=
WARNS?= 3
@ -21,6 +22,58 @@ CFLAGS+=-D__FBSDID=__RCSID
main.o: ${MAKEFILE}
# Directive table. We use a hash table. This hash table has been
# generated with mph which can be found on the usual GNU mirrors.
# If you change the directives (adding, deleting, reordering) you
# need to create a new table and hash function (directive_hash).
#
# The following changes have been made to the generated code:
#
# o prefix the names of the g, T0 and T1 arrays with 'directive_'.
#
# o make the type of the tables 'const [un]signed char' (if you change
# anything make sure that the numbers fit into a char).
#
# o make the hash function use the length for termination,
# not the trailing '\0', via the -l flag in emitc and some editing.
LOCALBASE ?= /usr/local
MPH ?= ${LOCALBASE}/bin/mph
EMITC ?= ${LOCALBASE}/bin/emitc
.PRECIOUS: hash
hash:
( echo '/*' ; \
echo ' * DO NOT EDIT' ; \
echo ' * $$FreeBSD$$' ; \
echo -n ' * auto-generated from ' ; \
sed -nEe '/\$$FreeBSD/s/^.*\$$(.*)\$$.*$$/\1/p' \
${.CURDIR}/parse.c ; \
echo ' * DO NOT EDIT' ; \
echo ' */' ; \
echo '#include <sys/types.h>' ; \
echo ; \
echo '#include "directive_hash.h"' ; \
echo ; \
cat ${.CURDIR}/parse.c | sed \
-e '1,/DIRECTIVES-START-TAG/d' \
-e '/DIRECTIVES-END-TAG/,$$d' \
-e 's/^[^"]*"\([^"]*\)".*$$/\1/' | \
${MPH} -d2 -m1 | ${EMITC} -l -s | \
sed \
-e 's/^static int g\[\]/static const signed char directive_g[]/' \
-e 's/^static int T0\[\]/static const u_char directive_T0[]/' \
-e 's/^static int T1\[\]/static const u_char directive_T1[]/' \
-e '/^#define uchar unsigned char/d' \
-e 's/uchar/u_char/g' \
-e 's/^hash(/directive_hash(/' \
-e 's/; \*kp;/; kp < key + len;/' \
-e 's/int len)/size_t len)/' \
-e 's/= T0\[/= directive_T0\[/' \
-e 's/= T1\[/= directive_T1\[/' \
-e 's/g\[f/directive_g[f/g' \
) > ${.CURDIR}/directive_hash.c
# Set the shell which make(1) uses. Bourne is the default, but a decent
# Korn shell works fine, and much faster. Using the C shell for this
# will almost certainly break everything, but it's Unix tradition to

View File

@ -0,0 +1,66 @@
/*
* DO NOT EDIT
* $FreeBSD$
* auto-generated from FreeBSD: src/usr.bin/make/parse.c,v 1.96 2005/04/11 07:40:54 harti Exp
* DO NOT EDIT
*/
#include <sys/types.h>
#include "directive_hash.h"
/*
* d=2
* n=38
* m=18
* c=2.09
* maxlen=1
* minklen=2
* maxklen=9
* minchar=97
* maxchar=119
* loop=0
* numiter=2
* seed=
*/
static const signed char directive_g[] = {
16, 0, -1, 14, 5, 2, 2, -1, 0, 0,
-1, -1, 16, 11, -1, 15, -1, 14, 7, -1,
8, 6, 1, -1, -1, 0, 4, 6, -1, 0,
0, 2, 0, 13, -1, 14, -1, 0,
};
static const u_char directive_T0[] = {
11, 25, 14, 30, 14, 26, 23, 15, 9, 37,
27, 32, 27, 1, 17, 27, 35, 13, 8, 22,
8, 28, 7,
};
static const u_char directive_T1[] = {
19, 20, 31, 17, 29, 2, 7, 12, 1, 31,
11, 18, 11, 20, 10, 2, 15, 19, 4, 10,
13, 36, 3,
};
int
directive_hash(const u_char *key, size_t len)
{
unsigned f0, f1;
const u_char *kp = key;
if (len < 2 || len > 9)
return -1;
for (f0=f1=0; kp < key + len; ++kp) {
if (*kp < 97 || *kp > 119)
return -1;
f0 += directive_T0[-97 + *kp];
f1 += directive_T1[-97 + *kp];
}
f0 %= 38;
f1 %= 38;
return (directive_g[f0] + directive_g[f1]) % 18;
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2005 Max Okumoto.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $DragonFly$
* $FreeBSD$
*/
#ifndef directive_hash_h_
#define directive_hash_h_
#include <sys/types.h>
int directive_hash(const u_char *, size_t);
#endif

View File

@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
#include "cond.h"
#include "config.h"
#include "dir.h"
#include "directive_hash.h"
#include "for.h"
#include "globals.h"
#include "GNode.h"
@ -231,58 +232,19 @@ static struct {
{ ".WAIT", Wait, 0 },
};
/*
* Directive table. We use a hash table. This hash table has been generated
* with mph which can be found on the usual GNU mirrors. If you change the
* directives (adding, deleting, reordering) you need to create a new table
* and hash function (directive_hash). The command line to generate the
* table is:
*
* mph -d2 -m1 <tab | emitc -l -s
*
* Where tab is a file containing just the directive strings, one per line.
*
* While inporting the result of this the following changes have been made
* to the generated code:
*
* prefix the names of the g, T0 and T1 arrays with 'directive_'.
*
* make the type of the tables 'const [un]signed char'.
*
* make the hash function use the length for termination,
* not the trailing '\0'.
*/
static void parse_include(char *, int, int);
static void parse_message(char *, int, int);
static void parse_undef(char *, int, int);
static void parse_for(char *, int, int);
static void parse_endfor(char *, int, int);
static const signed char directive_g[] = {
16, 0, -1, 14, 5, 2, 2, -1, 0, 0,
-1, -1, 16, 11, -1, 15, -1, 14, 7, -1,
8, 6, 1, -1, -1, 0, 4, 6, -1, 0,
0, 2, 0, 13, -1, 14, -1, 0,
};
static const unsigned char directive_T0[] = {
11, 25, 14, 30, 14, 26, 23, 15, 9, 37,
27, 32, 27, 1, 17, 27, 35, 13, 8, 22,
8, 28, 7,
};
static const unsigned char directive_T1[] = {
19, 20, 31, 17, 29, 2, 7, 12, 1, 31,
11, 18, 11, 20, 10, 2, 15, 19, 4, 10,
13, 36, 3,
};
static const struct directive {
const char *name;
int code;
Boolean skip_flag; /* execute even when skipped */
void (*func)(char *, int, int);
} directives[] = {
/* DIRECTIVES-START-TAG */
{ "elif", COND_ELIF, TRUE, Cond_If },
{ "elifdef", COND_ELIFDEF, TRUE, Cond_If },
{ "elifmake", COND_ELIFMAKE, TRUE, Cond_If },
@ -301,6 +263,7 @@ static const struct directive {
{ "include", 0, FALSE, parse_include },
{ "undef", 0, FALSE, parse_undef },
{ "warning", 0, FALSE, parse_message },
/* DIRECTIVES-END-TAG */
};
#define NDIRECTS (sizeof(directives) / sizeof(directives[0]))
@ -2330,31 +2293,6 @@ parse_endfor(char *line __unused, int code __unused, int lineno __unused)
Parse_Error(PARSE_FATAL, "for-less endfor");
}
/**
* directive_hash
*/
static int
directive_hash(const u_char *key, size_t len)
{
unsigned f0, f1;
const u_char *kp = key;
if (len < 2 || len > 9)
return (-1);
for (f0 = f1 = 0; kp < key + len; ++kp) {
if (*kp < 97 || *kp > 119)
return (-1);
f0 += directive_T0[-97 + *kp];
f1 += directive_T1[-97 + *kp];
}
f0 %= 38;
f1 %= 38;
return (directive_g[f0] + directive_g[f1]) % 18;
}
/**
* parse_directive
* Got a line starting with a '.'. Check if this is a directive