Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/config Strengthen the logic that wraps allocations g...
details: https://anonhg.NetBSD.org/src/rev/7775d72a510a
branches: trunk
changeset: 777971:7775d72a510a
user: dholland <dholland%NetBSD.org@localhost>
date: Sun Mar 11 07:27:02 2012 +0000
description:
Strengthen the logic that wraps allocations going on the parser stack.
(This allows cleaning up when a syntax error occurs, because yacc just
dumps the parser stack on the floor.)
The new logic can handle arbitrary data types instead of being limited
to struct nvlist.
diffstat:
usr.bin/config/gram.y | 128 ++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 110 insertions(+), 18 deletions(-)
diffs (178 lines):
diff -r 9593092428d2 -r 7775d72a510a usr.bin/config/gram.y
--- a/usr.bin/config/gram.y Sun Mar 11 06:53:18 2012 +0000
+++ b/usr.bin/config/gram.y Sun Mar 11 07:27:02 2012 +0000
@@ -1,5 +1,5 @@
%{
-/* $NetBSD: gram.y,v 1.30 2012/03/11 02:56:25 dholland Exp $ */
+/* $NetBSD: gram.y,v 1.31 2012/03/11 07:27:02 dholland Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -58,10 +58,31 @@
static struct config conf; /* at most one active at a time */
-/* the following is used to recover nvlist space after errors */
-static struct nvlist *alloc[1000];
-static int adepth;
-#define new0(n,s,p,i,x) (alloc[adepth++] = newnv(n, s, p, i, x))
+
+/*
+ * Allocation wrapper functions
+ */
+static void wrap_alloc(void *ptr, unsigned code);
+static void wrap_continue(void);
+static void wrap_cleanup(void);
+
+/*
+ * Allocation wrapper type codes
+ */
+#define WRAP_CODE_nvlist 1
+
+/*
+ * The allocation wrappers themselves
+ */
+#define DECL_ALLOCWRAP(t) static struct t *wrap_mk_##t(struct t *arg)
+
+DECL_ALLOCWRAP(nvlist);
+
+/*
+ * Macros for allocating new objects
+ */
+
+#define new0(n,s,p,i,x) wrap_mk_nvlist(newnv(n, s, p, i, x))
#define new_n(n) new0(n, NULL, NULL, 0, NULL)
#define new_nx(n, x) new0(n, NULL, NULL, 0, x)
#define new_ns(n, s) new0(n, s, NULL, 0, NULL)
@@ -80,7 +101,10 @@
#define fx_and(e1, e2) new0(NULL, NULL, e1, FX_AND, e2)
#define fx_or(e1, e2) new0(NULL, NULL, e1, FX_OR, e2)
-static void cleanup(void);
+/*
+ * Other private functions
+ */
+
static void setmachine(const char *, const char *, struct nvlist *, int);
static void check_maxpart(void);
@@ -238,8 +262,8 @@
definitions:
/* empty */
| definitions '\n'
- | definitions definition '\n' { adepth = 0; }
- | definitions error '\n' { cleanup(); }
+ | definitions definition '\n' { wrap_continue(); }
+ | definitions error '\n' { wrap_cleanup(); }
| definitions ENDFILE { enddefs(); checkfiles(); }
;
@@ -557,8 +581,8 @@
config_items:
/* empty */
| config_items '\n'
- | config_items config_item '\n' { adepth = 0; }
- | config_items error '\n' { cleanup(); }
+ | config_items config_item '\n' { wrap_continue(); }
+ | config_items error '\n' { wrap_cleanup(); }
;
/* One config item. */
@@ -855,21 +879,89 @@
cfgerror("%s", s);
}
+/************************************************************/
+
/*
- * Cleanup procedure after syntax error: release any nvlists
- * allocated during parsing the current line.
+ * Wrap allocations that live on the parser stack so that we can free
+ * them again on error instead of leaking.
+ */
+
+#define MAX_WRAP 1000
+
+struct wrap_entry {
+ void *ptr;
+ unsigned typecode;
+};
+
+static struct wrap_entry wrapstack[MAX_WRAP];
+static unsigned wrap_depth;
+
+/*
+ * Remember pointer PTR with type-code CODE.
+ */
+static void
+wrap_alloc(void *ptr, unsigned code)
+{
+ unsigned pos;
+
+ if (wrap_depth >= MAX_WRAP) {
+ panic("allocation wrapper stack overflow");
+ }
+ pos = wrap_depth++;
+ wrapstack[pos].ptr = ptr;
+ wrapstack[pos].typecode = code;
+}
+
+/*
+ * We succeeded; commit to keeping everything that's been allocated so
+ * far and clear the stack.
*/
static void
-cleanup(void)
+wrap_continue(void)
{
- struct nvlist **np;
- int i;
+ wrap_depth = 0;
+}
+
+/*
+ * We failed; destroy all the objects allocated.
+ */
+static void
+wrap_cleanup(void)
+{
+ unsigned i;
- for (np = alloc, i = adepth; --i >= 0; np++)
- nvfree(*np);
- adepth = 0;
+ for (i=0; i<wrap_depth; i++) {
+ switch (wrapstack[i].typecode) {
+ case WRAP_CODE_nvlist:
+ nvfree(wrapstack[i].ptr);
+ break;
+ default:
+ panic("invalid code %u on allocation wrapper stack",
+ wrapstack[i].typecode);
+ }
+ }
+ wrap_depth = 0;
}
+/*
+ * Instantiate the wrapper functions.
+ *
+ * Each one calls wrap_alloc to save the pointer and then returns the
+ * pointer again; these need to be generated with the preprocessor in
+ * order to be typesafe.
+ */
+#define DEF_ALLOCWRAP(t) \
+ static struct t * \
+ wrap_mk_##t(struct t *arg) \
+ { \
+ wrap_alloc(arg, WRAP_CODE_##t); \
+ return arg; \
+ }
+
+DEF_ALLOCWRAP(nvlist);
+
+/************************************************************/
+
static void
setmachine(const char *mch, const char *mcharch, struct nvlist *mchsubarches,
int isioconf)
Home |
Main Index |
Thread Index |
Old Index