Module Name: src
Committed By: rillig
Date: Mon Aug 24 20:15:51 UTC 2020
Modified Files:
src/usr.bin/make: enum.c enum.h make.c make.h targ.c var.c
Log Message:
make(1): in debug mode, print GNode details in symbols
A string like OP_DEPENDS|OP_OPTIONAL|OP_PRECIOUS is much easier to read
and understand than the bit pattern 00000089.
The implementation in enum.h looks really bloated and ugly, but using
this API is as simple and natural as possible. That's the trade-off.
In enum.h, I thought about choosing the numbers in the macros such that
it is always possible to combine two of them in order to reach an
arbitrary number, because of the "part1, part2" in the ENUM__SPEC macro.
The powers of 2 are not these numbers, as 7 cannot be expressed as the
sum of two of them. Neither are the fibonacci numbers since 12 cannot
be expressed as the sum of 2 fibonacci numbers. I tried to find a
general pattern to generate these minimal 2-sum numbers, but failed.
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/usr.bin/make/enum.c
cvs rdiff -u -r1.6 -r1.7 src/usr.bin/make/enum.h
cvs rdiff -u -r1.121 -r1.122 src/usr.bin/make/make.c
cvs rdiff -u -r1.125 -r1.126 src/usr.bin/make/make.h
cvs rdiff -u -r1.71 -r1.72 src/usr.bin/make/targ.c
cvs rdiff -u -r1.469 -r1.470 src/usr.bin/make/var.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/make/enum.c
diff -u src/usr.bin/make/enum.c:1.3 src/usr.bin/make/enum.c:1.4
--- src/usr.bin/make/enum.c:1.3 Sun Aug 9 09:44:14 2020
+++ src/usr.bin/make/enum.c Mon Aug 24 20:15:51 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: enum.c,v 1.3 2020/08/09 09:44:14 rillig Exp $ */
+/* $NetBSD: enum.c,v 1.4 2020/08/24 20:15:51 rillig Exp $ */
/*
Copyright (c) 2020 Roland Illig <[email protected]>
@@ -28,11 +28,11 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: enum.c,v 1.3 2020/08/09 09:44:14 rillig Exp $";
+static char rcsid[] = "$NetBSD: enum.c,v 1.4 2020/08/24 20:15:51 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: enum.c,v 1.3 2020/08/09 09:44:14 rillig Exp $");
+__RCSID("$NetBSD: enum.c,v 1.4 2020/08/24 20:15:51 rillig Exp $");
#endif
#endif
@@ -44,8 +44,8 @@ __RCSID("$NetBSD: enum.c,v 1.3 2020/08/0
/* Convert a bitset into a string representation showing the names of the
* individual bits, or optionally shortcuts for groups of bits. */
const char *
-Enum_ToString(char *buf, size_t buf_size, int value,
- const EnumToStringSpec *spec)
+Enum_FlagsToString(char *buf, size_t buf_size,
+ int value, const EnumToStringSpec *spec)
{
const char *buf_start = buf;
const char *sep = "";
@@ -81,3 +81,14 @@ Enum_ToString(char *buf, size_t buf_size
buf[0] = '\0';
return buf_start;
}
+
+/* Convert a fixed-value enum into a string representation. */
+const char *
+Enum_ValueToString(int value, const EnumToStringSpec *spec)
+{
+ for (; spec->es_name[0] != '\0'; spec++) {
+ if (value == spec->es_value)
+ return spec->es_name;
+ }
+ assert(!"unknown enum value");
+}
Index: src/usr.bin/make/enum.h
diff -u src/usr.bin/make/enum.h:1.6 src/usr.bin/make/enum.h:1.7
--- src/usr.bin/make/enum.h:1.6 Sun Aug 23 09:28:52 2020
+++ src/usr.bin/make/enum.h Mon Aug 24 20:15:51 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: enum.h,v 1.6 2020/08/23 09:28:52 rillig Exp $ */
+/* $NetBSD: enum.h,v 1.7 2020/08/24 20:15:51 rillig Exp $ */
/*
Copyright (c) 2020 Roland Illig <[email protected]>
@@ -41,58 +41,95 @@ typedef struct {
const char *es_name;
} EnumToStringSpec;
-const char *Enum_ToString(char *, size_t, int, const EnumToStringSpec *);
+const char *Enum_FlagsToString(char *, size_t, int, const EnumToStringSpec *);
+const char *Enum_ValueToString(int, const EnumToStringSpec *);
#define ENUM__SEP "|"
#define ENUM__JOIN_1(v1) \
#v1
#define ENUM__JOIN_2(v1, v2) \
- #v1 ENUM__SEP ENUM__JOIN_1(v2)
-#define ENUM__JOIN_3(v1, v2, v3) \
- #v1 ENUM__SEP ENUM__JOIN_2(v2, v3)
+ #v1 ENUM__SEP #v2
#define ENUM__JOIN_4(v1, v2, v3, v4) \
- #v1 ENUM__SEP ENUM__JOIN_3(v2, v3, v4)
-#define ENUM__JOIN_5(v1, v2, v3, v4, v5) \
- #v1 ENUM__SEP ENUM__JOIN_4(v2, v3, v4, v5)
-#define ENUM__JOIN_6(v1, v2, v3, v4, v5, v6) \
- #v1 ENUM__SEP ENUM__JOIN_5(v2, v3, v4, v5, v6)
-#define ENUM__JOIN_7(v1, v2, v3, v4, v5, v6, v7) \
- #v1 ENUM__SEP ENUM__JOIN_6(v2, v3, v4, v5, v6, v7)
+ ENUM__JOIN_2(v1, v2) ENUM__SEP ENUM__JOIN_2(v3, v4)
#define ENUM__JOIN_8(v1, v2, v3, v4, v5, v6, v7, v8) \
- #v1 ENUM__SEP ENUM__JOIN_7(v2, v3, v4, v5, v6, v7, v8)
+ ENUM__JOIN_4(v1, v2, v3, v4) ENUM__SEP ENUM__JOIN_4(v5, v6, v7, v8)
+#define ENUM__JOIN_16(v01, v02, v03, v04, v05, v06, v07, v08, \
+ v09, v10, v11, v12, v13, v14, v15, v16) \
+ ENUM__JOIN_8(v01, v02, v03, v04, v05, v06, v07, v08) ENUM__SEP \
+ ENUM__JOIN_8(v09, v10, v11, v12, v13, v14, v15, v16)
+#define ENUM__JOIN_32(v01, v02, v03, v04, v05, v06, v07, v08, \
+ v09, v10, v11, v12, v13, v14, v15, v16, \
+ v17, v18, v19, v20, v21, v22, v23, v24, \
+ v25, v26, v27, v28, v29, v30, v31, v32) \
+ ENUM__JOIN_16(v01, v02, v03, v04, v05, v06, v07, v08, \
+ v09, v10, v11, v12, v13, v14, v15, v16) ENUM__SEP \
+ ENUM__JOIN_16(v17, v18, v19, v20, v21, v22, v23, v24, \
+ v25, v26, v27, v28, v29, v30, v31, v32)
+#define ENUM__JOIN(part1, part2) \
+ part1 ENUM__SEP part2
#define ENUM__RTTI(typnam, specs, joined) \
static const EnumToStringSpec typnam ## _ ## ToStringSpecs[] = specs; \
enum { typnam ## _ ## ToStringSize = sizeof joined }
-#define ENUM__SPEC(v) { v, #v }
-
-#define ENUM__SPEC_3(v1, v2, v3) { \
- ENUM__SPEC(v1), \
- ENUM__SPEC(v2), \
- ENUM__SPEC(v3), \
- { 0, "" } }
-
-#define ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8) { \
- ENUM__SPEC(v1), \
- ENUM__SPEC(v2), \
- ENUM__SPEC(v3), \
- ENUM__SPEC(v4), \
- ENUM__SPEC(v5), \
- ENUM__SPEC(v6), \
- ENUM__SPEC(v7), \
- ENUM__SPEC(v8), \
- { 0, "" } }
+#define ENUM__SPEC_1(v1) { v1, #v1 }
+#define ENUM__SPEC_2(v1, v2) \
+ ENUM__SPEC_1(v1), \
+ ENUM__SPEC_1(v2)
+#define ENUM__SPEC_4(v1, v2, v3, v4) \
+ ENUM__SPEC_2(v1, v2), \
+ ENUM__SPEC_2(v3, v4)
+#define ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8) \
+ ENUM__SPEC_4(v1, v2, v3, v4), \
+ ENUM__SPEC_4(v5, v6, v7, v8)
+#define ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
+ v09, v10, v11, v12, v13, v14, v15, v16) \
+ ENUM__SPEC_8(v01, v02, v03, v04, v05, v06, v07, v08), \
+ ENUM__SPEC_8(v09, v10, v11, v12, v13, v14, v15, v16)
+#define ENUM__SPEC(part1, part2) \
+ { part1, part2, { 0, "" } }
#define ENUM_RTTI_3(typnam, v1, v2, v3) \
ENUM__RTTI(typnam, \
- ENUM__SPEC_3(v1, v2, v3), \
- ENUM__JOIN_3(v1, v2, v3))
+ ENUM__SPEC(ENUM__SPEC_2(v1, v2), ENUM__SPEC_1(v3)), \
+ ENUM__JOIN_2(ENUM__JOIN_2(v1, v2), ENUM__JOIN_1(v3)))
#define ENUM_RTTI_8(typnam, v1, v2, v3, v4, v5, v6, v7, v8) \
ENUM__RTTI(typnam, \
- ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8), \
- ENUM__JOIN_8(v1, v2, v3, v4, v5, v6, v7, v8))
+ ENUM__SPEC( \
+ ENUM__SPEC_4(v1, v2, v3, v4), \
+ ENUM__SPEC_4(v5, v6, v7, v8)), \
+ ENUM__JOIN( \
+ ENUM__JOIN_4(v1, v2, v3, v4), \
+ ENUM__JOIN_4(v5, v6, v7, v8)))
+
+#define ENUM_RTTI_10(typnam, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) \
+ ENUM__RTTI(typnam, \
+ ENUM__SPEC( \
+ ENUM__SPEC_8(v1, v2, v3, v4, v5, v6, v7, v8), \
+ ENUM__SPEC_2(v9, v10)), \
+ ENUM__JOIN( \
+ ENUM__JOIN_8(v1, v2, v3, v4, v5, v6, v7, v8), \
+ ENUM__JOIN_2(v9, v10)))
+
+#define ENUM_RTTI_32( \
+ typnam, \
+ v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, \
+ v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, \
+ v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, \
+ v31, v32) \
+ ENUM__RTTI( \
+ typnam, \
+ ENUM__SPEC( \
+ ENUM__SPEC_16(v01, v02, v03, v04, v05, v06, v07, v08, \
+ v09, v10, v11, v12, v13, v14, v15, v16), \
+ ENUM__SPEC_16(v17, v18, v19, v20, v21, v22, v23, v24, \
+ v25, v26, v27, v28, v29, v30, v31, v32)), \
+ ENUM__JOIN_32( \
+ v01, v02, v03, v04, v05, v06, v07, v08, \
+ v09, v10, v11, v12, v13, v14, v15, v16, \
+ v17, v18, v19, v20, v21, v22, v23, v24, \
+ v25, v26, v27, v28, v29, v30, v31, v32))
#endif
Index: src/usr.bin/make/make.c
diff -u src/usr.bin/make/make.c:1.121 src/usr.bin/make/make.c:1.122
--- src/usr.bin/make/make.c:1.121 Sat Aug 22 22:57:53 2020
+++ src/usr.bin/make/make.c Mon Aug 24 20:15:51 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: make.c,v 1.121 2020/08/22 22:57:53 rillig Exp $ */
+/* $NetBSD: make.c,v 1.122 2020/08/24 20:15:51 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: make.c,v 1.121 2020/08/22 22:57:53 rillig Exp $";
+static char rcsid[] = "$NetBSD: make.c,v 1.122 2020/08/24 20:15:51 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)make.c 8.1 (Berkeley) 6/6/93";
#else
-__RCSID("$NetBSD: make.c,v 1.121 2020/08/22 22:57:53 rillig Exp $");
+__RCSID("$NetBSD: make.c,v 1.122 2020/08/24 20:15:51 rillig Exp $");
#endif
#endif /* not lint */
#endif
@@ -116,7 +116,7 @@ __RCSID("$NetBSD: make.c,v 1.121 2020/08
*/
#include "make.h"
-#include "hash.h"
+#include "enum.h"
#include "dir.h"
#include "job.h"
@@ -151,6 +151,42 @@ make_abort(GNode *gn, int line)
abort();
}
+ENUM_RTTI_8(GNodeMade,
+ UNMADE, DEFERRED, REQUESTED, BEINGMADE,
+ MADE, UPTODATE, ERROR, ABORTED);
+
+ENUM_RTTI_32(GNodeType,
+ OP_DEPENDS, OP_FORCE, OP_DOUBLEDEP, OP_OPMASK,
+ OP_OPTIONAL, OP_USE, OP_EXEC, OP_IGNORE,
+ OP_PRECIOUS, OP_SILENT, OP_MAKE, OP_JOIN,
+ OP_MADE, OP_SPECIAL, OP_USEBEFORE, OP_INVISIBLE,
+ OP_NOTMAIN, OP_PHONY, OP_NOPATH, OP_WAIT,
+ OP_NOMETA, OP_META, OP_NOMETA_CMP, OP_SUBMAKE,
+ OP_TRANSFORM, OP_MEMBER, OP_LIB, OP_ARCHV,
+ OP_HAS_COMMANDS, OP_SAVE_CMDS, OP_DEPS_FOUND, OP_MARK);
+
+ENUM_RTTI_10(GNodeFlags,
+ REMAKE, CHILDMADE, FORCE, DONE_WAIT,
+ DONE_ORDER, FROM_DEPEND, DONE_ALLSRC, CYCLE,
+ DONECYCLE, INTERNAL);
+
+void
+GNode_FprintDetails(FILE *f, const char *prefix, const GNode *gn,
+ const char *suffix)
+{
+ char type_buf[GNodeType_ToStringSize];
+ char flags_buf[GNodeFlags_ToStringSize];
+
+ fprintf(f, "%smade %s, type %s, flags %s%s",
+ prefix,
+ Enum_ValueToString(gn->made, GNodeMade_ToStringSpecs),
+ Enum_FlagsToString(type_buf, sizeof type_buf,
+ gn->type, GNodeType_ToStringSpecs),
+ Enum_FlagsToString(flags_buf, sizeof flags_buf,
+ gn->flags, GNodeFlags_ToStringSpecs),
+ suffix);
+}
+
/*-
*-----------------------------------------------------------------------
* Make_TimeStamp --
@@ -1156,15 +1192,15 @@ MakePrintStatusOrder(void *ognp, void *g
/* not waiting for this one */
return 0;
- printf(" `%s%s' has .ORDER dependency against %s%s "
- "(made %d, flags %x, type %x)\n",
- gn->name, gn->cohort_num,
- ogn->name, ogn->cohort_num, ogn->made, ogn->flags, ogn->type);
- if (DEBUG(MAKE) && debug_file != stdout)
- fprintf(debug_file, " `%s%s' has .ORDER dependency against %s%s "
- "(made %d, flags %x, type %x)\n",
- gn->name, gn->cohort_num,
- ogn->name, ogn->cohort_num, ogn->made, ogn->flags, ogn->type);
+ printf(" `%s%s' has .ORDER dependency against %s%s ",
+ gn->name, gn->cohort_num, ogn->name, ogn->cohort_num);
+ GNode_FprintDetails(stdout, "(", ogn, ")\n");
+
+ if (DEBUG(MAKE) && debug_file != stdout) {
+ fprintf(debug_file, " `%s%s' has .ORDER dependency against %s%s ",
+ gn->name, gn->cohort_num, ogn->name, ogn->cohort_num);
+ GNode_FprintDetails(debug_file, "(", ogn, ")\n");
+ }
return 0;
}
@@ -1191,12 +1227,13 @@ MakePrintStatus(void *gnp, void *v_error
case REQUESTED:
case BEINGMADE:
(*errors)++;
- printf("`%s%s' was not built (made %d, flags %x, type %x)!\n",
- gn->name, gn->cohort_num, gn->made, gn->flags, gn->type);
- if (DEBUG(MAKE) && debug_file != stdout)
- fprintf(debug_file,
- "`%s%s' was not built (made %d, flags %x, type %x)!\n",
- gn->name, gn->cohort_num, gn->made, gn->flags, gn->type);
+ printf("`%s%s' was not built", gn->name, gn->cohort_num);
+ GNode_FprintDetails(stdout, " (", gn, ")!\n");
+ if (DEBUG(MAKE) && debug_file != stdout) {
+ fprintf(debug_file, "`%s%s' was not built",
+ gn->name, gn->cohort_num);
+ GNode_FprintDetails(debug_file, " (", gn, ")!\n");
+ }
/* Most likely problem is actually caused by .ORDER */
Lst_ForEach(gn->order_pred, MakePrintStatusOrder, gn);
break;
Index: src/usr.bin/make/make.h
diff -u src/usr.bin/make/make.h:1.125 src/usr.bin/make/make.h:1.126
--- src/usr.bin/make/make.h:1.125 Sun Aug 23 17:04:21 2020
+++ src/usr.bin/make/make.h Mon Aug 24 20:15:51 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: make.h,v 1.125 2020/08/23 17:04:21 rillig Exp $ */
+/* $NetBSD: make.h,v 1.126 2020/08/24 20:15:51 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -513,6 +513,7 @@ int mkTempFile(const char *, char **);
int str2Lst_Append(Lst, char *, const char *);
int cached_lstat(const char *, void *);
int cached_stat(const char *, void *);
+void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *);
#ifdef __GNUC__
#define UNCONST(ptr) ({ \
Index: src/usr.bin/make/targ.c
diff -u src/usr.bin/make/targ.c:1.71 src/usr.bin/make/targ.c:1.72
--- src/usr.bin/make/targ.c:1.71 Sat Aug 22 18:20:31 2020
+++ src/usr.bin/make/targ.c Mon Aug 24 20:15:51 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: targ.c,v 1.71 2020/08/22 18:20:31 rillig Exp $ */
+/* $NetBSD: targ.c,v 1.72 2020/08/24 20:15:51 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: targ.c,v 1.71 2020/08/22 18:20:31 rillig Exp $";
+static char rcsid[] = "$NetBSD: targ.c,v 1.72 2020/08/24 20:15:51 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)targ.c 8.2 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: targ.c,v 1.71 2020/08/22 18:20:31 rillig Exp $");
+__RCSID("$NetBSD: targ.c,v 1.72 2020/08/24 20:15:51 rillig Exp $");
#endif
#endif /* not lint */
#endif
@@ -632,8 +632,8 @@ Targ_PrintNode(void *gnp, void *passp)
GNode *gn = (GNode *)gnp;
int pass = passp ? *(int *)passp : 0;
- fprintf(debug_file, "# %s%s, flags %x, type %x, made %d\n",
- gn->name, gn->cohort_num, gn->flags, gn->type, gn->made);
+ fprintf(debug_file, "# %s%s", gn->name, gn->cohort_num);
+ GNode_FprintDetails(debug_file, ", ", gn, "\n");
if (gn->flags == 0)
return 0;
Index: src/usr.bin/make/var.c
diff -u src/usr.bin/make/var.c:1.469 src/usr.bin/make/var.c:1.470
--- src/usr.bin/make/var.c:1.469 Sun Aug 23 22:49:45 2020
+++ src/usr.bin/make/var.c Mon Aug 24 20:15:51 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.469 2020/08/23 22:49:45 rillig Exp $ */
+/* $NetBSD: var.c,v 1.470 2020/08/24 20:15:51 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: var.c,v 1.469 2020/08/23 22:49:45 rillig Exp $";
+static char rcsid[] = "$NetBSD: var.c,v 1.470 2020/08/24 20:15:51 rillig Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: var.c,v 1.469 2020/08/23 22:49:45 rillig Exp $");
+__RCSID("$NetBSD: var.c,v 1.470 2020/08/24 20:15:51 rillig Exp $");
#endif
#endif /* not lint */
#endif
@@ -3130,10 +3130,10 @@ ApplyModifiers(
VAR_DEBUG("Applying ${%s:%c%s} to \"%s\" "
"(eflags = %s, vflags = %s)\n",
st.v->name, mod[0], is_single_char ? "" : "...", st.val,
- Enum_ToString(eflags_str, sizeof eflags_str, st.eflags,
- VarEvalFlags_ToStringSpecs),
- Enum_ToString(vflags_str, sizeof vflags_str, st.v->flags,
- VarFlags_ToStringSpecs));
+ Enum_FlagsToString(eflags_str, sizeof eflags_str,
+ st.eflags, VarEvalFlags_ToStringSpecs),
+ Enum_FlagsToString(vflags_str, sizeof vflags_str,
+ st.v->flags, VarFlags_ToStringSpecs));
}
switch (*mod) {
@@ -3275,10 +3275,10 @@ ApplyModifiers(
VAR_DEBUG("Result of ${%s:%.*s} is %s%s%s "
"(eflags = %s, vflags = %s)\n",
st.v->name, (int)(p - mod), mod, quot, newVal, quot,
- Enum_ToString(eflags_str, sizeof eflags_str, st.eflags,
- VarEvalFlags_ToStringSpecs),
- Enum_ToString(vflags_str, sizeof vflags_str, st.v->flags,
- VarFlags_ToStringSpecs));
+ Enum_FlagsToString(eflags_str, sizeof eflags_str,
+ st.eflags, VarEvalFlags_ToStringSpecs),
+ Enum_FlagsToString(vflags_str, sizeof vflags_str,
+ st.v->flags, VarFlags_ToStringSpecs));
}
if (st.newVal != st.val) {
@@ -3410,8 +3410,8 @@ Var_Parse(const char * const str, GNode
char eflags_str[VarEvalFlags_ToStringSize];
VAR_DEBUG("%s: %s with %s\n", __func__, str,
- Enum_ToString(eflags_str, sizeof eflags_str, eflags,
- VarEvalFlags_ToStringSpecs));
+ Enum_FlagsToString(eflags_str, sizeof eflags_str, eflags,
+ VarEvalFlags_ToStringSpecs));
*freePtr = NULL;
extramodifiers = NULL; /* extra modifiers to apply first */