#include "tex_table.h" #include #include #include "tex_table_tags.h" #include "zalloc_ext.h" #include "zalloc.h" #include "c_const.h" /* only for debug */ #define __TEX_TABLE_DEBUG 0 #include int parse_table(const char *table_source, size_t len, struct table_s *table, struct xerror_s *error) { error->code = 0; error->message = NULL; if (!len) len = strlen(table_source); enum where_e { IN_UNDEF = 0, // undefined place IN_COMMENT, // any comment IN_TAG, // any tag IN_TAG_UNKNOWN, // unknown tag IN_SPACE, // space, \tag { for example IN_TAGPARM, // in \tag{} curly braces IN_TAG_BEGIN, IN_TAG_CLINE, IN_TAG_END, IN_TAG_ENDFOOT, IN_TAG_ENDHEAD, IN_TAG_HLINE, IN_TAG_HSPACE, IN_TAG_MULTICOLUMN, IN_TAG_MULTIROW, IN_TAG_TABULARNEWLINE, IN_TAG_SLASH, IN_FORMULA, // in $...$ IN_LONGTABLE, // in longtable } where_stack[MAX_TEX_STACK_LEVEL] = {IN_UNDEF}; char *tag = NULL; size_t i = 0; size_t tex_level = 0; for (i = 0; i < len; i++) { /* stack checking */ if (tex_level + 1 == MAX_TEX_STACK_LEVEL) { error->code = (int)i; error->message = "stack overflow"; return error->code; } /* read one character from input stream */ char c = table_source[i]; #ifdef __TEX_TABLE_DEBUG printf("tex_level = %lu, c = %c\n", tex_level, c); #endif /* looking at where_stack and encountered character */ switch (where_stack[tex_level]) { case IN_UNDEF: if (c == '\\') { tag = zfree_null(tag); where_stack[++tex_level] = IN_TAG; } else if (isspace(c)) { where_stack[++tex_level] = IN_SPACE; } else if (c == '%') { where_stack[++tex_level] = IN_COMMENT; } else { error->code = (int)i; error->message = "unexpected symbol (IN_UDEF)"; return error->code; } break; case IN_COMMENT: if (c == '\r' || c == '\n') { where_stack[tex_level--] = IN_UNDEF; } break; case IN_TAG: if (isalnum(c)) { tag = zalloc_append8_str(tag, c); } else if (!tag && (c == '\\' || c == ',' || c == '%')) { // newline tag or \, where_stack[tex_level--] = IN_UNDEF; } else if (!tag) { error->code = (int)i; error->message = "empty tag (IN_TAG)"; return error->code; } else { if (!strcmp(tag, TEX_TAG_BEGIN)) { where_stack[tex_level] = IN_TAG_BEGIN; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else if (!strcmp(tag, TEX_TAG_CLINE)) { where_stack[tex_level] = IN_TAG_CLINE; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else if (!strcmp(tag, TEX_TAG_END)) { where_stack[tex_level] = IN_TAG_END; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else if (!strcmp(tag, TEX_TAG_ENDFOOT)) { where_stack[tex_level] = IN_TAG_ENDFOOT; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else if (!strcmp(tag, TEX_TAG_ENDHEAD)) { where_stack[tex_level] = IN_TAG_ENDHEAD; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else if (!strcmp(tag, TEX_TAG_HLINE)) { where_stack[tex_level] = IN_TAG_HLINE; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else if (!strcmp(tag, TEX_TAG_HSPACE)) { where_stack[tex_level] = IN_TAG_HSPACE; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else if (!strcmp(tag, TEX_TAG_MULTICOLUMN)) { where_stack[tex_level] = IN_TAG_MULTICOLUMN; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else if (!strcmp(tag, TEX_TAG_MULTIROW)) { where_stack[tex_level] = IN_TAG_MULTIROW; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else if (!strcmp(tag, TEX_TAG_TABULARNEWLINE)) { where_stack[tex_level] = IN_TAG_TABULARNEWLINE; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else if (!strcmp(tag, TEX_TAG_SLASH)) { where_stack[tex_level] = IN_TAG_SLASH; #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); } else { #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); where_stack[tex_level] = IN_TAG_UNKNOWN; } if (isspace(c)) { // \tag { for example #ifdef __TEX_TABLE_DEBUG printf("\\%s\n", tag); #endif tag = zfree_null(tag); where_stack[tex_level] = IN_TAG_UNKNOWN; where_stack[++tex_level] = IN_SPACE; } else if (c == '\\' || c == '}' || c == ']' || c == '{' || c == '[' || c == '%') i--; } break; case IN_SPACE: if (isspace(c)) { } else { where_stack[tex_level--] = IN_UNDEF; i--; } break; case IN_TAGPARM: if (c == '{' || c == '[') { // tag params where_stack[++tex_level] = IN_TAGPARM; } else if (c == '}' || c == ']') { // end tag params where_stack[tex_level--] = IN_UNDEF; } else if (c == '\\') { // new tag tag = zfree_null(tag); where_stack[++tex_level] = IN_TAG; } else if (isspace(c)) { where_stack[++tex_level] = IN_SPACE; } else if (c == '%') { where_stack[++tex_level] = IN_COMMENT; } else if (isgraph(c) || c < 0) { } else { error->code = (int)i; error->message = "unexpected symbol (IN_TAGPARM)"; return error->code; } break; case IN_TAG_UNKNOWN: if (c == '{' || c == '[') { // tag params where_stack[++tex_level] = IN_TAGPARM; } else if (c == '\\') { // new tag tag = zfree_null(tag); where_stack[tex_level] = IN_TAG; } else if (c == '%') { where_stack[++tex_level] = IN_COMMENT; } else if (isspace(c)) { where_stack[++tex_level] = IN_SPACE; } else if (c == '}' || c == ']') { where_stack[tex_level--] = IN_UNDEF; i--; } else if (isgraph(c) || c < 0) { } else { error->code = (int)i; error->message = "unexpected symbol (IN_TAG_UNKNOWN)"; return error->code; } break; case IN_TAG_BEGIN: if (c == '{' || c == '[') { // tag params where_stack[++tex_level] = IN_TAGPARM; } else if (c == '\\') { // new tag tag = zfree_null(tag); where_stack[tex_level] = IN_TAG; } else if (c == '%') { where_stack[++tex_level] = IN_COMMENT; } else if (isspace(c)) { where_stack[++tex_level] = IN_SPACE; } else if (c == '}' || c == ']') { where_stack[tex_level--] = IN_UNDEF; i--; } else if (isalnum(c) || c == '#') { } else { error->code = (int)i; error->message = "unexpected symbol (IN_TAG_BEGIN)"; return error->code; } break; case IN_TAG_CLINE: if (c == '{' || c == '[') { // tag params where_stack[++tex_level] = IN_TAGPARM; } else if (c == '\\') { // new tag tag = zfree_null(tag); where_stack[tex_level] = IN_TAG; } else if (c == '%') { where_stack[++tex_level] = IN_COMMENT; } else if (isspace(c)) { where_stack[++tex_level] = IN_SPACE; } else if (c == '}' || c == ']') { where_stack[tex_level--] = IN_UNDEF; i--; } else if (isgraph(c) || c < 0) { } else { error->code = (int)i; error->message = "unexpected symbol (IN_TAG_UNKNOWN)"; return error->code; } break; case IN_TAG_END: if (c == '{' || c == '[') { // tag params where_stack[++tex_level] = IN_TAGPARM; } else if (c == '\\') { // new tag tag = zfree_null(tag); where_stack[tex_level] = IN_TAG; } else if (c == '%') { where_stack[++tex_level] = IN_COMMENT; } else if (isspace(c)) { where_stack[++tex_level] = IN_SPACE; } else if (c == '}' || c == ']') { where_stack[tex_level--] = IN_UNDEF; i--; } else if (isgraph(c) || c < 0) { } else { error->code = (int)i; error->message = "unexpected symbol (IN_TAG_UNKNOWN)"; return error->code; } break; case IN_TAG_ENDFOOT: break; case IN_TAG_ENDHEAD: break; case IN_TAG_HLINE: where_stack[tex_level--] = IN_UNDEF; break; case IN_TAG_HSPACE: break; case IN_TAG_MULTICOLUMN: if (c == '{' || c == '[') { // tag params where_stack[++tex_level] = IN_TAGPARM; } else if (c == '\\') { // new tag tag = zfree_null(tag); where_stack[tex_level] = IN_TAG; } else if (c == '%') { where_stack[++tex_level] = IN_COMMENT; } else if (isspace(c)) { where_stack[++tex_level] = IN_SPACE; } else if (c == '}' || c == ']') { where_stack[tex_level--] = IN_UNDEF; i--; } else if (isalnum(c) || c == '#') { } else { error->code = (int)i; error->message = "unexpected symbol (IN_TAG_MULTICOLUMN)"; return error->code; } break; case IN_TAG_MULTIROW: if (c == '{' || c == '[') { // tag params where_stack[++tex_level] = IN_TAGPARM; } else if (c == '\\') { // new tag tag = zfree_null(tag); where_stack[tex_level] = IN_TAG; } else if (c == '%') { where_stack[++tex_level] = IN_COMMENT; } else if (isspace(c)) { where_stack[++tex_level] = IN_SPACE; } else if (c == '}' || c == ']') { where_stack[tex_level--] = IN_UNDEF; i--; } else if (isgraph(c) || c < 0) { } else { error->code = (int)i; error->message = "unexpected symbol (IN_TAG_MULTIROW)"; return error->code; } break; case IN_TAG_TABULARNEWLINE: if (c == '{' || c == '[') { // tag params where_stack[++tex_level] = IN_TAGPARM; } else if (c == '\\') { // new tag tag = zfree_null(tag); where_stack[tex_level] = IN_TAG; } else if (c == '%') { where_stack[++tex_level] = IN_COMMENT; } else if (isspace(c)) { where_stack[++tex_level] = IN_SPACE; } else if (c == '}' || c == ']') { where_stack[tex_level--] = IN_UNDEF; i--; } else if (isalnum(c) || c == '#') { } else { error->code = (int)i; error->message = "unexpected symbol (IN_TAG_TABULARNEWLINE)"; return error->code; } break; case IN_TAG_SLASH: break; case IN_FORMULA: break; case IN_LONGTABLE: break; default: error->code = (int)i; error->message = "unknown error"; return error->code; break; } } printf("tex_level = %lu\n", tex_level); table->id = "Drossel1.Table1"; return 0; }