From 7b52cc13af4e85f1ca2deb6b6c77de9c95ea0dcf Mon Sep 17 00:00:00 2001 From: scuri Date: Fri, 17 Oct 2008 06:10:33 +0000 Subject: First commit - moving from LuaForge to SourceForge --- src/pdflib/pdcore/pc_optparse.c | 1383 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1383 insertions(+) create mode 100644 src/pdflib/pdcore/pc_optparse.c (limited to 'src/pdflib/pdcore/pc_optparse.c') diff --git a/src/pdflib/pdcore/pc_optparse.c b/src/pdflib/pdcore/pc_optparse.c new file mode 100644 index 0000000..dee18ad --- /dev/null +++ b/src/pdflib/pdcore/pc_optparse.c @@ -0,0 +1,1383 @@ +/*---------------------------------------------------------------------------* + | PDFlib - A library for generating PDF on the fly | + +---------------------------------------------------------------------------+ + | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. | + +---------------------------------------------------------------------------+ + | | + | This software is subject to the PDFlib license. It is NOT in the | + | public domain. Extended versions and commercial licenses are | + | available, please check http://www.pdflib.com. | + | | + *---------------------------------------------------------------------------*/ + +/* $Id: pc_optparse.c,v 1.1 2008/10/17 06:10:43 scuri Exp $ + * + * Parser options routines + * + */ + +#include "pc_util.h" +#include "pc_geom.h" +#include "pc_ctype.h" + +/* result of an option */ +struct pdc_resopt_s +{ + int numdef; /* number of definitions */ + const pdc_defopt *defopt; /* pointer to option definition */ + int num; /* number of parsed values */ + void *val; /* list of parsed values */ + char *origval; /* original value as string */ + int flags; /* flags */ + int pcmask; /* percentage mask */ + int currind; /* index of current option */ + int lastind; /* index of last option */ + pdc_bool isutf8; /* optionlist UTF-8 encoded */ +}; + +/* sizes of option types. must be parallel to pdc_opttype */ +static const size_t pdc_typesizes[] = +{ + sizeof (pdc_bool), + sizeof (char *), + sizeof (int), + sizeof (int), + sizeof (float), + sizeof (double), + sizeof (pdc_scalar), + sizeof (int), + sizeof (pdc_polyline), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), + sizeof (int), +}; + +static const pdc_keyconn pdc_handletypes[] = +{ + {"3ddata", pdc_3ddatahandle}, + {"3dview", pdc_3dviewhandle}, + {"action", pdc_actionhandle}, + {"bookmark", pdc_bookmarkhandle}, + {"color", pdc_colorhandle}, + {"document", pdc_documenthandle}, + {"font", pdc_fonthandle}, + {"gstate", pdc_gstatehandle}, + {"iccprofile", pdc_iccprofilehandle}, + {"image", pdc_imagehandle}, + {"layer", pdc_layerhandle}, + {"page", pdc_pagehandle}, + {"pattern", pdc_patternhandle}, + {"shading", pdc_shadinghandle}, + {"table", pdc_tablehandle}, + {"template", pdc_templatehandle}, + {"textflow", pdc_textflowhandle}, + {"string", pdc_stringhandle}, + {NULL, 0} +}; + +int +pdc_get_keycode(const char *keyword, const pdc_keyconn *keyconn) +{ + int i; + for (i = 0; keyconn[i].word != 0; i++) + { + if (!strcmp(keyword, keyconn[i].word)) + return keyconn[i].code; + } + return PDC_KEY_NOTFOUND; +} + +int +pdc_get_keycode_ci(const char *keyword, const pdc_keyconn *keyconn) +{ + int i; + for (i = 0; keyconn[i].word != 0; i++) + { + if (!pdc_stricmp(keyword, keyconn[i].word)) + return keyconn[i].code; + } + return PDC_KEY_NOTFOUND; +} + +int +pdc_get_keycode_unique(const char *keyword, const pdc_keyconn *keyconn) +{ + int i, j; + size_t len = strlen(keyword); + + for (i = 0; keyconn[i].word != 0; i++) + { + if (!strncmp(keyword, keyconn[i].word, len)) + { + for (j = i + 1; keyconn[j].word != 0; j++) + if (!strncmp(keyword, keyconn[j].word, len)) + return PDC_KEY_NOTUNIQUE; + return keyconn[i].code; + } + } + return PDC_KEY_NOTFOUND; +} + +int +pdc_get_keymask_ci(pdc_core *pdc, const char *option, + const char *keywordlist, const pdc_keyconn *keyconn) +{ + char **keys = NULL; + int nkeys, i, j, k = 0; + + nkeys = pdc_split_stringlist(pdc, keywordlist, NULL, 0, &keys); + + for (j = 0; j < nkeys; j++) + { + for (i = 0; keyconn[i].word != NULL; i++) + if (!pdc_stricmp(keys[j], keyconn[i].word)) + break; + + if (keyconn[i].word == NULL) + { + const char *stemp = pdc_errprintf(pdc, "%.*s", + PDC_ERR_MAXSTRLEN, keys[j]); + pdc_cleanup_stringlist(pdc, keys); + pdc_set_errmsg(pdc, PDC_E_OPT_ILLKEYWORD, option, stemp, 0, 0); + return PDC_KEY_NOTFOUND; + } + + k |= keyconn[i].code; + } + + pdc_cleanup_stringlist(pdc, keys); + return k; +} + +/* + * flags: PDC_INT_HEXADEC, PDC_INT_CASESENS + */ +int +pdc_get_keycode_num(pdc_core *pdc, const char *option, const char *i_keyword, + int flags, const pdc_keyconn *keyconn, int *o_num) +{ + static const char *fn = "pdc_get_keycode_num"; + char *keyword; + int i, len, keycode; + + keyword = pdc_strdup_ext(pdc, i_keyword, 0, fn); + len = (int) strlen(keyword); + *o_num = -1; + + /* parse number */ + for (i = 0; i < len; i++) + { + if (pdc_isdigit(keyword[i])) + { + if (pdc_str2integer(&keyword[i], flags, o_num)) + { + keyword[i] = 0; + } + else + { + pdc_set_errmsg(pdc, PDC_E_OPT_ILLINTEGER, option, &keyword[i], + 0, 0); + } + break; + } + } + + if (flags & PDC_INT_CASESENS) + keycode = pdc_get_keycode(keyword, keyconn); + else + keycode = pdc_get_keycode_ci(keyword, keyconn); + + if (keycode == PDC_KEY_NOTFOUND) + pdc_set_errmsg(pdc, PDC_E_OPT_ILLKEYWORD, option, keyword, 0, 0); + + pdc_free(pdc, keyword); + + return keycode; +} + +const char * +pdc_get_keyword(int keycode, const pdc_keyconn *keyconn) +{ + int i; + for (i = 0; keyconn[i].word != 0; i++) + { + if (keycode == keyconn[i].code) + return keyconn[i].word; + } + return NULL; +} + +const char * +pdc_get_int_keyword(const char *keyword, const pdc_keyconn *keyconn) +{ + int i; + for (i = 0; keyconn[i].word != 0; i++) + { + if (!pdc_stricmp(keyword, keyconn[i].word)) + return keyconn[i].word; + } + return NULL; +} + +void +pdc_cleanup_optstringlist(pdc_core *pdc, char **stringlist, int ns) +{ + int j; + + for (j = 0; j < ns; j++) + { + if (stringlist[j] != NULL) + pdc_free(pdc, stringlist[j]); + } + pdc_free(pdc, stringlist); +} + +static void +pdc_delete_optvalue(pdc_core *pdc, pdc_resopt *resopt) +{ + if (resopt->val && !(resopt->flags & PDC_OPT_SAVEALL)) + { + int j; + int ja = (resopt->flags & PDC_OPT_SAVE1ELEM) ? 1 : 0; + + if (resopt->defopt->type == pdc_stringlist) + { + char **s = (char **) resopt->val; + for (j = ja; j < resopt->num; j++) + if (s[j] != NULL) + pdc_free(pdc, s[j]); + } + else if (resopt->defopt->type == pdc_polylinelist) + { + pdc_polyline *pl = (pdc_polyline *) resopt->val; + for (j = ja; j < resopt->num; j++) + if (pl[j].p != NULL) + pdc_free(pdc, pl[j].p); + } + pdc_free(pdc, resopt->val); + resopt->val = NULL; + } + if (resopt->origval && !(resopt->flags & PDC_OPT_SAVEORIG)) + { + pdc_free(pdc, resopt->origval); + resopt->origval = NULL; + } + resopt->num = 0; +} + +static int +pdc_optname_compare(const void *a, const void *b) +{ + return (strcmp(((pdc_resopt *)a)->defopt->name, + ((pdc_resopt *)b)->defopt->name)); +} + +/* destructor function for freeing temporary memory */ +static void +pdc_cleanup_optionlist_tmp(void *opaque, void *mem) +{ + if (mem) + { + pdc_core *pdc = (pdc_core *) opaque; + pdc_resopt *resopt = (pdc_resopt *) mem; + int i; + + for (i = 0; i < resopt[0].numdef; i++) + pdc_delete_optvalue(pdc, &resopt[i]); + } +} + +pdc_resopt * +pdc_parse_optionlist(pdc_core *pdc, const char *optlist, + const pdc_defopt *defopt, + const pdc_clientdata *clientdata, pdc_bool verbose) +{ + static const char *fn = "pdc_parse_optionlist"; + pdc_bool logg5 = pdc_logg_is_enabled(pdc, 5, trc_optlist); + const char *stemp1 = NULL, *stemp2 = NULL, *stemp3 = NULL; + char **items = NULL, *keyword = NULL; + char **values = NULL, *value = NULL, **strings = NULL; + int i, j, k, nd, is, iss, it, iv; + int numdef, nitems = 0, nvalues, ncoords = 0, errcode = 0; + void *resval; + double dz, maxval; + int retval, iz; + pdc_sint32 lz = 0; + pdc_uint32 ulz = 0; + size_t len; + const pdc_defopt *dopt = NULL; + pdc_resopt *resopt = NULL; + pdc_bool ignore = pdc_false; + pdc_bool boolval = pdc_false; + pdc_bool tocheck = pdc_false; + pdc_bool issorted = pdc_true; + pdc_bool ishandle = pdc_true; + pdc_bool isutf8 = pdc_false; + + pdc_logg_cond(pdc, 1, trc_optlist, "\n\tOption list: \"%T\"\n", + optlist ? optlist : "", 0); + + /* split option list */ + if (optlist != NULL) + { + nitems = pdc_split_stringlist(pdc, optlist, PDC_OPT_LISTSEPS, + PDC_SPLIT_ISOPTLIST, &items); + isutf8 = pdc_is_utf8_bytecode(optlist); + } + if (nitems < 0) + { + keyword = (char *) optlist; + errcode = PDC_E_OPT_NOTBAL; + goto PDC_OPT_SYNTAXERROR; + } + + /* initialize result list */ + for (numdef = 0; defopt[numdef].name != NULL; numdef++) + { + /* */ ; + } + + /* allocate temporary memory for option parser result struct */ + resopt = (pdc_resopt *) pdc_calloc_tmp(pdc, numdef * sizeof(pdc_resopt), + fn, pdc, pdc_cleanup_optionlist_tmp); + for (i = 0; i < numdef; i++) + { + resopt[i].numdef = numdef; + resopt[i].defopt = &defopt[i]; + + if (defopt[i].flags & PDC_OPT_IGNOREIF1 || + defopt[i].flags & PDC_OPT_IGNOREIF2 || + defopt[i].flags & PDC_OPT_REQUIRIF1 || + defopt[i].flags & PDC_OPT_REQUIRIF2 || + defopt[i].flags & PDC_OPT_REQUIRED) + tocheck = pdc_true; + + if (i && issorted) + issorted = (strcmp(defopt[i-1].name, defopt[i].name) <= 0) ? + pdc_true : pdc_false; + } + + /* loop over all option list elements */ + for (is = 0; is < nitems; is++) + { + /* search keyword */ + boolval = pdc_undef; + keyword = items[is]; + for (it = 0; it < numdef; it++) + { + /* special handling for booleans */ + if (defopt[it].type == pdc_booleanlist) + { + if (!pdc_stricmp(keyword, defopt[it].name) || + (keyword[1] != 0 && + !pdc_stricmp(&keyword[2], defopt[it].name))) + { + iss = is + 1; + if (iss == nitems || + (pdc_stricmp(items[iss], "true") && + pdc_stricmp(items[iss], "false"))) + { + i = pdc_strincmp(defopt[it].name, "no", 2) ? 0 : 2; + if (!pdc_strincmp(&keyword[i], "no", 2)) + { + boolval = pdc_false; + break; + } + else + { + boolval = pdc_true; + break; + } + } + } + } + + if (!pdc_stricmp(keyword, defopt[it].name)) break; + } + + if (logg5) + pdc_logg(pdc, "\t\t\toption \"%s\" specified: ", keyword); + + if (it == numdef) + { + errcode = PDC_E_OPT_UNKNOWNKEY; + goto PDC_OPT_SYNTAXERROR; + } + + /* initialize */ + dopt = &defopt[it]; + ignore = pdc_false; + nvalues = 1; + values = NULL; + ishandle = pdc_true; + + /* compatibility */ + if (clientdata && clientdata->compatibility) + { + int compatibility = clientdata->compatibility; + + for (iv = PDC_1_3; iv <= PDC_X_X_LAST; iv++) + { + if (logg5 && (dopt->flags & (1L<= %s) ", + pdc_get_pdfversion(pdc, iv)); + + if ((dopt->flags & (1L<flags & PDC_OPT_UNSUPP) + { + if (logg5) + pdc_logg(pdc, "(unsupported)\n"); + + keyword = (char *) dopt->name; + errcode = PDC_E_OPT_UNSUPP; + goto PDC_OPT_SYNTAXERROR; + } + + /* parse values */ + if (boolval == pdc_undef) + { + is++; + if (is == nitems) + { + errcode = PDC_E_OPT_NOVALUES; + goto PDC_OPT_SYNTAXERROR; + } + if (!ignore) + { + if (dopt->type == pdc_stringlist && + pdc_is_utf8_bytecode(items[is])) + resopt[it].flags |= PDC_OPT_ISUTF8; + + if (dopt->type != pdc_stringlist || dopt->maxnum > 1) + nvalues = pdc_split_stringlist(pdc, items[is], + (dopt->flags & PDC_OPT_SUBOPTLIST) ? + PDC_OPT_LISTSEPS : NULL, + PDC_SPLIT_ISOPTLIST, &values); + + if (dopt->flags & PDC_OPT_DUPORIGVAL) + resopt[it].origval = pdc_strdup(pdc, items[is]); + } + } + + /* ignore */ + if (ignore) continue; + + /* number of values check */ + if (nvalues < dopt->minnum) + { + stemp2 = pdc_errprintf(pdc, "%d", dopt->minnum); + errcode = PDC_E_OPT_TOOFEWVALUES; + goto PDC_OPT_SYNTAXERROR; + } + else if (nvalues > dopt->maxnum) + { + stemp2 = pdc_errprintf(pdc, "%d", dopt->maxnum); + errcode = PDC_E_OPT_TOOMANYVALUES; + goto PDC_OPT_SYNTAXERROR; + } + + /* number of values must be even */ + if (dopt->flags & PDC_OPT_EVENNUM && (nvalues % 2)) + { + errcode = PDC_E_OPT_ODDNUM; + goto PDC_OPT_SYNTAXERROR; + } + + /* number of values must be odd */ + if (dopt->flags & PDC_OPT_ODDNUM && !(nvalues % 2)) + { + errcode = PDC_E_OPT_EVENNUM; + goto PDC_OPT_SYNTAXERROR; + } + + /* option already exists */ + if (resopt[it].num) + { + pdc_delete_optvalue(pdc, &resopt[it]); + } + + /* no values */ + if (!nvalues ) continue; + + /* maximal value */ + switch (dopt->type) + { + case pdc_3ddatahandle: + maxval = clientdata->max3ddata; + break; + + case pdc_3dviewhandle: + maxval = clientdata->max3dview; + break; + + case pdc_actionhandle: + maxval = clientdata->maxaction; + break; + + case pdc_bookmarkhandle: + maxval = clientdata->maxbookmark; + break; + + case pdc_colorhandle: + maxval = clientdata->maxcolor; + break; + + case pdc_documenthandle: + maxval = clientdata->maxdocument; + break; + + case pdc_fonthandle: + maxval = clientdata->maxfont; + break; + + case pdc_gstatehandle: + maxval = clientdata->maxgstate; + break; + + case pdc_iccprofilehandle: + maxval = clientdata->maxiccprofile; + break; + + case pdc_imagehandle: + maxval = clientdata->maximage; + break; + + case pdc_layerhandle: + maxval = clientdata->maxlayer; + break; + + case pdc_pagehandle: + maxval = clientdata->maxpage; + break; + + case pdc_patternhandle: + maxval = clientdata->maxpattern; + break; + + case pdc_shadinghandle: + maxval = clientdata->maxshading; + break; + + case pdc_tablehandle: + maxval = clientdata->maxtable; + break; + + case pdc_templatehandle: + maxval = clientdata->maxtemplate; + break; + + case pdc_textflowhandle: + maxval = clientdata->maxtextflow; + break; + + case pdc_stringhandle: + maxval = clientdata->maxstring; + break; + + case pdc_polylinelist: + ncoords = 0; + + default: + maxval = dopt->maxval; + ishandle = pdc_false; + break; + } + + /* allocate value array */ + resopt[it].val = pdc_calloc(pdc, + (size_t) (nvalues * pdc_typesizes[dopt->type]), fn); + resopt[it].num = nvalues; + resopt[it].currind = it; + + if (logg5) + pdc_logg(pdc, "{"); + + /* analyze type */ + resval = resopt[it].val; + for (iv = 0; iv < nvalues; iv++) + { + errcode = 0; + if (dopt->maxnum > 1 && nvalues) + value = values[iv]; + else + value = items[is]; + if (logg5) + pdc_logg(pdc, "%s{%T}", iv ? " " : "", value, 0); + switch (dopt->type) + { + /* boolean list */ + case pdc_booleanlist: + if (boolval == pdc_true || !pdc_stricmp(value, "true")) + { + *(pdc_bool *) resval = pdc_true; + } + else if (boolval == pdc_false || !pdc_stricmp(value, "false")) + { + *(pdc_bool *) resval = pdc_false; + } + else + { + errcode = PDC_E_OPT_ILLBOOLEAN; + } + break; + + /* string list */ + case pdc_stringlist: + if (dopt->flags & PDC_OPT_NOSPACES) + { + if (pdc_split_stringlist(pdc, value, NULL, 0, &strings) > 1) + errcode = PDC_E_OPT_ILLSPACES; + pdc_cleanup_stringlist(pdc, strings); + } + if (!errcode) + { + len = strlen(value); + dz = (double) len; + if (dz < dopt->minval) + { + stemp3 = pdc_errprintf(pdc, "%d", (int) dopt->minval); + errcode = PDC_E_OPT_TOOSHORTSTR; + } + else if (dz > maxval) + { + stemp3 = pdc_errprintf(pdc, "%d", (int) maxval); + errcode = PDC_E_OPT_TOOLONGSTR; + } + + if (dopt->flags & PDC_OPT_CONVUTF8) + { + int flags = PDC_CONV_EBCDIC | PDC_CONV_WITHBOM; + + if (isutf8 || (resopt[it].flags & PDC_OPT_ISUTF8)) + flags |= PDC_CONV_ISUTF8; + + *((char **) resval) = + pdc_convert_name(pdc, value, 0, flags); + } + else + { + *((char **) resval) = pdc_strdup(pdc, value); + } + } + break; + + /* keyword list */ + case pdc_keywordlist: + if (dopt->flags & PDC_OPT_CASESENS) + iz = pdc_get_keycode(value, dopt->keylist); + else + iz = pdc_get_keycode_ci(value, dopt->keylist); + if (iz == PDC_KEY_NOTFOUND) + { + errcode = PDC_E_OPT_ILLKEYWORD; + } + else + { + *(int *) resval = iz; + } + break; + + /* character list */ + case pdc_unicharlist: + iz = pdc_string2unicode(pdc, value, dopt->flags, dopt->keylist, + pdc_false); + if (iz < 0) + { + errcode = PDC_E_OPT_ILLCHAR; + break; + } + dz = iz; + if (dz < dopt->minval) + { + stemp3 = pdc_errprintf(pdc, "%g", dopt->minval); + errcode = PDC_E_OPT_TOOSMALLVAL; + } + else if (dz > maxval) + { + stemp3 = pdc_errprintf(pdc, "%g", maxval); + errcode = PDC_E_OPT_TOOBIGVAL; + } + *(int *) resval = iz; + break; + + /* string list */ + case pdc_polylinelist: + { + int np = pdc_split_stringlist(pdc, value, NULL, 0, + &strings); + pdc_polyline *pl = (pdc_polyline *) resval; + + pl->np = np / 2; + pl->p = NULL; + + /* number of coordinates must be even */ + if (np % 2) + { + errcode = PDC_E_OPT_ODDNUM; + np = 0; + } + + /* polyline must be a box */ + else if ((dopt->flags & PDC_OPT_ISBOX) && np != 4) + { + errcode = PDC_E_OPT_ILLBOX; + np = 0; + } + + /* polyline will be closed */ + else if ((dopt->flags & PDC_OPT_CLOSEPOLY) && np <= 4) + { + errcode = PDC_E_OPT_ILLPOLYLINE; + np = 0; + } + + /* polyline not empty */ + if (np) + { + if (dopt->flags & PDC_OPT_CLOSEPOLY) + pl->np += 1; + pl->p = (pdc_vector *) pdc_malloc(pdc, + pl->np * sizeof(pdc_vector), fn); + + iz = PDC_KEY_NOTFOUND; + j = 0; + for (i = 0; i < np; i++) + { + char *sk = strings[i]; + + if (dopt->keylist) + { + /* optional keyword list */ + if (dopt->flags & PDC_OPT_CASESENS) + iz = pdc_get_keycode(sk, dopt->keylist); + else + iz = pdc_get_keycode_ci(sk, dopt->keylist); + } + if (iz == PDC_KEY_NOTFOUND) + { + /* percentage */ + if (dopt->flags & PDC_OPT_PERCENT) + { + k = (int) strlen(sk) - 1; + if (sk[k] == '%') + { + sk[k] = 0; + if (ncoords < 32) + { + resopt[it].pcmask |= (1L <flags & PDC_OPT_PERCRANGE) + { + if (dz < 0) + errcode = PDC_E_OPT_TOOSMALLPERCVAL; + if (dz > 100) + errcode = PDC_E_OPT_TOOBIGPERCVAL; + } + dz /= 100.0; + } + } + else + { + dz = (double) iz; + } + + if (!(i % 2)) + { + pl->p[j].x = dz; + } + else + { + pl->p[j].y = dz; + j++; + } + ncoords++; + } + + if (dopt->flags & PDC_OPT_CLOSEPOLY) + pl->p[pl->np - 1] = pl->p[0]; + } + pdc_cleanup_stringlist(pdc, strings); + } + break; + + /* number list */ + case pdc_3ddatahandle: + case pdc_3dviewhandle: + case pdc_actionhandle: + case pdc_bookmarkhandle: + case pdc_colorhandle: + case pdc_documenthandle: + case pdc_fonthandle: + case pdc_gstatehandle: + case pdc_iccprofilehandle: + case pdc_imagehandle: + case pdc_layerhandle: + case pdc_pagehandle: + case pdc_patternhandle: + case pdc_shadinghandle: + case pdc_tablehandle: + case pdc_templatehandle: + case pdc_textflowhandle: + case pdc_integerlist: + case pdc_floatlist: + case pdc_doublelist: + case pdc_scalarlist: + + if (dopt->keylist && + (!(dopt->flags & PDC_OPT_KEYLIST1) || !iv)) + { + /* optional keyword and/or allowed integer list */ + if (dopt->flags & PDC_OPT_CASESENS) + iz = pdc_get_keycode(value, dopt->keylist); + else + iz = pdc_get_keycode_ci(value, dopt->keylist); + if (iz == PDC_KEY_NOTFOUND) + { + if (dopt->flags & PDC_OPT_INTLIST) + { + errcode = PDC_E_OPT_ILLINTEGER; + break; + } + } + else + { + switch (dopt->type) + { + default: + case pdc_integerlist: + *(int *) resval = iz; + break; + + case pdc_floatlist: + *(float *) resval = (float) iz; + break; + + case pdc_doublelist: + *(double *) resval = (double) iz; + break; + + case pdc_scalarlist: + *(pdc_scalar *) resval = (pdc_scalar) iz; + break; + } + break; + } + } + + /* percentage */ + if (dopt->flags & PDC_OPT_PERCENT) + { + i = (int) strlen(value) - 1; + if (value[i] == '%') + { + value[i] = 0; + if (iv < 32) + { + resopt[it].pcmask |= (1L << iv); + } + else + { + errcode = PDC_E_OPT_TOOMANYPERCVALS; + } + } + else + { + resopt[it].pcmask &= ~(1L << iv); + } + } + + case pdc_stringhandle: + + if (dopt->type == pdc_floatlist || + dopt->type == pdc_doublelist || + dopt->type == pdc_scalarlist) + { + retval = pdc_str2double(value, &dz); + } + else + { + if (dopt->minval >= 0) + { + retval = pdc_str2integer(value, PDC_INT_UNSIGNED, &ulz); + dz = ulz; + } + else + { + retval = pdc_str2integer(value, 0, &lz); + dz = lz; + } + + if (retval && ishandle && pdc->hastobepos && + dopt->type != pdc_bookmarkhandle && + dopt->type != pdc_stringhandle) + { + dz -= 1; + lz = (pdc_sint32) dz; + ulz = (pdc_uint32) dz; + } + } + if (!retval) + { + errcode = PDC_E_OPT_ILLNUMBER; + } + else + { + if (resopt[it].pcmask & (1L << iv)) + { + if (dopt->flags & PDC_OPT_PERCRANGE) + { + if (dz < 0) + errcode = PDC_E_OPT_TOOSMALLPERCVAL; + if (dz > 100) + errcode = PDC_E_OPT_TOOBIGPERCVAL; + } + dz /= 100.0; + } + + if (errcode == 0) + { + if (dz < dopt->minval) + { + if (ishandle) + { + stemp3 = pdc_get_keyword(dopt->type, + pdc_handletypes); + errcode = PDC_E_OPT_ILLHANDLE; + } + else + { + stemp3 = pdc_errprintf(pdc, "%g", dopt->minval); + errcode = PDC_E_OPT_TOOSMALLVAL; + } + } + else if (dz > maxval) + { + if (ishandle) + { + stemp3 = pdc_get_keyword(dopt->type, + pdc_handletypes); + errcode = PDC_E_OPT_ILLHANDLE; + } + else + { + stemp3 = pdc_errprintf(pdc, "%g", maxval); + errcode = PDC_E_OPT_TOOBIGVAL; + } + } + else if (dopt->flags & PDC_OPT_NOZERO && + fabs(dz) < PDC_FLOAT_PREC) + { + errcode = PDC_E_OPT_ZEROVAL; + } + else if (dopt->type == pdc_scalarlist) + { + *(pdc_scalar *) resval = dz; + } + else if (dopt->type == pdc_doublelist) + { + *(double *) resval = dz; + } + else if (dopt->type == pdc_floatlist) + { + *(float *) resval = (float) dz; + } + else + { + if (dopt->minval >= 0) + *(pdc_uint32 *) resval = ulz; + else + *(pdc_sint32 *) resval = lz; + } + } + } + break; + } + + if (errcode) + { + stemp2 = pdc_errprintf(pdc, "%.*s", PDC_ERR_MAXSTRLEN, value); + goto PDC_OPT_SYNTAXERROR; + } + + /* increment value pointer */ + resval = (void *) ((char *)(resval) + pdc_typesizes[dopt->type]); + } + pdc_cleanup_stringlist(pdc, values); + values = NULL; + + if (logg5) + pdc_logg(pdc, "}\n"); + + /* build OR bit pattern */ + if (dopt->flags & PDC_OPT_BUILDOR && nvalues > 1) + { + int *bcode = (int *) resopt[it].val; + for (iv = 1; iv < nvalues; iv++) + { + bcode[0] |= bcode[iv]; + } + resopt[it].num = 1; + } + } + pdc_cleanup_stringlist(pdc, items); + items = NULL; + + /* required and to be ignored options */ + for (is = 0; tocheck && is < numdef; is++) + { + /* to be ignored option */ + if (resopt[is].num) + { + nd = 0; + if (defopt[is].flags & PDC_OPT_IGNOREIF1) nd = 1; + if (defopt[is].flags & PDC_OPT_IGNOREIF2) nd = 2; + for (it = is - 1; it >= is - nd && it >= 0; it--) + { + if (resopt[it].num) + { + pdc_delete_optvalue(pdc, &resopt[is]); + if (verbose) + pdc_warning(pdc, PDC_E_OPT_IGNORE, defopt[is].name, + defopt[it].name, 0, 0); + } + } + } + + /* required option */ + if (!resopt[is].num && + ((defopt[is].flags & PDC_OPT_REQUIRED) || + (defopt[is].flags & PDC_OPT_REQUIRIF1 && resopt[is-1].num) || + (defopt[is].flags & PDC_OPT_REQUIRIF2 && + (resopt[is-1].num || resopt[is-2].num)))) + { + keyword = (char *) defopt[is].name; + errcode = PDC_E_OPT_NOTFOUND; + goto PDC_OPT_SYNTAXERROR; + } + } + + /* is no sorted */ + if (!issorted) + { + qsort((void *)resopt, (size_t) numdef, sizeof(pdc_resopt), + pdc_optname_compare); + } + + /* global UTF-8 check after sort */ + if (isutf8) + resopt[0].isutf8 = pdc_true; + + /* index of last got option */ + resopt[0].lastind = -1; + + /* protocol */ + if (pdc_logg_is_enabled(pdc, 1, trc_optlist)) + { + for (is = 0; is < numdef; is++) + { + if (resopt[is].num) + pdc_logg(pdc, "\tOption \"%s\": %d value%s found\n", + resopt[is].defopt->name, resopt[is].num, + resopt[is].num == 1 ? "" : "s"); + else if (logg5) + pdc_logg(pdc, "\t\t\toption \"%s\" not specified\n", + resopt[is].defopt->name); + for (iv = 0; iv < resopt[is].num; iv++) + { + switch (resopt[is].defopt->type) + { + case pdc_booleanlist: + case pdc_keywordlist: + case pdc_integerlist: + case pdc_3ddatahandle: + case pdc_3dviewhandle: + case pdc_actionhandle: + case pdc_bookmarkhandle: + case pdc_colorhandle: + case pdc_documenthandle: + case pdc_fonthandle: + case pdc_gstatehandle: + case pdc_iccprofilehandle: + case pdc_imagehandle: + case pdc_layerhandle: + case pdc_pagehandle: + case pdc_patternhandle: + case pdc_shadinghandle: + case pdc_tablehandle: + case pdc_templatehandle: + case pdc_textflowhandle: + case pdc_stringhandle: + pdc_logg(pdc, "\tValue %d: %d\n", + iv + 1, *((int *) resopt[is].val + iv)); + break; + + case pdc_stringlist: + pdc_logg(pdc, "\tValue %d: \"%T\"\n", + iv + 1, *((char **) resopt[is].val + iv), 0); + break; + + case pdc_floatlist: + pdc_logg(pdc, "\tValue %d: %f\n", + iv + 1, *((float *) resopt[is].val + iv)); + break; + + case pdc_doublelist: + pdc_logg(pdc, "\tValue %d: %f\n", + iv + 1, *((double *) resopt[is].val + iv)); + break; + + case pdc_scalarlist: + pdc_logg(pdc, "\tValue %d: %f\n", + iv + 1, *((pdc_scalar *) resopt[is].val + iv)); + break; + + case pdc_unicharlist: + pdc_logg(pdc, "\tValue %d: %d\n", + iv + 1, *((int *) resopt[is].val + iv)); + break; + + case pdc_polylinelist: + pdc_logg(pdc, "\t\t#%d: ", iv + 1); + { + pdc_polyline *pl = (pdc_polyline *) resopt[is].val + iv; + + for (j = 0; j < pl->np; j++) + pdc_logg(pdc, "%f,%f ", pl->p[j].x, pl->p[j].y); + pdc_logg(pdc, "\n"); + } + break; + } + } + } + } + + return resopt; + + PDC_OPT_SYNTAXERROR: + stemp1 = pdc_errprintf(pdc, "%.*s", PDC_ERR_MAXSTRLEN, keyword); + pdc_cleanup_stringlist(pdc, items); + pdc_cleanup_stringlist(pdc, values); + + pdc_set_errmsg(pdc, errcode, stemp1, stemp2, stemp3, 0); + if (verbose) + pdc_error(pdc, -1, 0, 0, 0, 0); + + return NULL; +} + +int +pdc_get_optvalues(const char *keyword, pdc_resopt *resopt, + void *lvalues, char ***mvalues) +{ + pdc_resopt *ropt = NULL; + void *values = NULL; + int nvalues = 0; + size_t nbytes; + if (mvalues) *mvalues = NULL; + + if (resopt) + { + int i, cmp; + int lo = 0; + int hi = resopt[0].numdef; + + while (lo < hi) + { + i = (lo + hi) / 2; + cmp = strcmp(keyword, resopt[i].defopt->name); + + /* keyword found */ + if (cmp == 0) + { + ropt = &resopt[i]; + nvalues = ropt->num; + values = ropt->val; + resopt[0].lastind = i; + break; + } + + if (cmp < 0) + hi = i; + else + lo = i + 1; + } + } + + if (nvalues) + { + /* copy values */ + if (lvalues) + { + if (ropt->defopt->type == pdc_stringlist && + ropt->defopt->maxnum == 1) + { + strcpy((char *)lvalues, *((char **) values)); + } + else + { + nbytes = (size_t) (nvalues * pdc_typesizes[ropt->defopt->type]); + memcpy(lvalues, values, nbytes); + } + } + + /* copy pointer */ + if (mvalues) + { + *mvalues = (char **) values; + } + } + + return nvalues; +} + +void * +pdc_save_lastopt(pdc_resopt *resopt, int flags) +{ + int i = resopt[0].lastind; + + if (i > -1 && resopt[i].num) + { + if (flags & PDC_OPT_SAVEALL) + { + resopt[i].flags |= PDC_OPT_SAVEALL; + return resopt[i].val; + } + else if (resopt[i].defopt->type == pdc_stringlist && + (flags & PDC_OPT_SAVE1ELEM)) + { + char **s = (char **) resopt[i].val; + resopt[i].flags |= PDC_OPT_SAVE1ELEM; + return (void *) s[0]; + } + else if (flags & PDC_OPT_SAVEORIG) + { + resopt[i].flags |= PDC_OPT_SAVEORIG; + return (void *) resopt[i].origval; + } + } + + return NULL; +} + +int +pdc_get_lastopt_index(pdc_resopt *resopt) +{ + int i = resopt[0].lastind; + + if (i > -1) + return resopt[i].currind; + else + return -1; +} + +pdc_bool +pdc_is_lastopt_percent(pdc_resopt *resopt, int ind) +{ + int i = resopt[0].lastind; + + if (i > -1 && resopt[i].num < 32) + return (resopt[i].pcmask & (1L << ind)) ? pdc_true : pdc_false; + else + return pdc_false; +} + +pdc_bool +pdc_is_lastopt_utf8(pdc_resopt *resopt) +{ + int i = resopt[0].lastind; + + if (i > -1) + return resopt[0].isutf8 || + ((resopt[i].flags & PDC_OPT_ISUTF8) ? pdc_true : pdc_false); + else + return pdc_false; +} + +int +pdc_get_opt_utf8strings(pdc_core *pdc, const char *keyword, pdc_resopt *resopt, + int flags, char ***strings) +{ + int ns = pdc_get_optvalues(keyword, resopt, NULL, strings); + + if (ns) + { + if (pdc_is_lastopt_utf8(resopt)) + { + int i = resopt[0].lastind; + pdc_resopt *ropt = &resopt[i]; + char **s = (char **) ropt->val; + int j; + + for (j = 0; j < ropt->num; j++) + { + char *sb = pdc_strdup_withbom(pdc, s[j]); + + if (s[j] != NULL) + pdc_free(pdc, s[j]); + s[j] = sb; + } + } + + pdc_save_lastopt(resopt, flags); + } + + return ns; +} + +void +pdc_cleanup_optionlist(pdc_core *pdc, pdc_resopt *resopt) +{ + if (resopt != NULL) + pdc_free_tmp(pdc, resopt); +} + +const char * +pdc_get_handletype(pdc_opttype type) +{ + return pdc_get_keyword(type, pdc_handletypes); +} + -- cgit v1.2.3