Files correlati : pdflib Ricompilazione Demo : [ ] Commento : Aggiornata PDFlib git-svn-id: svn://10.65.10.50/trunk@17433 c028cbd2-c16b-5b4b-a496-9718f37d4682
1919 lines
51 KiB
C
Executable File
1919 lines
51 KiB
C
Executable File
/*---------------------------------------------------------------------------*
|
||
| 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_resource.c,v 1.2 2008-10-20 14:35:00 guy Exp $
|
||
*
|
||
* Resource routines
|
||
*
|
||
*/
|
||
|
||
#define PC_RESOURCE_C
|
||
|
||
#include <errno.h>
|
||
|
||
#include "pc_util.h"
|
||
#include "pc_file.h"
|
||
#include "pc_resource.h"
|
||
#include "pc_ctype.h"
|
||
|
||
#if defined(WIN32)
|
||
#define WIN32_LEAN_AND_MEAN
|
||
#include <windows.h>
|
||
#endif
|
||
|
||
|
||
/* -------------------------- resource handling ----------------------------- */
|
||
|
||
struct pdc_res_s
|
||
{
|
||
char *name;
|
||
char *value;
|
||
pdc_res *prev;
|
||
pdc_res *next;
|
||
};
|
||
|
||
struct pdc_category_s
|
||
{
|
||
char *category;
|
||
pdc_res *kids;
|
||
pdc_category *next;
|
||
};
|
||
|
||
struct pdc_reslist_s
|
||
{
|
||
pdc_category *resources; /* anchor for the category resource list */
|
||
pdc_bool filepending; /* to read resource file is pending */
|
||
char *filename; /* name of the resource file */
|
||
};
|
||
|
||
typedef enum
|
||
{
|
||
pdc_FontOutline,
|
||
pdc_FontAFM,
|
||
pdc_FontPFM,
|
||
pdc_HostFont,
|
||
pdc_Encoding,
|
||
pdc_ICCProfile,
|
||
pdc_StandardOutputIntent,
|
||
pdc_SearchPath,
|
||
pdc_CMap,
|
||
pdc_GlyphList,
|
||
pdc_CodeList
|
||
}
|
||
pdc_rescategory;
|
||
|
||
static const pdc_keyconn pdc_rescategories[] =
|
||
{
|
||
{"FontOutline", pdc_FontOutline},
|
||
{"FontAFM", pdc_FontAFM},
|
||
{"FontPFM", pdc_FontPFM},
|
||
{"HostFont", pdc_HostFont},
|
||
{"Encoding", pdc_Encoding},
|
||
{"ICCProfile", pdc_ICCProfile},
|
||
{"StandardOutputIntent", pdc_StandardOutputIntent},
|
||
{"SearchPath", pdc_SearchPath},
|
||
{"CMap", pdc_CMap},
|
||
{"GlyphList", pdc_GlyphList},
|
||
{"CodeList", pdc_CodeList},
|
||
{NULL, 0}
|
||
};
|
||
|
||
#define RESOURCEFILEENVNAME "%sRESOURCEFILE"
|
||
|
||
#ifndef MVS
|
||
#define DEFAULTRESOURCEFILE "%s.upr"
|
||
#else
|
||
#define DEFAULTRESOURCEFILE "upr"
|
||
#endif
|
||
|
||
#ifdef WIN32
|
||
#define REGISTRYKEY "Software\\PDFlib\\%s\\%s"
|
||
#endif
|
||
|
||
pdc_reslist *
|
||
pdc_new_reslist(pdc_core *pdc)
|
||
{
|
||
static const char fn[] = "pdc_new_reslist";
|
||
|
||
pdc_reslist *resl = (pdc_reslist *) pdc_malloc(pdc, sizeof(pdc_reslist),fn);
|
||
|
||
resl->resources = NULL;
|
||
resl->filepending = pdc_true;
|
||
resl->filename = NULL;
|
||
|
||
pdc->reslist = resl;
|
||
|
||
return resl;
|
||
}
|
||
|
||
static pdc_category *
|
||
pdc_delete_rescategory(pdc_core *pdc, pdc_category *prevcat, pdc_category *cat,
|
||
pdc_bool empty)
|
||
{
|
||
pdc_category *nextcat;
|
||
pdc_res *res, *lastres;
|
||
|
||
for (res = cat->kids; res != NULL; /* */)
|
||
{
|
||
lastres = res;
|
||
res = lastres->next;
|
||
pdc_free(pdc, lastres->name);
|
||
lastres->name = NULL;
|
||
if (lastres->value)
|
||
{
|
||
pdc_free(pdc, lastres->value);
|
||
lastres->value = NULL;
|
||
}
|
||
pdc_free(pdc, lastres);
|
||
}
|
||
nextcat = cat->next;
|
||
|
||
if (empty)
|
||
{
|
||
cat->kids = NULL;
|
||
}
|
||
else
|
||
{
|
||
pdc_free(pdc, cat->category);
|
||
cat->category = NULL;
|
||
pdc_free(pdc, cat);
|
||
cat = NULL;
|
||
|
||
if (prevcat != NULL)
|
||
{
|
||
pdc_reslist *resl = pdc->reslist;
|
||
|
||
if (prevcat != cat)
|
||
prevcat->next = nextcat;
|
||
else
|
||
resl->resources = nextcat;
|
||
}
|
||
}
|
||
|
||
return nextcat;
|
||
}
|
||
|
||
void
|
||
pdc_delete_reslist(pdc_core *pdc)
|
||
{
|
||
pdc_reslist *resl = pdc->reslist;
|
||
|
||
if (resl != NULL)
|
||
{
|
||
pdc_category *cat;
|
||
|
||
for (cat = resl->resources; cat != NULL; /* */)
|
||
cat = pdc_delete_rescategory(pdc, NULL, cat, pdc_false);
|
||
|
||
if (resl->filename)
|
||
pdc_free(pdc, resl->filename);
|
||
|
||
pdc_free(pdc, resl);
|
||
pdc->reslist = NULL;
|
||
}
|
||
}
|
||
|
||
static pdc_reslist *
|
||
pdc_get_reslist(pdc_core *pdc)
|
||
{
|
||
pdc_reslist *resl = pdc->reslist;
|
||
|
||
if (resl == NULL)
|
||
resl = pdc_new_reslist(pdc);
|
||
|
||
return resl;
|
||
}
|
||
|
||
void
|
||
pdc_set_resourcefile(pdc_core *pdc, const char *filename)
|
||
{
|
||
if (filename != NULL && *filename)
|
||
{
|
||
pdc_reslist *resl = pdc_get_reslist(pdc);
|
||
|
||
if (resl->filename)
|
||
pdc_free(pdc, resl->filename);
|
||
|
||
resl->filename = pdc_strdup(pdc, filename);
|
||
resl->filepending = pdc_true;
|
||
}
|
||
}
|
||
|
||
const char *
|
||
pdc_get_resourcefile(pdc_core *pdc)
|
||
{
|
||
pdc_reslist *resl = pdc_get_reslist(pdc);
|
||
|
||
return (resl->filename);
|
||
}
|
||
|
||
static void
|
||
pdc_read_resourcefile(pdc_core *pdc, const char *filename)
|
||
{
|
||
pdc_reslist *resl = pdc_get_reslist(pdc);
|
||
pdc_file *fp = NULL;
|
||
char **linelist;
|
||
char *line;
|
||
char *category = NULL;
|
||
char *uprfilename = NULL;
|
||
char tmpname[PDC_FILENAMELEN];
|
||
#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;
|
||
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\n\tSearching for resource file...\n");
|
||
|
||
#ifdef WIN32
|
||
|
||
/* don't add patchlevel's to registry searchpath */
|
||
#define stringiz1(x) #x
|
||
#define stringiz(x) stringiz1(x)
|
||
|
||
sprintf(regkey, REGISTRYKEY, pdc->prodname, pdc->version);
|
||
|
||
#endif /* WIN32 */
|
||
|
||
#ifdef AS400
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tSet AS400 default resources\n");
|
||
strcpy (buffer, "/pdflib/");
|
||
strcat (buffer, pdc->version);
|
||
il = (int) strlen(buffer);
|
||
strcat (buffer, "/fonts");
|
||
pdc_add_resource(pdc, "SearchPath", buffer, "");
|
||
strcpy(&buffer[il], "/bind/data");
|
||
pdc_add_resource(pdc, "SearchPath", buffer, "");
|
||
#endif /* AS400 */
|
||
|
||
#ifdef WIN32
|
||
/* process registry entries */
|
||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
|
||
(REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
||
{
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tRead registry key \"%s\":\n", regkey);
|
||
|
||
size = BUFSIZE - 2;
|
||
if (RegQueryValueExA(hKey, "searchpath", (LPDWORD) NULL,
|
||
&lType, (LPBYTE) buffer, &size)
|
||
== ERROR_SUCCESS && *buffer)
|
||
{
|
||
char **pathlist;
|
||
int ip, np;
|
||
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tsearchpath entry: \"%s\"\n", buffer);
|
||
|
||
np = pdc_split_stringlist(pdc, buffer, ";", 0, &pathlist);
|
||
for (ip = 0; ip < np; ip++)
|
||
pdc_add_resource(pdc, "SearchPath", pathlist[ip], "");
|
||
pdc_cleanup_stringlist(pdc, pathlist);
|
||
}
|
||
|
||
RegCloseKey(hKey);
|
||
}
|
||
#endif /* WIN32 */
|
||
|
||
/* searching for name of upr file */
|
||
uprfilename = (char *)filename;
|
||
if (uprfilename == NULL || *uprfilename == '\0')
|
||
{
|
||
/* upr file name via environment variable */
|
||
sprintf(tmpname, RESOURCEFILEENVNAME, pdc->prodname);
|
||
pdc_strtoupper(tmpname);
|
||
uprfilename = pdc_getenv(tmpname);
|
||
|
||
#ifdef WIN32
|
||
/* registry upr file name */
|
||
if (uprfilename == NULL || *uprfilename == '\0')
|
||
{
|
||
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)
|
||
{
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tresourcefile entry: \"%s\"\n", buffer);
|
||
|
||
uprfilename = buffer;
|
||
}
|
||
|
||
RegCloseKey(hKey);
|
||
}
|
||
}
|
||
#endif /* WIN32 */
|
||
|
||
/* default upr file name */
|
||
if (uprfilename == NULL || *uprfilename == '\0')
|
||
{
|
||
sprintf(tmpname, DEFAULTRESOURCEFILE, pdc->prodname);
|
||
uprfilename = pdc_strtolower(tmpname);
|
||
|
||
/* user-supplied upr file */
|
||
fp = pdc_fsearch_fopen(pdc, uprfilename, NULL, NULL, 0);
|
||
if (fp == NULL)
|
||
{
|
||
uprfilename = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (uprfilename != NULL && *uprfilename != '\0')
|
||
{
|
||
char *resfilename = resl->filename;
|
||
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tRead resource file \"%s\":\n", uprfilename);
|
||
|
||
resl->filename = pdc_strdup(pdc, uprfilename);
|
||
if (resfilename)
|
||
pdc_free(pdc, resfilename);
|
||
|
||
/* read upr file */
|
||
if (fp == NULL)
|
||
{
|
||
fp = pdc_fsearch_fopen(pdc, resl->filename, NULL, "UPR ",
|
||
PDC_FILE_TEXT);
|
||
if (fp == NULL)
|
||
pdc_error(pdc, -1, 0, 0, 0, 0);
|
||
}
|
||
|
||
nlines = pdc_read_textfile(pdc, fp, 0, &linelist);
|
||
pdc_fclose(fp);
|
||
|
||
if (nlines)
|
||
{
|
||
/* 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;
|
||
|
||
/* Category expected */
|
||
if (nextcat)
|
||
{
|
||
/* Ressource Category */
|
||
category = line;
|
||
nextcat = 0;
|
||
continue;
|
||
}
|
||
|
||
/* Add resource */
|
||
if (strlen(line))
|
||
pdc_add_resource(pdc, category, line, NULL);
|
||
}
|
||
|
||
pdc_cleanup_stringlist(pdc, linelist);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* pdc_add_resource_ext add a new resource to the resource data base
|
||
* for specified resource category.
|
||
*
|
||
* resvalue == NULL:
|
||
* resname string has the format "resname [= resvalue]"
|
||
* Then string splitting has to be performed.
|
||
* [EBCDIC-]UTF-8 must be specified by a BOM: resname = resvalue
|
||
*
|
||
* Otherwise resname and resvalue are [EBCDIC-]UTF-8 encoded.
|
||
*
|
||
*/
|
||
void
|
||
pdc_add_resource_ext(pdc_core *pdc, const char *category, const char *resname,
|
||
const char *resvalue, pdc_encoding enc, int codepage)
|
||
{
|
||
static const char fn[] = "pdc_add_resource";
|
||
pdc_reslist *resl = pdc_get_reslist(pdc);
|
||
pdc_rescategory rescat;
|
||
pdc_category *cat = NULL, *lastcat = NULL;
|
||
pdc_res *res = NULL, *lastres = NULL;
|
||
char *resnamutf8 = NULL;
|
||
char *resvalutf8 = NULL;
|
||
int resnamflags = PDC_CONV_EBCDIC;
|
||
int resvalflags = PDC_CONV_EBCDIC;
|
||
int k;
|
||
|
||
if (!resvalue || !strlen(resvalue))
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tAdd \"%s\" to resource category \"%s\"\n", resname, category);
|
||
else
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tAdd \"%s=%s\" to resource category \"%s\"\n",
|
||
resname, resvalue, category);
|
||
|
||
/* We no longer raise an error but silently ignore unknown categories */
|
||
k = pdc_get_keycode_ci(category, pdc_rescategories);
|
||
if (k == PDC_KEY_NOTFOUND)
|
||
{
|
||
pdc_warning(pdc, PDC_E_RES_BADCAT, category, 0, 0, 0);
|
||
return;
|
||
}
|
||
rescat = (pdc_rescategory) k;
|
||
|
||
/* Read resource configuration file if it is pending */
|
||
if (resl->filepending)
|
||
{
|
||
resl->filepending = pdc_false;
|
||
pdc_read_resourcefile(pdc, resl->filename);
|
||
}
|
||
|
||
/* Find start of this category's resource list, if the category exists */
|
||
lastcat = resl->resources;
|
||
for (cat = lastcat; cat != NULL; cat = cat->next)
|
||
{
|
||
if (!pdc_stricmp(cat->category, category))
|
||
break;
|
||
lastcat = cat;
|
||
}
|
||
if (cat == NULL)
|
||
{
|
||
cat = (pdc_category *) pdc_malloc(pdc, sizeof(pdc_category), fn);
|
||
cat->category = pdc_strdup(pdc, category);
|
||
cat->kids = NULL;
|
||
cat->next = NULL;
|
||
if (lastcat != NULL)
|
||
lastcat->next = cat;
|
||
else
|
||
resl->resources = cat;
|
||
}
|
||
|
||
/* resvalue */
|
||
if (resvalue == NULL)
|
||
{
|
||
char **strlist = NULL;
|
||
|
||
/* splitting of resname string */
|
||
int ns = pdc_split_stringlist(pdc, resname, "=", 0, &strlist);
|
||
|
||
if (ns >= 1)
|
||
pdc_str2trim(strlist[0]);
|
||
if (ns == 2)
|
||
pdc_str2trim(strlist[1]);
|
||
if (ns > 2 ||
|
||
(rescat != pdc_SearchPath && (ns == 0 || !strlen(strlist[0]))))
|
||
{
|
||
pdc_cleanup_stringlist(pdc, strlist);
|
||
pdc_error(pdc, PDC_E_RES_BADRES, resname, category, 0, 0);
|
||
}
|
||
|
||
/* resource name */
|
||
if (ns > 0)
|
||
{
|
||
if (pdc_is_utf8_bytecode(resname))
|
||
resnamflags |= PDC_CONV_ISUTF8;
|
||
resnamutf8 = pdc_convert_name_ext(pdc, strlist[0], 0,
|
||
enc, codepage, resnamflags);
|
||
}
|
||
|
||
/* resource value */
|
||
if (ns == 2)
|
||
{
|
||
resvalflags = resnamflags;
|
||
resvalutf8 = pdc_convert_name_ext(pdc, strlist[1], 0,
|
||
enc, codepage, resvalflags);
|
||
}
|
||
else
|
||
{
|
||
resvalutf8 = pdc_strdup(pdc, "");
|
||
}
|
||
pdc_cleanup_stringlist(pdc, strlist);
|
||
}
|
||
else
|
||
{
|
||
resnamflags |= PDC_CONV_ISUTF8;
|
||
resnamutf8 = pdc_convert_name_ext(pdc, resname, 0,
|
||
enc, codepage, resnamflags);
|
||
|
||
resvalflags |= PDC_CONV_ISUTF8;
|
||
resvalutf8 = pdc_convert_name_ext(pdc, resvalue, 0,
|
||
enc, codepage, resvalflags);
|
||
}
|
||
|
||
switch (rescat)
|
||
{
|
||
case pdc_FontOutline:
|
||
case pdc_FontAFM:
|
||
case pdc_FontPFM:
|
||
case pdc_HostFont:
|
||
case pdc_Encoding:
|
||
case pdc_ICCProfile:
|
||
case pdc_CMap:
|
||
case pdc_GlyphList:
|
||
case pdc_CodeList:
|
||
{
|
||
if (!strlen(resnamutf8) || !strlen(resvalutf8))
|
||
{
|
||
pdc_free(pdc, resnamutf8);
|
||
pdc_free(pdc, resvalutf8);
|
||
if (resvalue == NULL)
|
||
pdc_error(pdc, PDC_E_RES_BADRES, resname, category, 0, 0);
|
||
else
|
||
pdc_error(pdc, PDC_E_RES_BADRES2, resname, resvalue,
|
||
category, 0);
|
||
}
|
||
|
||
/* file name check */
|
||
resvalutf8 = pdc_check_filename(pdc, resvalutf8);
|
||
}
|
||
break;
|
||
|
||
case pdc_SearchPath:
|
||
{
|
||
if (strlen(resvalutf8))
|
||
{
|
||
if (resnamutf8 != NULL)
|
||
pdc_free(pdc, resnamutf8);
|
||
pdc_free(pdc, resvalutf8);
|
||
pdc_error(pdc, PDC_E_RES_BADRES, resname, category, 0, 0);
|
||
}
|
||
|
||
if (resvalutf8 != NULL)
|
||
{
|
||
pdc_free(pdc, resvalutf8);
|
||
resvalutf8 = NULL;
|
||
}
|
||
|
||
/* file name check */
|
||
if (resnamutf8 != NULL && strlen(resnamutf8))
|
||
{
|
||
resnamutf8 = pdc_check_filename(pdc, resnamutf8);
|
||
}
|
||
else
|
||
{
|
||
/* delete all entries */
|
||
if (resnamutf8 != NULL)
|
||
pdc_free(pdc, resnamutf8);
|
||
pdc_delete_rescategory(pdc, lastcat, cat, pdc_true);
|
||
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tResource category \"%s\" removed\n", category);
|
||
|
||
return;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case pdc_StandardOutputIntent:
|
||
break;
|
||
}
|
||
|
||
/* Find resource name in resource list */
|
||
lastres = NULL;
|
||
for (res = cat->kids; res != NULL; res = res->next)
|
||
{
|
||
if (!strcmp(res->name, resnamutf8))
|
||
break;
|
||
lastres = res;
|
||
}
|
||
|
||
/* New resource */
|
||
if (res == NULL)
|
||
{
|
||
res = (pdc_res *) pdc_calloc(pdc, sizeof(pdc_res), fn);
|
||
if (lastres)
|
||
lastres->next = res;
|
||
else
|
||
cat->kids = res;
|
||
res->prev = lastres;
|
||
res->name = resnamutf8;
|
||
}
|
||
else
|
||
{
|
||
pdc_free(pdc, resnamutf8);
|
||
}
|
||
|
||
/* New value */
|
||
if (res->value)
|
||
pdc_free(pdc, res->value);
|
||
res->value = resvalutf8;
|
||
|
||
if (res->value && strlen(res->value))
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tNew category.resource: \"%s.%s = %s\"\n",
|
||
category, res->name, res->value);
|
||
else
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tNew category.resource: \"%s.%s\"\n",
|
||
category, res->name);
|
||
}
|
||
|
||
void
|
||
pdc_add_resource(pdc_core *pdc, const char *category, const char *resname,
|
||
const char *resvalue)
|
||
{
|
||
pdc_add_resource_ext(pdc, category, resname, resvalue, pdc_invalidenc, 0);
|
||
}
|
||
|
||
const char *
|
||
pdc_find_resource(pdc_core *pdc, const char *category, const char *name)
|
||
{
|
||
pdc_reslist *resl = pdc_get_reslist(pdc);
|
||
pdc_category *cat;
|
||
pdc_res *res;
|
||
|
||
/* Read resource configuration file if it is pending */
|
||
if (resl->filepending)
|
||
{
|
||
resl->filepending = pdc_false;
|
||
pdc_read_resourcefile(pdc, resl->filename);
|
||
}
|
||
|
||
for (cat = resl->resources; cat != (pdc_category *) NULL; cat = cat->next)
|
||
{
|
||
if (!pdc_stricmp(cat->category, category))
|
||
{
|
||
for (res = cat->kids; res != (pdc_res *)NULL; res = res->next)
|
||
{
|
||
if (!strcmp(res->name, name))
|
||
{
|
||
if (pdc_logg_is_enabled(pdc, 1, trc_resource))
|
||
{
|
||
const char *resval = res->name, *separ = "";
|
||
|
||
if (res->value && strlen(res->value))
|
||
{
|
||
resval = res->value;
|
||
separ = " = ";
|
||
}
|
||
|
||
pdc_logg(pdc,
|
||
"\tFound category.resource: \"%s.%s%s%s\"\n",
|
||
category, res->name, separ, resval);
|
||
}
|
||
|
||
return res->value;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
const char *
|
||
pdc_find_resource_nr(pdc_core *pdc, const char *category, int nr)
|
||
{
|
||
pdc_reslist *resl = pdc_get_reslist(pdc);
|
||
pdc_category *cat;
|
||
pdc_rescategory rescat;
|
||
pdc_res *res;
|
||
int n = 0;
|
||
|
||
/* Read resource configuration file if it is pending */
|
||
if (resl->filepending)
|
||
{
|
||
resl->filepending = pdc_false;
|
||
pdc_read_resourcefile(pdc, resl->filename);
|
||
}
|
||
|
||
rescat = (pdc_rescategory) pdc_get_keycode_ci(category, pdc_rescategories);
|
||
|
||
for (cat = resl->resources; cat != (pdc_category *) NULL; cat = cat->next)
|
||
{
|
||
if (!pdc_stricmp(cat->category, category))
|
||
{
|
||
for (res = cat->kids; res != (pdc_res *)NULL; res = res->next)
|
||
{
|
||
n++;
|
||
if (n == nr)
|
||
{
|
||
char *resname = (char *) "", *resval = res->name;
|
||
const char *separ = "", *retval;
|
||
pdc_bool tobefree = pdc_false;
|
||
|
||
if (res->value && strlen(res->value))
|
||
{
|
||
resname = res->name;
|
||
resval = res->value;
|
||
separ = "=";
|
||
}
|
||
|
||
pdc_logg_cond(pdc, 1, trc_resource,
|
||
"\tFound %d. category.resource: "
|
||
"\"%s.%s%s%s\"\n",
|
||
nr, category, resname, separ, resval);
|
||
|
||
/* conversion of host encoded file names back to UTF-8 */
|
||
switch (rescat)
|
||
{
|
||
case pdc_StandardOutputIntent:
|
||
break;
|
||
|
||
default:
|
||
resval = pdc_get_filename(pdc, resval);
|
||
tobefree = pdc_true;
|
||
break;
|
||
}
|
||
|
||
retval =
|
||
pdc_errprintf(pdc, "%s%s%s", resname, separ, resval);
|
||
|
||
if (tobefree)
|
||
pdc_free(pdc, resval);
|
||
|
||
return retval;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return "";
|
||
}
|
||
|
||
|
||
/* ----------------------- virtual file handling ---------------------------- */
|
||
|
||
struct pdc_virtfile_s
|
||
{
|
||
char *name;
|
||
const void *data;
|
||
size_t size;
|
||
pdc_bool iscopy;
|
||
int lockcount;
|
||
pdc_virtfile *next;
|
||
};
|
||
|
||
static pdc_virtfile *
|
||
pdc_find_pvf(pdc_core *pdc, const char *filename, pdc_virtfile **lastvfile)
|
||
{
|
||
pdc_virtfile *vfile;
|
||
pdc_virtfile *filesystem = pdc->filesystem;
|
||
|
||
if (lastvfile != NULL)
|
||
*lastvfile = NULL;
|
||
for (vfile = filesystem; vfile != NULL; vfile = vfile->next)
|
||
{
|
||
if (!strcmp(vfile->name, filename))
|
||
{
|
||
pdc_logg_cond(pdc, 1, trc_filesearch,
|
||
"\n\tVirtual file \"%s\" found\n", filename);
|
||
return vfile;
|
||
}
|
||
if (lastvfile != NULL)
|
||
*lastvfile = vfile;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
/* definitions of pvf options */
|
||
static const pdc_defopt pdc_create_pvf_options[] =
|
||
{
|
||
{"copy", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
|
||
|
||
PDC_OPT_TERMINATE
|
||
};
|
||
|
||
void
|
||
pdc__create_pvf(pdc_core *pdc, const char *filename,
|
||
const void *data, size_t size, const char *optlist)
|
||
{
|
||
static const char fn[] = "pdc__create_pvf";
|
||
pdc_bool iscopy = pdc_false;
|
||
pdc_virtfile *vfile, *lastvfile = NULL;
|
||
pdc_resopt *results;
|
||
|
||
if (!data)
|
||
pdc_error(pdc, PDC_E_ILLARG_EMPTY, "data", 0, 0, 0);
|
||
|
||
if (!size)
|
||
pdc_error(pdc, PDC_E_ILLARG_EMPTY, "size", 0, 0, 0);
|
||
|
||
/* Parse optlist */
|
||
results = pdc_parse_optionlist(pdc, optlist, pdc_create_pvf_options,
|
||
NULL, pdc_true);
|
||
pdc_get_optvalues("copy", results, &iscopy, NULL);
|
||
pdc_cleanup_optionlist(pdc, results);
|
||
|
||
/* Find virtual file in file system */
|
||
vfile = pdc_find_pvf(pdc, filename, &lastvfile);
|
||
|
||
/* Name already exists */
|
||
if (vfile != NULL)
|
||
pdc_error(pdc, PDC_E_PVF_NAMEEXISTS, filename, 0, 0, 0);
|
||
|
||
/* New virtual file */
|
||
vfile = (pdc_virtfile *) pdc_calloc(pdc, sizeof(pdc_virtfile), fn);
|
||
if (lastvfile)
|
||
lastvfile->next = vfile;
|
||
else
|
||
pdc->filesystem = vfile;
|
||
|
||
/* Fill up file struct */
|
||
vfile->name = pdc_strdup(pdc, filename);
|
||
if (iscopy == pdc_true)
|
||
{
|
||
vfile->data = (const void *) pdc_malloc(pdc, size, fn);
|
||
memcpy((void *) vfile->data, data, size);
|
||
}
|
||
else
|
||
{
|
||
vfile->data = data;
|
||
}
|
||
vfile->size = size;
|
||
vfile->iscopy = iscopy;
|
||
vfile->lockcount = 0;
|
||
vfile->next = NULL;
|
||
|
||
pdc_logg_cond(pdc, 1, trc_filesearch,
|
||
"\n\tVirtual file \"%s\" created\n", filename);
|
||
}
|
||
|
||
int
|
||
pdc__delete_pvf(pdc_core *pdc, const char *filename)
|
||
{
|
||
pdc_virtfile *vfile, *lastvfile = NULL;
|
||
|
||
/* Find virtual file in file system */
|
||
vfile = pdc_find_pvf(pdc, filename, &lastvfile);
|
||
if (vfile)
|
||
{
|
||
/* File exists but locked */
|
||
if (vfile->lockcount > 0)
|
||
{
|
||
return pdc_undef;
|
||
}
|
||
|
||
/* Delete */
|
||
if (vfile->iscopy == pdc_true)
|
||
{
|
||
pdc_free(pdc, (void *) vfile->data);
|
||
vfile->data = NULL;
|
||
}
|
||
pdc_free(pdc, vfile->name);
|
||
if (lastvfile)
|
||
lastvfile->next = vfile->next;
|
||
else
|
||
pdc->filesystem = vfile->next;
|
||
pdc_free(pdc, vfile);
|
||
|
||
pdc_logg_cond(pdc, 1, trc_filesearch,
|
||
"\tVirtual file \"%s\" deleted\n", filename);
|
||
}
|
||
|
||
return pdc_true;
|
||
}
|
||
|
||
void
|
||
pdc_lock_pvf(pdc_core *pdc, const char *filename)
|
||
{
|
||
pdc_virtfile *vfile = pdc_find_pvf(pdc, filename, NULL);
|
||
if (vfile)
|
||
{
|
||
(vfile->lockcount)++;
|
||
|
||
pdc_logg_cond(pdc, 1, trc_filesearch,
|
||
"\tVirtual file \"%s\" locked\n", filename);
|
||
}
|
||
}
|
||
|
||
void
|
||
pdc_unlock_pvf(pdc_core *pdc, const char *filename)
|
||
{
|
||
pdc_virtfile *vfile = pdc_find_pvf(pdc, filename, NULL);
|
||
if (vfile)
|
||
{
|
||
(vfile->lockcount)--;
|
||
|
||
pdc_logg_cond(pdc, 1, trc_filesearch,
|
||
"\tVirtual file \"%s\" unlocked\n", filename);
|
||
}
|
||
}
|
||
|
||
void
|
||
pdc_delete_filesystem(pdc_core *pdc)
|
||
{
|
||
pdc_virtfile *vfile, *nextvfile;
|
||
pdc_virtfile *filesystem = pdc->filesystem;
|
||
|
||
for (vfile = filesystem; vfile != NULL; /* */)
|
||
{
|
||
nextvfile = vfile->next;
|
||
if (vfile->iscopy == pdc_true && vfile->data)
|
||
pdc_free(pdc, (void *) vfile->data);
|
||
if (vfile->name)
|
||
pdc_free(pdc, vfile->name);
|
||
pdc_free(pdc, vfile);
|
||
vfile = nextvfile;
|
||
}
|
||
pdc->filesystem = NULL;
|
||
}
|
||
|
||
|
||
/* ------------------------ file search handling ---------------------------- */
|
||
|
||
#if defined(_MSC_VER) && defined(_MANAGED)
|
||
#pragma unmanaged
|
||
#endif
|
||
pdc_file *
|
||
pdc_fsearch_fopen(pdc_core *pdc, const char *filename, char *fullname,
|
||
const char *qualifier, int flags)
|
||
{
|
||
pdc_reslist *resl = pdc_get_reslist(pdc);
|
||
char fullname_s[PDC_FILENAMELEN];
|
||
const pdc_byte *data = NULL;
|
||
pdc_file *sfp = NULL;
|
||
size_t size = 0;
|
||
pdc_virtfile *vfile;
|
||
|
||
if (fullname == NULL)
|
||
fullname = fullname_s;
|
||
strcpy(fullname, filename);
|
||
|
||
vfile = pdc_find_pvf(pdc, filename, NULL);
|
||
if (vfile)
|
||
{
|
||
size = vfile->size;
|
||
data = (const pdc_byte *) vfile->data;
|
||
sfp = pdc_fopen(pdc, filename, qualifier, data, size, flags);
|
||
}
|
||
else
|
||
{
|
||
pdc_category *cat;
|
||
|
||
/* Bad filename */
|
||
if (!*filename || !strcmp(filename, ".") || !strcmp(filename, ".."))
|
||
{
|
||
pdc_set_errmsg(pdc, PDC_E_IO_ILLFILENAME, filename, 0, 0, 0);
|
||
return NULL;
|
||
}
|
||
|
||
|
||
/* Read resource configuration file if it is pending */
|
||
if (resl->filepending)
|
||
{
|
||
resl->filepending = pdc_false;
|
||
pdc_read_resourcefile(pdc, resl->filename);
|
||
}
|
||
|
||
pdc_logg_cond(pdc, 1, trc_filesearch,
|
||
"\n\tSearching for file \"%s\":\n", filename);
|
||
|
||
/* Searching resource category */
|
||
for (cat = resl->resources;
|
||
cat != (pdc_category *) NULL;
|
||
cat = cat->next)
|
||
if (!pdc_stricmp(cat->category, "SearchPath")) break;
|
||
|
||
if (!cat)
|
||
{
|
||
/* No resource category */
|
||
sfp = pdc_fopen(pdc, filename, qualifier, NULL, 0, flags);
|
||
}
|
||
else
|
||
{
|
||
pdc_res *res = cat->kids;
|
||
pdc_res *lastres = cat->kids;
|
||
char *pathname = NULL;
|
||
FILE *fp = NULL;
|
||
int errnum = PDC_E_IO_RDOPEN_NF;
|
||
pdc_bool fatal = pdc_false;
|
||
|
||
/* Find last SearchPath entry */
|
||
while (res != (pdc_res *) NULL)
|
||
{
|
||
lastres = res;
|
||
res = res->next;
|
||
}
|
||
|
||
/* First local search and then search with concatenated
|
||
* filename with search paths one after another backwards
|
||
*/
|
||
while (1)
|
||
{
|
||
/* Test opening */
|
||
pdc_file_fullname(pdc, pathname, filename, fullname);
|
||
|
||
if (pathname != NULL)
|
||
pdc_logg_cond(pdc, 1, trc_filesearch,
|
||
"\tin directory \"%s\": \"%s\"\n", pathname, fullname);
|
||
|
||
fp = pdc_fopen_logg(pdc, fullname, READBMODE);
|
||
if (fp)
|
||
{
|
||
/* File found */
|
||
pdc_fclose_logg(pdc, fp);
|
||
sfp = pdc_fopen(pdc, fullname, qualifier, NULL, 0,flags);
|
||
break;
|
||
}
|
||
errnum = pdc_get_fopen_errnum(pdc, PDC_E_IO_RDOPEN);
|
||
if (errno != 0 && errnum != PDC_E_IO_RDOPEN_NF)
|
||
{
|
||
fatal = pdc_true;
|
||
pdc_set_fopen_errmsg(pdc, PDC_E_IO_RDOPEN,
|
||
qualifier, fullname);
|
||
}
|
||
|
||
#if defined(WIN32)
|
||
/* file name beginning with a drive letter: 'x:'
|
||
* is already full specified.
|
||
*/
|
||
if (pdc_isalpha(filename[0]) && filename[1] == ':')
|
||
break;
|
||
#endif
|
||
|
||
if (lastres == (pdc_res *) NULL)
|
||
break;
|
||
|
||
pathname = lastres->name;
|
||
lastres = lastres->prev;
|
||
}
|
||
|
||
if (sfp == NULL && !fatal)
|
||
pdc_set_fopen_errmsg(pdc, PDC_E_IO_RDOPEN,
|
||
qualifier, filename);
|
||
else
|
||
filename = fullname;
|
||
}
|
||
}
|
||
|
||
pdc_logg_cond(pdc, 1, trc_filesearch,
|
||
"\tFile \"%s\" %sfound\n", fullname, sfp == NULL ? "not " : "");
|
||
return sfp;
|
||
}
|
||
#if defined(_MSC_VER) && defined(_MANAGED)
|
||
#pragma managed
|
||
#endif
|
||
|
||
|
||
/* ----------------------- logging file handling ---------------------------- */
|
||
|
||
# ifndef DEFAULTLOGFILE
|
||
# if defined(MVS)
|
||
# define DEFAULTLOGFILE "pdflog"
|
||
# elif defined(MAC) || defined(AS400)
|
||
# define DEFAULTLOGFILE "/%s.log"
|
||
# elif defined(WIN32)
|
||
# define DEFAULTLOGFILE "\\%s.log"
|
||
# else
|
||
# define DEFAULTLOGFILE "/tmp/%s.log"
|
||
# endif
|
||
# endif
|
||
|
||
#define LOGFILEENVNAME "%sLOGFILE"
|
||
#define LOGGINGENVNAME "%sLOGGING"
|
||
|
||
#define PDC_CLASSLIST_SIZE 32
|
||
#define PDC_CLASSLIST_MAX 10
|
||
|
||
struct pdc_loggdef_s
|
||
{
|
||
pdc_bool enabled; /* logging enabled */
|
||
char *filename; /* name of the logging file */
|
||
pdc_bool fromenviron; /* logging file name defined environment */
|
||
pdc_bool header; /* with header and separation line */
|
||
pdc_bool flush; /* logging file will be opened and
|
||
* and closed immediately */
|
||
FILE *fp; /* flush = false: file handle */
|
||
pdc_strform_kind strform; /* format for logging strings */
|
||
int maxchar; /* maximal number of characters
|
||
* of logging strings */
|
||
int sri; /* first index in classlist for save/restore */
|
||
char classlist[PDC_CLASSLIST_MAX][PDC_CLASSLIST_SIZE];
|
||
/* list array of levels for logging classes */
|
||
pdc_bool classapi; /* only api class has level = 1
|
||
* and warning class has level = 1 */
|
||
};
|
||
|
||
static pdc_loggdef *
|
||
pdc_new_logg(pdc_core *pdc)
|
||
{
|
||
static const char fn[] = "pdc_new_logg";
|
||
char envname[32];
|
||
const char *envval = NULL;
|
||
|
||
pdc_loggdef *logg = (pdc_loggdef *)
|
||
pdc_malloc(pdc, sizeof(pdc_loggdef), fn);
|
||
|
||
logg->enabled = pdc_false;
|
||
logg->filename = NULL;
|
||
logg->fromenviron = pdc_false;
|
||
logg->header = pdc_true;
|
||
logg->flush = pdc_false;
|
||
logg->fp = NULL;
|
||
logg->strform = strform_readable;
|
||
logg->maxchar = 0;
|
||
logg->sri = 0;
|
||
memset(logg->classlist[0], 0, PDC_CLASSLIST_SIZE);
|
||
logg->classlist[0][trc_api] = 1;
|
||
logg->classlist[0][trc_warning] = 1;
|
||
logg->classapi = pdc_true;
|
||
|
||
pdc->logg = logg;
|
||
|
||
/* logging file name defined by environment variable */
|
||
sprintf(envname, LOGFILEENVNAME, pdc->prodname);
|
||
pdc_strtoupper(envname);
|
||
envval = pdc_getenv(envname);
|
||
if (envval != NULL)
|
||
{
|
||
logg->filename = pdc_strdup(pdc, envval);
|
||
logg->fromenviron = pdc_true;
|
||
}
|
||
|
||
return logg;
|
||
}
|
||
|
||
void
|
||
pdc_delete_logg(pdc_core *pdc)
|
||
{
|
||
if (pdc->logg != NULL)
|
||
{
|
||
pdc_loggdef *logg = pdc->logg;
|
||
|
||
logg->enabled = pdc_false;
|
||
|
||
/* close file */
|
||
if (logg->fp != NULL && logg->fp != stdout && logg->fp != stderr)
|
||
{
|
||
fclose(logg->fp);
|
||
logg->fp = NULL;
|
||
}
|
||
|
||
if (logg->filename != NULL)
|
||
{
|
||
pdc_free(pdc, logg->filename);
|
||
logg->filename = NULL;
|
||
}
|
||
|
||
pdc_free(pdc, logg);
|
||
pdc->logg = NULL;
|
||
}
|
||
}
|
||
|
||
static pdc_loggdef *
|
||
pdc_get_logg(pdc_core *pdc)
|
||
{
|
||
pdc_loggdef *logg = pdc->logg;
|
||
|
||
if (logg == NULL)
|
||
logg = pdc_new_logg(pdc);
|
||
|
||
return logg;
|
||
}
|
||
|
||
static const pdc_keyconn pdc_strform_keylist[] =
|
||
{
|
||
{"readable", strform_readable},
|
||
{"readable0", strform_readable0},
|
||
{"octal", strform_octal},
|
||
{"hex", strform_hexa},
|
||
{"java", strform_java},
|
||
{NULL, 0}
|
||
};
|
||
|
||
static const pdc_keyconn pdf_protoclass_keylist[] =
|
||
{
|
||
{"api", trc_api},
|
||
{"encoding", trc_encoding},
|
||
{"digsig", trc_digsig},
|
||
{"filesearch", trc_filesearch},
|
||
{"font", trc_font},
|
||
{"image", trc_image},
|
||
{"memory", trc_memory},
|
||
{"optlist", trc_optlist},
|
||
{"other", trc_other},
|
||
{"pcos", trc_pcos},
|
||
{"pdi", trc_pdi},
|
||
{"resource", trc_resource},
|
||
{"shadow", trc_shadow},
|
||
{"table", trc_table},
|
||
{"text", trc_text},
|
||
{"textflow", trc_textflow},
|
||
{"user", trc_user},
|
||
{"warning", trc_warning},
|
||
{"wordfinder", trc_wordfinder},
|
||
{"xmp", trc_xmp},
|
||
{"zones", trc_zones},
|
||
{NULL, 0}
|
||
};
|
||
|
||
#define PDC_FILENAMELEN 1024
|
||
|
||
static const pdc_defopt pdc_logg_options[] =
|
||
{
|
||
{"header", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
||
0.0, 0.0, NULL},
|
||
|
||
{"enable", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
||
0.0, 0.0, NULL},
|
||
|
||
{"disable", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
||
0.0, 0.0, NULL},
|
||
|
||
{"flush", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
||
0.0, 0.0, NULL},
|
||
|
||
{"remove", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
||
0.0, 0.0, NULL},
|
||
|
||
{"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1,
|
||
0.0, PDC_FILENAMELEN, NULL},
|
||
|
||
{"restore", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
||
0.0, 0.0, NULL},
|
||
|
||
{"save", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
|
||
0.0, 0.0, NULL},
|
||
|
||
{"stringformat", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
|
||
0.0, 0.0, pdc_strform_keylist},
|
||
|
||
{"stringlimit", pdc_integerlist, PDC_OPT_NONE, 1, 1,
|
||
0.0, PDC_INT_MAX, NULL},
|
||
|
||
{"classes", pdc_stringlist, PDC_OPT_EVENNUM |PDC_OPT_SUBOPTLIST,
|
||
1, 2 * PDC_CLASSLIST_SIZE, 1.0, 64, NULL},
|
||
|
||
PDC_OPT_TERMINATE
|
||
};
|
||
|
||
static const char *separstr =
|
||
"[ --------------------------------------------------------- ]\n";
|
||
|
||
void
|
||
pdc_set_logg_options(pdc_core *pdc, const char *optlist)
|
||
{
|
||
pdc_loggdef *logg = pdc_get_logg(pdc);
|
||
pdc_resopt *resopts = NULL;
|
||
char **strlist, *keyword;
|
||
char filename[PDC_FILENAMELEN+1];
|
||
pdc_bool sare = pdc_false;
|
||
pdc_bool enable = pdc_true;
|
||
pdc_bool remfile = pdc_false;
|
||
pdc_char level;
|
||
int inum, i, pclass = 0, sumlevel = 0;
|
||
|
||
filename[0] = 0;
|
||
if (optlist && strlen(optlist))
|
||
{
|
||
resopts = pdc_parse_optionlist(pdc, optlist, pdc_logg_options,
|
||
NULL, pdc_true);
|
||
|
||
if (pdc_get_optvalues("save", resopts, &sare, NULL) && sare)
|
||
{
|
||
i = logg->sri + 1;
|
||
if (i >= PDC_CLASSLIST_MAX)
|
||
pdc_error(pdc, PDC_E_INT_TOOMUCH_SARE, 0, 0, 0, 0);
|
||
memcpy(logg->classlist[i], logg->classlist[logg->sri],
|
||
PDC_CLASSLIST_SIZE);
|
||
logg->sri = i;
|
||
}
|
||
|
||
if (pdc_get_optvalues("restore", resopts, &sare, NULL) && sare)
|
||
{
|
||
i = logg->sri - 1;
|
||
if (i < 0)
|
||
pdc_error(pdc, PDC_E_INT_TOOMUCH_SARE, 0, 0, 0, 0);
|
||
logg->sri = i;
|
||
}
|
||
|
||
if (pdc_get_optvalues("disable", resopts, &inum, NULL))
|
||
enable = inum ? pdc_false : pdc_true;
|
||
|
||
pdc_get_optvalues("header", resopts, &logg->header, NULL);
|
||
|
||
pdc_get_optvalues("flush", resopts, &logg->flush, NULL);
|
||
|
||
pdc_get_optvalues("remove", resopts, &remfile, NULL);
|
||
|
||
if (!logg->fromenviron)
|
||
{
|
||
pdc_get_optvalues("filename", resopts, filename, NULL);
|
||
|
||
}
|
||
|
||
if (pdc_get_optvalues("stringformat", resopts, &inum, NULL))
|
||
logg->strform = (pdc_strform_kind) inum;
|
||
|
||
pdc_get_optvalues("stringlimit", resopts, &logg->maxchar, NULL);
|
||
|
||
inum = pdc_get_optvalues("classes", resopts, NULL, &strlist);
|
||
if (inum)
|
||
{
|
||
for (i = 0; i < inum; i++, i++)
|
||
{
|
||
if (!pdc_stricmp(strlist[i], "other"))
|
||
{
|
||
i++;
|
||
if (pdc_str2integer(strlist[i],
|
||
PDC_INT_CHAR | PDC_INT_UNSIGNED,
|
||
&level))
|
||
{
|
||
memset(logg->classlist[logg->sri], (int)level,
|
||
PDC_CLASSLIST_SIZE);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
for (i = 0; i < inum; i++)
|
||
{
|
||
keyword = strlist[i];
|
||
pclass = pdc_get_keycode_ci(keyword, pdf_protoclass_keylist);
|
||
if (pclass == PDC_KEY_NOTFOUND)
|
||
pdc_error(pdc, PDC_E_OPT_ILLKEYWORD,
|
||
"classes", keyword, 0, 0);
|
||
i++;
|
||
if (!pdc_str2integer(strlist[i],
|
||
PDC_INT_CHAR | PDC_INT_UNSIGNED,
|
||
&level))
|
||
pdc_error(pdc, PDC_E_OPT_ILLINTEGER,
|
||
keyword, strlist[i], 0, 0);
|
||
|
||
logg->classlist[logg->sri][pclass] = level;
|
||
}
|
||
|
||
for (i = 0; i < PDC_CLASSLIST_SIZE; i++)
|
||
sumlevel += (int) logg->classlist[logg->sri][i];
|
||
logg->classapi =
|
||
(sumlevel == 2 &&
|
||
logg->classlist[logg->sri][trc_api] &&
|
||
logg->classlist[logg->sri][trc_warning]) ?
|
||
pdc_true : pdc_false;
|
||
}
|
||
|
||
pdc_cleanup_optionlist(pdc, resopts);
|
||
}
|
||
|
||
/* disable */
|
||
if (logg->enabled && logg->header && !enable)
|
||
{
|
||
pdc_logg(pdc, "\n");
|
||
pdc_logg(pdc, separstr);
|
||
}
|
||
|
||
/* no new logging file name specified */
|
||
if (!strlen(filename))
|
||
{
|
||
if (logg->filename == NULL)
|
||
{
|
||
char tmpname[PDC_FILENAMELEN];
|
||
|
||
sprintf(tmpname, DEFAULTLOGFILE, pdc->prodname);
|
||
pdc_strtolower(tmpname);
|
||
strcpy(filename, tmpname);
|
||
}
|
||
else
|
||
{
|
||
strcpy(filename, logg->filename);
|
||
}
|
||
}
|
||
|
||
/* new logging file */
|
||
if (logg->filename == NULL || strcmp(logg->filename, filename))
|
||
{
|
||
pdc_time ltime;
|
||
|
||
/* close file */
|
||
if (logg->fp != stdout && logg->fp != stderr && logg->filename)
|
||
{
|
||
pdc_localtime(<ime);
|
||
pdc_logg(pdc, "[%04d-%02d-%02d %02d:%02d:%02d]\n",
|
||
ltime.year + 1900, ltime.month + 1, ltime.mday,
|
||
ltime.hour, ltime.minute, ltime.second);
|
||
if (logg->fp != NULL)
|
||
fclose(logg->fp);
|
||
}
|
||
logg->enabled = pdc_false;
|
||
|
||
/* remove file */
|
||
if (remfile && strcmp(filename, "stdout") && strcmp(filename, "stderr"))
|
||
remove(filename);
|
||
|
||
/* file name */
|
||
if (logg->filename != NULL)
|
||
pdc_free(pdc, logg->filename);
|
||
logg->filename = pdc_strdup(pdc, filename);
|
||
|
||
/* open file */
|
||
if (!logg->flush)
|
||
{
|
||
if (!strcmp(logg->filename, "stdout"))
|
||
logg->fp = stdout;
|
||
else if (!strcmp(logg->filename, "stderr"))
|
||
logg->fp = stderr;
|
||
else
|
||
logg->fp = fopen(logg->filename, APPENDMODE);
|
||
if (logg->fp == NULL)
|
||
{
|
||
pdc_error(pdc, PDC_E_IO_WROPEN, "log ", logg->filename,
|
||
0, 0);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
logg->fp = NULL;
|
||
}
|
||
|
||
|
||
/* header line */
|
||
logg->enabled = enable;
|
||
if (logg->enabled && logg->header && pdc->prodname != NULL)
|
||
{
|
||
char binding[64];
|
||
|
||
pdc_localtime(<ime);
|
||
binding[0] = 0;
|
||
if (pdc->binding)
|
||
{
|
||
strcat(binding, pdc->binding);
|
||
strcat(binding, " binding ");
|
||
}
|
||
pdc_logg(pdc, separstr);
|
||
pdc_logg(pdc, "[ %s %s %son %s (%s) ",
|
||
pdc->prodname, pdc->version, binding,
|
||
PDF_PLATFORM, PDC_ISBIGENDIAN ? "be" : "le");
|
||
pdc_logg(pdc, "%04d-%02d-%02d %02d:%02d:%02d ]\n",
|
||
ltime.year + 1900, ltime.month + 1, ltime.mday,
|
||
ltime.hour, ltime.minute, ltime.second);
|
||
|
||
if (logg->classapi)
|
||
pdc_logg(pdc, "[ Use %%s/\\[[^]]*\\]//g and %%s/)$/);"
|
||
"/ in vi to compile it ]\n");
|
||
pdc_logg(pdc, separstr);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
logg->enabled = enable;
|
||
}
|
||
}
|
||
|
||
const char *
|
||
pdc_print_loggstring(pdc_core *pdc, const char *str, int len)
|
||
{
|
||
pdc_strform_kind strform = strform_readable0;
|
||
int maxchar = 0;
|
||
|
||
if (pdc->logg != NULL && pdc->logg->enabled)
|
||
{
|
||
|
||
maxchar = pdc->logg->maxchar;
|
||
strform = pdc->logg->strform;
|
||
}
|
||
|
||
str = pdc_strprint(pdc, str, len, maxchar, strform);
|
||
|
||
|
||
return str;
|
||
}
|
||
|
||
/* logging function without any class level check and decorations
|
||
*/
|
||
static void
|
||
pdc_logg_output(pdc_core *pdc, const char *fmt, va_list ap)
|
||
{
|
||
pdc_loggdef *logg = pdc->logg;
|
||
|
||
if (logg->flush)
|
||
{
|
||
FILE *fp = NULL;
|
||
|
||
if (!strcmp(logg->filename, "stdout"))
|
||
fp = stdout;
|
||
else if (!strcmp(logg->filename, "stderr"))
|
||
fp = stderr;
|
||
else
|
||
fp = fopen(logg->filename, APPENDMODE);
|
||
|
||
if (fp == NULL)
|
||
{
|
||
logg->enabled = pdc_false;
|
||
pdc_error(pdc, PDC_E_IO_WROPEN, "log ", logg->filename,
|
||
0, 0);
|
||
}
|
||
|
||
pdc_vfprintf(pdc, pdc_false, fp, fmt, ap);
|
||
|
||
if (fp != stdout && fp != stderr)
|
||
fclose(fp);
|
||
}
|
||
else
|
||
{
|
||
pdc_vfprintf(pdc, pdc_false, logg->fp, fmt, ap);
|
||
fflush(logg->fp);
|
||
}
|
||
}
|
||
|
||
|
||
/* standard logging protocol functions for api function calls
|
||
*/
|
||
pdc_bool
|
||
pdc_enter_api_logg(pdc_core *pdc, const char *funame, pdc_bool enter_api,
|
||
const char *fmt, va_list args)
|
||
{
|
||
pdc_bool retval = pdc_true;
|
||
|
||
if (enter_api)
|
||
retval = pdc_enter_api(pdc, funame);
|
||
|
||
if (retval)
|
||
{
|
||
/* logging option list defined by environment variable */
|
||
if (pdc->loggenv == pdc_false)
|
||
{
|
||
char envname[32];
|
||
const char *envval = NULL;
|
||
|
||
pdc->loggenv = pdc_true;
|
||
sprintf(envname, LOGGINGENVNAME, pdc->prodname);
|
||
pdc_strtoupper(envname);
|
||
envval = pdc_getenv(envname);
|
||
if (envval != NULL)
|
||
{
|
||
pdc_set_logg_options(pdc, envval);
|
||
}
|
||
#if defined(WIN32)
|
||
else
|
||
{
|
||
char buffer[BUFSIZE];
|
||
char regkey[128];
|
||
HKEY hKey = NULL;
|
||
DWORD size, lType;
|
||
|
||
sprintf(regkey, REGISTRYKEY, pdc->prodname, pdc->version);
|
||
|
||
/* process registry entries */
|
||
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
|
||
(REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
|
||
{
|
||
size = BUFSIZE - 2;
|
||
pdc_strtolower(envname);
|
||
if (RegQueryValueExA(hKey, envname, (LPDWORD) NULL,
|
||
&lType, (LPBYTE) buffer, &size)
|
||
== ERROR_SUCCESS && *buffer)
|
||
{
|
||
pdc_set_logg_options(pdc, buffer);
|
||
}
|
||
|
||
RegCloseKey(hKey);
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
if (pdc->logg != NULL &&
|
||
pdc->logg->enabled &&
|
||
pdc->logg->classlist[pdc->logg->sri][trc_api])
|
||
{
|
||
/* time stamp */
|
||
if (pdc->logg->classlist[pdc->logg->sri][trc_api] > 1)
|
||
{
|
||
pdc_time ltime;
|
||
|
||
if (funame[0] == '\n')
|
||
{
|
||
pdc_logg(pdc, "\n");
|
||
funame++;
|
||
}
|
||
|
||
pdc_localtime(<ime);
|
||
pdc_logg(pdc, "[%02d:%02d:%02d] ",
|
||
ltime.hour, ltime.minute, ltime.second);
|
||
}
|
||
|
||
/* function name */
|
||
pdc_logg(pdc, "%s", funame);
|
||
|
||
/* function arg list */
|
||
pdc_logg_output(pdc, fmt, args);
|
||
}
|
||
}
|
||
|
||
return retval;
|
||
}
|
||
|
||
void
|
||
pdc_logg_exit_api(pdc_core *pdc, pdc_bool cleanup, const char *fmt, ...)
|
||
{
|
||
if (fmt != NULL && pdc != NULL &&
|
||
pdc->logg != NULL &&
|
||
pdc->logg->enabled &&
|
||
pdc->logg->classlist[pdc->logg->sri][trc_api])
|
||
{
|
||
va_list ap;
|
||
|
||
va_start(ap, fmt);
|
||
pdc_logg_output(pdc, fmt, ap);
|
||
va_end(ap);
|
||
}
|
||
|
||
if (cleanup)
|
||
pdc_tmlist_cleanup(pdc);
|
||
}
|
||
|
||
/*
|
||
* General logging functions
|
||
*/
|
||
|
||
/*
|
||
* pdc_logg_enable() enables/disables logging
|
||
*/
|
||
void
|
||
pdc_logg_enable(pdc_core *pdc, pdc_bool enable)
|
||
{
|
||
if (pdc != NULL && pdc->logg != NULL)
|
||
pdc->logg->enabled = enable;
|
||
}
|
||
|
||
/*
|
||
* pdc_logg_is_enabled() returns pdc_true
|
||
* if logging is enabled for logging class 'pclass' and level 'level'.
|
||
* Otherwise pdc_false will be returned.
|
||
*/
|
||
pdc_bool
|
||
pdc_logg_is_enabled(pdc_core *pdc, int level, int pclass)
|
||
{
|
||
return pdc->logg != NULL &&
|
||
pdc->logg->enabled &&
|
||
level <= pdc->logg->classlist[pdc->logg->sri][pclass];
|
||
}
|
||
|
||
|
||
/*
|
||
* pdc_logg() writes formatted text in the current logging file
|
||
* without checking whether logging is enabled.
|
||
* This function should only be used in connection with
|
||
* pdc_logg_is_enabled():
|
||
*/
|
||
void
|
||
pdc_logg(pdc_core *pdc, const char *fmt, ...)
|
||
{
|
||
if (pdc != NULL && pdc->logg != NULL && pdc->logg->enabled)
|
||
{
|
||
va_list ap;
|
||
|
||
va_start(ap, fmt);
|
||
pdc_logg_output(pdc, fmt, ap);
|
||
va_end(ap);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* pdc_logg_cond() writes formatted text in the current logging file
|
||
* if logging is enabled for logging class 'pclass' and level 'level'.
|
||
*/
|
||
void
|
||
pdc_logg_cond(pdc_core *pdc, int level, int pclass, const char *fmt, ...)
|
||
{
|
||
if (pdc != NULL && pdc->logg != NULL &&
|
||
pdc->logg->enabled &&
|
||
level <= pdc->logg->classlist[pdc->logg->sri][pclass])
|
||
{
|
||
va_list ap;
|
||
|
||
va_start(ap, fmt);
|
||
pdc_logg_output(pdc, fmt, ap);
|
||
va_end(ap);
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* pdc_logg_getlevel() returns the current level for a logging class
|
||
*/
|
||
int
|
||
pdc_logg_getlevel(pdc_core *pdc, int pclass)
|
||
{
|
||
if (pdc->logg != NULL && pdc->logg->enabled)
|
||
return (int) pdc->logg->classlist[pdc->logg->sri][pclass];
|
||
else
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* pdc_logg_bitarr() writes the literal representation of a bit array
|
||
(including a descriptive message) in 1 line in the current logging file.
|
||
variable nbit must be <=32.
|
||
*/
|
||
void
|
||
pdc_logg_bitarr(pdc_core *pdc, const char *msg, const char *bitarr, int nbit)
|
||
{
|
||
int i;
|
||
|
||
pdc_logg(pdc,"%s = ", msg);
|
||
|
||
nbit = MIN(nbit, 32);
|
||
for (i = 0; i <= nbit; i++)
|
||
{
|
||
if (!(i%8))
|
||
{
|
||
pdc_logg(pdc, "|");
|
||
}
|
||
if (i == nbit)
|
||
{
|
||
if (nbit == 8)
|
||
pdc_logg(pdc, " (%02X)", bitarr[0]);
|
||
else if (nbit == 16)
|
||
pdc_logg(pdc, " (%04X)", *((pdc_uint16 *) &bitarr[0]));
|
||
else if (nbit == 32)
|
||
pdc_logg(pdc, " (%08X)", *((pdc_uint32 *) &bitarr[0]));
|
||
pdc_logg(pdc, "\n");
|
||
}
|
||
else
|
||
{
|
||
pdc_logg(pdc, "%s", pdc_getbit(bitarr, i) ? "1" : "0");
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* pdc_logg_hexdump() writes the hexadecimal output of the specified buffer
|
||
(including a descriptive message) in the current logging file.
|
||
*/
|
||
void
|
||
pdc_logg_hexdump(pdc_core *pdc, const char *msg, const char *prefix,
|
||
const char *text, int tlen)
|
||
{
|
||
int i, k;
|
||
pdc_byte ct;
|
||
|
||
if (tlen == 1)
|
||
{
|
||
ct = (pdc_byte) text[0];
|
||
pdc_logg(pdc, "%s%s: %02X '%c'\n", prefix, msg, ct,
|
||
pdc_logg_isprint((int) ct) ? ct : '.');
|
||
}
|
||
else
|
||
{
|
||
pdc_logg(pdc,"%s%s:\n", prefix, msg);
|
||
|
||
for (i = 0; i < tlen; i += 16)
|
||
{
|
||
pdc_logg(pdc,"%s", prefix);
|
||
for (k = 0; k < 16; ++k)
|
||
{
|
||
if (i + k < tlen)
|
||
{
|
||
ct = (pdc_byte) text[i + k];
|
||
pdc_logg(pdc,"%02X ", ct);
|
||
}
|
||
else
|
||
pdc_logg(pdc," ");
|
||
}
|
||
|
||
pdc_logg(pdc," ");
|
||
for (k = 0; k < 16; ++k)
|
||
{
|
||
if (i + k < tlen)
|
||
{
|
||
ct = (pdc_byte) text[i + k];
|
||
pdc_logg(pdc,"%c", pdc_logg_isprint((int)ct) ? ct : '.');
|
||
}
|
||
else
|
||
pdc_logg(pdc," ");
|
||
}
|
||
|
||
pdc_logg(pdc,"\n");
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* pdc_warning() is the former function of PDFlib exception handling.
|
||
* Now, pdc_warning() calls the function pdc_set_warnmsg(), which writes
|
||
* only a warning message generated from a xx_generr.h file into the logfile,
|
||
* if warning = 1.
|
||
*/
|
||
void
|
||
pdc_warning(pdc_core *pdc, int errnum, const char *parm1, const char *parm2,
|
||
const char *parm3, const char *parm4)
|
||
{
|
||
if (!pdc->smokerun)
|
||
pdc_set_warnmsg(pdc, errnum, parm1, parm2, parm3, parm4);
|
||
}
|
||
|
||
/*
|
||
* utility function for logging a Unicode character
|
||
*
|
||
*/
|
||
void
|
||
pdc_logg_unichar(pdc_core *pdc, int unichar, pdc_bool kfill, pdc_bool newline)
|
||
{
|
||
if (unichar > 0xFFFF)
|
||
{
|
||
pdc_logg(pdc, "U+%05X", unichar);
|
||
}
|
||
else
|
||
{
|
||
pdc_logg(pdc, "U+%04X", unichar);
|
||
|
||
if ((unichar >= PDC_UNICODE_SPACE && unichar <= PDC_UNICODE_DELETE) ||
|
||
(unichar >= PDC_UNICODE_NBSP && unichar <= PDC_UNICODE_MAXLATIN1))
|
||
{
|
||
char c = (char) unichar;
|
||
|
||
|
||
pdc_logg(pdc, " [%c]", c);
|
||
}
|
||
else if (kfill)
|
||
{
|
||
pdc_logg(pdc, " ");
|
||
}
|
||
}
|
||
|
||
if (newline)
|
||
pdc_logg(pdc, "\n");
|
||
}
|
||
|
||
/*
|
||
* utility function for logging a Unicode string
|
||
*
|
||
*/
|
||
static const pdc_keyconn pdc_ascii_escape_keylist[] =
|
||
{
|
||
{"a", 0x07},
|
||
{"b", 0x08},
|
||
{"e", 0x1B},
|
||
{"f", 0x0C},
|
||
{"n", 0x0A},
|
||
{"r", 0x0D},
|
||
{"t", 0x09},
|
||
{"v", 0x0B},
|
||
{NULL, 0}
|
||
};
|
||
|
||
void
|
||
pdc_logg_unitext(pdc_core *pdc, pdc_ushort *ustext, int len, pdc_bool newline)
|
||
{
|
||
int i;
|
||
pdc_ushort usv;
|
||
const char *s;
|
||
char c;
|
||
|
||
pdc_logg(pdc, "\"");
|
||
for (i = 0; i < len; i++)
|
||
{
|
||
usv = ustext[i];
|
||
if (usv > PDC_UNICODE_MAXLATIN1)
|
||
{
|
||
pdc_logg(pdc, "\\u%04X", usv);
|
||
}
|
||
else
|
||
{
|
||
if (usv < PDC_UNICODE_SPACE)
|
||
{
|
||
s = pdc_get_keyword((int) usv, pdc_ascii_escape_keylist);
|
||
if (s != NULL)
|
||
{
|
||
pdc_logg(pdc, "\\%s", s);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if ((usv >= PDC_UNICODE_SPACE && usv <= PDC_UNICODE_DELETE) ||
|
||
(usv >= PDC_UNICODE_NBSP && usv <= PDC_UNICODE_MAXLATIN1))
|
||
{
|
||
c = (char) usv;
|
||
|
||
|
||
pdc_logg(pdc, "%c", c);
|
||
}
|
||
else
|
||
{
|
||
pdc_logg(pdc, "\\x%02X", usv);
|
||
}
|
||
}
|
||
}
|
||
|
||
pdc_logg(pdc, "\"");
|
||
if (newline)
|
||
pdc_logg(pdc, "\n");
|
||
}
|
||
|
||
|