Files correlati : pdflib Ricompilazione Demo : [ ] Commento : Aggiornata pdflib.dll alla versione 7.0.4 git-svn-id: svn://10.65.10.50/trunk@18580 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1985 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1985 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /*---------------------------------------------------------------------------*
 | ||
|  |              PDFlib - A library for generating PDF on the fly             |
 | ||
|  +---------------------------------------------------------------------------+
 | ||
|  | Copyright (c) 1997-2008 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.3 2009-03-23 08:51:17 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_bool logg1 = pdc_logg_is_enabled(pdc, 1, trc_resource);
 | ||
|     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];
 | ||
|     char prodname[32];
 | ||
|     char prodversion[32];
 | ||
|     char *c;
 | ||
| #define BUFSIZE 2048
 | ||
|     char buffer[BUFSIZE];
 | ||
| #ifdef WIN32
 | ||
|     char regkey[128];
 | ||
|     HKEY hKey = NULL;
 | ||
|     DWORD size, lType;
 | ||
| #endif
 | ||
|     int il, ip, nlines = 0, nextcat, begin;
 | ||
| 
 | ||
|     if (logg1)
 | ||
|         pdc_logg(pdc, "\n\tSearching for resource file...\n");
 | ||
| 
 | ||
|     /* product name */
 | ||
|     strcpy(prodname, pdc->prodname);
 | ||
| 
 | ||
|     /* product version: <major>.<minor> */
 | ||
|     strcpy(prodversion, pdc->version);
 | ||
|     if (strlen(pdc->version))
 | ||
