mce_schema.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. #include <opc/opc.h>
  2. #include <stdio.h>
  3. #include <time.h>
  4. #ifdef WIN32
  5. #include <crtdbg.h>
  6. #endif
  7. static pbool_t specialChar(int ch) {
  8. return ch<'0' || (ch>'9' && ch<'A') || (ch>'Z' && ch<'a' && '_'!=ch) || ch>'z';
  9. }
  10. xmlChar *readSourceLine(FILE *f) {
  11. xmlChar *ret=NULL;
  12. int len=0;
  13. int ch=0;
  14. while(EOF!=(ch=fgetc(f)) && '\n'!=ch) {
  15. ret=(xmlChar *)xmlRealloc(ret, len+2); // +2 => reserve trailing "0" too
  16. if (NULL!=ret) {
  17. pbool_t ws=(ch==' ' || ch=='\t' || ch=='\r' || ch=='\n');
  18. if (ws) {
  19. pbool_t preceeding_ws=(len==0 && ws);
  20. if (len>0 && !specialChar(ret[len-1])) {
  21. ret[len++]=' ';
  22. }
  23. } else {
  24. if (len>0 && specialChar(ch) && ret[len-1]==' ') {
  25. len--;
  26. }
  27. ret[len++]=ch;
  28. }
  29. ret[len]=0;
  30. }
  31. }
  32. if ('\n'==ch && 0==len) {
  33. ret=(xmlChar *)xmlRealloc(ret, len+1);
  34. if (NULL!=ret) {
  35. ret[len]=0;
  36. }
  37. }
  38. return ret;
  39. }
  40. typedef enum LINE_TOKEN_ID {
  41. LINE_TOKEN_ID_DEF,
  42. LINE_TOKEN_ID_REF,
  43. LINE_TOKEN_ID_START_DOCUMENT,
  44. LINE_TOKEN_ID_END_DOCUMENT,
  45. LINE_TOKEN_ID_START_ELEMENT,
  46. LINE_TOKEN_ID_END_ELEMENT,
  47. LINE_TOKEN_ID_START_CHILDREN,
  48. LINE_TOKEN_ID_END_CHILDREN,
  49. LINE_TOKEN_ID_SKIP_CHILDREN,
  50. LINE_TOKEN_ID_START_ATTRIBUTES,
  51. LINE_TOKEN_ID_END_ATTRIBUTES,
  52. LINE_TOKEN_ID_SKIP_ATTRIBUTES,
  53. LINE_TOKEN_ID_START_CHOICE,
  54. LINE_TOKEN_ID_END_CHOICE,
  55. LINE_TOKEN_ID_MATCH_ELEMENT,
  56. LINE_TOKEN_ID_MATCH_ATTRIBUTE,
  57. LINE_TOKEN_ID_START_TEXT,
  58. LINE_TOKEN_ID_END_TEXT,
  59. LINE_TOKEN_ID_START_ATTRIBUTE,
  60. LINE_TOKEN_ID_END_ATTRIBUTE,
  61. LINE_TOKEN_ID_INVALID,
  62. LINE_TOKEN_ID_EOF
  63. } LineTokenId_t;
  64. typedef struct LINE_TOKEN_DECLARATION {
  65. LineTokenId_t id;
  66. char name[50];
  67. } LineTokenDeclaration;
  68. static LineTokenDeclaration s_token[] = {
  69. { LINE_TOKEN_ID_DEF, "mce_def"},
  70. { LINE_TOKEN_ID_REF, "mce_ref"},
  71. { LINE_TOKEN_ID_START_DOCUMENT, "mce_start_document" },
  72. { LINE_TOKEN_ID_END_DOCUMENT, "mce_end_document" },
  73. { LINE_TOKEN_ID_START_ELEMENT, "mce_start_element" },
  74. { LINE_TOKEN_ID_END_ELEMENT, "mce_end_element" },
  75. { LINE_TOKEN_ID_START_CHILDREN, "mce_start_children" },
  76. { LINE_TOKEN_ID_END_CHILDREN, "mce_end_children" },
  77. { LINE_TOKEN_ID_SKIP_CHILDREN, "mce_skip_children" },
  78. { LINE_TOKEN_ID_START_ATTRIBUTES, "mce_start_attributes" },
  79. { LINE_TOKEN_ID_END_ATTRIBUTES, "mce_end_attributes" },
  80. { LINE_TOKEN_ID_SKIP_ATTRIBUTES, "mce_skip_children" },
  81. { LINE_TOKEN_ID_START_CHOICE, "mce_start_choice" },
  82. { LINE_TOKEN_ID_END_CHOICE, "mce_end_choice" },
  83. { LINE_TOKEN_ID_MATCH_ELEMENT, "mce_match_element" },
  84. { LINE_TOKEN_ID_MATCH_ATTRIBUTE, "mce_match_attribute" },
  85. { LINE_TOKEN_ID_START_TEXT, "mce_start_text" },
  86. { LINE_TOKEN_ID_END_TEXT, "mce_end_text" },
  87. { LINE_TOKEN_ID_START_ATTRIBUTE, "mce_start_attribute" },
  88. { LINE_TOKEN_ID_END_ATTRIBUTE, "mce_end_attribute" },
  89. { LINE_TOKEN_ID_INVALID, "" },
  90. { LINE_TOKEN_ID_EOF, "" }
  91. };
  92. typedef struct LINE_TOKEN_INSTANCE {
  93. LineTokenId_t id;
  94. char param[3][255];
  95. } LineTokenInstance;
  96. typedef struct SOURCE_QNAME {
  97. xmlChar *p;
  98. xmlChar *ns;
  99. } SourceQName;
  100. typedef struct SCHEMA_DECLARATION {
  101. xmlChar *ns;
  102. xmlChar *ln;
  103. puint32_t def_id;
  104. } SchemaDeclaration;
  105. typedef struct SCHEMA_DEFINITION {
  106. xmlChar *name; // if definition has a name
  107. puint32_t max_occurs;
  108. SchemaDeclaration *attr_array;
  109. puint32_t attr_len;
  110. SchemaDeclaration *decl_array;
  111. puint32_t decl_len;
  112. } SchemaDefinition;
  113. typedef struct SOURCE_CONTEXT {
  114. FILE *f;
  115. SourceQName *binding_array;
  116. puint32_t binding_len;
  117. SchemaDefinition *def_array;
  118. puint32_t def_len;
  119. SchemaDeclaration *decl_array;
  120. puint32_t decl_len;
  121. pbool_t error_flag;
  122. } SourceContext;
  123. static void addBinding(SourceContext *sc, const xmlChar *p, const xmlChar *ns) {
  124. puint32_t i=0;
  125. while(i<sc->binding_len && 0!=xmlStrcmp(sc->binding_array[i].p, p)) i++;
  126. if (i==sc->binding_len) {
  127. sc->binding_array=(SourceQName*)xmlRealloc(sc->binding_array, (sc->binding_len+1)*sizeof(SourceQName));
  128. i=sc->binding_len++;
  129. memset(sc->binding_array+i, 0, sizeof(sc->binding_array[i]));
  130. sc->binding_array[i].p=xmlStrdup(p);
  131. } else {
  132. OPC_ASSERT(0==xmlStrcmp(sc->binding_array[i].p, p));
  133. }
  134. if (NULL!=sc->binding_array && i<sc->binding_len) {
  135. if (NULL!=sc->binding_array[i].ns) xmlFree(sc->binding_array[i].ns);
  136. sc->binding_array[i].ns=xmlStrdup(ns);
  137. }
  138. }
  139. static xmlChar *getBinding(SourceContext *sc, const xmlChar *p) {
  140. puint32_t i=0;
  141. while(i<sc->binding_len && 0!=xmlStrcmp(sc->binding_array[i].p, p)) i++;
  142. if (i<sc->binding_len) {
  143. return sc->binding_array[i].ns;
  144. } else {
  145. return NULL;
  146. }
  147. }
  148. static puint32_t addDef(SourceContext *sc, xmlChar *def) {
  149. sc->def_array=(SchemaDefinition*)xmlRealloc(sc->def_array, (sc->def_len+1)*sizeof(SchemaDefinition));
  150. if (NULL!=sc->def_array) {
  151. puint32_t i=sc->def_len++;
  152. memset(&sc->def_array[i], 0, sizeof(sc->def_array[i]));
  153. if (NULL!=def) {
  154. sc->def_array[i].name=xmlStrdup(def);
  155. }
  156. return i;
  157. } else {
  158. return -1;
  159. }
  160. }
  161. static puint32_t findDef(SourceContext *sc, xmlChar *def) {
  162. for(puint32_t i=0;i<sc->def_len;i++) {
  163. if (NULL!=sc->def_array[i].name && 0==xmlStrcmp(sc->def_array[i].name, def)) {
  164. return i;
  165. }
  166. }
  167. return -1;
  168. }
  169. static void freeDecls(SchemaDeclaration **decl_array, puint32_t *decl_len);
  170. static void freeDef(SchemaDefinition *def) {
  171. if (NULL!=def->name) xmlFree(def->name);
  172. freeDecls(&def->decl_array, &def->decl_len);
  173. }
  174. static SchemaDeclaration* addDecl(SchemaDeclaration **decl_array, puint32_t *decl_len, const xmlChar *ns, const xmlChar *ln) {
  175. *decl_array=(SchemaDeclaration *)xmlRealloc(*decl_array, (1+*decl_len)*sizeof(SchemaDeclaration));
  176. if (NULL!=*decl_array) {
  177. memset((*decl_array)+(*decl_len), 0, sizeof((*decl_array)[(*decl_len)]));
  178. (*decl_array)[(*decl_len)].def_id=-1;
  179. if (NULL!=ns) (*decl_array)[(*decl_len)].ns=xmlStrdup(ns);
  180. if (NULL!=ln) (*decl_array)[(*decl_len)].ln=xmlStrdup(ln);
  181. return (*decl_array)+(*decl_len)++;
  182. } else {
  183. return NULL;
  184. }
  185. }
  186. static void freeDecls(SchemaDeclaration **decl_array, puint32_t *decl_len) {
  187. if (NULL!=*decl_array) {
  188. for(puint32_t j=0;j<*decl_len;j++) {
  189. if (NULL!=(*decl_array)[j].ln) xmlFree((*decl_array)[j].ln);
  190. if (NULL!=(*decl_array)[j].ns) xmlFree((*decl_array)[j].ns);
  191. }
  192. xmlFree(*decl_array);
  193. }
  194. }
  195. static void readParam(SourceContext *sc, xmlChar *line, int *ofs, char *param, int param_max) {
  196. int j=0;
  197. while(line[*ofs]!=0 && line[*ofs]!=',') {
  198. if (j+2<param_max) {
  199. if ('('==line[*ofs]) {
  200. j=0;
  201. }
  202. if ('\"'==line[*ofs] || !specialChar(line[*ofs])) {
  203. param[j++]=line[*ofs];
  204. }
  205. param[j]=0;
  206. }
  207. (*ofs)++;
  208. }
  209. if (j>1 && '\"'==param[0] && '\"'==param[j-1]) {
  210. for(int i=0;i<j-2;i++) {
  211. param[i]=param[i+1];
  212. }
  213. param[j-2]=0;
  214. } else if (NULL!=sc) {
  215. xmlChar *v=getBinding(sc, _X(param));
  216. if (NULL!=v && xmlStrlen(v)+1<param_max) {
  217. strcpy(param, (const char *)v);
  218. } else {
  219. printf("ERROR: can not resolve %s\n", param);
  220. }
  221. }
  222. }
  223. static int findStringInLine(xmlChar *line, const xmlChar *str) {
  224. int i=0;
  225. int str_len=xmlStrlen(str);
  226. while(0!=line[i] && 0!=xmlStrncmp(line+i, str, str_len)) {
  227. i++;
  228. }
  229. if (0==xmlStrncmp(line+i, str, str_len)) {
  230. return i;
  231. } else {
  232. return -1;
  233. }
  234. }
  235. LineTokenId_t readLineToken(SourceContext *sc, LineTokenInstance* ti) {
  236. static const char ns_decl[]="static const char ";
  237. memset(ti, 0, sizeof(*ti));
  238. ti->id=LINE_TOKEN_ID_INVALID;
  239. while(!sc->error_flag) {
  240. xmlChar *line=readSourceLine(sc->f);
  241. if (NULL!=line) {
  242. int ofs=-1;
  243. int mce_def_ofs=-1;
  244. if ('#'==line[0] && 'd'==line[1] && 'e'==line[2] && 'f'==line[3] && 'i'==line[4] && 'n'==line[5] && 'e'==line[6]) {
  245. // filter out #define s
  246. } else if (-1!=(mce_def_ofs=findStringInLine(line, _X("mce_def ")))) {
  247. ti->id=LINE_TOKEN_ID_DEF;
  248. int j=0;
  249. ofs=mce_def_ofs+xmlStrlen(_X("mce_def "));
  250. while(line[ofs]!=0 && !specialChar(line[ofs])) {
  251. if (j+2<sizeof(ti->param[0])) {
  252. ti->param[0][j++]=line[ofs];
  253. ti->param[0][j]=0;
  254. }
  255. ofs++;
  256. }
  257. } else if (-1!=(mce_def_ofs=findStringInLine(line, _X("mce_ref(")))) {
  258. ti->id=LINE_TOKEN_ID_REF;
  259. int j=0;
  260. ofs=mce_def_ofs+xmlStrlen(_X("mce_ref("));
  261. while(line[ofs]!=0 && !specialChar(line[ofs])) {
  262. if (j+2<sizeof(ti->param[0])) {
  263. ti->param[0][j++]=line[ofs];
  264. ti->param[0][j]=0;
  265. }
  266. ofs++;
  267. }
  268. } else {
  269. if ('m'==line[0] && 'c'==line[1] && 'e'==line[2] && '_'==line[3]) {
  270. ofs=0;
  271. } else if ('}'==line[0] && 'm'==line[1] && 'c'==line[2] && 'e'==line[3] && '_'==line[4]) {
  272. ofs=1;
  273. }
  274. if (ofs>=0) {
  275. int t=0; while (LINE_TOKEN_ID_INVALID!=s_token[t].id && 0!=xmlStrncmp(_X(s_token[t].name), line+ofs, xmlStrlen(_X(s_token[t].name)))) t++;
  276. if (LINE_TOKEN_ID_INVALID!=s_token[t].id) {
  277. ti->id=s_token[t].id;
  278. PASSERT(0==xmlStrncmp(_X(s_token[ti->id].name), line+ofs, xmlStrlen(_X(s_token[ti->id].name))));
  279. ofs+=xmlStrlen(_X(s_token[t].name));
  280. readParam(NULL, line, &ofs, ti->param[0], sizeof(ti->param[0]));
  281. if (line[ofs]==',') { ofs++; readParam(sc, line, &ofs, ti->param[1], sizeof(ti->param[1])); }
  282. if (line[ofs]==',') { ofs++; readParam(sc, line, &ofs, ti->param[2], sizeof(ti->param[2])); }
  283. } else {
  284. // printf("UNKOWN TOKEN: %s\n", line);
  285. }
  286. } else if (0==xmlStrncmp(_X(ns_decl), line, xmlStrlen(_X(ns_decl)))) {
  287. char prefix[50];
  288. char ns[255];
  289. int ofs=xmlStrlen(_X(ns_decl));
  290. int j=0;
  291. while(0!=line[ofs] && '['!=line[ofs]) {
  292. if (j+2<sizeof(prefix)) {
  293. prefix[j++]=line[ofs];
  294. prefix[j]=0;
  295. }
  296. ofs++;
  297. }
  298. if (line[ofs]=='[') {
  299. while(0!=line[ofs] && '\"'!=line[ofs]) ofs++;
  300. if ('\"'==line[ofs]) {
  301. ofs++;
  302. int j=0;
  303. while(0!=line[ofs] && '\"'!=line[ofs]) {
  304. if (j+2<sizeof(ns)) {
  305. ns[j++]=line[ofs];
  306. ns[j]=0;
  307. }
  308. ofs++;
  309. }
  310. if ('\"'==line[ofs]) {
  311. addBinding(sc, _X(prefix), _X(ns));
  312. }
  313. }
  314. }
  315. }
  316. }
  317. xmlFree(line);
  318. if (LINE_TOKEN_ID_INVALID!=ti->id) {
  319. return ti->id;
  320. }
  321. } else {
  322. ti->id=LINE_TOKEN_ID_EOF;
  323. return ti->id;
  324. }
  325. }
  326. ti->id=LINE_TOKEN_ID_EOF; // error
  327. return ti->id;
  328. }
  329. static void errorToken(SourceContext *sc, LineTokenInstance *ti) {
  330. printf("ERROR %s(%s, %s, %s)\n", s_token[ti->id].name, ti->param[0], ti->param[1], ti->param[2]);
  331. ti->id=LINE_TOKEN_ID_EOF;
  332. sc->error_flag=PTRUE;
  333. }
  334. static pbool_t parseDeclarations(SourceContext *sc, LineTokenInstance *ti, puint32_t def_id);
  335. static pbool_t parseStartDeclaration(SourceContext *sc, LineTokenInstance *ti, SchemaDeclaration **decl_array, puint32_t *decl_len) {
  336. if (LINE_TOKEN_ID_START_ELEMENT==ti->id || LINE_TOKEN_ID_START_ATTRIBUTE==ti->id || LINE_TOKEN_ID_START_TEXT==ti->id) {
  337. LineTokenId_t const end_id=(LINE_TOKEN_ID_START_ELEMENT==ti->id
  338. ?LINE_TOKEN_ID_END_ELEMENT:LINE_TOKEN_ID_START_ATTRIBUTE==ti->id?LINE_TOKEN_ID_END_ATTRIBUTE
  339. :LINE_TOKEN_ID_START_TEXT==ti->id
  340. ?LINE_TOKEN_ID_END_TEXT:ti->id);
  341. SchemaDeclaration *decl=addDecl(decl_array, decl_len, _X(ti->param[1]), _X(ti->param[2]));
  342. PASSERT(NULL!=decl && -1==decl->def_id);
  343. readLineToken(sc, ti); // consume start token
  344. if (LINE_TOKEN_ID_REF==ti->id) {
  345. decl->def_id=findDef(sc, _X(ti->param[0]));
  346. if (-1==decl->def_id) {
  347. decl->def_id=addDef(sc, _X(ti->param[0]));
  348. }
  349. } else {
  350. decl->def_id=addDef(sc, NULL);
  351. }
  352. PASSERT(NULL!=decl && -1!=decl->def_id);
  353. if (decl->def_id>=0 && decl->def_id<sc->def_len) {
  354. parseDeclarations(sc, ti, decl->def_id); // attributes
  355. parseDeclarations(sc, ti, decl->def_id); // children
  356. if (end_id==ti->id) {
  357. sc->def_array[decl->def_id].max_occurs=PUINT32_MAX;
  358. readLineToken(sc, ti); // consume end token
  359. return PTRUE;
  360. }
  361. }
  362. }
  363. return PFALSE;
  364. }
  365. static pbool_t parseDeclarations(SourceContext *sc, LineTokenInstance *ti, puint32_t def_id) {
  366. if (LINE_TOKEN_ID_START_CHILDREN==ti->id) {
  367. readLineToken(sc, ti); // consume start token
  368. while(parseStartDeclaration(sc, ti, &sc->def_array[def_id].decl_array, &sc->def_array[def_id].decl_len)) {
  369. }
  370. if (LINE_TOKEN_ID_END_CHILDREN==ti->id) {
  371. readLineToken(sc, ti); // consume end token
  372. return PTRUE;
  373. } else {
  374. return PFALSE;
  375. }
  376. } else if (LINE_TOKEN_ID_START_ATTRIBUTES==ti->id) {
  377. readLineToken(sc, ti); // consume start token
  378. while(parseStartDeclaration(sc, ti, &sc->def_array[def_id].attr_array, &sc->def_array[def_id].attr_len)) {
  379. }
  380. if (LINE_TOKEN_ID_END_ATTRIBUTES==ti->id) {
  381. readLineToken(sc, ti); // consume end token
  382. return PTRUE;
  383. } else {
  384. return PFALSE;
  385. }
  386. } else if (LINE_TOKEN_ID_SKIP_CHILDREN==ti->id) {
  387. readLineToken(sc, ti); // consume token
  388. return PTRUE;
  389. } else if (LINE_TOKEN_ID_SKIP_ATTRIBUTES==ti->id) {
  390. readLineToken(sc, ti); // consume token
  391. return PTRUE;
  392. } else if (LINE_TOKEN_ID_REF==ti->id) {
  393. readLineToken(sc, ti); // consume token
  394. return PTRUE;
  395. } else {
  396. return PFALSE;
  397. }
  398. }
  399. static pbool_t parseStartDocument(SourceContext *sc, LineTokenInstance *ti) {
  400. if (LINE_TOKEN_ID_START_DOCUMENT==ti->id) {
  401. readLineToken(sc, ti); // consume start_document token
  402. if (parseStartDeclaration(sc, ti, &sc->decl_array, &sc->decl_len)) {
  403. return (LINE_TOKEN_ID_END_DOCUMENT==ti->id?LINE_TOKEN_ID_INVALID!=readLineToken(sc, ti):PFALSE); // consume end_document
  404. }
  405. }
  406. return PFALSE;
  407. }
  408. static pbool_t parseDefinition(SourceContext *sc, LineTokenInstance *ti) {
  409. if (LINE_TOKEN_ID_DEF==ti->id) {
  410. puint32_t def_id=findDef(sc, _X(ti->param[0]));
  411. if (-1==def_id) {
  412. def_id=addDef(sc, _X(ti->param[0]));
  413. }
  414. PASSERT(-1!=def_id);
  415. readLineToken(sc, ti); // consume def token
  416. if (def_id>=0 && def_id<sc->def_len) {
  417. parseDeclarations(sc, ti, def_id); // attributes
  418. parseDeclarations(sc, ti, def_id); // children
  419. return PTRUE;
  420. }
  421. }
  422. return PFALSE;
  423. }
  424. static void dumpDecl(SourceContext *sc, FILE *out, int indent, SchemaDeclaration *decl);
  425. static void dumpDef(SourceContext *sc, FILE *out, int indent, puint32_t def_id) {
  426. printf("%*sattrs:\n", indent, "");
  427. for(puint32_t i=0;i<sc->def_array[def_id].attr_len;i++) {
  428. dumpDecl(sc, out, indent, &sc->def_array[def_id].attr_array[i]);
  429. }
  430. printf("%*schildren:\n", indent, "");
  431. for(puint32_t i=0;i<sc->def_array[def_id].decl_len;i++) {
  432. dumpDecl(sc, out, indent, &sc->def_array[def_id].decl_array[i]);
  433. }
  434. }
  435. static void dumpDecl(SourceContext *sc, FILE *out, int indent, SchemaDeclaration *decl) {
  436. pbool_t const has_children=(decl->def_id>=0 && decl->def_id<sc->def_len && NULL==sc->def_array[decl->def_id].name && (sc->def_array[decl->def_id].attr_len>0 || sc->def_array[decl->def_id].decl_len>0));
  437. fprintf(out, "%*s\"%s\" \"%s\" -> \"%s\" %s\n", indent, "", decl->ns, decl->ln, sc->def_array[decl->def_id].name, (has_children?" {":""));
  438. if (has_children) {
  439. dumpDef(sc, out, indent+2, decl->def_id);
  440. fprintf(out, "%*s}\n", indent, "");
  441. }
  442. }
  443. void dumpGrammar(SourceContext *sc, FILE *out) {
  444. for(puint32_t i=0;i<sc->def_len;i++) {
  445. if (NULL!=sc->def_array[i].name) {
  446. fprintf(out, "def %s {\n", sc->def_array[i].name);
  447. dumpDef(sc, out, 2, i);
  448. fprintf(out, "}\n");
  449. }
  450. }
  451. fprintf(out, "start {\n");
  452. for(puint32_t i=0;i<sc->decl_len;i++) {
  453. dumpDecl(sc, out, 2, &sc->decl_array[i]);
  454. }
  455. fprintf(out, "}\n");
  456. }
  457. void parseSourceCode(SourceContext *sc, xmlChar *filename) {
  458. sc->f=fopen((const char*)filename, "r");
  459. if (NULL!=sc->f) {
  460. LineTokenInstance ti;
  461. readLineToken(sc, &ti); // read first token
  462. while(LINE_TOKEN_ID_EOF!=ti.id) {
  463. if (parseStartDocument(sc, &ti)) {
  464. } else if (parseDefinition(sc, &ti)) {
  465. } else {
  466. errorToken(sc, &ti);
  467. readLineToken(sc, &ti); // consumer token, try to recover
  468. }
  469. }
  470. fclose(sc->f);
  471. }
  472. }
  473. void parseSchema(xmlChar *filename) {
  474. mceTextReader_t reader;
  475. if (0==mceTextReaderInit(&reader, xmlNewTextReaderFilename((const char*)filename))) {
  476. mce_start_document(&reader) {
  477. } mce_end_document(&reader);
  478. mceTextReaderCleanup(&reader);
  479. }
  480. }
  481. int main( int argc, const char* argv[] )
  482. {
  483. #ifdef WIN32
  484. _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  485. #endif
  486. opcInitLibrary();
  487. SourceContext sc;
  488. memset(&sc, 0, sizeof(sc));
  489. addBinding(&sc, _X("NULL"), _X("*"));
  490. for(int i=1;i<argc;i++) {
  491. parseSourceCode(&sc, _X(argv[i]));
  492. }
  493. dumpGrammar(&sc, stdout);
  494. if (NULL!=sc.binding_array) {
  495. for(puint32_t i=0;i<sc.binding_len;i++) {
  496. if (NULL!=sc.binding_array[i].p) xmlFree(sc.binding_array[i].p);
  497. if (NULL!=sc.binding_array[i].ns) xmlFree(sc.binding_array[i].ns);
  498. }
  499. xmlFree(sc.binding_array);
  500. }
  501. freeDecls(&sc.decl_array, &sc.decl_len);
  502. if (NULL!=sc.def_array) {
  503. for(puint32_t i=0;i<sc.def_len;i++) {
  504. freeDef(&sc.def_array[i]);
  505. }
  506. xmlFree(sc.def_array);
  507. }
  508. opcFreeLibrary();
  509. return 0;
  510. }