leptris 1.9.319.0-arm-linux → 1.9.321.0-arm-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,13 +13,122 @@
13
13
  #define XSD_NS "http://www.w3.org/2001/XMLSchema"
14
14
 
15
15
  extern int xsd_simple_valid(const XsdSimple* simple, const char* v);
16
+ extern struct xsd_validator* xsd_validator_new(
17
+ struct leptris_xsd_schema* s);
18
+ extern void xsd_validator_free(struct xsd_validator* v);
19
+ extern int xsd_validator_run(struct xsd_validator* v, LeptrisDocument doc);
20
+ extern size_t xsd_validator_error_count(struct xsd_validator* v);
21
+ extern const char* xsd_validator_error_at(struct xsd_validator* v,
22
+ size_t i);
23
+
24
+ extern int xsd_content_valid(struct leptris_xsd_schema* s, XsdCm* model,
25
+ const char* target_ns,
26
+ const char* const* names,
27
+ const char* const* ns_uris, size_t count);
16
28
 
17
29
  struct leptris_xsd_schema {
18
30
  size_t declaration_count;
19
31
  XsdSimple* simple_types;
32
+ XsdElementDecl* elements;
33
+ XsdCm* complex_types; /* name-carrying model roots */
34
+ XsdTypeAttrs* type_attrs;
35
+ char* target_ns;
36
+ void* validator; /* slice-4 parked error list */
20
37
  char* error;
21
38
  };
22
39
 
