diff -r 6bcc0aa4be39 -r 889504eac4fb xml/cxmllibrary/dictionary/dict_creator.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xml/cxmllibrary/dictionary/dict_creator.c Tue Aug 31 17:02:56 2010 +0300 @@ -0,0 +1,1051 @@ +/* +* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* Author: Frank Richichi +* Created: Thu Apr 25 10:34:06 2002 +* Modified: Thu Apr 25 11:12:35 2002 (Frank Richichi) richichi@D5250215 +* Language: C +* Subsystem: N/A +* RCS: $Id$ +* +*/ + + +/* **************************************************************** +** Copyright 2000 - Nokia Corporation All rights reserved. +** Nokia Americas +** 6000 Connection Drive +** Irving, Texas 75039 +** +** Restricted Rights: Use, duplication, or disclosure by the +** U.S. Government is subject to restrictions as set forth in +** subparagraph (c)(1)(ii) of DFARS 252.227-7013, or in FAR +** 52.227-19, or in FAR 52.227-14 Alt. III, as applicable. +** +** This software is proprietary to and embodies the confidential +** technology of Nokia Possession, use, or copying of this software +** and media is authorized only pursuant to a valid written license +** from Nokia or an authorized sublicensor. +** +** Nokia - Wireless Software Solutions +*****************************************************************/ + +#include +#include +#include +#include +#include +#include + + +/* ----------------------------------------------------------------------- ** + The following strings are used to identify the beginning of a tag or + attribute list in the input file. +** ----------------------------------------------------------------------- **/ + +#define TAG_TABLE_HEADING "TAGS_FOR_CODE_PAGE" +#define ATTR_TABLE_HEADING "ATTRIBUTES_FOR_CODE_PAGE" +#define NO_STRINGS "NO_STRINGS" + +/* ----------------------------------------------------------------------- ** + Types for various tables. +** ----------------------------------------------------------------------- **/ +#define NAME_TABLE_T "NW_Byte" +#define TOKEN_TABLE_T "NW_WBXML_DictEntry_t" +#define CODEPAGE_TABLE_T "NW_WBXML_Codepage_t" +#define DICTIONARY_TABLE_T "NW_WBXML_Dictionary_t" +#define NAMES_T "NW_String_UCS2Buff_t" +#define ELEMENT_T "NW_%s_Element" +#define ATTRIBUTE_T "NW_%s_Attribute" +#define ELEMENT_TOKEN_T "NW_%s_ElementToken" +#define ATTRIBUTE_TOKEN_T "NW_%s_AttributeToken" + +/* ----------------------------------------------------------------------- ** + Misc array limits +** ----------------------------------------------------------------------- **/ +#define TABLE_SIZE 255 +#define MAX_LINE 255 +#define MAX_NAME 255 +#define MAX_TOKEN 4 +#define MAX_DICT_NAME 255 +#define MAX_PUBLIC_ID 255 +#define MAX_DOC_TYPE 255 +#define MAX_START_NAME 255 +#define MAX_TYPE_NAME 255 + +/* ----------------------------------------------------------------------- ** + Names used in the generated tables +** ----------------------------------------------------------------------- **/ +#define TAG_NAME "tag" +#define ATTR_NAME "attribute" + + +/* ----------------------------------------------------------------------- ** + Define a type for codepage storage +** ----------------------------------------------------------------------- **/ +typedef struct codepage_s { + int num; /* the code page number */ + int size; /* the number of entries in table */ +} codepage_t; + + +/* ----------------------------------------------------------------------- ** + Header information +** ----------------------------------------------------------------------- **/ +char dict_name[MAX_DICT_NAME]; +char doc_type[MAX_DOC_TYPE]; +char public_id[10]; + +/* ----------------------------------------------------------------------- ** + Scratch tables +** ----------------------------------------------------------------------- **/ +char * tokens[TABLE_SIZE]; +char * names[TABLE_SIZE]; +int sorted_indexes[TABLE_SIZE]; +codepage_t tag_codepages[TABLE_SIZE]; +codepage_t attr_codepages[TABLE_SIZE]; + + +/* ----------------------------------------------------------------------- ** + Records time of program execution and command line arguments +** ----------------------------------------------------------------------- **/ +static time_t timestamp; +static int main_argc = 1; +static char** main_argv; + +/* ----------------------------------------------------------------------- ** + Globals so error clean up is easy +** ----------------------------------------------------------------------- **/ +static FILE* input_dict; +static FILE* output_c; +static FILE* output_h; + +static void exit_error(int exit_code) { + static char errmsg[] + = "#error \"Bad input dictionary data cannot complete code generation\"\n"; + if (input_dict) fclose(input_dict); + if (output_c) { + fprintf(output_c, errmsg); + fclose(output_c); + } + if (output_h) { + fprintf(output_h, errmsg); + fclose(output_h); + } + exit(exit_code); +} + +void print_usage(char* progname) +{ + fprintf(stderr, + "Dictionary creator - creates a .c and .h source file for a\n" + "NW_Wbxml_Dictionary_t structure from a dictionary data file.\n" + "\n" + "Usage: %s data_input_file dot_c_output_file dot_h_output_file\n" + "\n" + " - all args are required\n" + "\n" + "Comments are defined to be:\n" + "\n" + " - A line whose first non-whitespace char is '#'\n" + " - A blank line or line with only whitespace\n" + " Note: Comments are NOT permitted at the end of other lines.\n" + "\n" + "Input format:\n" + "\n" + " - Dictionary name = the first non-comment line. The dictionary\n" + " that will be created will use this string in the dictionary \n" + " name. For example, if the dictionary name is \"wml\", the\n" + " following dictionary will be created:\n" + "\n" + " NW_Wbxml_Dictionary_t NW_wml_dictionary = { ... }\n" + "\n" + " - Public id = the second non-comment line. This is the Public \n" + " Identifier as specified in section 7.2 of the WBML spec. If\n" + " a public id has not been defined, use \"1\".\n" + "\n" + " - Doc Type = the third non-comment line. This is the source\n" + " document's Document Type Declaration.\n" + "\n" + " - The beginning of a Tag table has the following syntax:\n" + "\n" + " TAGS_FOR_CODE_PAGE [NO_STRINGS]\n" + "\n" + " is required and is a base 10 number\n" + "\n" + " [NO_STRINGS] is an optional keyword which means output only\n" + " the token structures, treat all token names as empty strings\n" + "\n" + " - The beginning of an Attribute table has the following syntax:\n" + "\n" + " ATTRIBUTES_FOR_CODE_PAGE [NO_STRINGS]\n" + " \n" + " is required and is a base 10 number\n" + "\n" + " [NO_STRINGS] is an optional keyword which means output only\n" + " the token structures, treat all token names as empty strings\n" + "\n" + " - The syntax for an entry is the same for both Tag and Attribute \n" + " tables\n" + "\n" + " \n" + "\n" + " must be a hexadecimal number written as 0x?? (e.g., 0x07)\n" + " NOTE: Tokens are sorted as strings so 0x7 MUST be entered as 0x07\n" + " or the sorting won't work! It is ok to mix case as all hex\n" + " digits are converted to lower case before the sort.\n" + "\n" + " is any sequence of printable characters without whitespace\n" + "\n" + " - The input tables do NOT have to be sorted \n" + "\n" + " - If a language has \"Attribute Value Tokens\", they should be included\n" + " in the Attribute table\n" + "\n" + "Example input file (example.dict):\n" + "\n" + " #\n" + " # Sample dictionary for the WML language\n" + " #\n" + " wml\n" + " #\n" + " # WML version 1.2 has a public id of 9\n" + " #\n" + " 9\n" + " #\n" + " # WML 1.2 doc type\n" + " #\n" + " -//WAPFORUM//DTD WML 1.1//EN\n" + " #\n" + " # Tags\n" + " #\n" + " TAGS_FOR_CODE_PAGE 0\n" + " 0x2b go\n" + " 0x1d td\n" + " #\n" + " # Attributes\n" + " #\n" + " ATTRIBUTES_FOR_CODE_PAGE 0\n" + " 0x12 format\n" + " 0xA0 wrap\n" + " 0x23 newcontext=true\n" + " 0x8F http://www.\n" + "\n" + "Example run command:\n" + "\n" + " %s example.dict example.c example.h\n", + progname, progname); +} + +static void print_automaticallyGeneratedCodeWarning(FILE *f) +{ + int i; + static char automaticallyGeneratedCodeWarning[] = + "/*\n" + "** WARNING\n" + "**\n" + "** DO NOT EDIT - THIS CODE IS AUTOMATICALLY GENERATED\n" + "** FROM A DATA FILE BY THE DICTIONARY CREATION PROGRAM"; + + fprintf(f, "%s\n", automaticallyGeneratedCodeWarning); + fprintf(f, + "**\n" + "** This file generated on %s" + "** (coordinated universal time)\n" + "**\n" + "** Command line: ", + asctime(gmtime(×tamp))); /* asctime() generates a newline at the end */ + fprintf(f, "%s", main_argv[0]); + for (i = 1; i < main_argc; i++) { + fprintf(f, " %s", main_argv[i]); + } + fprintf(f, "\n*/"); +} + +static void print_copyright(FILE *f) +{ + struct tm* tm_time; + static const char copyright[] = + "/* ****************************************************************\n" + "** Copyright %d - Nokia Corporation All rights reserved.\n" + "** Nokia Americas\n" + "** 6000 Connection Drive\n" + "** Irving, Texas 75039\n" + "**\n" + "** Restricted Rights: Use, duplication, or disclosure by the\n" + "** U.S. Government is subject to restrictions as set forth in\n" + "** subparagraph (c)(1)(ii) of DFARS 252.227-7013, or in FAR\n" + "** 52.227-19, or in FAR 52.227-14 Alt. III, as applicable.\n" + "**\n" + "** This software is proprietary to and embodies the confidential\n" + "** technology of Nokia Possession, use, or copying of this software\n" + "** and media is authorized only pursuant to a valid written license\n" + "** from Nokia or an authorized sublicensor.\n" + "**\n" + "** Nokia - Wireless Software Solutions\n" + "*****************************************************************/"; + + tm_time = gmtime(×tamp); + fprintf(f, copyright, + tm_time->tm_year + 1900); +} + +static FILE * open_file(char* fn, char *perms){ + FILE* f; + + if ((fn == 0)||((f = fopen(fn, perms)) == 0)){ + return 0; + }else{ + return f; + } + +} + +static init() { + int i; + + for (i=0; i < TABLE_SIZE; i++) { + tag_codepages[i].num = -1; + attr_codepages[i].num = -1; + } +} + + +/* ----------------------------------------------------------------------- ** + Read the next line of input and store it in s. + + NOTE: s will have the new-line character stripped + + RETURN: 1 for success and 0 for EOF or failure +** ----------------------------------------------------------------------- **/ +static int get_line(FILE *f, char s[], int n){ + int i = 0, j, indx, len; + char line[MAX_LINE]; + + for(;;) { + if ((fgets(line, n, f)) == 0) { + /* Either EOF or an error occurred */ + return 0; + } + len = (int) strlen(line); + /* Skip any preceeding whitespace */ + for (i=0; i < len; i++) { + if (isspace(line[i])) + continue; + break; + } + if (i >= len || line[i] == '#') + continue; + break; + } + + /* Fill in s */ + for (j=i, indx = 0; j < (int) strlen(line); i++, j++, indx++) { + if (line[j] == '\n') { + break; + } + if (line[j] == '\t') { + /* convert tab to space for isprint() test */ + line[j] = ' '; + } + if (!isprint(line[j])) { + /* stops on bogus char */ + fprintf(stderr, + "ERROR: Illegal character (may be control char) in input text " + "near file byte offset %ld\n", + ftell(f)); + exit_error(1); + } + s[indx] = line[j]; + if (indx + 1 == MAX_LINE) break; + } + + if (indx > 0) + s[indx] = '\000'; + + return 1; +} + + +/* ----------------------------------------------------------------------- ** + Read the a line of input and break it into three items: + For table header + 1. Table type name + 2. Code page number + 3. Optional "NO_STRINGS" + For table entry + 1. 0x?? token value + 2. token string (optional, extends from first nonspace to eol) + 3. null + + RETURN: 1 for success and 0 for EOF or failure + ** ----------------------------------------------------------------------- **/ +static int get_tuple(FILE *f, char item1[], char item2[], char item3[]) +{ + char line[MAX_LINE]; + int i; + int j; + int len; + + if ((get_line(f, line, MAX_LINE)) != 1) { + return 0; + } + + len = (int)strlen(line); + + /* tablename or token hex value */ + j = 0; + for (i = 0; i < len; i++) { + if (isspace(line[i])) break; + if (item1[0] == '0' && j == MAX_TOKEN) { + /* have to check for leading '0' because this func is called to process + TAG_TABLE_HEADING lines too where length could be longer than MAX_TOKEN */ + fprintf(stderr, "ERROR: token value too long near input file byte offset %ld\n", + ftell(f)); + exit_error(1); + break; + } + item1[j++] = line[i]; + } + item1[j] = '\0'; + + /* whitespace */ + for (; i < len; i++) { + if (!isspace(line[i])) break; + } + + /* codepage or token string */ + j = 0; + for (/* continue with i */; i < len; i++) { + if (item1[0] != '0' && isspace(line[i])) break; + if (j == MAX_NAME) { + fprintf(stderr, "ERROR: token string too long near input file byte offset %ld\n", + ftell(f)); + exit_error(1); + break; + } + item2[j++] = line[i]; + } + item2[j] = '\0'; + + /* whitespace */ + for (; i < len; i++) { + if (!isspace(line[i])) break; + } + + /* nostrings or nothing */ + j = 0; + for (/* continue with i */; i < len; i++) { + item3[j++] = line[i]; + } + item3[j] = '\0'; + + return 1; +} + +static void process_header(FILE *f) +{ + if ((get_line(f, dict_name, MAX_DICT_NAME)) != 1) { + fprintf(stderr, "ERROR: reading dictionary name\n"); + exit_error(1); + } + + if ((get_line(f, public_id, MAX_PUBLIC_ID)) != 1) { + fprintf(stderr, "ERROR: reading public id\n"); + exit_error(1); + } + + if ((get_line(f, doc_type, MAX_DOC_TYPE)) != 1) { + fprintf(stderr, "ERROR: reading doc type\n"); + exit_error(1); + } +} + +static void print_file_header(FILE *output, FILE *outputHeader) +{ + fprintf(output, "/*\n"); + fprintf(output, " * Dictionary = %s\n", dict_name); + fprintf(output, " * Public id = %s\n", public_id); + fprintf(output, " * Doc Type = %s\n", doc_type); + fprintf(output, " */\n"); + fprintf(output, "\n"); + + fprintf(output, "#include \"%s\"\n", main_argv[3]); + fprintf(output, "#include \"xml\/cxml\/nw_wbxml_dictionary.h\"\n"); + + fprintf(output, "\n"); + + /* Including the typedef for public id */ + fprintf(outputHeader, "#define NW_%s_PublicId %s\n", dict_name, public_id); +} + +static void print_table_header(FILE *output, char * table_type, char *type, char *key, char *code_page, int n) +{ + print_automaticallyGeneratedCodeWarning(output); + fprintf(output, "\n\n"); + fprintf(output, "/*\n"); + fprintf(output, " * %s entries - sorted by %s\n", type, key); + fprintf(output, " */\n"); + fprintf(output, "static const\n"); + fprintf(output, "%s NW_%s_%s_%s_%s[%d] = {\n", table_type, dict_name, type, key, code_page, n); +} + +static void process_entry(int i, char *token, char *name) +{ + tokens[i] = strdup(token); + names[i] = strdup(name); + sorted_indexes[i] = i; +} + + +/* ----------------------------------------------------------------------- ** + Print the table of tokens and names - sorted by token + Also create a list of the items, sorted by name + ** ----------------------------------------------------------------------- **/ +static void print_token_table(FILE *output, FILE* outputHeader, + char *type, char *key, char *code_page, int n, + int use_strings) +{ + static char tagTypeString[MAX_TYPE_NAME]; + static char tokenTypeString[MAX_TYPE_NAME]; + + /* Must first sort by token */ + int i, j; + char *tmp_token; + char *tmp_name; + char *tagType = &tagTypeString[0]; + + if (strcmp("tag", type) == 0) + { + (void)sprintf(tagTypeString, ELEMENT_T, dict_name); + (void)sprintf(tokenTypeString, ELEMENT_TOKEN_T, dict_name); + } + else if (strcmp("attribute", type) == 0) + { + (void)sprintf(tagTypeString, ATTRIBUTE_T, dict_name); + (void)sprintf(tokenTypeString, ATTRIBUTE_TOKEN_T, dict_name); + } + else { + fprintf(stderr, "ERROR: internal error\n"); + exit_error(1); + } + + /* make all the tokens lower case */ + for (i=0; i < n; i++) { + int l = (int)strlen(tokens[i]); + if (l != 4) { + fprintf(stderr, + "ERROR: Badly formatted token %s\n" + "All token values must be in the form 0x?? (e.g., 0x07) " + "or the sorting algorithm won't work.\n" + , tokens[i]); + exit_error(1); + } + for (j=0; j < l; j++) { + if (isupper(tokens[i][j])) { + tokens[i][j] = (char)tolower(tokens[i][j]); + } + if ((tokens[i][j] != 'x') && isalpha(tokens[i][j])) { + if ((tokens[i][j] < 'a') || (tokens[i][j] > 'f')) { + fprintf(stderr, + "ERROR: Illegal hex digit in token %s\n" + , tokens[i]); + exit_error(1); + } + } + } + } + + for (i=0; i < n-1; i++) { + for (j=0; j < n-1; j++) { + /* + * Sort by token + */ + if ((strcmp(tokens[j], tokens[j+1])) > 0) { + /* Swap the two elements */ + tmp_token = tokens[j]; + tmp_name = names[j]; + tokens[j] = tokens[j+1]; + names[j] = names[j+1]; + tokens[j+1] = tmp_token; + names[j+1] = tmp_name; + } + } + } + + /* + * print variables + */ + fprintf(output, "\n"); + for (i=0; i < n; i++) { + char tempName[MAX_NAME+1]; + int l; + if (isdigit(names[i][0])) { + tempName[0] = '_'; + strcpy(tempName+1, names[i]); + } else { + strcpy(tempName, names[i]); + } + l = (int)strlen(tempName); + for (j = 0; j < l; j++) { + if (isdigit(tempName[j]) + || isalpha(tempName[j]) + || (tempName[j] == '_')) { + continue; + } + tempName[j] = '_'; + } + if (use_strings) { + fprintf(output, + "static const NW_Ucs2 %sTag_%s[] = {" + , tagType, tempName); + for (j=0; j < (int) strlen(names[i]); j++) { + if (names[i][j] == '\\') { + fprintf(output, "\'\\\\\',"); + } else { + fprintf(output, "\'%c\',", names[i][j]); + } + } + fprintf(output, "\'\\0\'};\n"); + } + } + if (!use_strings) { + fprintf(output, + "static const NW_Ucs2 %sTag_emptyString_%s[] = { \'\\0\' };\n" + , tagType, code_page); + } + fprintf(output, "\n"); + + print_table_header(output, TOKEN_TABLE_T, type, key, code_page, n); + if (use_strings) { + fprintf(outputHeader, + "\ntypedef enum %sToken_%s_e{\n", + tagType, code_page); + } + /* + * Print the table + */ + for (i=0; i < n; i++) { + char tempName[MAX_NAME+1] ; + char tempToken[6] ; + char *token; + int l; + if (isdigit(names[i][0])) { + tempName[0] = '_'; + strcpy(tempName+1, names[i]); + } else { + strcpy(tempName, names[i]); + } + l = (int)strlen(tempName); + for (j = 0; j < l; j++) { + if (isdigit(tempName[j]) + || isalpha(tempName[j]) + || (tempName[j] == '_')) { + continue; + } + tempName[j] = '_'; + } + strcpy(tempToken, tokens[i]); + token = strchr(tempToken, 'x'); + token++; + if (use_strings) { + fprintf(output, "\t{%s, (%s *) %sTag_%s", tokens[i], NAMES_T, tagType, tempName); + fprintf(outputHeader, "\t%s_%s = 0x0%s%s", tokenTypeString, tempName, code_page, token); + } else { + fprintf(output, "\t{%s, &%sTag_emptyString_%s", tokens[i], tagType, code_page); + } + + if (i == (n-1)) + { + fprintf(output, "}\n"); + if (use_strings) { + fprintf(outputHeader, "\n"); + } + } + else + { + fprintf(output, "},\n"); + if (use_strings) { + fprintf(outputHeader, ",\n"); + } + } + } + fprintf(output, "};\n\n"); + if (use_strings) { + fprintf(outputHeader, "}%sToken_%s_t;\n\n", tagType, code_page); + } + + if (use_strings) { + /* + * Create an array of the names sorted by index + */ + for (i=0; i < n-1; i++) { + for (j=0; j < n-1; j++) { + /* + * Since we will need an array of the names sorted by index, + * generate that arrary now. + */ + if ((strcmp(names[j], names[j+1])) > 0) { + /* Swap the two names */ + int tmp_token; + tmp_name = names[j]; + tmp_token = sorted_indexes[j]; + names[j] = names[j+1]; + names[j+1] = tmp_name; + sorted_indexes[j] = sorted_indexes[j+1]; + sorted_indexes[j+1] = tmp_token; + } + } + } + } +} + +static void cache_codepage(codepage_t table[], char *cp_num, int n) +{ + int num = atoi(cp_num); + + if (num >= TABLE_SIZE) { + fprintf(stderr, "ERROR: Codepage '%d' is too large!\n", num); + exit(1); + } + + table[num].num = num; + table[num].size = n; +} + +/* + * Print a table of the names + */ +static void print_name_table(FILE *output, char *type, char *key, char *code_page, int n, + int use_strings) +{ + int i; + + print_table_header(output, NAME_TABLE_T, type, key, code_page, n); + + for (i=0; i < n; i++) { + if (use_strings) { + fprintf(output, "\t%d,\n", sorted_indexes[i]); + } else { + fprintf(output, "\t0,\n"); + } + } + + fprintf(output, "};\n"); +} + +static process_content(FILE *f, FILE *output, FILE* outputHeader) +{ + char token[MAX_START_NAME+1]; /* Must be big enough to hold a + tag/attr start string */ + char name[MAX_NAME+1]; + char optional[MAX_LINE+1]; + char *tag_code_page = ""; + char *attr_code_page = ""; + char processing_tag = 2; /* processing state: 1 = tag, 0 = attribute, 2 = init */ + int n = 0; + int use_strings = 1; + + for(;;) { + + if ((get_tuple(f, token, name, optional)) != 1) { + break; + } + + if (!strcmp(token, TAG_TABLE_HEADING)) { + use_strings = strcmp(optional, NO_STRINGS); + if (processing_tag == 1) { + /* Process the current tag table */ + print_token_table(output, outputHeader, TAG_NAME, "token", tag_code_page, n, use_strings); + print_name_table(output, TAG_NAME, "name", tag_code_page, n, use_strings); + cache_codepage(tag_codepages, tag_code_page, n); + n = 0; + } else if (processing_tag == 0) { + /* Process the current attribute table */ + print_token_table(output, outputHeader, ATTR_NAME, "token", attr_code_page, n, use_strings); + print_name_table(output, ATTR_NAME, "name", attr_code_page, n, use_strings); + cache_codepage(attr_codepages, attr_code_page, n); + n = 0; + } + tag_code_page = strdup(name); + processing_tag = 1; + } + else if (!strcmp(token, ATTR_TABLE_HEADING)) { + use_strings = strcmp(optional, NO_STRINGS); + if (processing_tag == 1) { + /* Process the current tag table */ + print_token_table(output, outputHeader, TAG_NAME, "token", tag_code_page, n, use_strings); + print_name_table(output, TAG_NAME, "name", tag_code_page, n, use_strings); + cache_codepage(tag_codepages, tag_code_page, n); + n = 0; + } else if (processing_tag == 0) { + /* Process the current attribute table */ + print_token_table(output, outputHeader, ATTR_NAME, "token", attr_code_page, n, use_strings); + print_name_table(output, ATTR_NAME, "name", attr_code_page, n, use_strings); + cache_codepage(attr_codepages, attr_code_page, n); + n = 0; + } + attr_code_page = strdup(name); + processing_tag = 0; + } else { + process_entry(n, token, name); + n++; + } + } + + if (processing_tag == 2) { + fprintf(stderr, + "ERROR: Could not find tag or attribute table starts in file.\n" + " Input file syntax has changed.\n" + " See usage by executing this program with no arguments.\n"); + exit_error(1); + } + + /* + * If anything is left, process it + */ + if (n > 0) { + if (processing_tag == 1) { + print_token_table(output, outputHeader, TAG_NAME, "token", tag_code_page, n, use_strings); + print_name_table(output, TAG_NAME, "name", tag_code_page, n, use_strings); + cache_codepage(tag_codepages, tag_code_page, n); + } else if (processing_tag == 0) { + print_token_table(output, outputHeader, ATTR_NAME, "token", attr_code_page, n, use_strings); + print_name_table(output, ATTR_NAME, "name", attr_code_page, n, use_strings); + cache_codepage(attr_codepages, attr_code_page, n); + } + } +} + +static void get_num_codepages(codepage_t cp[], int *n, int *max) +{ + int i; + /* Determine the number of codepages */ + for (i=0; i < TABLE_SIZE; i++) { + if (cp[i].num != -1) { + *max = i; + (*n)++; + } + } +} + +static void print_codepage_table(FILE *output, codepage_t cp[], int n, int max, char *type) +{ + int i; + + if (n == 0) + return; + + fprintf(output, "static const\n"); + fprintf(output, "%s NW_%s_%s_codepages[%d] = {\n", CODEPAGE_TABLE_T, + dict_name, type, max + 1); + + for (i=0; i <= max && i < TABLE_SIZE; i++) { + if (cp[i].num == -1) { + fprintf(output, "\t{0, 0, 0},\n"); + } else { + fprintf(output, "\t{%d, (%s*)&NW_%s_%s_token_%d[0], ", + cp[i].size, TOKEN_TABLE_T, dict_name, type, cp[i].num); + fprintf(output, "(NW_Byte *)&NW_%s_%s_name_%d[0]},\n", + dict_name, type, cp[i].num); + } + } + fprintf(output, "};\n"); +} + +static void print_codepage_tables(FILE *output) +{ + int n=0, max=0; + + /* Tag tables */ + fprintf(output, + "\n" + "/*\n" + " * Tag codepage table\n" + " */\n" + ); + + get_num_codepages(tag_codepages, &n, &max); + print_codepage_table(output, tag_codepages, n, max, TAG_NAME); + + /* Attr tables */ + fprintf(output, + "\n" + "/*\n" + " * Attribute codepage table\n" + " */\n" + ); + + n = max = 0; + get_num_codepages(attr_codepages, &n, &max); + print_codepage_table(output, attr_codepages, n, max, ATTR_NAME); +} + +static void add_codepage(FILE *output, codepage_t cp[], char *type) +{ + int n=0, max=0; + + get_num_codepages(cp, &n, &max); + + if (n == 0) + fprintf(output, "\t0, 0,\n"); + else + fprintf(output, "\t%d, (%s*)&NW_%s_%s_codepages[0],\n", max + 1, CODEPAGE_TABLE_T, dict_name, type); +} + +static void print_dictionary_table(FILE *output, FILE *outputHeader) +{ + int i; + if (strlen(doc_type) > 0) + { + fprintf(output, "\nstatic const NW_Ucs2 NW_%s_docType[] = {", dict_name); + for (i=0; i < (int) strlen(doc_type); i++) + fprintf(output, "\'%c\',", doc_type[i]); + fprintf(output, "\'\\0\'};\n"); + } + + fprintf(output, + "\n" + "/*\n" + " * Dictionary\n" + " */\n" + ); + + fprintf(outputHeader, "extern const %s NW_%s_WBXMLDictionary\n", + DICTIONARY_TABLE_T, dict_name); + fprintf(output, "%s NW_%s_WBXMLDictionary = {\n", DICTIONARY_TABLE_T, dict_name); + fprintf(output, "\tNW_%s_PublicId,\n", dict_name); + + /* Print the doc type as a UCS2 string */ + fprintf(output, "\t(%s *)NW_%s_docType,\n", "NW_Ucs2", dict_name); + + /* Add the tag and attribute code page */ + add_codepage(output, tag_codepages, TAG_NAME); + add_codepage(output, attr_codepages, ATTR_NAME); + + fprintf(output, "};\n"); +} + +static void process_file(FILE *f, FILE *output, FILE* outputHeader) +{ + process_header(f); + + print_file_header(output, outputHeader); + + process_content(f, output, outputHeader); + + print_codepage_tables(output); + + print_dictionary_table(output, outputHeader); +} + +int main(int argc, char ** argv){ + if (argc < 4) { + print_usage(argv[0]); + exit_error(1); + } + + init(); + + input_dict = NULL; + output_c = NULL; + output_h = NULL; + + /* ----------------------------------------------------------------------- ** + Save info used in print_automaticallyGeneratedCodeWarning() + ** ----------------------------------------------------------------------- **/ + (void)time(×tamp); + main_argc = argc; + main_argv = argv; + + + /* ----------------------------------------------------------------------- ** + Work on files in text mode to ease end-of-line processing in DOS. + ** ----------------------------------------------------------------------- **/ + if ((input_dict = open_file(argv[1], "rt")) == NULL) { + fprintf(stderr, "ERROR: Input File '%s' could NOT be opened!\n", argv[1]); + exit_error(1); + } + + if ((output_c = open_file(argv[2], "wt")) == NULL) { + fprintf(stderr, "ERROR: Output .c File '%s' could NOT be opened!\n", argv[2]); + exit_error(1); + } + + if ((output_h = open_file(argv[3], "wt")) == NULL) { + fprintf(stderr, "ERROR: Output .h File '%s' could NOT be opened!\n", argv[3]); + exit_error(1); + } + + print_copyright(output_c); + fprintf(output_c, "\n\n"); + print_automaticallyGeneratedCodeWarning(output_c); + fprintf(output_c, "\n\n"); + + print_copyright(output_h); + fprintf(output_h, "\n\n"); + print_automaticallyGeneratedCodeWarning(output_h); + fprintf(output_h, "\n\n"); + + { + int l; + char* p = strrchr(argv[3], '.'); + l = (p == NULL) ? (int)strlen(argv[3]) : p - argv[3]; + + fprintf(output_h, "#ifndef HEADER_GUARD_%.*s", l, argv[3]); + if (p != NULL) fprintf(output_h, "_%s", p+1); + fprintf(output_h, + "\n" + "#define HEADER_GUARD_%.*s" + , l, argv[3]); + if (p != NULL) fprintf(output_h, "_%s", p+1); + fprintf(output_h, + "\n" + "\n" + "#ifdef __cplusplus\n" + "extern \"C\"\n" + "{\n" + "#endif\n" + "\n" + "\n" + ); + } + + /* process input */ + process_file(input_dict, output_c, output_h); + + fprintf(output_c, "\n"); + print_automaticallyGeneratedCodeWarning(output_c); + + fprintf(output_c, "\n"); + fprintf(output_h, "\n"); + print_automaticallyGeneratedCodeWarning(output_h); + + fprintf(output_h, + "\n" + "\n" + "#ifdef __cplusplus\n" + "} /* extern \"C\" */\n" + "#endif\n" + "\n" + "#endif\n" + ); + + /* close files */ + fclose(input_dict); + fclose(output_c); + fclose(output_h); + + return 0; +}