|     {
 | ||
|         c = strchr(prodversion, '.');
 | ||
|         if (c != NULL)
 | ||
|         {
 | ||
|             c++;
 | ||
|             if (*c)
 | ||
|             {
 | ||
|                 c++;
 | ||
|                 if (pdc_isdigit(*c))
 | ||
|                     c++;
 | ||
|                 *c = 0;
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     if (logg1)
 | ||
|         pdc_logg(pdc, "\tProduct name=%s, version=%s\n",
 | ||
|                  prodname, prodversion);
 | ||
| 
 | ||
| #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
 | ||
|     if (logg1)
 | ||
|         pdc_logg(pdc, "\tSet AS400 default SearchPath entries\n");
 | ||
| 
 | ||
|     sprintf(buffer, "/%s/%s/fonts", prodname, pdc->version);
 | ||
|     pdc_add_resource(pdc, "SearchPath", buffer, "");
 | ||
| 
 | ||
|     sprintf(buffer, "/%s/%s/bind/data", prodname, pdc->version);
 | ||
|     pdc_add_resource(pdc, "SearchPath", buffer, "");
 | ||
| #endif  /* AS400 */
 | ||
| 
 | ||
| #ifdef MVS
 | ||
|     (void) buffer;
 | ||
|     (void) ip;
 | ||
| #endif
 | ||
| 
 | ||
| #ifdef WIN32
 | ||
|     /* process registry entries */
 | ||
|     if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
 | ||
|         (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
 | ||
|     {
 | ||
|         if (logg1)
 | ||
|             pdc_logg(pdc, "\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 np;
 | ||
| 
 | ||
|             if (logg1)
 | ||
|                 pdc_logg(pdc, "\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 */
 | ||
| 
 | ||
| #if !defined(WIN32) && !defined(AS400) && !defined(MVS)
 | ||
|     if (logg1)
 | ||
|         pdc_logg(pdc, "\tSet UNIX default SearchPath entries\n");
 | ||
| 
 | ||
|     for (il = 0; rootdirectories[il] != NULL; il++)
 | ||
|     {
 | ||
|         const char *home = pdc_getenv("HOME");
 | ||
| 
 | ||
|         if (home != NULL)
 | ||
|              sprintf(tmpname, rootdirectories[il], home);
 | ||
|         else
 | ||
|              strcpy(tmpname, rootdirectories[il]);
 | ||
| 
 | ||
|         for (ip = 0; defsearchpathlist[ip] != NULL; ip++)
 | ||
|         {
 | ||
|             sprintf(buffer, defsearchpathlist[ip],
 | ||
|                     tmpname, prodname, prodversion);
 | ||
|             pdc_add_resource(pdc, "SearchPath", buffer, "");
 | ||
|         }
 | ||
|     }
 | ||
| #endif /* !WIN32 && !AS400 && !MVS */
 | ||
| 
 | ||
|     /* 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)
 | ||
|                 {
 | ||
|                     if (logg1)
 | ||
|                         pdc_logg(pdc, "\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, "UPR ", 0);
 | ||
|             if (fp == NULL)
 | ||
|             {
 | ||
|                 uprfilename = NULL;
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     if (uprfilename != NULL && *uprfilename != '\0')
 | ||
|     {
 | ||
|         char *resfilename = resl->filename;
 | ||
| 
 | ||
|         if (logg1)
 | ||
|             pdc_logg(pdc, "\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_bool logg1 = pdc_logg_is_enabled(pdc, 1, trc_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 | PDC_CONV_TMPALLOC;
 | ||
|     int resvalflags = PDC_CONV_EBCDIC | PDC_CONV_TMPALLOC;
 | ||
|     int k;
 | ||
| 
 | ||
|     if (logg1)
 | ||
|     {
 | ||
|         if (!resvalue || !strlen(resvalue))
 | ||
|             pdc_logg(pdc, "\tAdd \"%s\" to resource category \"%s\"\n",
 | ||
|                      resname, category);
 | ||
|         else
 | ||
|             pdc_logg(pdc, "\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_ext(pdc, "", PDC_CONV_TMPALLOC, fn);
 | ||
|         }
 | ||
|         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))
 | ||
|             {
 | ||
|                 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))
 | ||
|             {
 | ||
|                 pdc_error(pdc, PDC_E_RES_BADRES, resname, category, 0, 0);
 | ||
|             }
 | ||
| 
 | ||
|             if (resvalutf8 != NULL)
 | ||
|             {
 | ||
|                 pdc_free_tmp(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_tmp(pdc, resnamutf8);
 | ||
|                 pdc_delete_rescategory(pdc, lastcat, cat, pdc_true);
 | ||
| 
 | ||
|                 if (logg1)
 | ||
|                     pdc_logg(pdc, "\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 = pdc_strdup(pdc, resnamutf8);
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|         pdc_free_tmp(pdc, resnamutf8);
 | ||
|     }
 | ||
| 
 | ||
|     /* New value */
 | ||
|     if (res->value)
 | ||
|         pdc_free(pdc, res->value);
 | ||
|     res->value = pdc_strdup(pdc, resvalutf8);
 | ||
| 
 | ||
|     if (logg1)
 | ||
|     {
 | ||
|         if (res->value && strlen(res->value))
 | ||
|             pdc_logg(pdc, "\tNew category.resource: \"%s.%s = %s\"\n",
 | ||
|                      category, res->name, res->value);
 | ||
|         else
 | ||
|             pdc_logg(pdc, "\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_tmp(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;
 | ||
|     const char *stemp = NULL;
 | ||
|     pdc_resopt *results;
 | ||
| 
 | ||
|     if (data == NULL)
 | ||
|         stemp = "data = NULL";
 | ||
| 
 | ||
|     if (!size)
 | ||
|         stemp = "size = 0";
 | ||
| 
 | ||
|     if (stemp != NULL)
 | ||
|         pdc_error(pdc, PDC_E_PAR_NODATA, stemp, 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)
 | ||
|         {
 | ||
|             const char *fname = pdc_get_opt_filename(pdc, "filename", resopts);
 | ||
| 
 | ||
|             if (fname != NULL)
 | ||
|                 strcpy(filename, fname);
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|         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)
 | ||
|         {
 | ||
|             /* due to honorlang, codeset of LANG: UTF-8 */
 | ||
|             i = pdc_is_utf8_bytecode(logg->filename) ? 3 : 0;
 | ||
| 
 | ||
|             if (!strcmp(logg->filename, "stdout"))
 | ||
|                 logg->fp = stdout;
 | ||
|             else if (!strcmp(logg->filename, "stderr"))
 | ||
|                 logg->fp = stderr;
 | ||
|             else
 | ||
|                 logg->fp = fopen(&logg->filename[i], 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;
 | ||
| 
 | ||
|         /* due to honorlang, codeset of LANG: UTF-8 */
 | ||
|         int i = pdc_is_utf8_bytecode(logg->filename) ? 3 : 0;
 | ||
| 
 | ||
|         if (!strcmp(logg->filename, "stdout"))
 | ||
|             fp = stdout;
 | ||
|         else if (!strcmp(logg->filename, "stderr"))
 | ||
|             fp = stderr;
 | ||
|         else
 | ||
|             fp = fopen(&logg->filename[i], 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");
 | ||
| }
 | ||
| 
 | ||
| 
 |