mirror of
https://github.com/openbsd/src.git
synced 2025-01-10 06:47:55 -08:00
clean up internal lookup interface:
define an interface with explicit define/pushdef/popdef... and use it. That way, most details of the hashtable are no longer visible. okay millert@
This commit is contained in:
parent
182f6d021d
commit
3509e8ffae
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: eval.c,v 1.48 2003/06/18 21:08:07 espie Exp $ */
|
||||
/* $OpenBSD: eval.c,v 1.49 2003/06/30 21:42:50 espie Exp $ */
|
||||
/* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */
|
||||
|
||||
/*
|
||||
@ -37,7 +37,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)eval.c 8.2 (Berkeley) 4/27/95";
|
||||
#else
|
||||
static char rcsid[] = "$OpenBSD: eval.c,v 1.48 2003/06/18 21:08:07 espie Exp $";
|
||||
static char rcsid[] = "$OpenBSD: eval.c,v 1.49 2003/06/30 21:42:50 espie Exp $";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -61,9 +61,6 @@ static char rcsid[] = "$OpenBSD: eval.c,v 1.48 2003/06/18 21:08:07 espie Exp $";
|
||||
#include "extern.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
#define BUILTIN_MARKER "__builtin_"
|
||||
|
||||
static void setup_definition(ndptr, const char *);
|
||||
static void dodefn(const char *);
|
||||
static void dopushdef(const char *, const char *);
|
||||
static void dodump(const char *[], int);
|
||||
@ -82,7 +79,7 @@ static void map(char *, const char *, const char *, const char *);
|
||||
static const char *handledash(char *, char *, const char *);
|
||||
static void expand_builtin(const char *[], int, int);
|
||||
static void expand_macro(const char *[], int);
|
||||
static void dump_one_def(ndptr);
|
||||
static void dump_one_def(const char *, struct macro_definition *);
|
||||
|
||||
unsigned long expansion_id;
|
||||
|
||||
@ -91,7 +88,7 @@ unsigned long expansion_id;
|
||||
* argc - number of elements in argv.
|
||||
* argv - element vector :
|
||||
* argv[0] = definition of a user
|
||||
* macro or nil if built-in.
|
||||
* macro or NULL if built-in.
|
||||
* argv[1] = name of the macro or
|
||||
* built-in.
|
||||
* argv[2] = parameters to user-defined
|
||||
@ -196,7 +193,7 @@ expand_builtin(const char *argv[], int argc, int td)
|
||||
* another definition
|
||||
*/
|
||||
if (argc > 3) {
|
||||
if (lookup(argv[2]) != nil)
|
||||
if (lookup_macro_definition(argv[2]) != NULL)
|
||||
pbstr(argv[3]);
|
||||
else if (argc > 4)
|
||||
pbstr(argv[4]);
|
||||
@ -344,7 +341,7 @@ expand_builtin(const char *argv[], int argc, int td)
|
||||
*/
|
||||
if (argc > 2)
|
||||
for (n = 2; n < argc; n++)
|
||||
remhash(argv[n], ALL);
|
||||
macro_undefine(argv[n]);
|
||||
break;
|
||||
|
||||
case POPDTYPE:
|
||||
@ -355,7 +352,7 @@ expand_builtin(const char *argv[], int argc, int td)
|
||||
*/
|
||||
if (argc > 2)
|
||||
for (n = 2; n < argc; n++)
|
||||
remhash(argv[n], TOP);
|
||||
macro_popdef(argv[n]);
|
||||
break;
|
||||
|
||||
case MKTMTYPE:
|
||||
@ -562,49 +559,16 @@ expand_macro(const char *argv[], int argc)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* common part to dodefine and dopushdef
|
||||
*/
|
||||
static void
|
||||
setup_definition(ndptr p, const char *defn)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0) {
|
||||
n = builtin_type(defn+sizeof(BUILTIN_MARKER)-1);
|
||||
if (n != -1) {
|
||||
p->type = n & TYPEMASK;
|
||||
if ((n & NOARGS) == 0)
|
||||
p->type |= NEEDARGS;
|
||||
p->defn = xstrdup(defn+sizeof(BUILTIN_MARKER)-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!*defn)
|
||||
p->defn = null;
|
||||
else
|
||||
p->defn = xstrdup(defn);
|
||||
p->type = MACRTYPE;
|
||||
}
|
||||
|
||||
/*
|
||||
* dodefine - install definition in the table
|
||||
*/
|
||||
void
|
||||
dodefine(const char *name, const char *defn)
|
||||
{
|
||||
ndptr p;
|
||||
|
||||
if (!*name)
|
||||
errx(1, "%s at line %lu: null definition.", CURRENT_NAME,
|
||||
CURRENT_LINE);
|
||||
if ((p = lookup(name)) == nil)
|
||||
p = addent(name);
|
||||
else if (p->defn != null)
|
||||
free((char *) p->defn);
|
||||
setup_definition(p, defn);
|
||||
if (STREQ(name, defn))
|
||||
p->type |= RECDEF;
|
||||
macro_define(name, defn);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -614,10 +578,10 @@ dodefine(const char *name, const char *defn)
|
||||
static void
|
||||
dodefn(const char *name)
|
||||
{
|
||||
ndptr p;
|
||||
struct macro_definition *p;
|
||||
char *real;
|
||||
|
||||
if ((p = lookup(name)) != nil) {
|
||||
if ((p = lookup_macro_definition(name)) != NULL) {
|
||||
if ((p->type & TYPEMASK) == MACRTYPE) {
|
||||
pbstr(rquote);
|
||||
pbstr(p->defn);
|
||||
@ -639,31 +603,26 @@ dodefn(const char *name)
|
||||
static void
|
||||
dopushdef(const char *name, const char *defn)
|
||||
{
|
||||
ndptr p;
|
||||
|
||||
if (!*name)
|
||||
errx(1, "%s at line %lu: null definition", CURRENT_NAME,
|
||||
CURRENT_LINE);
|
||||
p = addent(name);
|
||||
setup_definition(p, defn);
|
||||
if (STREQ(name, defn))
|
||||
p->type |= RECDEF;
|
||||
macro_pushdef(name, defn);
|
||||
}
|
||||
|
||||
/*
|
||||
* dump_one_def - dump the specified definition.
|
||||
*/
|
||||
static void
|
||||
dump_one_def(ndptr p)
|
||||
dump_one_def(const char *name, struct macro_definition *p)
|
||||
{
|
||||
if (mimic_gnu) {
|
||||
if ((p->type & TYPEMASK) == MACRTYPE)
|
||||
fprintf(traceout, "%s:\t%s\n", p->name, p->defn);
|
||||
fprintf(traceout, "%s:\t%s\n", name, p->defn);
|
||||
else {
|
||||
fprintf(traceout, "%s:\t<%s>\n", p->name, p->defn);
|
||||
fprintf(traceout, "%s:\t<%s>\n", name, p->defn);
|
||||
}
|
||||
} else
|
||||
fprintf(traceout, "`%s'\t`%s'\n", p->name, p->defn);
|
||||
fprintf(traceout, "`%s'\t`%s'\n", name, p->defn);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -675,17 +634,14 @@ static void
|
||||
dodump(const char *argv[], int argc)
|
||||
{
|
||||
int n;
|
||||
ndptr p;
|
||||
struct macro_definition *p;
|
||||
|
||||
if (argc > 2) {
|
||||
for (n = 2; n < argc; n++)
|
||||
if ((p = lookup(argv[n])) != nil)
|
||||
dump_one_def(p);
|
||||
} else {
|
||||
for (n = 0; n < HASHSIZE; n++)
|
||||
for (p = hashtab[n]; p != nil; p = p->nxtptr)
|
||||
dump_one_def(p);
|
||||
}
|
||||
if ((p = lookup_macro_definition(argv[n])) != NULL)
|
||||
dump_one_def(argv[n], p);
|
||||
} else
|
||||
macro_for_all(dump_one_def);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: extern.h,v 1.33 2003/06/18 21:08:07 espie Exp $ */
|
||||
/* $OpenBSD: extern.h,v 1.34 2003/06/30 21:42:50 espie Exp $ */
|
||||
/* $NetBSD: extern.h,v 1.3 1996/01/13 23:25:24 pk Exp $ */
|
||||
|
||||
/*-
|
||||
@ -58,10 +58,17 @@ extern void doesyscmd(const char *);
|
||||
|
||||
|
||||
/* look.c */
|
||||
extern ndptr addent(const char *);
|
||||
extern unsigned hash(const char *);
|
||||
extern ndptr lookup(const char *);
|
||||
extern void remhash(const char *, int);
|
||||
|
||||
extern struct macro_definition *lookup_macro_definition(const char *);
|
||||
extern void macro_define(const char *, const char *);
|
||||
extern void macro_pushdef(const char *, const char *);
|
||||
extern void macro_popdef(const char *);
|
||||
extern void macro_undefine(const char *);
|
||||
extern void setup_builtin(const char *, unsigned int);
|
||||
extern void macro_for_all(void (*)(const char *, struct macro_definition *));
|
||||
extern const char *macro_name(ndptr);
|
||||
extern struct macro_definition *macro_getdef(ndptr);
|
||||
|
||||
/* main.c */
|
||||
extern void outputstr(const char *);
|
||||
@ -149,3 +156,4 @@ extern char scommt[MAXCCHARS+1];/* start character for comment */
|
||||
extern int synch_lines; /* line synchronisation directives */
|
||||
|
||||
extern int mimic_gnu; /* behaves like gnu-m4 */
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: gnum4.c,v 1.21 2003/06/08 22:42:27 espie Exp $ */
|
||||
/* $OpenBSD: gnum4.c,v 1.22 2003/06/30 21:42:50 espie Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 Marc Espie
|
||||
@ -159,9 +159,9 @@ fopen_trypath(struct input_file *i, const char *filename)
|
||||
void
|
||||
doindir(const char *argv[], int argc)
|
||||
{
|
||||
ndptr p;
|
||||
struct macro_definition *p;
|
||||
|
||||
p = lookup(argv[2]);
|
||||
p = lookup_macro_definition(argv[2]);
|
||||
if (p == NULL)
|
||||
errx(1, "undefined macro %s", argv[2]);
|
||||
argv[1] = p->defn;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: look.c,v 1.11 2003/06/03 02:56:10 millert Exp $ */
|
||||
/* $OpenBSD: look.c,v 1.12 2003/06/30 21:42:50 espie Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@ -51,9 +51,19 @@ static char sccsid[] = "@(#)look.c 8.1 (Berkeley) 6/6/93";
|
||||
#include "stdd.h"
|
||||
#include "extern.h"
|
||||
|
||||
struct ndblock { /* hastable structure */
|
||||
char *name; /* entry name.. */
|
||||
struct macro_definition d;
|
||||
unsigned int hv; /* hash function value.. */
|
||||
ndptr nxtptr; /* link to next entry.. */
|
||||
};
|
||||
|
||||
static void freent(ndptr);
|
||||
static void remhash(const char *, int);
|
||||
static unsigned hash(const char *);
|
||||
static ndptr addent(const char *);
|
||||
|
||||
unsigned int
|
||||
static unsigned int
|
||||
hash(const char *name)
|
||||
{
|
||||
unsigned int h = 0;
|
||||
@ -72,7 +82,7 @@ lookup(const char *name)
|
||||
unsigned int h;
|
||||
|
||||
h = hash(name);
|
||||
for (p = hashtab[h % HASHSIZE]; p != nil; p = p->nxtptr)
|
||||
for (p = hashtab[h % HASHSIZE]; p != NULL; p = p->nxtptr)
|
||||
if (h == p->hv && STREQ(name, p->name))
|
||||
break;
|
||||
return (p);
|
||||
@ -82,7 +92,7 @@ lookup(const char *name)
|
||||
* hash and create an entry in the hash table.
|
||||
* The new entry is added in front of a hash bucket.
|
||||
*/
|
||||
ndptr
|
||||
static ndptr
|
||||
addent(const char *name)
|
||||
{
|
||||
unsigned int h;
|
||||
@ -101,15 +111,15 @@ static void
|
||||
freent(ndptr p)
|
||||
{
|
||||
free((char *) p->name);
|
||||
if (p->defn != null)
|
||||
free((char *) p->defn);
|
||||
if (p->d.defn != null)
|
||||
free((char *) p->d.defn);
|
||||
free((char *) p);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove an entry from the hashtable
|
||||
*/
|
||||
void
|
||||
static void
|
||||
remhash(const char *name, int all)
|
||||
{
|
||||
unsigned int h;
|
||||
@ -117,11 +127,11 @@ remhash(const char *name, int all)
|
||||
|
||||
h = hash(name);
|
||||
mp = hashtab[h % HASHSIZE];
|
||||
tp = nil;
|
||||
while (mp != nil) {
|
||||
tp = NULL;
|
||||
while (mp != NULL) {
|
||||
if (mp->hv == h && STREQ(mp->name, name)) {
|
||||
mp = mp->nxtptr;
|
||||
if (tp == nil) {
|
||||
if (tp == NULL) {
|
||||
freent(hashtab[h % HASHSIZE]);
|
||||
hashtab[h % HASHSIZE] = mp;
|
||||
}
|
||||
@ -139,3 +149,113 @@ remhash(const char *name, int all)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct macro_definition *
|
||||
lookup_macro_definition(const char *name)
|
||||
{
|
||||
ndptr p;
|
||||
|
||||
p = lookup(name);
|
||||
if (p)
|
||||
return &(p->d);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_definition(struct macro_definition *d, const char *defn)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0) {
|
||||
n = builtin_type(defn+sizeof(BUILTIN_MARKER)-1);
|
||||
if (n != -1) {
|
||||
d->type = n & TYPEMASK;
|
||||
if ((n & NOARGS) == 0)
|
||||
d->type |= NEEDARGS;
|
||||
d->defn = xstrdup(defn+sizeof(BUILTIN_MARKER)-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!*defn)
|
||||
d->defn = null;
|
||||
else
|
||||
d->defn = xstrdup(defn);
|
||||
d->type = MACRTYPE;
|
||||
}
|
||||
|
||||
void
|
||||
macro_define(const char *name, const char *defn)
|
||||
{
|
||||
ndptr p;
|
||||
|
||||
if ((p = lookup(name)) == NULL)
|
||||
p = addent(name);
|
||||
else if (p->d.defn != null)
|
||||
free((char *) p->d.defn);
|
||||
setup_definition(&(p->d), defn);
|
||||
if (STREQ(name, defn))
|
||||
p->d.type |= RECDEF;
|
||||
}
|
||||
|
||||
void
|
||||
macro_pushdef(const char *name, const char *defn)
|
||||
{
|
||||
ndptr p;
|
||||
|
||||
p = addent(name);
|
||||
setup_definition(&(p->d), defn);
|
||||
if (STREQ(name, defn))
|
||||
p->d.type |= RECDEF;
|
||||
}
|
||||
|
||||
void
|
||||
macro_undefine(const char *name)
|
||||
{
|
||||
remhash(name, ALL);
|
||||
}
|
||||
|
||||
void
|
||||
macro_popdef(const char *name)
|
||||
{
|
||||
remhash(name, TOP);
|
||||
}
|
||||
|
||||
void
|
||||
macro_for_all(void (*f)(const char *, struct macro_definition *))
|
||||
{
|
||||
int n;
|
||||
ndptr p;
|
||||
|
||||
for (n = 0; n < HASHSIZE; n++)
|
||||
for (p = hashtab[n]; p != NULL; p = p->nxtptr)
|
||||
f(p->name, &(p->d));
|
||||
}
|
||||
|
||||
void
|
||||
setup_builtin(const char *name, unsigned int type)
|
||||
{
|
||||
unsigned int h;
|
||||
ndptr p;
|
||||
|
||||
h = hash(name);
|
||||
p = (ndptr) xalloc(sizeof(struct ndblock));
|
||||
p->nxtptr = hashtab[h % HASHSIZE];
|
||||
hashtab[h % HASHSIZE] = p;
|
||||
p->name = xstrdup(name);
|
||||
p->d.defn = xstrdup(name);
|
||||
p->hv = h;
|
||||
p->d.type = type;
|
||||
}
|
||||
|
||||
const char *
|
||||
macro_name(ndptr p)
|
||||
{
|
||||
return p->name;
|
||||
}
|
||||
|
||||
struct macro_definition *
|
||||
macro_getdef(ndptr p)
|
||||
{
|
||||
return &(p->d);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: main.c,v 1.58 2003/06/18 21:08:07 espie Exp $ */
|
||||
/* $OpenBSD: main.c,v 1.59 2003/06/30 21:42:50 espie Exp $ */
|
||||
/* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */
|
||||
|
||||
/*-
|
||||
@ -43,7 +43,7 @@ static char copyright[] =
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
static char rcsid[] = "$OpenBSD: main.c,v 1.58 2003/06/18 21:08:07 espie Exp $";
|
||||
static char rcsid[] = "$OpenBSD: main.c,v 1.59 2003/06/30 21:42:50 espie Exp $";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -207,7 +207,7 @@ main(int argc, char *argv[])
|
||||
addtoincludepath(optarg);
|
||||
break;
|
||||
case 'U': /* undefine... */
|
||||
remhash(optarg, TOP);
|
||||
macro_popdef(optarg);
|
||||
break;
|
||||
case 'g':
|
||||
mimic_gnu = 1;
|
||||
@ -317,24 +317,24 @@ macro(void)
|
||||
t = gpbc();
|
||||
if (t == '_' || isalpha(t)) {
|
||||
p = inspect(t, token);
|
||||
if (p != nil)
|
||||
if (p != NULL)
|
||||
putback(l = gpbc());
|
||||
if (p == nil || (l != LPAREN &&
|
||||
(p->type & NEEDARGS) != 0))
|
||||
if (p == NULL || (l != LPAREN &&
|
||||
(macro_getdef(p)->type & NEEDARGS) != 0))
|
||||
outputstr(token);
|
||||
else {
|
||||
/*
|
||||
* real thing.. First build a call frame:
|
||||
*/
|
||||
pushf(fp); /* previous call frm */
|
||||
pushf(p->type); /* type of the call */
|
||||
pushf(macro_getdef(p)->type); /* type of the call */
|
||||
pushf(0); /* parenthesis level */
|
||||
fp = sp; /* new frame pointer */
|
||||
/*
|
||||
* now push the string arguments:
|
||||
*/
|
||||
pushs1(p->defn); /* defn string */
|
||||
pushs1(p->name); /* macro name */
|
||||
pushs1(macro_getdef(p)->defn); /* defn string */
|
||||
pushs1((char *)macro_name(p)); /* macro name */
|
||||
pushs(ep); /* start next..*/
|
||||
|
||||
if (l != LPAREN && PARLEV == 0) {
|
||||
@ -528,8 +528,7 @@ reallyputchar(int c)
|
||||
|
||||
/*
|
||||
* build an input token..
|
||||
* consider only those starting with _ or A-Za-z. This is a
|
||||
* combo with lookup to speed things up.
|
||||
* consider only those starting with _ or A-Za-z.
|
||||
*/
|
||||
static ndptr
|
||||
inspect(int c, char *tp)
|
||||
@ -539,10 +538,10 @@ inspect(int c, char *tp)
|
||||
ndptr p;
|
||||
unsigned int h;
|
||||
|
||||
h = *tp++ = c;
|
||||
*tp++ = c;
|
||||
|
||||
while ((isalnum(c = gpbc()) || c == '_') && tp < etp)
|
||||
h = (h << 5) + h + (*tp++ = c);
|
||||
*tp++ = c;
|
||||
if (c != EOF)
|
||||
PUTBACK(c);
|
||||
*tp = EOS;
|
||||
@ -557,13 +556,10 @@ inspect(int c, char *tp)
|
||||
CHRSAVE(c);
|
||||
}
|
||||
*name = EOS;
|
||||
return nil;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (p = hashtab[h % HASHSIZE]; p != nil; p = p->nxtptr)
|
||||
if (h == p->hv && STREQ(name, p->name))
|
||||
break;
|
||||
return p;
|
||||
return lookup(name);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -576,21 +572,14 @@ inspect(int c, char *tp)
|
||||
static void
|
||||
initkwds(void)
|
||||
{
|
||||
size_t i;
|
||||
unsigned int h;
|
||||
ndptr p;
|
||||
unsigned int type;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXKEYS; i++) {
|
||||
h = hash(keywrds[i].knam);
|
||||
p = (ndptr) xalloc(sizeof(struct ndblock));
|
||||
p->nxtptr = hashtab[h % HASHSIZE];
|
||||
hashtab[h % HASHSIZE] = p;
|
||||
p->name = xstrdup(keywrds[i].knam);
|
||||
p->defn = xstrdup(keywrds[i].knam);
|
||||
p->hv = h;
|
||||
p->type = keywrds[i].ktyp & TYPEMASK;
|
||||
type = keywrds[i].ktyp & TYPEMASK;
|
||||
if ((keywrds[i].ktyp & NOARGS) == 0)
|
||||
p->type |= NEEDARGS;
|
||||
type |= NEEDARGS;
|
||||
setup_builtin(keywrds[i].knam, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: mdef.h,v 1.24 2003/06/12 14:36:43 espie Exp $ */
|
||||
/* $OpenBSD: mdef.h,v 1.25 2003/06/30 21:42:50 espie Exp $ */
|
||||
/* $NetBSD: mdef.h,v 1.7 1996/01/13 23:25:27 pk Exp $ */
|
||||
|
||||
/*
|
||||
@ -85,6 +85,7 @@
|
||||
#define TRACEONTYPE 42
|
||||
#define TRACEOFFTYPE 43
|
||||
|
||||
#define BUILTIN_MARKER "__builtin_"
|
||||
|
||||
#define TYPEMASK 63 /* Keep bits really corresponding to a type. */
|
||||
#define RECDEF 256 /* Pure recursive def, don't expand it */
|
||||
@ -135,16 +136,11 @@
|
||||
|
||||
typedef struct ndblock *ndptr;
|
||||
|
||||
struct ndblock { /* hastable structure */
|
||||
char *name; /* entry name.. */
|
||||
struct macro_definition {
|
||||
char *defn; /* definition.. */
|
||||
unsigned int type; /* type of the entry.. */
|
||||
unsigned int hv; /* hash function value.. */
|
||||
ndptr nxtptr; /* link to next entry.. */
|
||||
};
|
||||
|
||||
#define nil ((ndptr) 0)
|
||||
|
||||
|
||||
struct keyblk {
|
||||
char *knam; /* keyword name */
|
||||
int ktyp; /* keyword type */
|
||||
|
Loading…
Reference in New Issue
Block a user