exip  Alpha 0.5.4
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
grammars.c
Go to the documentation of this file.
1 /*==================================================================*\
2 | EXIP - Embeddable EXI Processor in C |
3 |--------------------------------------------------------------------|
4 | This work is licensed under BSD 3-Clause License |
5 | The full license terms and conditions are located in LICENSE.txt |
6 \===================================================================*/
7 
17 #include "grammars.h"
18 #include "stringManipulate.h"
19 #include "memManagement.h"
20 #include "sTables.h"
21 #include "ioUtil.h"
22 
23 #define DEF_DOC_GRAMMAR_RULE_NUMBER 2 // first rule is excluded
24 #define DEF_FRAG_GRAMMAR_RULE_NUMBER 1 // first rule is excluded
25 #define DEF_ELEMENT_GRAMMAR_RULE_NUMBER 2
26 
27 errorCode createDocGrammar(EXIPSchema* schema, QNameID* elQnameArr, Index qnameCount)
28 {
29  GrammarRule* tmp_rule;
30 
32  schema->docGrammar.props = 0;
35  if(schema->docGrammar.rule == NULL)
37 
38  /* Rule for Document */
39  /*
40  * Document :
41  * SD DocContent 0
42  */
43 
44  // IGNORED!
45 
46  /* Rule for document content */
47  tmp_rule = &schema->docGrammar.rule[GR_DOC_CONTENT];
48 
49  if(elQnameArr != NULL) // Creates Schema Informed Grammar
50  {
51  unsigned int e = 0;
52  Index tmp_code1;
53 
55  tmp_code1 = qnameCount + 1;
56 
57  tmp_rule->production = (Production*) memManagedAllocate(&schema->memList, sizeof(Production)*tmp_code1);
58  if(tmp_rule->production == NULL)
60 
61  /*
62  * DocContent :
63  * SE (G-0) DocEnd 0
64  * SE (G-1) DocEnd 1
65  * ⋮ ⋮ ⋮
66  * SE (G-n−1) DocEnd n-1
67  * // SE (*) DocEnd n // This is created as part of the Built-In grammar further on
68  */
69 
70  for(e = 0; e < qnameCount; e++)
71  {
72  SET_PROD_EXI_EVENT(tmp_rule->production[qnameCount - e].content, EVENT_SE_QNAME);
73  SET_PROD_NON_TERM(tmp_rule->production[qnameCount - e].content, GR_DOC_END);
74  tmp_rule->production[qnameCount - e].typeId = GET_LN_URI_QNAME(schema->uriTable, elQnameArr[e]).elemGrammar;
75  tmp_rule->production[qnameCount - e].qnameId = elQnameArr[e];
76  }
77  tmp_rule->pCount = tmp_code1;
78  }
79  else
80  {
81  tmp_rule->production = (Production*) memManagedAllocate(&schema->memList, sizeof(Production));
82  if(tmp_rule->production == NULL)
84 
85  tmp_rule->pCount = 1;
86  tmp_rule->meta = 0;
87  }
88 
89  /*
90  * DocContent :
91  * SE (*) DocEnd 0
92  */
95  tmp_rule->production[0].typeId = INDEX_MAX;
96  tmp_rule->production[0].qnameId.uriId = URI_MAX;
97  tmp_rule->production[0].qnameId.lnId = LN_MAX;
98 
99  /* Rule for Document end */
100  /*
101  * DocEnd :
102  * ED 0
103  */
104  tmp_rule = &schema->docGrammar.rule[GR_DOC_END];
105 
106  // TODO: consider ignoring this rule as well. In exipg generation as well ...
107 
108  /* Part 1 */
109  tmp_rule->production = (Production*) memManagedAllocate(&schema->memList, sizeof(Production));
110  if(tmp_rule->production == NULL)
112 
115  tmp_rule->production[0].typeId = INDEX_MAX;
116  tmp_rule->production[0].qnameId.uriId = URI_MAX;
117  tmp_rule->production[0].qnameId.lnId = LN_MAX;
118 
119  tmp_rule->pCount = 1;
120  tmp_rule->meta = 0;
121 
122  return EXIP_OK;
123 }
124 
125 #if BUILD_IN_GRAMMARS_USE
126 errorCode createBuiltInElementGrammar(EXIGrammar* elementGrammar, EXIStream* strm)
127 {
128  DynGrammarRule* tmp_rule;
129 
130  elementGrammar->count = DEF_ELEMENT_GRAMMAR_RULE_NUMBER;
131  elementGrammar->props = 0;
132  SET_BUILT_IN_ELEM_GR(elementGrammar->props);
134  if(elementGrammar->rule == NULL)
136 
137  /* Rule for StartTagContent */
138  /* StartTagContent :
139  * EE 0.0
140  * AT (*) StartTagContent 0.1
141  * NS StartTagContent 0.2
142  * SC Fragment 0.3
143  * SE (*) ElementContent 0.4
144  * CH ElementContent 0.5
145  * ER ElementContent 0.6
146  * CM ElementContent 0.7.0
147  * PI ElementContent 0.7.1
148  */
149 
150  tmp_rule = &((DynGrammarRule*) elementGrammar->rule)[GR_START_TAG_CONTENT];
151 
152  /* Part 1 */
154  if(tmp_rule->production == NULL)
156 
157  /* The part 1 productions get added later... */
158  tmp_rule->pCount = 0;
159  tmp_rule->meta = 0;
160  tmp_rule->prodDim = DEFAULT_PROD_ARRAY_DIM;
161 
162  /* Rule for ElementContent */
163  /* ElementContent :
164  * EE 0
165  * SE (*) ElementContent 1.0
166  * CH ElementContent 1.1
167  * ER ElementContent 1.2
168  * CM ElementContent 1.3.0
169  * PI ElementContent 1.3.1
170  */
171  tmp_rule = &((DynGrammarRule*) elementGrammar->rule)[GR_ELEMENT_CONTENT];
172 
173  /* Part 1 */
175  if(tmp_rule->production == NULL)
177 
178  /* EE 0 */
181  tmp_rule->production[0].typeId = INDEX_MAX;
182  tmp_rule->production[0].qnameId.uriId = URI_MAX;
183  tmp_rule->production[0].qnameId.lnId = LN_MAX;
184  tmp_rule->pCount = 1;
185  tmp_rule->meta = 0;
186  tmp_rule->prodDim = DEFAULT_PROD_ARRAY_DIM;
187  /* More part 1 productions get added later... */
188 
189  return EXIP_OK;
190 }
191 
192 errorCode insertZeroProduction(DynGrammarRule* rule, EventType eventType, SmallIndex nonTermID, QNameID* qnameId, boolean hasSecondLevelProd)
193 {
194  if(rule->pCount == rule->prodDim) // The dynamic array rule->production needs to be resized
195  {
196  void* ptr = EXIP_REALLOC(rule->production, sizeof(Production)*(rule->prodDim + DEFAULT_PROD_ARRAY_DIM));
197  if(ptr == NULL)
199 
200  rule->production = ptr;
202  }
203 
204  SET_PROD_EXI_EVENT(rule->production[rule->pCount].content, eventType);
205  SET_PROD_NON_TERM(rule->production[rule->pCount].content, nonTermID);
206  rule->production[rule->pCount].typeId = INDEX_MAX;
207  rule->production[rule->pCount].qnameId = *qnameId;
208 
209  rule->pCount += 1;
210  return EXIP_OK;
211 }
212 #endif
213 
214 errorCode pushGrammar(EXIGrammarStack** gStack, QNameID currQNameID, EXIGrammar* grammar)
215 {
216  struct GrammarStackNode* node = (struct GrammarStackNode*)EXIP_MALLOC(sizeof(struct GrammarStackNode));
217  if(node == NULL)
219 
220  node->grammar = grammar;
222  node->currQNameID = currQNameID;
223  node->nextInStack = *gStack;
224  *gStack = node;
225  return EXIP_OK;
226 }
227 
229 {
230  struct GrammarStackNode* node = *gStack;
231  if((*gStack) != NULL)
232  {
233  node = *gStack;
234  *gStack = (*gStack)->nextInStack;
235 
236  EXIP_MFREE(node);
237  }
238 }
239 
240 errorCode createFragmentGrammar(EXIPSchema* schema, QNameID* elQnameArr, Index qnameCount)
241 {
242  GrammarRule* tmp_rule;
243 
245  schema->docGrammar.props = 0;
247  if(schema->docGrammar.rule == NULL)
249 
250  /* Rule for Fragment */
251  /* Fragment : SD FragmentContent 0 */
252  // IGNORED!
253 
254  /* Rule for Fragment content */
255  tmp_rule = &schema->docGrammar.rule[GR_FRAGMENT_CONTENT];
256 
257  /* Part 1 */
258  if(elQnameArr != NULL) // Creates Schema Informed Grammar
259  {
260  unsigned int e = 0;
261  Index tmp_code1;
262 
263  SET_SCHEMA_GR(schema->docGrammar.props);
264  tmp_code1 = qnameCount + 2;
265 
266  tmp_rule->production = (Production*) memManagedAllocate(&schema->memList, sizeof(Production)*tmp_code1);
267  if(tmp_rule->production == NULL)
269 
270  /*
271  * FragmentContent :
272  * SE (F-0) FragmentContent 0
273  * SE (F-1) FragmentContent 1
274  * ⋮ ⋮ ⋮
275  * SE (F-n−1) FragmentContent n-1
276  * // SE (*) FragmentContent n // This is created as part of the Build-In grammar further on
277  * // ED n+1 // This is created as part of the Build-In grammar further on
278  */
279 
280  for(e = 0; e < qnameCount; e++)
281  {
282  SET_PROD_EXI_EVENT(tmp_rule->production[qnameCount - e].content, EVENT_SE_QNAME);
283  SET_PROD_NON_TERM(tmp_rule->production[qnameCount - e].content, GR_FRAGMENT_CONTENT);
284  tmp_rule->production[qnameCount - e].typeId = GET_LN_URI_QNAME(schema->uriTable, elQnameArr[e]).elemGrammar;
285  tmp_rule->production[qnameCount - e].qnameId = elQnameArr[e];
286  }
287  tmp_rule->pCount = tmp_code1;
288  }
289  else
290  {
291  tmp_rule->production = (Production*) memManagedAllocate(&schema->memList, sizeof(Production)*2);
292  if(tmp_rule->production == NULL)
294 
295  /* Productions further on... */
296  tmp_rule->pCount = 2;
297  }
298 
299  /*
300  * FragmentContent :
301  * SE (*) FragmentContent 0
302  * ED 1
303  */
304 
307  tmp_rule->production[0].typeId = INDEX_MAX;
308  tmp_rule->production[0].qnameId.uriId = URI_MAX;
309  tmp_rule->production[0].qnameId.lnId = LN_MAX;
310 
313  tmp_rule->production[1].typeId = INDEX_MAX;
314  tmp_rule->production[1].qnameId.uriId = URI_MAX;
315  tmp_rule->production[1].qnameId.lnId = LN_MAX;
316 
317  return EXIP_OK;
318 }
319 
320 unsigned int getBitsFirstPartCode(EXIStream* strm, Index prodCount, SmallIndex currentRuleIndx)
321 {
322  boolean secondLevelExists = FALSE;
323 
324  if(IS_BUILT_IN_ELEM(strm->gStack->grammar->props))
325  {
326  // Built-in element grammar
327  // There is always a second level production
328  secondLevelExists = TRUE;
329  }
330  else if(IS_DOCUMENT(strm->gStack->grammar->props))
331  {
332  // Document grammar
334  secondLevelExists = TRUE;
335  else if(currentRuleIndx == 0 && IS_PRESERVED(strm->header.opts.preserve, PRESERVE_DTD))
336  secondLevelExists = TRUE;
337  }
338  else if(IS_FRAGMENT(strm->gStack->grammar->props))
339  {
340  // Fragment grammar
342  secondLevelExists = TRUE;
343  }
344  else
345  {
346  // Schema-informed element/type grammar
347  if(WITH_STRICT(strm->header.opts.enumOpt))
348  {
349  // Strict mode
350  if(strm->context.isNilType == FALSE && currentRuleIndx == 0)
351  {
353  secondLevelExists = TRUE;
354  }
355  }
356  else // Non-strict mode
357  {
358  // There is always a second level production
359  secondLevelExists = TRUE;
360  }
361  }
362 
363  return getBitsNumber(prodCount - 1 + secondLevelExists);
364 }
365 
366 #if EXIP_DEBUG == ON
367 
368 static void writeValueTypeString(EXIType exiType)
369 {
370  switch(exiType)
371  {
372  case VALUE_TYPE_NONE:
373  DEBUG_MSG(INFO, EXIP_DEBUG, ("[N/A]"));
374  break;
375  case VALUE_TYPE_STRING:
376  DEBUG_MSG(INFO, EXIP_DEBUG, ("[str]"));
377  break;
378  case VALUE_TYPE_FLOAT:
379  DEBUG_MSG(INFO, EXIP_DEBUG, ("[float]"));
380  break;
381  case VALUE_TYPE_DECIMAL:
382  DEBUG_MSG(INFO, EXIP_DEBUG, ("[dec]"));
383  break;
385  DEBUG_MSG(INFO, EXIP_DEBUG, ("[dateTime]"));
386  break;
387  case VALUE_TYPE_YEAR:
388  DEBUG_MSG(INFO, EXIP_DEBUG, ("[gYear]"));
389  break;
390  case VALUE_TYPE_DATE:
391  DEBUG_MSG(INFO, EXIP_DEBUG, ("[date]"));
392  break;
393  case VALUE_TYPE_MONTH:
394  DEBUG_MSG(INFO, EXIP_DEBUG, ("[month]"));
395  break;
396  case VALUE_TYPE_TIME:
397  DEBUG_MSG(INFO, EXIP_DEBUG, ("[time]"));
398  break;
399  case VALUE_TYPE_BOOLEAN:
400  DEBUG_MSG(INFO, EXIP_DEBUG, ("[bool]"));
401  break;
402  case VALUE_TYPE_BINARY:
403  DEBUG_MSG(INFO, EXIP_DEBUG, ("[bin]"));
404  break;
405  case VALUE_TYPE_LIST:
406  DEBUG_MSG(INFO, EXIP_DEBUG, ("[list]"));
407  break;
408  case VALUE_TYPE_QNAME:
409  DEBUG_MSG(INFO, EXIP_DEBUG, ("[qname]"));
410  break;
411  case VALUE_TYPE_UNTYPED:
412  DEBUG_MSG(INFO, EXIP_DEBUG, ("[untyped]"));
413  break;
414  case VALUE_TYPE_INTEGER:
415  DEBUG_MSG(INFO, EXIP_DEBUG, ("[int]"));
416  break;
418  DEBUG_MSG(INFO, EXIP_DEBUG, ("[short]"));
419  break;
421  DEBUG_MSG(INFO, EXIP_DEBUG, ("[uint]"));
422  break;
423  }
424 }
425 
427 {
428  Index j = 0;
429  Production* tmpProd;
430  EXIType exiType = VALUE_TYPE_NONE;
431 
432  DEBUG_MSG(INFO, EXIP_DEBUG, ("\n>RULE\n"));
433  DEBUG_MSG(INFO, EXIP_DEBUG, ("NT-%u:", (unsigned int) nonTermID));
434 
435  DEBUG_MSG(INFO, EXIP_DEBUG, ("\n"));
436 
437  for(j = 0; j < rule->pCount; j++)
438  {
439  String *localName = NULL;
440  tmpProd = &rule->production[rule->pCount - 1 - j];
441  DEBUG_MSG(INFO, EXIP_DEBUG, ("\t"));
442 
443  if(GET_PROD_EXI_EVENT(tmpProd->content) != EVENT_SE_QNAME && tmpProd->typeId != INDEX_MAX)
444  exiType = GET_EXI_TYPE(schema->simpleTypeTable.sType[tmpProd->typeId].content);
445  else
446  exiType = VALUE_TYPE_NONE;
447 
448  switch(GET_PROD_EXI_EVENT(tmpProd->content))
449  {
450  case EVENT_SD:
451  DEBUG_MSG(INFO, EXIP_DEBUG, ("SD "));
452  break;
453  case EVENT_ED:
454  DEBUG_MSG(INFO, EXIP_DEBUG, ("ED "));
455  break;
456  case EVENT_SE_QNAME:
457  {
458  QNameID *qname = &tmpProd->qnameId;
459  localName = &(GET_LN_URI_P_QNAME(schema->uriTable, qname).lnStr);
460  DEBUG_MSG(INFO, EXIP_DEBUG, ("SE (qname: %u:%u) ", (unsigned int) qname->uriId, (unsigned int) qname->lnId));
461  break;
462  }
463  case EVENT_SE_URI:
464  DEBUG_MSG(INFO, EXIP_DEBUG, ("SE (uri) "));
465  break;
466  case EVENT_SE_ALL:
467  DEBUG_MSG(INFO, EXIP_DEBUG, ("SE (*) "));
468  break;
469  case EVENT_EE:
470  DEBUG_MSG(INFO, EXIP_DEBUG, ("EE "));
471  break;
472  case EVENT_AT_QNAME:
473  {
474  QNameID *qname = &tmpProd->qnameId;
475  localName = &(GET_LN_URI_P_QNAME(schema->uriTable, qname).lnStr);
476  DEBUG_MSG(INFO, EXIP_DEBUG, ("AT (qname %u:%u) ", (unsigned int) tmpProd->qnameId.uriId, (unsigned int) tmpProd->qnameId.lnId));
477  writeValueTypeString(exiType);
478  break;
479  }
480  case EVENT_AT_URI:
481  DEBUG_MSG(INFO, EXIP_DEBUG, ("AT (uri) "));
482  break;
483  case EVENT_AT_ALL:
484  DEBUG_MSG(INFO, EXIP_DEBUG, ("AT (*) "));
485  writeValueTypeString(exiType);
486  break;
487  case EVENT_CH:
488  DEBUG_MSG(INFO, EXIP_DEBUG, ("CH "));
489  writeValueTypeString(exiType);
490  break;
491  case EVENT_NS:
492  DEBUG_MSG(INFO, EXIP_DEBUG, ("NS "));
493  break;
494  case EVENT_CM:
495  DEBUG_MSG(INFO, EXIP_DEBUG, ("CM "));
496  break;
497  case EVENT_PI:
498  DEBUG_MSG(INFO, EXIP_DEBUG, ("PI "));
499  break;
500  case EVENT_DT:
501  DEBUG_MSG(INFO, EXIP_DEBUG, ("DT "));
502  break;
503  case EVENT_ER:
504  DEBUG_MSG(INFO, EXIP_DEBUG, ("ER "));
505  break;
506  case EVENT_SC:
507  DEBUG_MSG(INFO, EXIP_DEBUG, ("SC "));
508  break;
509  case EVENT_VOID:
510  DEBUG_MSG(INFO, EXIP_DEBUG, (" "));
511  break;
512  default:
513  return EXIP_UNEXPECTED_ERROR;
514  }
515  DEBUG_MSG(INFO, EXIP_DEBUG, ("\t"));
517  {
518  DEBUG_MSG(INFO, EXIP_DEBUG, ("NT-%u", (unsigned int) GET_PROD_NON_TERM(tmpProd->content)));
519  }
520  DEBUG_MSG(INFO, EXIP_DEBUG, ("\t"));
521 
522  DEBUG_MSG(INFO, EXIP_DEBUG, ("%u", (unsigned int) j));
523 
524  if (localName != NULL)
525  {
526  DEBUG_MSG(INFO, EXIP_DEBUG, ("\t"));
527  printString(localName);
528  }
529  DEBUG_MSG(INFO, EXIP_DEBUG, ("\n"));
530  }
531  return EXIP_OK;
532 }
533 
534 #endif // EXIP_DEBUG