Example #1
0
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;
}
Example #2
0
const char *
pdf_get_usematchbox(PDF *p, const char *option, const char *optval,
                    int *istart, int *istop)
{
    const char *boxname = NULL, *stemp = NULL;
    char **strlist = NULL;
    int errcode = 0;
    int k, ir, ns, irect = 1, nrect = 0;

    ns = pdc_split_stringlist(p->pdc, optval, NULL, PDC_SPLIT_ISOPTLIST,
                              &strlist);
    if (ns)
    {
        boxname = pdc_strdup_tmp(p->pdc, strlist[0]);

        /* number of rectangles */
        pdf_get_mbox(p, NULL, boxname, 0, &nrect);

        if (ns == 2)
        {
            stemp = pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN,
                                  strlist[1]);

            /* rectangle number or all rectangles */
            if (!pdc_str2integer(stemp, 0, &ir))
            {
                k = pdc_get_keycode_ci(stemp, pdf_mbox_keylist);
                if (k == PDC_KEY_NOTFOUND)
                {
                    errcode = PDC_E_OPT_ILLKEYWORD;
                    goto PDF_USEMATCHBOX_ERROR;
                }
            }
            else if (ir <= 0)
            {
                errcode = PDC_E_OPT_ILLINTEGER;
                goto PDF_USEMATCHBOX_ERROR;
            }
            else
            {
                irect = ir;
                nrect = MIN(irect, nrect);
            }
        }
        else
        {
            irect = 1;
        }
    }

    PDF_USEMATCHBOX_ERROR:

    pdc_cleanup_stringlist(p->pdc, strlist);

    if (errcode)
        pdc_error(p->pdc, errcode, option, stemp, 0, 0);

    *istart = irect;
    *istop = nrect;

    return boxname;
}
Example #3
0
static void
fnt_parse_cid_widths(pdc_core *pdc, fnt_font *font)
{
    static const char fn[] = "fnt_parse_cid_widths";
    int slot, slota, slotm;
    const char *chunk;
    char **strlist = NULL, **sstrlist = NULL, *str;
    int cid = 0, cidfirst, cidlast, width;
    int il, is, ns, nss = 0;
    int wformat = 2;

    /* search for font name */
    slotm = 100;
    for (slot = 0; slot < slotm; slot += FNT_CIDMETRIC_INCR)
    {
        if (!strcmp(fnt_cid_width_arrays[slot], font->name))
            break;
    }
    if (slot == slotm)
        return;

    /* we take the maximum */
    font->m.numwidths = fnt_get_maxcid(font->m.charcoll, -1) + 1;
    font->m.widths = (int *) pdc_malloc(pdc,
                                 font->m.numwidths * sizeof(int), fn);

    slota = slot + 1;                       /* skip font name  */
    slotm = slot + FNT_CIDMETRIC_INCR;
    for (slot = slota; slot < slotm; slot++)
    {
        chunk = fnt_cid_width_arrays[slot];

        ns = pdc_split_stringlist(pdc, chunk, " \n", 0, &strlist);
        for (is = 0; is < ns; is++)
        {
            str = strlist[is];

            /* check for next format 1 chunk */
            if (wformat == 2 && strchr(str, '['))
            {
                nss = pdc_split_stringlist(pdc, str, " [", 0, &sstrlist);
                str = sstrlist[0];
                pdc_str2integer(str, 0, &cidfirst);
                for (; cid < cidfirst; cid++)
                    font->m.widths[cid] = FNT_DEFAULT_CIDWIDTH;
                str = sstrlist[1];
                wformat = 1;
            }

            /* format 1:  cid [width_1 width_2 ... width_n] */
            if (wformat == 1)
            {
                il = (int) strlen(str) - 1;
                if (str[il] == ']')
                {
                    str[il] = 0;
                    wformat = 2;
                }

                pdc_str2integer(str, 0, &font->m.widths[cid]);
                cid++;

                if (nss)
                {
                    pdc_cleanup_stringlist(pdc, sstrlist);
                    nss = 0;
                }
            }
            else
            {
                /* format 2:  cid_first cid_last width */
                pdc_str2integer(str, 0, &cidfirst);
                is++;
                str = strlist[is];
                pdc_str2integer(str, 0, &cidlast);
                is++;
                str = strlist[is];
                pdc_str2integer(str, 0, &width);

                for (; cid < cidfirst; cid++)
                    font->m.widths[cid] = FNT_DEFAULT_CIDWIDTH;
                for (; cid <= cidlast; cid++)
                    font->m.widths[cid] = width;
            }
        }

        pdc_cleanup_stringlist(pdc, strlist);
    }

    for (; cid < font->m.numwidths; cid++)
        font->m.widths[cid] = FNT_DEFAULT_CIDWIDTH;

    if (pdc_logg_is_enabled(pdc, 5, trc_font))
    {
        for (cid = 0; cid < font->m.numwidths; cid++)
            pdc_logg(pdc, "\t\t\tCID width[%d]: %d\n",
                     cid, font->m.widths[cid]);
    }
}
Example #4
0
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, *s1, *s2;
    char **items = NULL, *keyword = NULL;
    char **values = NULL, *value = NULL, **strings = NULL;
    int i, j, k, nd, is, iss, it, iv, icoord;
    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++)
    {
        pdc_bool isequal = pdc_false;

        /* search keyword */
        boolval = pdc_undef;
        keyword = items[is];
        for (it = 0; it < numdef; it++)
        {
            s1 = keyword;
            s2 = defopt[it].name;

            /* if (!pdc_stricmp(keyword, defopt[it].name))
             *     isequal = pdc_true;
             */
            for (; *s1; ++s1, ++s2)
            {
                if (pdc_tolower(*s1) != pdc_tolower(*s2))
                    break;
            }
            if (pdc_tolower(*s1) == pdc_tolower(*s2))
                isequal = pdc_true;

            /* special handling for booleans */
            if (defopt[it].type == pdc_booleanlist)
            {
                if (isequal ||
                    (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 if (isequal)
                        {
                            boolval = pdc_true;
                            break;
                        }
                    }
                }
            }

            if (isequal)
                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<<iv)))
                    pdc_logg(pdc, "(compatibility >= %s) ",
                             pdc_get_pdfversion(pdc, iv));

                if ((dopt->flags & (1L<<iv)) && compatibility < iv)
                {
                    if (logg5)
                        pdc_logg(pdc, "\n");
                    stemp2 = pdc_get_pdfversion(pdc, compatibility);
                    errcode = PDC_E_OPT_VERSION;
                    goto PDC_OPT_SYNTAXERROR;
                }
            }
        }

        /* not supported */
        if (dopt->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;
        }

        /* deprecated option since PDFlib 7 */
        if (dopt->flags & PDC_OPT_PDFLIB_7)
        {
            pdc_logg_cond(pdc, 2, trc_api,
                  "[Option \"%s\" is deprecated since PDFlib 7]\n",
                  keyword);
        }

        /* 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 (dopt->flags & PDC_OPT_PERCENT)
            memset(resopt[it].pcbits, 0, PDC_PCBITS_SIZE);

        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;
                        icoord = ncoords;
                        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 < PDC_MAX_PERCENTS)
                                        {
                                            pdc_setbit(resopt[it].pcbits,
                                                       ncoords);
                                        }
                                        else
                                        {
                                            errcode = PDC_E_OPT_TOOMANYPERCVALS;
                                        }
                                    }
                                }

                                retval = pdc_str2double(sk, &dz);
                                if (!retval)
                                {
                                    errcode = PDC_E_OPT_ILLNUMBER;
                                }
                                else if (pdc_getbit(resopt[it].pcbits, ncoords))
                                {
                                    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;
                                }
                            }
                            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];
                            if (pdc_getbit(resopt[it].pcbits, icoord))
                                pdc_setbit(resopt[it].pcbits, ncoords);
                            ncoords++;
                            if (pdc_getbit(resopt[it].pcbits, icoord + 1))
                                pdc_setbit(resopt[it].pcbits, ncoords);
                            ncoords++;
                        }
                    }
                    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 < PDC_MAX_PERCENTS)
                        {
                            pdc_setbit(resopt[it].pcbits, iv);
                        }
                        else
                        {
                            errcode = PDC_E_OPT_TOOMANYPERCVALS;
                        }
                    }
                }

                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 (pdc_getbit(resopt[it].pcbits, 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;
}
Example #5
0
static pdc_bool
pdf_parse_afm(
    PDF *p,
    pdc_file *fp,
    pdf_font *font,
    const char *fontname,
    const char *filename)
{
    static const char fn[] = "pdf_parse_afm";
    fnt_font_metric *ftm = &font->ft.m;
    const char *afmtype = NULL;
    char **wordlist = NULL, *keyword, *arg1;
    char line[AFM_LINEBUF];
    int i, cmp, lo, hi, nwords, nglyphs = 0, nline = 0;
    int tablen = ((sizeof keyStrings) / (sizeof (char *)));
    pdc_sint32 iz;
    double dz;
    pdc_scalar charwidth = -1;
    pdf_afmkey keynumber;
    fnt_glyphwidth *glw;
    pdc_bool toskip = pdc_false;
    pdc_bool is_zadbfont = !strcmp(fontname, "ZapfDingbats");

    /* all new glyph names of AGL 2.0 are missing */
    font->missingglyphs = 0xFFFFFFFF;

    /* read loop. because of Mac files we use pdc_fgetline */
    while (pdc_fgetline(line, AFM_LINEBUF, fp) != NULL)
    {
        /* split line */
        nline++;
        nwords = pdc_split_stringlist(p->pdc, line, AFM_SEPARATORS, 0,
                                      &wordlist);
        if (!nwords) continue;
        keyword = wordlist[0];

        /* find keynumber */
        lo = 0;
        hi = tablen;
        keynumber = NOPE;
        while (lo < hi)
        {
            i = (lo + hi) / 2;
            cmp = strcmp(keyword, keyStrings[i]);

            if (cmp == 0)
            {
                keynumber = (pdf_afmkey) i;
                break;
            }

            if (cmp < 0)
                hi = i;
            else
                lo = i + 1;
        }

        /* unkown key */
        if (keynumber == NOPE)
        {
            pdc_warning(p->pdc, PDF_E_T1_AFMBADKEY, keyword, filename, 0,0);
            goto PDF_PARSECONTD;
        }
        if (keynumber == ENDDIRECTION)
            toskip = pdc_false;

        if (nwords == 1 || toskip == pdc_true)
            goto PDF_PARSECONTD;

        /* key switch */
        arg1 = wordlist[1];
        switch (keynumber)
        {
            case STARTDIRECTION:
            if (pdc_str2integer(arg1, 0, &iz) != pdc_true)
                goto PDF_SYNTAXERROR;
            if (iz)
                toskip = pdc_true;
            break;

            case STARTCOMPFONTMETRICS:
            afmtype = "ACFM";
            goto PDF_SYNTAXERROR;

            case STARTMASTERFONTMETRICS:
            afmtype = "AMFM";
            goto PDF_SYNTAXERROR;

            case ISCIDFONT:
            afmtype = "CID font";
            if (!strcmp(arg1, "true"))
                goto PDF_SYNTAXERROR;
            break;

            case FONTNAME:
            font->ft.name = pdc_strdup(p->pdc, arg1);
            ftm->name = pdc_strdup(p->pdc, arg1);
            pdc_logg_cond(p->pdc, 1, trc_font,
                "\tPostScript font name: \"%s\"\n", ftm->name);
            break;

            /* Recognize Multiple Master fonts by last part of name */
            case FAMILYNAME:
            if (!strcmp(wordlist[nwords-1], "MM"))
                ftm->type = fnt_MMType1;
            else
                ftm->type = fnt_Type1;
            break;

            /* Default: FontSpecific */
            case ENCODINGSCHEME:
            if (!pdc_stricmp(arg1, "StandardEncoding") ||
                !pdc_stricmp(arg1, "AdobeStandardEncoding"))
                font->ft.issymbfont = pdc_false;
            break;

            case STDHW:
            if (pdc_str2double(arg1, &dz) != pdc_true)
                goto PDF_SYNTAXERROR;
            ftm->StdHW = (int) dz;
            break;

            case STDVW:
            if (pdc_str2double(arg1, &dz) != pdc_true)
                goto PDF_SYNTAXERROR;
            ftm->StdVW = (int) dz;
            break;

            case WEIGHT:
            font->ft.weight = fnt_check_weight(fnt_weightname2weight(arg1));
            break;

            case ISFIXEDPITCH:
            if (!pdc_stricmp(arg1, "false"))
                ftm->isFixedPitch = pdc_false;
            else
                ftm->isFixedPitch = pdc_true;
            break;

            /* New AFM 4.1 keyword "CharWidth" implies fixed pitch */
            case CHARWIDTH:
            if (pdc_str2double(arg1, &dz) != pdc_true)
                goto PDF_SYNTAXERROR;
            charwidth = dz;
            ftm->isFixedPitch = pdc_true;
            break;

            case ITALICANGLE:
            {
                if (pdc_str2double(arg1, &dz) != pdc_true)
                    goto PDF_SYNTAXERROR;
                ftm->italicAngle = dz;
            }
            break;

            case UNDERLINEPOSITION:
            if (pdc_str2double(arg1, &dz) != pdc_true)
                goto PDF_SYNTAXERROR;
            ftm->underlinePosition = (int) dz;
            break;

            case UNDERLINETHICKNESS:
            if (pdc_str2double(arg1, &dz) != pdc_true)
                goto PDF_SYNTAXERROR;
            ftm->underlineThickness = (int) dz;
            break;

            case FONTBBOX:
            {
                if (nwords != 5)
                    goto PDF_SYNTAXERROR;
                for (i = 1; i < nwords; i++)
                {
                    if (pdc_str2double(wordlist[i], &dz) != pdc_true)
                        goto PDF_SYNTAXERROR;
                    if (i == 1)
                        ftm->llx = dz;
                    else if (i == 2)
                        ftm->lly = dz;
                    else if (i == 3)
                        ftm->urx = dz;
                    else if (i == 4)
                        ftm->ury = dz;
                }
            }
            break;

            case CAPHEIGHT:
            if (pdc_str2double(arg1, &dz) != pdc_true)
                goto PDF_SYNTAXERROR;
            ftm->capHeight = (int) dz;
            break;

            case XHEIGHT:
            if (pdc_str2double(arg1, &dz) != pdc_true)
                goto PDF_SYNTAXERROR;
            ftm->xHeight = (int) dz;
            break;

            case DESCENDER:
            if (pdc_str2double(arg1, &dz) != pdc_true)
                goto PDF_SYNTAXERROR;
            ftm->descender = (int) dz;
            break;

            case ASCENDER:
            if (pdc_str2double(arg1, &dz) != pdc_true)
                goto PDF_SYNTAXERROR;
            ftm->ascender = (int) dz;
            break;

            /* Character widths */

            case STARTCHARMETRICS:
            if (pdc_str2integer(arg1, PDC_INT_UNSIGNED, (pdc_sint32 *) &nglyphs)
                != pdc_true || nglyphs <= 0)
                goto PDF_SYNTAXERROR;
            ftm->glw = (fnt_glyphwidth *) pdc_calloc(p->pdc,
                            (size_t) nglyphs * sizeof(fnt_glyphwidth), fn);
            break;

            /* Character code */
            case CODE:
            case CODEHEX:
            if (!nglyphs || !ftm->glw)
                goto PDF_SYNTAXERROR;
            if (font->ft.numglyphs >= nglyphs)
            {
                nglyphs++;
                ftm->glw = (fnt_glyphwidth *) pdc_realloc(p->pdc, ftm->glw,
                                (size_t) nglyphs * sizeof(fnt_glyphwidth), fn);
            }
            glw = &ftm->glw[font->ft.numglyphs];
            if (keynumber == CODE)
            {
                if (pdc_str2integer(arg1, 0, &iz) != pdc_true)
                    goto PDF_SYNTAXERROR;
            }
            else
            {
                if (pdc_str2integer(arg1, PDC_INT_HEXADEC, &iz) != pdc_true)
                    goto PDF_SYNTAXERROR;
            }
            glw->code = (pdc_short) iz;
            glw->unicode = 0;
            glw->width = (pdc_ushort)
                (font->opt.monospace ? font->opt.monospace : charwidth);
            font->ft.numglyphs++;

            /* Character width and name */
            for (i = 2; i < nwords; i++)
            {
                if (!strcmp(wordlist[i], "WX") ||
                    !strcmp(wordlist[i], "W0X") ||
                    !strcmp(wordlist[i], "W"))
                {
                    i++;
                    if (i == nwords)
                        goto PDF_SYNTAXERROR;
                    if (pdc_str2double(wordlist[i], &dz) != pdc_true)
                        goto PDF_SYNTAXERROR;
                    glw->width = (pdc_ushort)
                         (font->opt.monospace ? font->opt.monospace : dz);
                }

                if (!strcmp(wordlist[i], "N"))
                {
                    i++;
                    if (i == nwords)
                        goto PDF_SYNTAXERROR;

                    /* Unicode value by means of AGL,
                     * internal and private table
                     */
                    glw->unicode = is_zadbfont ?
                         (pdc_ushort) pdc_zadb2unicode(wordlist[i]):
                         pdc_insert_glyphname(p->pdc, wordlist[i]);
                    pdc_delete_missingglyph_bit(glw->unicode,
                                                &font->missingglyphs);

                }
            }
            break;


            default:
            break;
        }

        PDF_PARSECONTD:
        pdc_cleanup_stringlist(p->pdc, wordlist);
        wordlist = NULL;

        if (keynumber == ENDFONTMETRICS)
            break;
    }

    /* necessary font struct members */
    if (font->ft.name == NULL || ftm->glw == NULL)
        goto PDF_SYNTAXERROR;

    pdc_fclose(fp);

    ftm->numglwidths = font->ft.numglyphs;
    return pdc_true;

    PDF_SYNTAXERROR:
    pdc_fclose(fp);
    pdc_cleanup_stringlist(p->pdc, wordlist);

    if (afmtype)
        pdc_set_errmsg(p->pdc, PDF_E_T1_UNSUPP_FORMAT, afmtype, 0, 0, 0);
    else
        pdc_set_errmsg(p->pdc, PDC_E_IO_ILLSYNTAX, "AFM ", filename,
                       pdc_errprintf(p->pdc, "%d", nline), 0);
    return pdc_false;
}
Example #6
0
static void
pdf_read_resourcefile(PDF *p, const char *filename)
{
    pdc_file   *fp = NULL;
    char      **linelist;
    char       *line;
    char       *category = NULL;
    char       *uprfilename = NULL;
#if defined(AS400) || defined(WIN32)
#define BUFSIZE 2048
    char        buffer[BUFSIZE];
#ifdef WIN32
    char        regkey[128];
    HKEY        hKey = NULL;
    DWORD       size, lType;
#endif
#endif
    int         il, nlines = 0, nextcat, begin;

#ifdef WIN32

/* don't add patchlevel's to registry searchpath */
#define stringiz1(x)	#x
#define stringiz(x)	stringiz1(x)

#define PDFLIBKEY  "Software\\PDFlib\\PDFlib\\"

    strcpy(regkey, PDFLIBKEY);
    strcat(regkey, PDFLIB_VERSIONSTRING);

    /* process registry entries */
    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
        (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
    {
        size = BUFSIZE - 2;
        if (RegQueryValueExA(hKey, "SearchPath", (LPDWORD) NULL,
                             &lType, (LPBYTE) buffer, &size)
            == ERROR_SUCCESS && *buffer)
        {
            char **pathlist;
            int ip, np;

            np = pdc_split_stringlist(p->pdc, buffer,
                                      ";", &pathlist);
            for (ip = 0; ip < np; ip++)
                pdf_add_resource(p, "SearchPath", pathlist[ip]);
            pdc_cleanup_stringlist(p->pdc, pathlist);
        }

        size = BUFSIZE - 2;
        if (RegQueryValueExA(hKey, "prefix", (LPDWORD) NULL,
                             &lType, (LPBYTE) buffer, &size)
            == ERROR_SUCCESS && *buffer)
        {
            /* '/' because of downward compatibility */
            if (p->prefix)
            {
                pdc_free(p->pdc, p->prefix);
                p->prefix = NULL;
            }
            p->prefix = pdc_strdup(p->pdc,
                            &buffer[buffer[0] == '/' ? 1 : 0]);
        }

        RegCloseKey(hKey);
    }
#endif  /* WIN32 */

#ifdef AS400
    strcpy (buffer, "/pdflib/");
    strcat (buffer, PDFLIB_VERSIONSTRING);
    il = (int) strlen(buffer);
    strcat (buffer, "/fonts");
    pdf_add_resource(p, "SearchPath", buffer);
    strcpy(&buffer[il], "/bind/data");
    pdf_add_resource(p, "SearchPath", buffer);
#endif  /* AS400 */

    /* searching for name of upr file */
    uprfilename = (char *)filename;
    if (!uprfilename || *uprfilename == '\0')
    {
        /* user-supplied upr file */
        uprfilename = pdc_getenv(RESOURCEFILE);
        if (!uprfilename || *uprfilename == '\0')
        {
            uprfilename = DEFAULTRESOURCEFILE;

            /* user-supplied upr file */
            fp = pdf_fopen(p, uprfilename, NULL, 0);
            if (fp == NULL)
            {
                uprfilename = NULL;
#ifdef WIN32
                /* process registry entries */
                if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
                    (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
                {
                    size = BUFSIZE - 2;
                    if (RegQueryValueExA(hKey, "resourcefile", (LPDWORD) NULL,
                                         &lType, (LPBYTE) buffer, &size)
                        == ERROR_SUCCESS && *buffer)
                    {
                        uprfilename = buffer;
                    }

                    RegCloseKey(hKey);
                }
#endif  /* WIN32 */
            }
        }

        if (!uprfilename || *uprfilename == '\0')
            return;

        if (p->resourcefilename)
        {
            pdc_free(p->pdc, p->resourcefilename);
            p->resourcefilename = NULL;
        }
        p->resourcefilename = pdc_strdup(p->pdc, uprfilename);
    }

    /* read upr file */
    if ((fp == NULL) && ((fp = pdf_fopen(p, uprfilename, "UPR ", 0)) == NULL))
	pdc_error(p->pdc, -1, 0, 0, 0, 0);

    nlines = pdc_read_textfile(p->pdc, fp, &linelist);
    pdc_fclose(fp);

    if (!nlines) return;

    /* Lines loop */
    begin = 1;
    nextcat = 0;
    for (il = 0; il < nlines; il++)
    {
        line = linelist[il];

        /* Next category */
        if (line[0] == '.' && strlen(line) == 1)
        {
            begin = 0;
            nextcat = 1;
            continue;
        }

        /* Skip category list */
        if (begin) continue;

        /* Prefiex or category expected */
        if (nextcat)
        {
            /* Directory prefix */
            if (line[0] == '/')
            {
                if (p->prefix)
                {
                    pdc_free(p->pdc, p->prefix);
                    p->prefix = NULL;
                }
                p->prefix = pdc_strdup(p->pdc, &line[1]);
                continue;
            }

            /* Ressource Category */
            category = line;
            nextcat = 0;
            continue;
        }

        /* Add resource */
        pdf_add_resource(p, category, line);
    }

    pdc_cleanup_stringlist(p->pdc, linelist);
}