diff options
Diffstat (limited to 'Build/source/texk/dvipdfm-x/otl_conf.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/otl_conf.c | 641 |
1 files changed, 641 insertions, 0 deletions
diff --git a/Build/source/texk/dvipdfm-x/otl_conf.c b/Build/source/texk/dvipdfm-x/otl_conf.c new file mode 100644 index 00000000000..cffbe505645 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/otl_conf.c @@ -0,0 +1,641 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +*/ + +#ifdef _HAVE_CONFIG_H +#include "config.h" +#endif /* _HAVE_CONFIG_H */ + +#include "system.h" +#include "error.h" +#include "mem.h" +#include "dpxfile.h" +#include "dpxutil.h" + +#include "pdfobj.h" +#include "pdfparse.h" + +#include "agl.h" + +#include "otl_conf.h" + +#define VERBOSE_LEVEL_MIN 0 +static int verbose = 0; +void +otl_conf_set_verbose (void) +{ + verbose++; +} + +static pdf_obj * +parse_uc_coverage (pdf_obj *gclass, const char **pp, const char *endptr) +{ + pdf_obj *coverage; + pdf_obj *value; + long ucv = 0; + char *glyphname, *glyphclass; + + if (*pp + 1 >= endptr) + return NULL; + + if (**pp == '[') + (*pp)++; + + coverage = pdf_new_array(); + + while (*pp < endptr) { + skip_white(pp, endptr); + switch (**pp) { + case ']': case ';': + (*pp)++; + return coverage; + break; + case ',': + (*pp)++; + break; + case '@': + { + pdf_obj *cvalues; + int i, size; + + (*pp)++; + glyphclass = parse_c_ident(pp, endptr); + cvalues = pdf_lookup_dict(gclass, glyphclass); + if (!cvalues) + ERROR("%s not defined...", glyphclass); + size = pdf_array_length(cvalues); + for (i = 0; i < size; i++) { + pdf_add_array(coverage, + pdf_link_obj(pdf_get_array(cvalues, i))); + } + } + break; + default: + glyphname = parse_c_ident(pp, endptr); + if (!glyphname) + ERROR("Invalid Unicode character specified."); + + skip_white(pp, endptr); + if (*pp + 1 < endptr && **pp == '-') { + value = pdf_new_array(); + + if (agl_get_unicodes(glyphname, &ucv, 1) != 1) + ERROR("Invalid Unicode char: %s", glyphname); + pdf_add_array(value, pdf_new_number(ucv)); + RELEASE(glyphname); + + (*pp)++; skip_white(pp, endptr); + glyphname = parse_c_ident(pp, endptr); + if (!glyphname) + ERROR("Invalid Unicode char: %s", glyphname); + if (agl_get_unicodes(glyphname, &ucv, 1) != 1) + ERROR("Invalid Unicode char: %s", glyphname); + pdf_add_array(value, pdf_new_number(ucv)); + RELEASE(glyphname); + + } else { + if (agl_get_unicodes(glyphname, &ucv, 1) != 1) + ERROR("Invalid Unicode char: %s", glyphname); + value = pdf_new_number(ucv); + RELEASE(glyphname); + } + pdf_add_array(coverage, value); + break; + } + skip_white(pp, endptr); + } + + return coverage; +} + +static pdf_obj *parse_block (pdf_obj *gclass, const char **pp, const char *endptr); + +static void +add_rule (pdf_obj *rule, pdf_obj *gclass, + char *first, char *second, char *suffix) +{ + pdf_obj *glyph1, *glyph2; +#define MAX_UNICODES 16 + long unicodes[MAX_UNICODES]; + int i, n_unicodes; + + if (first[0] == '@') { + glyph1 = pdf_lookup_dict(gclass, &first[1]); + if (!glyph1) { + WARN("No glyph class \"%s\" found.", &first[1]); + return; + } + pdf_link_obj(glyph1); + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otl_conf>> Output glyph sequence: %s\n", first); + } + + } else { + n_unicodes = agl_get_unicodes(first, unicodes, MAX_UNICODES); + if (n_unicodes < 1) { + WARN("Failed to convert glyph \"%s\" to Unicode sequence.", + first); + return; + } + glyph1 = pdf_new_array(); + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otl_conf>> Output glyph sequence: %s ->", first); + } + + for (i = 0; i < n_unicodes; i++) { + pdf_add_array(glyph1, pdf_new_number(unicodes[i])); + + if (verbose > VERBOSE_LEVEL_MIN) { + if (unicodes[i] < 0x10000) { + MESG(" U+%04X", unicodes[i]); + } else { + MESG(" U+%06X", unicodes[i]); + } + } + } + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("\n"); + } + } + + if (second[0] == '@') { + glyph2 = pdf_lookup_dict(gclass, &second[1]); + if (!glyph2) { + WARN("No glyph class \"%s\" found.", &second[1]); + return; + } + pdf_link_obj(glyph2); + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otl_conf>> Input glyph sequence: %s (%s)\n", second, suffix); + } + + } else { + n_unicodes = agl_get_unicodes(second, unicodes, 16); + if (n_unicodes < 1) { + WARN("Failed to convert glyph \"%s\" to Unicode sequence.", + second); + return; + } + + if (verbose > VERBOSE_LEVEL_MIN) { + if (suffix) + MESG("otl_conf>> Input glyph sequence: %s.%s ->", second, suffix); + else + MESG("otl_conf>> Input glyph sequence: %s ->", second); + } + + glyph2 = pdf_new_array(); + for (i = 0; i < n_unicodes; i++) { + pdf_add_array(glyph2, pdf_new_number(unicodes[i])); + + if (verbose > VERBOSE_LEVEL_MIN) { + if (unicodes[i] < 0x10000) { + MESG(" U+%04X", unicodes[i]); + } else { + MESG(" U+%06X", unicodes[i]); + } + } + } + if (verbose > VERBOSE_LEVEL_MIN) { + MESG(" (%s)\n", suffix); + } + } + + /* OK */ + if (suffix) { + pdf_add_array(rule, pdf_new_string(suffix, strlen(suffix))); + } else { + pdf_add_array(rule, pdf_new_null()); + } + pdf_add_array(rule, glyph1); + pdf_add_array(rule, glyph2); +} + +static pdf_obj * +parse_substrule (pdf_obj *gclass, const char **pp, const char *endptr) +{ + pdf_obj *substrule; + char *token; + + skip_white(pp, endptr); + if (*pp < endptr && **pp == '{') + (*pp)++; + + skip_white(pp, endptr); + if (*pp >= endptr) + return NULL; + + substrule = pdf_new_array(); + while (*pp < endptr && **pp != '}') { + skip_white(pp, endptr); + if (*pp >= endptr) + break; + + if (**pp == '#') { + while (*pp < endptr) { + if (**pp == '\r' || **pp == '\n') { + (*pp)++; + break; + } + (*pp)++; + } + continue; + } else if (**pp == ';') { + (*pp)++; + continue; + } + + skip_white(pp, endptr); + token = parse_c_ident(pp, endptr); + if (!token) + break; + + if (!strcmp(token, "assign") || !strcmp(token, "substitute")) { + char *tmp, *first, *second, *suffix; + + skip_white(pp, endptr); + + first = parse_c_ident(pp, endptr); + if (!first) + ERROR("Syntax error (1)"); + + skip_white(pp, endptr); + tmp = parse_c_ident(pp, endptr); + if (strcmp(tmp, "by") && strcmp(tmp, "to")) + ERROR("Syntax error (2): %s", *pp); + + skip_white(pp, endptr); + second = parse_c_ident(pp, endptr); /* allows @ */ + if (!second) + ERROR("Syntax error (3)"); + + /* (assign|substitute) tag dst src */ + pdf_add_array(substrule, pdf_new_name(token)); + if (*pp + 1 < endptr && **pp == '.') { + (*pp)++; + suffix = parse_c_ident(pp, endptr); + } else { + suffix = NULL; + } + add_rule(substrule, gclass, first, second, suffix); + + RELEASE(first); + RELEASE(tmp); + RELEASE(second); + if (suffix) + RELEASE(suffix); + } else { + ERROR("Unkown command %s.", token); + } + RELEASE(token); + skip_white(pp, endptr); + } + + if (*pp < endptr && **pp == '}') + (*pp)++; + return substrule; +} + +static pdf_obj * +parse_block (pdf_obj *gclass, const char **pp, const char *endptr) +{ + pdf_obj *rule; + char *token, *tmp; + + skip_white(pp, endptr); + if (*pp < endptr && **pp == '{') + (*pp)++; + + skip_white(pp, endptr); + if (*pp >= endptr) + return NULL; + + rule = pdf_new_dict(); + while (*pp < endptr && **pp != '}') { + skip_white(pp, endptr); + if (*pp >= endptr) + break; + if (**pp == '#') { + while (*pp < endptr) { + if (**pp == '\r' || **pp == '\n') { + (*pp)++; + break; + } + (*pp)++; + } + continue; + } else if (**pp == ';') { + (*pp)++; + continue; + } + + skip_white(pp, endptr); + token = parse_c_ident(pp, endptr); + if (!token) + break; + + if (!strcmp(token, "script") || + !strcmp(token, "language")) { + int i, len; + + skip_white(pp, endptr); + len = 0; + while (*pp + len < endptr && *(*pp + len) != ';') { + len++; + } + if (len > 0) { + tmp = NEW(len+1, char); + memset(tmp, 0, len+1); + for (i = 0; i < len; i++) { + if (!isspace(**pp)) + tmp[i] = **pp; + (*pp)++; + } + pdf_add_dict(rule, + pdf_new_name(token), + pdf_new_string(tmp, strlen(tmp))); + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otl_conf>> Current %s set to \"%s\"\n", token, tmp); + } + + RELEASE(tmp); + } + } else if (!strcmp(token, "option")) { + pdf_obj *opt_dict, *opt_rule; + + opt_dict = pdf_lookup_dict(rule, "option"); + if (!opt_dict) { + opt_dict = pdf_new_dict(); + pdf_add_dict(rule, + pdf_new_name("option"), opt_dict); + } + + skip_white(pp, endptr); + tmp = parse_c_ident(pp, endptr); + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otl_conf>> Reading option \"%s\"\n", tmp); + } + + skip_white(pp, endptr); + opt_rule = parse_block(gclass, pp, endptr); + pdf_add_dict(opt_dict, pdf_new_name(tmp), opt_rule); + + RELEASE(tmp); + } else if (!strcmp(token, "prefered") || + !strcmp(token, "required") || + !strcmp(token, "optional")) { + pdf_obj *subst, *rule_block; + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otl_conf>> Reading block (%s)\n", token); + } + + skip_white(pp, endptr); + if (*pp >= endptr || **pp != '{') + ERROR("Syntax error (1)"); + + rule_block = parse_substrule(gclass, pp, endptr); + subst = pdf_lookup_dict(rule, "rule"); + if (!subst) { + subst = pdf_new_array(); + pdf_add_dict(rule, pdf_new_name("rule"), subst); + } + pdf_add_array(subst, pdf_new_number(token[0])); + pdf_add_array(subst, rule_block); + } else if (token[0] == '@') { + pdf_obj *coverage; + + skip_white(pp, endptr); + (*pp)++; /* = */ + skip_white(pp, endptr); + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otl_conf>> Glyph class \"%s\"\n", token); + } + + coverage = parse_uc_coverage(gclass, pp, endptr); + if (!coverage) + ERROR("No valid Unicode characters..."); + + pdf_add_dict(gclass, + pdf_new_name(&token[1]), coverage); + } + RELEASE(token); + skip_white(pp, endptr); + } + + if (*pp < endptr && **pp == '}') + (*pp)++; + return rule; +} + + +static pdf_obj * +otl_read_conf (const char *conf_name) +{ + pdf_obj *rule; + pdf_obj *gclass; + FILE *fp; + char *filename, *wbuf, *p, *endptr; + const char *pp; + long size, len; + + filename = NEW(strlen(conf_name)+strlen(".otl")+1, char); + strcpy(filename, conf_name); + strcat(filename, ".otl"); + + fp = DPXFOPEN(filename, DPX_RES_TYPE_TEXT); + if (!fp) { + RELEASE(filename); + return NULL; + } + + size = file_size(fp); + rewind(fp); + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("\n"); + MESG("otl_conf>> Layout config. \"%s\" found: file=\"%s\" (%ld bytes)\n", + conf_name, filename, size); + } + RELEASE(filename); + if (size < 1) + return NULL; + + wbuf = NEW(size, char); + p = wbuf; endptr = p + size; + while (size > 0 && p < endptr) { + len = fread(p, sizeof(char), size, fp); + p += len; + size -= len; + } + + pp = wbuf; + gclass = pdf_new_dict(); + rule = parse_block(gclass, &pp, endptr); + pdf_release_obj(gclass); + + RELEASE(wbuf); + + return rule; +} + +static pdf_obj *otl_confs = NULL; + +pdf_obj * +otl_find_conf (const char *conf_name) +{ + pdf_obj *rule; + pdf_obj *script, *language; + pdf_obj *options; + + return NULL; + + if (otl_confs) + rule = pdf_lookup_dict(otl_confs, conf_name); + else { + otl_confs = pdf_new_dict(); + rule = NULL; + } + + if (!rule) { + rule = otl_read_conf(conf_name); + if (rule) { + pdf_add_dict(otl_confs, + pdf_new_name(conf_name), rule); + script = pdf_lookup_dict(rule, "script"); + language = pdf_lookup_dict(rule, "language"); + options = pdf_lookup_dict(rule, "option"); + if (!script) { + script = pdf_new_string("*", 1); + pdf_add_dict(rule, + pdf_new_name("script"), + script); + WARN("Script unspecified in \"%s\"...", conf_name); + } + if (!language) { + language = pdf_new_string("dflt", 4); + pdf_add_dict(rule, + pdf_new_name("language"), + language); + WARN("Language unspecified in \"%s\"...", conf_name); + } + + if (options) { + pdf_obj *optkeys, *opt, *key; + long i, num_opts; + + optkeys = pdf_dict_keys(options); + num_opts = pdf_array_length(optkeys); + for (i = 0; i < num_opts; i++) { + key = pdf_get_array(optkeys, i); + opt = pdf_lookup_dict(options, pdf_name_value(key)); + if (!pdf_lookup_dict(opt, "script")) + pdf_add_dict(opt, + pdf_new_name("script"), + pdf_link_obj(script)); + if (!pdf_lookup_dict(opt, "language")) + pdf_add_dict(opt, + pdf_new_name("language"), + pdf_link_obj(language)); + } + pdf_release_obj(optkeys); + } + + } + } + + return rule; +} + + +char * +otl_conf_get_script (pdf_obj *conf) +{ + pdf_obj *script; + + ASSERT(conf); + + script = pdf_lookup_dict(conf, "script"); + + return pdf_string_value(script); +} + +char * +otl_conf_get_language (pdf_obj *conf) +{ + pdf_obj *language; + + ASSERT(conf); + + language = pdf_lookup_dict(conf, "language"); + + return pdf_string_value(language); +} + +pdf_obj * +otl_conf_get_rule (pdf_obj *conf) +{ + ASSERT(conf); + return pdf_lookup_dict(conf, "rule"); +} + +pdf_obj * +otl_conf_find_opt (pdf_obj *conf, const char *opt_tag) +{ + pdf_obj *opt_conf = NULL; + pdf_obj *options; + + ASSERT(conf); + + options = pdf_lookup_dict(conf, "option"); + if (options && opt_tag) + opt_conf = pdf_lookup_dict(options, opt_tag); + else + opt_conf = NULL; + + return opt_conf; +} + +void +otl_init_conf (void) +{ + if (otl_confs) + pdf_release_obj(otl_confs); + otl_confs = pdf_new_dict(); + + if (verbose > VERBOSE_LEVEL_MIN + 10) { + pdf_release_obj(pdf_ref_obj(otl_confs)); + } +} + +void +otl_close_conf (void) +{ + pdf_release_obj(otl_confs); + otl_confs = NULL; +} |