Index: generic/schema.c ================================================================== --- generic/schema.c +++ generic/schema.c @@ -496,10 +496,11 @@ sdata->cdata = TMALLOC (Tcl_DString); Tcl_DStringInit (sdata->cdata); Tcl_InitHashTable (&sdata->ids, TCL_STRING_KEYS); sdata->unknownIDrefs = 0; Tcl_InitHashTable (&sdata->idTables, TCL_STRING_KEYS); + Tcl_InitHashTable (&sdata->keySpaces, TCL_STRING_KEYS); return sdata; } static void schemaInstanceDelete ( ClientData clientData @@ -509,10 +510,11 @@ unsigned int i; SchemaValidationStack *down; Tcl_HashEntry *h; Tcl_HashSearch search; SchemaDocKey *dk; + SchemaKeySpace *ks; /* Protect the clientData to be freed inside (even nested) * Tcl_Eval*() calls to avoid invalid mem access and postpone the * cleanup until the Tcl_Eval*() calls are finished (done in * schemaInstanceCmd(). */ @@ -574,10 +576,19 @@ dk = Tcl_GetHashValue (h); Tcl_DeleteHashTable (&dk->ids); FREE (dk); } Tcl_DeleteHashTable (&sdata->idTables); + for (h = Tcl_FirstHashEntry (&sdata->keySpaces, &search); + h != NULL; + h = Tcl_NextHashEntry (&search)) { + ks = Tcl_GetHashValue (h); + if (ks->active) { + Tcl_DeleteHashTable (&dk->ids); + } + FREE (ks); + } FREE (sdata); } static void cleanupLastPattern ( @@ -964,17 +975,31 @@ if (rc == 1) { updateStack (se, cp, ac); return 1; } popStack (sdata); - break; + case SCHEMA_CTYPE_KEYSPACE_END: - + candidate->keySpace->active--; + if (!candidate->keySpace->active) { + if (candidate->keySpace->unknownIDrefs) { + /* Recover or report error */ + } + Tcl_DeleteHashTable (&candidate->keySpace->ids); + } break; + case SCHEMA_CTYPE_KEYSPACE: - + if (!candidate->keySpace->active) { + Tcl_InitHashTable (&candidate->keySpace->ids, + TCL_STRING_KEYS); + candidate->keySpace->active = 1; + candidate->keySpace->unknownIDrefs = 0; + } else { + candidate->keySpace->active++; + } break; } if (!mayskip && mustMatch (cp->quants[ac], hm)) { if (recover (interp, sdata, S("MISSING_CP"))) { /* Skip the just opened element tag and the following @@ -1828,11 +1853,11 @@ case SCHEMA_CTYPE_KEYSPACE: break; - case SCHEMA_CTYPE_KEYSPACE: + case SCHEMA_CTYPE_KEYSPACE_END: break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_ANY: @@ -1901,11 +1926,11 @@ case SCHEMA_CTYPE_KEYSPACE: break; - case SCHEMA_CTYPE_KEYSPACE: + case SCHEMA_CTYPE_KEYSPACE_END: break; } break; } @@ -3818,13 +3843,15 @@ Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaCP *pattern; - int nrKeyspaces, i; + int nrKeyspaces, i, hnew; Tcl_Obj *ksObj; - + SchemaKeySpace *ks; + Tcl_HashEntry *h; + CHECK_SI CHECK_TOPLEVEL checkNrArgs (3, 3, "Expected: pattern"); if (sdata->cp->type != SCHEMA_CTYPE_NAME && sdata->cp->type != SCHEMA_CTYPE_PATTERN) { @@ -3848,13 +3875,24 @@ if (Tcl_EvalObjEx (interp, objv[2], TCL_EVAL_DIRECT) != TCL_OK) { return TCL_ERROR; } for (i = 0; i < nrKeyspaces; i++) { Tcl_ListObjIndex (interp, objv[1], i, &ksObj); + h = Tcl_CreateHashEntry (&sdata->keySpaces, + Tcl_GetString (ksObj), &hnew); + if (hnew) { + ks = TMALLOC (SchemaKeySpace); + ks->active = 0; + ks->unknownIDrefs = 0; + Tcl_SetHashValue (h, ks); + } else { + ks = Tcl_GetHashValue (h); + } pattern = initSchemaCP (SCHEMA_CTYPE_KEYSPACE_END, Tcl_GetString (ksObj), NULL); REMEMBER_PATTERN (pattern); + pattern->keySpace = ks; addToContent (sdata, pattern, SCHEMA_CQUANT_ONE, 0, 0); } return TCL_OK; } Index: generic/schema.h ================================================================== --- generic/schema.h +++ generic/schema.h @@ -33,11 +33,12 @@ SCHEMA_CTYPE_CHOICE, SCHEMA_CTYPE_INTERLEAVE, SCHEMA_CTYPE_PATTERN, SCHEMA_CTYPE_TEXT, SCHEMA_CTYPE_VIRTUAL, - SCHEMA_CTYPE_KEYSPACE + SCHEMA_CTYPE_KEYSPACE, + SCHEMA_CTYPE_KEYSPACE_END } Schema_CP_Type; typedef enum { SCHEMA_CQUANT_ONE, SCHEMA_CQUANT_OPT, @@ -83,10 +84,17 @@ int nrFields; int flags; struct domKeyConstraint *next; } domKeyConstraint; +typedef struct +{ + int active; + Tcl_HashTable ids; + int unknownIDrefs; +} SchemaKeySpace; + typedef struct SchemaCP { Schema_CP_Type type; char *namespace; char *name; @@ -97,10 +105,11 @@ unsigned int nc; SchemaAttr **attrs; unsigned int numAttr; unsigned int numReqAttr; domKeyConstraint *domKeys; + SchemaKeySpace *keySpace; } SchemaCP; typedef struct SchemaValidationStack { SchemaCP *pattern; @@ -121,11 +130,11 @@ typedef struct { Tcl_HashTable ids; int unknownIDrefs; } SchemaDocKey; - + typedef struct SchemaData_ { Tcl_Obj *self; char *start; char *startNamespace; @@ -166,10 +175,11 @@ unsigned int skipDeep; Tcl_DString *cdata; Tcl_HashTable ids; int unknownIDrefs; Tcl_HashTable idTables; + Tcl_HashTable keySpaces; } SchemaData; int schemaInstanceCmd ( ClientData clientData,