diff --git a/mkstructinfo.awk b/mkstructinfo.awk index 423d216..2e460a8 100755 --- a/mkstructinfo.awk +++ b/mkstructinfo.awk @@ -49,10 +49,10 @@ incomment { sizeinfo = sizeinfo "sizeof(((" instruct "*)NULL)->" buffer[i] ")"; if (i == 0) { - elms = buffer[i]; + elms = "\"" buffer[i] "\""; } else { - elms = elms "," buffer[i]; + elms = elms "," "\"" buffer[i] "\""; } } printf "define(`ELEMENTSOF_%s', `%s')\n", instruct, elms; diff --git a/processor/head.m4 b/processor/head.m4 index 78e8967..99500c3 100644 --- a/processor/head.m4 +++ b/processor/head.m4 @@ -305,6 +305,49 @@ static void xc_zend_extension_op_array_ctor_handler(zend_extension *extension, z } } /* }}} */ +/* {{{ field name checker */ +IFASSERT(`dnl +int xc_check_names(const char *file, int line, const char *functionName, const char **assert_names, int assert_names_count, HashTable *done_names) +{ + int errors = 0; + if (assert_names_count) { + int i; + Bucket *b; + + for (i = 0; i < assert_names_count; ++i) { + if (!zend_hash_exists(done_names, assert_names[i], strlen(assert_names[i]) + 1)) { + fprintf(stderr + , "missing field at %s `#'%d %s`' : %s\n" + , file, line, functionName + , assert_names[i] + ); + ++errors; + } + } + + for (b = done_names->pListHead; b != NULL; b = b->pListNext) { + int known = 0; + int i; + for (i = 0; i < assert_names_count; ++i) { + if (strcmp(assert_names[i], BUCKET_KEY_S(b)) == 0) { + known = 1; + break; + } + } + if (!known) { + fprintf(stderr + , "unknown field at %s `#'%d %s`' : %s\n" + , file, line, functionName + , BUCKET_KEY_S(b) + ); + ++errors; + } + } + } + return errors; +} +') +/* }}} */ dnl ================ export API define(`DEFINE_STORE_API', ` /* export: $1 *xc_processor_store_$1($1 *src TSRMLS_DC); :export {{{ */ diff --git a/processor/main.m4 b/processor/main.m4 index bd1e5bd..9edb6a6 100644 --- a/processor/main.m4 +++ b/processor/main.m4 @@ -205,12 +205,25 @@ foreach(`i', `($1)', `popdef(`item_'defn(`i'))')dnl ') dnl }}} dnl {{{ DONE_* -define(`DONE_SIZE', `IFASSERT(` +define(`DONE_SIZE', `IFASSERT(`dnl done_size += $1`'; done_count ++; ')') define(`DONE', ` - define(`ELEMENTS_DONE', defn(`ELEMENTS_DONE')`,$1') + define(`ELEMENTS_DONE', defn(`ELEMENTS_DONE')`,"$1"') + IFASSERT(`dnl + if (zend_hash_exists(&done_names, "$1", sizeof("$1"))) { + fprintf(stderr + , "duplicate field at %s `#'%d FUNC_NAME`' : %s\n" + , __FILE__, __LINE__ + , "$1" + ); + } + else { + zend_uchar b = 1; + zend_hash_add(&done_names, "$1", sizeof("$1"), (void*)&b, sizeof(b), NULL); + } + ') DONE_SIZE(`sizeof(src->$1)') ') define(`DISABLECHECK', ` diff --git a/processor/struct.m4 b/processor/struct.m4 index c50705a..f606134 100644 --- a/processor/struct.m4 +++ b/processor/struct.m4 @@ -29,11 +29,10 @@ define(`DEF_STRUCT_P_FUNC', ` DECL_STRUCT_P_FUNC(`$1', `$2', 1) { pushdef(`ELEMENTS_DONE') - ifdef(`SIZEOF_$1', , `m4_errprint(`AUTOCHECK WARN: $1: missing structinfo, dont panic')define(`SIZEOF_$1', 0)') IFASSERT(` /* {{{ init assert */ - ifdef(`SIZEOF_$1', , `m4_errprint(`missing SIZEOF_$1, safe to ignore')define(`SIZEOF_$1', 0)') - ifdef(`COUNTOF_$1', , `m4_errprint(`missing COUNTOF_$1, safe to ignore')define(`COUNTOF_$1', 0)') + ifdef(`SIZEOF_$1', , `m4_errprint(`missing SIZEOF_$1, safe to ignore')') + ifdef(`COUNTOF_$1', , `m4_errprint(`missing COUNTOF_$1, safe to ignore'))') dnl SIZEOF_x COUNTOF_x can be both defined or both not ifdef(`SIZEOF_$1', ` ifdef(`COUNTOF_$1', , `m4_errprint(`AUTOCHECK WARN: missing COUNTOF_$1')') @@ -47,11 +46,15 @@ DECL_STRUCT_P_FUNC(`$1', `$2', 1) ') int assert_size = SIZEOF_$1, assert_count = COUNTOF_$1; int done_size = 0, done_count = 0; + const char *assert_names[] = { ifdef(`ELEMENTSOF_$1', `ELEMENTSOF_$1') }; + HashTable done_names; + zend_hash_init(&done_names, 0, NULL, NULL, 0); /* }}} */ IFRESTORE(`assert(xc_is_shm(src));') IFCALCSTORE(`assert(!xc_is_shm(src));') do { ') + ifdef(`SIZEOF_$1', , `m4_errprint(`AUTOCHECK WARN: $1: missing structinfo, dont panic')') ifdef(`USEMEMCPY', `IFCOPY(` memcpy(dst, src, sizeof($1)); @@ -67,9 +70,17 @@ DECL_STRUCT_P_FUNC(`$1', `$2', 1) indent --; INDENT()fprintf(stderr, "}\n"); ') - ifdef(`SKIPASSERT_ONCE', `undefine(`SKIPASSERT_ONCE')', ` + ifdef(`SKIPASSERT_ONCE', ` + undefine(`SKIPASSERT_ONCE') IFASSERT(` - /* {{{ check assert */ + zend_hash_destroy(&done_names); + ') + ', ` + IFASSERT(` + /* {{{ check assert */ do { + int name_check_errors = xc_check_names(__FILE__, __LINE__, "FUNC_NAME", assert_names, sizeof(assert_names) / sizeof(assert_names[0]), &done_names); + zend_hash_destroy(&done_names); + if (done_count != assert_count) { fprintf(stderr , "count assertion failed at %s `#'%d FUNC_NAME`' : unexpected:%d - expecting:%d = %d != 0\n" @@ -84,10 +95,10 @@ DECL_STRUCT_P_FUNC(`$1', `$2', 1) , done_size, assert_size, done_size - assert_size ); } - if (done_count != assert_count || done_size != assert_size) { + if (name_check_errors || done_count != assert_count || done_size != assert_size) { assert(0); } - /* }}} */ + } while (0); /* }}} */ ') ifdef(`ELEMENTSOF_$1', ` pushdef(`ELEMENTS_UNDONE', LIST_DIFF(defn(`ELEMENTSOF_$1'), defn(`ELEMENTS_DONE')))