#include #include"ezxml.h" #include #include #include int main(int argc, char **argv) { ezxml_t schema = ezxml_parse_file(argv[1]); char *Name = strdup(argv[2]); char *NAME = strdup(Name); for(char *c = NAME; *c; c++) { *c = toupper(*c); } char *name = strdup(Name); for(char *c = name; *c; c++) { *c = tolower(*c); } printf("#ifndef %s_PARSER_H\n", NAME); printf("#define %s_PARSER_H\n", NAME); printf("#include\n"); printf("#include\n"); printf("#include\n"); printf("#include\n"); printf("#include\"eebie/reader.h\"\n"); for(ezxml_t el = ezxml_child(schema, "element"); el; el = el->next) { printf("#define %s_%s %sL\n", NAME, ezxml_attr(el, "name"), ezxml_attr(el, "id")); } printf("typedef struct %sParser {\n", Name); printf("\tvoid *ud;\n"); printf("\tuint8_t *accum;\n"); printf("\tsize_t accumLen;\n"); printf("\tEBMLReader ebml;\n"); for(ezxml_t el = ezxml_child(schema, "element"); el; el = el->next) { const char *type = ezxml_attr(el, "type"); if(!strcmp(type, "master")) { printf("\tvoid(*On%s)(struct %sParser*);\n", ezxml_attr(el, "name"), Name); } else if(!strcmp(type, "uinteger")) { printf("\tvoid(*On%s)(struct %sParser*, uint64_t value);\n", ezxml_attr(el, "name"), Name); } else if(!strcmp(type, "integer")) { printf("\tvoid(*On%s)(struct %sParser*, int64_t value);\n", ezxml_attr(el, "name"), Name); } else if(!strcmp(type, "date")) { printf("\tvoid(*On%s)(struct %sParser*, int64_t value);\n", ezxml_attr(el, "name"), Name); } else if(!strcmp(type, "float")) { printf("\tvoid(*On%s)(struct %sParser*, double value);\n", ezxml_attr(el, "name"), Name); } else { if(strcmp(type, "binary") && strcmp(type, "utf-8") && strcmp(type, "string")) { fprintf(stderr, "Interpreting unknown element type \"%s\" as binary\n", type); } printf("\tvoid(*On%s)(struct %sParser*, const uint8_t *data, size_t length);\n", ezxml_attr(el, "name"), Name); } } printf("} %sParser;\n", Name); printf("void %s_parser_init(%sParser*);\n", name, Name); printf("size_t %s_parser_feed(%sParser*, const uint8_t *data, size_t length);\n", name, Name); printf("#ifdef %s_PARSER_IMPLEMENTATION\n", NAME); printf("EBMLElementType %s_event_enter_element(EBMLReader *rdr, uint64_t id, uint64_t length) {\n", name); printf("\t%sParser *self = rdr->ud;\n", Name); for(ezxml_t el = ezxml_child(schema, "element"); el; el = el->next) { const char *type = ezxml_attr(el, "type"); if(!strcmp(type, "master")) { printf("\tif(id == %s_%s) {\n", NAME, ezxml_attr(el, "name")); printf("\t\tif(self->On%s) self->On%s(self);\n", ezxml_attr(el, "name"), ezxml_attr(el, "name")); printf("\t\treturn EBML_TREE;\n"); printf("\t}\n"); } } printf("\treturn EBML_BINARY;\n"); printf("}\n"); printf("void %s_event_data_chunk(EBMLReader *rdr, const uint8_t *data, uint64_t length) {\n", name); printf("\t%sParser *self = rdr->ud;\n", Name); printf("\tself->accum = realloc(self->accum, self->accumLen + length);\n"); printf("\tmemcpy(self->accum + self->accumLen, data, length);\n"); printf("\tself->accumLen += length;\n"); printf("}\n"); printf("void %s_event_exit_element(EBMLReader *rdr) {\n", name); printf("\t%sParser *self = rdr->ud;\n", Name); printf("\tuint64_t id = rdr->idStack[rdr->currentDepth - 1];\n"); for(ezxml_t el = ezxml_child(schema, "element"); el; el = el->next) { const char *type = ezxml_attr(el, "type"); printf("\tif(id == %s_%s) {\n", NAME, ezxml_attr(el, "name")); if(!strcmp(type, "uinteger") || !strcmp(type, "integer") || !strcmp(type, "date")) { printf("\t\t%s val = 0;\n", !strcmp(type, "uinteger") ? "uint64_t" : "int64_t"); printf("\t\tmemcpy((uint8_t*) &val + 8 - self->accumLen, self->accum, self->accumLen);\n"); printf("\t\tval = be64toh(val);\n"); printf("\t\tif(self->On%s) self->On%s(self, val);\n", ezxml_attr(el, "name"), ezxml_attr(el, "name")); } else if(!strcmp(type, "string") || !strcmp(type, "utf-8") || !strcmp(type, "binary")) { if(strcmp(type, "binary") != 0) { printf("\t\tself->accum = realloc(self->accum, self->accumLen + 1);\n"); printf("\t\tself->accum[self->accumLen] = 0;\n"); } printf("\t\tif(self->On%s) self->On%s(self, self->accum, self->accumLen);\n", ezxml_attr(el, "name"), ezxml_attr(el, "name")); } else if(!strcmp(type, "float")) { printf("\t\tdouble val;\n"); printf("\t\tif(self->accumLen == 4) {\n"); printf("\t\t\tfloat fval;\n"); printf("\t\t\tmemcpy(&fval, self->accum, 4);\n"); printf("\t\t\t*(uint32_t*) &fval = be32toh(*(uint32_t*) &fval);\n"); printf("\t\t\tval = fval;\n"); printf("\t\t} else {\n"); printf("\t\t\tmemcpy(&val, self->accum, 8);\n"); printf("\t\t\t*(uint64_t*) &val = be64toh(*(uint64_t*) &val);\n"); printf("\t\t}\n"); printf("\t\tif(self->On%s) self->On%s(self, val);\n", ezxml_attr(el, "name"), ezxml_attr(el, "name")); } else if(!strcmp(type, "master")) { // Do nothing. } else { fprintf(stderr, "Ignoring unknown type \"%s\"\n", type); } printf("\t}\n"); } printf("\tfree(self->accum); self->accum = NULL; self->accumLen = 0;\n"); printf("}\n"); printf("void %s_parser_init(%sParser *self) {\n", name, Name); printf("\tmemset(self, 0, sizeof(*self));\n"); printf("\tebml_reader_init(&self->ebml);\n"); printf("\tself->ebml.eventEnterElement = %s_event_enter_element;\n", name); printf("\tself->ebml.eventDataChunk = %s_event_data_chunk;\n", name); printf("\tself->ebml.eventExitElement = %s_event_exit_element;\n", name); printf("\tself->ebml.ud = self;\n"); printf("}\n"); printf("size_t %s_parser_feed(%sParser *self, const uint8_t *data, size_t length) {\n", name, Name); printf("\treturn ebml_reader_feed(&self->ebml, data, length);\n"); printf("}\n"); printf("#endif\n"); printf("#endif\n"); }