40
+ /* ---- slice 3: content-model capture ------------------------------ */
41
+
42
+ static char* xsd_strdup(const char* s);
43
+
44
+ static XsdCm* xsd_cm_new(XsdCmKind kind) {
45
+ XsdCm* cm = (XsdCm*)calloc(1, sizeof(*cm));
46
+ if (!cm) return NULL;
47
+ cm->kind = kind;
48
+ cm->min = 1;
49
+ cm->max = 1;
50
+ return cm;
51
+ }
52
+
53
+ static void xsd_cm_free(XsdCm* cm) {
54
+ while (cm) {
55
+ XsdCm* next = cm->next;
56
+ xsd_cm_free(cm->first_child);
57
+ free(cm->name);
58
+ free(cm->type);
59
+ free(cm->ns);
60
+ free(cm->any_ns);
61
+ free(cm);
62
+ cm = next;
63
+ }
64
+ }
65
+
66
+ static void xsd_cm_occurrence(XsdCm* cm, LeptrisElement e) {
67
+ const char* mn = leptris_element_attribute(e, "minOccurs");
68
+ if (mn) cm->min = (strcmp(mn, "unbounded") == 0) ? 0 : atoi(mn);
69
+ const char* mx = leptris_element_attribute(e, "maxOccurs");
70
+ if (mx) cm->max = (strcmp(mx, "unbounded") == 0) ? -1 : atoi(mx);
71
+ }
72
+
73
+ /* Recursive model build over sequence | choice | all | element |
74
+ * any children. Returns the child list head; *tail_out receives
75
+ * the list tail for sibling chaining. */
76
+ static XsdCm* xsd_cm_parse(LeptrisElement group, XsdCm** tail_out) {
77
+ XsdCm* head = NULL;
78
+ XsdCm* tail = NULL;
79
+ for (LeptrisNodeRef n =
80
+ leptris_node_first_child(leptris_element_as_node(group));
81
+ n; n = leptris_node_next_sibling(n)) {
82
+ if (leptris_node_get_type(n) != LEPTRIS_NODE_TYPE_ELEMENT)
83
+ continue;
84
+ LeptrisElement e = (LeptrisElement)n;
85
+ const char* local = NULL, *prefix = NULL, *uri = NULL;
86
+ leptris_element_expanded_name(e, &local, &prefix, &uri);
87
+ if (!local || (uri && strcmp(uri, XSD_NS) != 0)) continue;
88
+
89
+ XsdCm* cm = NULL;
90
+ if (strcmp(local, "sequence") == 0 || strcmp(local, "choice") == 0 ||
91
+ strcmp(local, "all") == 0) {
92
+ cm = xsd_cm_new(strcmp(local, "sequence") == 0 ? XSD_CM_SEQ
93
+ : strcmp(local, "choice") == 0 ? XSD_CM_CHOICE
94
+ : XSD_CM_ALL);
95
+ if (cm) cm->first_child = xsd_cm_parse(e, NULL);
96
+ } else if (strcmp(local, "element") == 0) {
97
+ cm = xsd_cm_new(XSD_CM_ELEMENT);
98
+ if (cm) {
99
+ const char* nm =
100
+ leptris_element_attribute(e, "name");
101
+ if (!nm) nm = leptris_element_attribute(e, "ref");
102
+ cm->name = xsd_strdup(nm);
103
+ cm->type = xsd_strdup(
104
+ leptris_element_attribute(e, "type"));
105
+ }
106
+ } else if (strcmp(local, "any") == 0) {
107
+ cm = xsd_cm_new(XSD_CM_ANY);
108
+ if (cm) {
109
+ cm->any_ns = xsd_strdup(
110
+ leptris_element_attribute(e, "namespace"));
111
+ const char* pc = leptris_element_attribute(
112
+ e, "processContents");
113
+ cm->process_skip =
114
+ (pc && (strcmp(pc, "skip") == 0 ||
115
+ strcmp(pc, "lax") == 0)) ? 1 : 0;
116
+ }
117
+ } else {
118
+ continue; /* annotation & friends */
119
+ }
120
+ if (!cm) continue;
121
+ xsd_cm_occurrence(cm, e);
122
+ if (tail)
123
+ tail->next = cm;
124
+ else
125
+ head = cm;
126
+ tail = cm;
127
+ }
128
+ if (tail_out) *tail_out = tail;
129
+ return head;
130
+ }
131
+
23
132
  static char* xsd_strdup(const char* s) {
24
133
  if (!s) return NULL;
25
134
  size_t n = strlen(s) + 1;
@@ -161,6 +270,9 @@ LEPTRIS_API LeptrisXsdSchema leptris_xsd_compile(const char* xsd_text,
161
270
  return NULL;
162
271
  }
163
272
 
273
+ /* target namespace (xs:any ##other/##targetNamespace filters) */
274
+ s->target_ns = NULL;
275
+
164
276
  LeptrisDocument doc = leptris_parse_string(xsd_text, len, status);
165
277
  if (!doc) {
166
278
  xsd_set_error(s, "schema document is not well-formed XML");
@@ -172,6 +284,8 @@ LEPTRIS_API LeptrisXsdSchema leptris_xsd_compile(const char* xsd_text,
172
284
  xsd_set_error(s, "schema document has no root element");
173
285
  goto fail;
174
286
  }
287
+ s->target_ns = xsd_strdup(
288
+ leptris_element_attribute(root, "targetNamespace"));
175
289
 
176
290
  const char* local = NULL;
177
291
  const char* prefix = NULL;
@@ -195,7 +309,77 @@ LEPTRIS_API LeptrisXsdSchema leptris_xsd_compile(const char* xsd_text,
195
309
  &uri);
196
310
  if (!xsd_is_declaration(local, uri)) continue;
197
311
  s->declaration_count++;
198
- if (strcmp(local, "simpleType") == 0 && uri && !strcmp(uri, XSD_NS)) {
312
+ if (strcmp(local, "element") == 0 && uri && !strcmp(uri, XSD_NS)) {
313
+ const char* nm = leptris_element_attribute((LeptrisElement)n,
314
+ "name");
315
+ const char* ty = leptris_element_attribute((LeptrisElement)n,
316
+ "type");
317
+ if (nm && ty) {
318
+ XsdElementDecl* d =
319
+ (XsdElementDecl*)calloc(1, sizeof(*d));
320
+ if (d) {
321
+ d->name = xsd_strdup(nm);
322
+ d->type = xsd_strdup(ty);
323
+ d->next = s->elements;
324
+ s->elements = d;
325
+ }
326
+ }
327
+ } else if (strcmp(local, "complexType") == 0 && uri &&
328
+ !strcmp(uri, XSD_NS)) {
329
+ const char* nm =
330
+ leptris_element_attribute((LeptrisElement)n, "name");
331
+ if (nm) {
332
+ XsdCm* root =
333
+ xsd_cm_new(XSD_CM_SEQ); /* wrapper keeps the name */
334
+ if (root) {
335
+ root->name = xsd_strdup(nm);
336
+ root->first_child =
337
+ xsd_cm_parse((LeptrisElement)n, NULL);
338
+ root->next = s->complex_types;
339
+ s->complex_types = root;
340
+ }
341
+ /* slice 4: attribute declarations of the type */
342
+ XsdAttrDecl* head = NULL;
343
+ XsdAttrDecl* tail = NULL;
344
+ for (LeptrisNodeRef ac = leptris_node_first_child(
345
+ leptris_element_as_node((LeptrisElement)n));
346
+ ac; ac = leptris_node_next_sibling(ac)) {
347
+ if (leptris_node_get_type(ac) !=
348
+ LEPTRIS_NODE_TYPE_ELEMENT)
349
+ continue;
350
+ LeptrisElement ae = (LeptrisElement)ac;
351
+ const char* al = NULL, *ap = NULL, *au = NULL;
352
+ leptris_element_expanded_name(ae, &al, &ap, &au);
353
+ if (!al || (au && strcmp(au, XSD_NS) != 0)) continue;
354
+ if (strcmp(al, "attribute") != 0) continue;
355
+ const char* an = leptris_element_attribute(ae, "name");
356
+ if (!an) continue; /* ref forms: slice 5 */
357
+ XsdAttrDecl* d = (XsdAttrDecl*)calloc(1, sizeof(*d));
358
+ if (!d) continue;
359
+ d->name = xsd_strdup(an);
360
+ d->type = xsd_strdup(
361
+ leptris_element_attribute(ae, "type"));
362
+ const char* use =
363
+ leptris_element_attribute(ae, "use");
364
+ d->required = (use && strcmp(use, "required") == 0);
365
+ if (tail)
366
+ tail->next = d;
367
+ else
368
+ head = d;
369
+ tail = d;
370
+ }
371
+ if (head) {
372
+ XsdTypeAttrs* ta =
373
+ (XsdTypeAttrs*)calloc(1, sizeof(*ta));
374
+ if (ta) {
375
+ ta->type_name = xsd_strdup(nm);
376
+ ta->attrs = head;
377
+ ta->next = s->type_attrs;
378
+ s->type_attrs = ta;
379
+ }
380
+ }
381
+ }
382
+ } else if (strcmp(local, "simpleType") == 0 && uri && !strcmp(uri, XSD_NS)) {
199
383
  XsdSimple* captured = xsd_capture_simple((LeptrisElement)n);
200
384
  if (captured) {
201
385
  captured->next = s->simple_types;
@@ -218,6 +402,33 @@ fail:
218
402
  LEPTRIS_API void leptris_xsd_free(LeptrisXsdSchema schema) {
219
403
  struct leptris_xsd_schema* s = (struct leptris_xsd_schema*)schema;
220
404
  if (!s) return;
405
+ xsd_cm_free(s->complex_types);
406
+ XsdTypeAttrs* ta = s->type_attrs;
407
+ while (ta) {
408
+ XsdTypeAttrs* tn = ta->next;
409
+ XsdAttrDecl* a = ta->attrs;
410
+ while (a) {
411
+ XsdAttrDecl* an = a->next;
412
+ free(a->name);
413
+ free(a->type);
414
+ free(a);
415
+ a = an;
416
+ }
417
+ free(ta->type_name);
418
+ free(ta);
419
+ ta = tn;
420
+ }
421
+ XsdElementDecl* d = s->elements;
422
+ while (d) {
423
+ XsdElementDecl* dn = d->next;
424
+ free(d->name);
425
+ free(d->type);
426
+ free(d);
427
+ d = dn;
428
+ }
429
+ free(s->target_ns);
430
+ if (s->validator)
431
+ xsd_validator_free((struct xsd_validator*)s->validator);
221
432
  XsdSimple* t = s->simple_types;
222
433
  while (t) {
223
434
  XsdSimple* next = t->next;
@@ -261,6 +472,103 @@ LEPTRIS_API int leptris_xsd_simple_valid(LeptrisXsdSchema schema,
261
472
  return xsd_valid_chain(s, t, lexical, 0);
262
473
  }
263
474
 
475
+ /* ---- validator accessors (validate.c) --------------------------- */
476
+
477
+ const XsdElementDecl* xsd_find_element(struct leptris_xsd_schema* s,
478
+ const char* name) {
479
+ if (!s || !name) return NULL;
480
+ for (XsdElementDecl* d = s->elements; d; d = d->next)
481
+ if (strcmp(d->name, name) == 0) return d;
482
+ return NULL;
483
+ }
484
+
485
+ XsdCm* xsd_find_complex(struct leptris_xsd_schema* s,
486
+ const char* type_name) {
487
+ if (!s || !type_name) return NULL;
488
+ for (XsdCm* c = s->complex_types; c; c = c->next)
489
+ if (strcmp(c->name, type_name) == 0) return c;
490
+ return NULL;
491
+ }
492
+
493
+ const XsdSimple* xsd_find_simple_pub(struct leptris_xsd_schema* s,
494
+ const char* name) {
495
+ return xsd_find_simple(s, name);
496
+ }
497
+
498
+ const char* xsd_target_ns(struct leptris_xsd_schema* s) {
499
+ return s ? s->target_ns : NULL;
500
+ }
501
+
502
+ const XsdTypeAttrs* xsd_find_type_attrs(struct leptris_xsd_schema* s,
503
+ const char* type_name) {
504
+ if (!s || !type_name) return NULL;
505
+ for (XsdTypeAttrs* t = s->type_attrs; t; t = t->next)
506
+ if (strcmp(t->type_name, type_name) == 0) return t;
507
+ return NULL;
508
+ }
509
+
510
+ /* ---- slice 4: instance validation (validate.c engine) ------------ */
511
+
512
+ LEPTRIS_API int leptris_xsd_validate(LeptrisXsdSchema schema,
513
+ LeptrisDocument doc) {
514
+ struct leptris_xsd_schema* s = (struct leptris_xsd_schema*)schema;
515
+ if (!s || !doc) return -1;
516
+ struct xsd_validator* v = xsd_validator_new(s);
517
+ if (!v) return -1;
518
+ int r = xsd_validator_run(v, doc);
519
+ /* park the run's errors on the schema for the accessors; a new
520
+ * validate run replaces them. */
521
+ struct xsd_validator* prev = (struct xsd_validator*)s->validator;
522
+ if (prev) xsd_validator_free(prev);
523
+ s->validator = v;
524
+ return r;
525
+ }
526
+
527
+ LEPTRIS_API size_t leptris_xsd_error_count(LeptrisXsdSchema schema) {
528
+ struct leptris_xsd_schema* s = (struct leptris_xsd_schema*)schema;
529
+ if (!s) return 0;
530
+ return xsd_validator_error_count(
531
+ (struct xsd_validator*)s->validator);
532
+ }
533
+
534
+ LEPTRIS_API const char* leptris_xsd_error_at(LeptrisXsdSchema schema,
535
+ size_t i) {
536
+ struct leptris_xsd_schema* s = (struct leptris_xsd_schema*)schema;
537
+ if (!s) return NULL;
538
+ return xsd_validator_error_at((struct xsd_validator*)s->validator,
539
+ i);
540
+ }
541
+
542
+ LEPTRIS_API int leptris_xsd_content_valid(
543
+ LeptrisXsdSchema schema, const char* element_name,
544
+ const char* const* child_names, const char* const* child_ns,
545
+ size_t child_count) {
546
+ struct leptris_xsd_schema* s = (struct leptris_xsd_schema*)schema;
547
+ if (!s || !element_name) return -1;
548
+
549
+ const XsdElementDecl* d = s->elements;
550
+ while (d && strcmp(d->name, element_name) != 0) d = d->next;
551
+ if (!d) return -1; /* unknown element */
552
+
553
+ if (!d->type) return 1; /* no type attr: anyType accepts all */
554
+
555
+ /* built-in or simpleType ref: element content is text-only —
556
+ * any element child fails */
557
+ if (strncmp(d->type, "xs:", 3) == 0 ||
558
+ xsd_find_simple(s, d->type))
559
+ return child_count == 0;
560
+
561
+ XsdCm* ct = s->complex_types;
562
+ while (ct && strcmp(ct->name, d->type) != 0) ct = ct->next;
563
+ if (!ct) return child_count == 0; /* unknown type: accept-empty */
564
+
565
+ XsdCm* model = ct->first_child;
566
+ if (!model) return child_count == 0;
567
+
568
+ return xsd_content_valid(s, model, s->target_ns, child_names,
569
+ child_ns, child_count);
570
+ }
571
+
264
572
  LEPTRIS_API size_t leptris_xsd_declaration_count(LeptrisXsdSchema schema) {
265
573
  if (!schema) return 0;
266
574
  return ((struct leptris_xsd_schema*)schema)->declaration_count;
@@ -0,0 +1,232 @@
1
+ /* xsd/content_model.c — #1075 slice 3: content-model evaluation.
2
+ *
3
+ * The compiled model tree lowers into a Thompson NFA (epsilon +
4
+ * symbol transitions, occurrence bounds via counting copies and a
5
+ * loop for unbounded) and the child sequence is consumed by
6
+ * simulating the live state set — linear in children x states, no
7
+ * backtracking blowup on nested choices.
8
+ *
9
+ * Namespace filters (xs:any/@namespace): "##any" (default),
10
+ * "##other" (not the target namespace, not unqualified),
11
+ * "##targetNamespace", "##local", or a space-separated URI list.
12
+ */
13
+ #include <stdlib.h>
14
+ #include <string.h>
15
+
16
+ #include "xsd_internal.h"
17
+
18
+ typedef struct {
19
+ int from;
20
+ int symbol; /* -1 = epsilon; else a particle transition */
21
+ XsdCm* particle; /* symbol owner (element ref or wildcard) */
22
+ int to;
23
+ } CmTrans;
24
+
25
+ typedef struct {
26
+ CmTrans* trans;
27
+ size_t count, cap;
28
+ int state_count; /* explicit: state ids are NOT transition ids */
29
+ int start, accept;
30
+ } CmNfa;
31
+
32
+ static int nfa_state(CmNfa* n) { return n->state_count++; }
33
+
34
+ static void nfa_trans(CmNfa* n, int from, int symbol, XsdCm* particle,
35
+ int to) {
36
+ if (n->count == n->cap) {
37
+ size_t cap = n->cap ? n->cap * 2 : 16;
38
+ CmTrans* grown = (CmTrans*)realloc(n->trans, cap * sizeof(*grown));
39
+ if (!grown) return; /* OOM: walk treats the NFA as non-matching */
40
+ n->trans = grown;
41
+ n->cap = cap;
42
+ }
43
+ n->trans[n->count].from = from;
44
+ n->trans[n->count].symbol = symbol;
45
+ n->trans[n->count].particle = particle;
46
+ n->trans[n->count].to = to;
47
+ n->count++;
48
+ }
49
+
50
+ static void cm_build(CmNfa* n, XsdCm* node, int from, int to);
51
+ static void cm_build_occurrence(CmNfa* n, XsdCm* node,
52
+ int from, int to);
53
+
54
+ /* chain the group children: first reads `from`, last writes `to`.
55
+ * xs:all is evaluated in sequence order for now (its order-free
56
+ * semantics arrive with slice 4's all-semantics pass). */
57
+ static void cm_build_children(CmNfa* n, XsdCm* node, int from, int to) {
58
+ XsdCm* c = node->first_child;
59
+ if (!c) {
60
+ nfa_trans(n, from, -1, NULL, to);
61
+ return;
62
+ }
63
+ int cursor = from;
64
+ while (c->next) {
65
+ int mid = nfa_state(n);
66
+ cm_build_occurrence(n, c, cursor, mid);
67
+ cursor = mid;
68
+ c = c->next;
69
+ }
70
+ cm_build_occurrence(n, c, cursor, to);
71
+ }
72
+
73
+ static void cm_build(CmNfa* n, XsdCm* node, int from, int to) {
74
+ switch (node->kind) {
75
+ case XSD_CM_ELEMENT:
76
+ case XSD_CM_ANY:
77
+ nfa_trans(n, from, 0, node, to);
78
+ return;
79
+ case XSD_CM_SEQ:
80
+ case XSD_CM_ALL:
81
+ cm_build_children(n, node, from, to);
82
+ return;
83
+ case XSD_CM_CHOICE: {
84
+ XsdCm* c = node->first_child;
85
+ if (!c) {
86
+ nfa_trans(n, from, -1, NULL, to);
87
+ return;
88
+ }
89
+ for (; c; c = c->next) cm_build_occurrence(n, c, from, to);
90
+ return;
91
+ }
92
+ }
93
+ }
94
+
95
+ /* occurrence bounds: min copies, then (max-min) optionals, or an
96
+ * epsilon self-loop region for unbounded. */
97
+ static void cm_build_occurrence(CmNfa* n, XsdCm* node, int from, int to) {
98
+ for (int i = 0; i < node->min; i++) {
99
+ int mid = nfa_state(n);
100
+ cm_build(n, node, from, mid);
101
+ from = mid;
102
+ }
103
+ if (node->max < 0) {
104
+ int loop = nfa_state(n);
105
+ nfa_trans(n, from, -1, NULL, loop);
106
+ cm_build(n, node, loop, loop);
107
+ nfa_trans(n, loop, -1, NULL, to);
108
+ return;
109
+ }
110
+ for (int i = node->min; i < node->max; i++) {
111
+ nfa_trans(n, from, -1, NULL, to);
112
+ int mid = nfa_state(n);
113
+ cm_build(n, node, from, mid);
114
+ from = mid;
115
+ }
116
+ nfa_trans(n, from, -1, NULL, to);
117
+ }
118
+
119
+ /* ---- namespace filter (xs:any/@namespace) ------------------------ */
120
+
121
+ static int any_ns_matches(XsdCm* any, const char* uri,
122
+ const char* target_ns) {
123
+ const char* f = any->any_ns ? any->any_ns : "##any";
124
+ if (strcmp(f, "##any") == 0) return 1;
125
+ if (strcmp(f, "##local") == 0) return uri == NULL;
126
+ if (strcmp(f, "##targetNamespace") == 0)
127
+ return target_ns && uri && strcmp(uri, target_ns) == 0;
128
+ if (strcmp(f, "##other") == 0)
129
+ return uri != NULL &&
130
+ !(target_ns && strcmp(uri, target_ns) == 0);
131
+ /* space-separated URI list (+##local) */
132
+ const char* p = f;
133
+ while (*p) {
134
+ while (*p == ' ') p++;
135
+ const char* start = p;
136
+ while (*p && *p != ' ') p++;
137
+ size_t len = (size_t)(p - start);
138
+ if (len == 0) break;
139
+ if (strncmp(start, "##local", len) == 0 && len == 7) {
140
+ if (uri == NULL) return 1;
141
+ continue;
142
+ }
143
+ if (uri && strlen(uri) == len && strncmp(start, uri, len) == 0)
144
+ return 1;
145
+ }
146
+ return 0;
147
+ }
148
+
149
+ /* ---- simulation --------------------------------------------------- */
150
+
151
+ typedef struct {
152
+ int* states;
153
+ size_t count, cap;
154
+ } StateSet;
155
+
156
+ static void ss_add(StateSet* ss, int st) {
157
+ for (size_t i = 0; i < ss->count; i++)
158
+ if (ss->states[i] == st) return;
159
+ if (ss->count == ss->cap) {
160
+ size_t cap = ss->cap ? ss->cap * 2 : 16;
161
+ int* grown = (int*)realloc(ss->states, cap * sizeof(int));
162
+ if (!grown) return;
163
+ ss->states = grown;
164
+ ss->cap = cap;
165
+ }
166
+ ss->states[ss->count++] = st;
167
+ }
168
+
169
+ static void ss_close(StateSet* ss, CmNfa* n) {
170
+ /* fixpoint over epsilon edges */
171
+ size_t i = 0;
172
+ while (i < ss->count) {
173
+ int st = ss->states[i];
174
+ for (size_t t = 0; t < n->count; t++)
175
+ if (n->trans[t].from == st && n->trans[t].symbol == -1)
176
+ ss_add(ss, n->trans[t].to);
177
+ i++;
178
+ }
179
+ }
180
+
181
+ int xsd_content_valid(struct leptris_xsd_schema* s, XsdCm* model,
182
+ const char* target_ns, const char* const* names,
183
+ const char* const* ns_uris, size_t count) {
184
+ (void)s;
185
+ if (!model) return -1;
186
+ CmNfa n;
187
+ memset(&n, 0, sizeof(n));
188
+ n.start = nfa_state(&n);
189
+ n.accept = nfa_state(&n);
190
+ cm_build_occurrence(&n, model, n.start, n.accept);
191
+
192
+ StateSet live;
193
+ memset(&live, 0, sizeof(live));
194
+ ss_add(&live, n.start);
195
+ ss_close(&live, &n);
196
+
197
+ for (size_t c = 0; c < count; c++) {
198
+ StateSet next;
199
+ memset(&next, 0, sizeof(next));
200
+ const char* uri = ns_uris ? ns_uris[c] : NULL;
201
+ for (size_t i = 0; i < live.count; i++) {
202
+ for (size_t t = 0; t < n.count; t++) {
203
+ CmTrans* tr = &n.trans[t];
204
+ if (tr->from != live.states[i] || tr->symbol == -1)
205
+ continue;
206
+ XsdCm* p = tr->particle;
207
+ if (p->kind == XSD_CM_ELEMENT) {
208
+ if (strcmp(p->name, names[c]) == 0 &&
209
+ (!p->ns || (uri && strcmp(uri, p->ns) == 0)))
210
+ ss_add(&next, tr->to);
211
+ } else if (p->kind == XSD_CM_ANY) {
212
+ if (any_ns_matches(p, uri, target_ns))
213
+ ss_add(&next, tr->to);
214
+ }
215
+ }
216
+ }
217
+ free(live.states);
218
+ live = next;
219
+ ss_close(&live, &n);
220
+ if (live.count == 0) {
221
+ free(n.trans);
222
+ return 0;
223
+ }
224
+ }
225
+
226
+ int accept = 0;
227
+ for (size_t i = 0; i < live.count; i++)
228
+ if (live.states[i] == n.accept) accept = 1;
229
+ free(live.states);
230
+ free(n.trans);
231
+ return accept;
232
+ }