Files correlati : Ricompilazione Demo : [ ] Commento : Riportata la versione 3.1 patch 650 git-svn-id: svn://10.65.10.50/trunk@14148 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1500 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1500 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*---------------------------------------------------------------------------*
 | 
						|
 |              PDFlib - A library for generating PDF on the fly             |
 | 
						|
 +---------------------------------------------------------------------------+
 | 
						|
 | Copyright (c) 1997-2005 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_core.c,v 1.2 2006-07-11 13:10:33 alex Exp $
 | 
						|
 *
 | 
						|
 * PDFlib core services
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include "pc_util.h"
 | 
						|
 | 
						|
#define PDF_NonfatalError 11
 | 
						|
#define PDF_UnknownError  12
 | 
						|
 | 
						|
#if defined(__ia64__) && defined (__linux__)
 | 
						|
#define PDC_ALIGN16
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
/* TODO: how to make this dynamic?
 | 
						|
** exception during pdc_core_init():
 | 
						|
**	- out of memory in pdc_sb_new()
 | 
						|
** exception during exception:
 | 
						|
**	- out of memory in pdc_sb_vprintf()
 | 
						|
**	- format error in pdc_sb_vprintf()
 | 
						|
*/
 | 
						|
#define PDC_ERRPARM_SIZE	2048
 | 
						|
#define PDC_ERRBUF_SIZE		(5 * PDC_ERRPARM_SIZE)
 | 
						|
#define PDC_XSTACK_INISIZE	10
 | 
						|
 | 
						|
#define PDC_CLASSLIST_SIZE      32
 | 
						|
 | 
						|
#define N_ERRTABS		(PDC_ET_LAST / 1000)
 | 
						|
 | 
						|
/* temporary free store.
 | 
						|
*/
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
    void  *		mem;
 | 
						|
    pdc_destructor	destr;
 | 
						|
    void  *		opaque;
 | 
						|
} pdc_tmpmem;
 | 
						|
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
    pdc_tmpmem *	tmpmem;
 | 
						|
    int			capacity;
 | 
						|
    int			size;
 | 
						|
} pdc_tmpmem_list;
 | 
						|
 | 
						|
static void pdc_tmlist_init(pdc_tmpmem_list *tm_list);
 | 
						|
static void pdc_tmlist_cleanup(pdc_core *pdc, pdc_tmpmem_list *tm_list);
 | 
						|
 | 
						|
 | 
						|
/* exception handling frame.
 | 
						|
*/
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
    pdc_jmpbuf		jbuf;
 | 
						|
} pdc_xframe;
 | 
						|
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
    pdc_error_info *	ei;
 | 
						|
    int			n_entries;
 | 
						|
} error_table;
 | 
						|
 | 
						|
 | 
						|
/* ------------------------ the core core structure ---------------------- */
 | 
						|
 | 
						|
struct pdc_core_s {
 | 
						|
    /* ------------ try/catch ------------ */
 | 
						|
    pdc_xframe *	x_stack;
 | 
						|
#ifdef PDC_ALIGN16
 | 
						|
    char *		x_alias;
 | 
						|
#endif
 | 
						|
    int			x_ssize;
 | 
						|
    int			x_sp;		/* exception stack pointer	*/
 | 
						|
 | 
						|
    /* ------------ error handling ------------ */
 | 
						|
    pdc_bool		warnings_enabled;
 | 
						|
    pdc_bool		in_error;
 | 
						|
    char		errbuf[PDC_ERRBUF_SIZE];
 | 
						|
    char		errparms[4][PDC_ERRPARM_SIZE];
 | 
						|
    int			epcount;
 | 
						|
    int			errnum;
 | 
						|
    pdc_bool		x_thrown;	/* exception thrown and not caught */
 | 
						|
    char *	        apiname;
 | 
						|
    pdc_error_fp	errorhandler;	/* client error handler		*/
 | 
						|
    void *		opaque;		/* client specific, opaque data */
 | 
						|
 | 
						|
    error_table		err_tables[N_ERRTABS];
 | 
						|
 | 
						|
    /* ------------------ tracing ---------------- */
 | 
						|
    pdc_bool		tracestatus;    /* trace status */
 | 
						|
                                        /* = pdc_undef: new file
 | 
						|
                                         * = pdc_true:  enabled
 | 
						|
                                         * = pdc_false: disabled */
 | 
						|
    char *		tracefilename;	/* name of the trace file */
 | 
						|
    pdc_bool            traceflush;     /* trace file will be opened and
 | 
						|
                                         * and closed immediately */
 | 
						|
    FILE *              tracefp;        /* traceflush = false: file handle */
 | 
						|
    pdc_strform_kind    tracestrform;   /* format for trace strings */
 | 
						|
    int                 tracemaxchar;   /* maximal number of characters
 | 
						|
                                         * of trace strings */
 | 
						|
    char                traceclasslist[PDC_CLASSLIST_SIZE];
 | 
						|
                                        /* list of levels for logging classes.
 | 
						|
                                         * Index 0 - 9:  reserved for pdcore.
 | 
						|
                                         * (see enum pdc_protocol_class)
 | 
						|
                                         * Index 10 - 63: reserved for client.
 | 
						|
                                         */
 | 
						|
    pdc_bool            traceclassapi;  /* only api class has level > 0 */
 | 
						|
    int			floatdigits;	/* floating point output precision */
 | 
						|
#ifdef	PDC_DEBUG
 | 
						|
    pdc_bool		hexdump;	/* hexdump feature enabled? */
 | 
						|
#endif /* PDC_DEBUG */
 | 
						|
 | 
						|
    /* ------------ memory management ------------ */
 | 
						|
    pdc_alloc_fp	allocproc;
 | 
						|
    pdc_realloc_fp	reallocproc;
 | 
						|
    pdc_free_fp		freeproc;
 | 
						|
    pdc_tmpmem_list	tm_list;
 | 
						|
 | 
						|
    /* ------------ encoding handling ------------ */
 | 
						|
    void *              pglyphtab;      /* private glyph table */
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ----------- default memory management & error handling ----------- */
 | 
						|
 | 
						|
static void *
 | 
						|
default_malloc(void *opaque, size_t size, const char *caller)
 | 
						|
{
 | 
						|
    (void) opaque;
 | 
						|
    (void) caller;
 | 
						|
 | 
						|
    return malloc(size);
 | 
						|
}
 | 
						|
 | 
						|
static void *
 | 
						|
default_realloc(void *opaque, void *mem, size_t size, const char *caller)
 | 
						|
{
 | 
						|
    (void) opaque;
 | 
						|
    (void) caller;
 | 
						|
 | 
						|
    return realloc(mem, size);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
default_free(void *opaque, void *mem)
 | 
						|
{
 | 
						|
    (void) opaque;
 | 
						|
 | 
						|
    free(mem);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
default_errorhandler(void *opaque, int errnum, const char *msg)
 | 
						|
{
 | 
						|
    (void) opaque;
 | 
						|
 | 
						|
    if (errnum == PDF_NonfatalError)
 | 
						|
    {
 | 
						|
	fprintf(stderr, "PDFlib warning (ignored): %s\n", msg);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	fprintf(stderr, "PDFlib exception (fatal): %s\n", msg);
 | 
						|
	exit(99);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
pdc_bool
 | 
						|
pdc_enter_api(pdc_core *pdc, const char *apiname, int flags)
 | 
						|
{
 | 
						|
    char *name = NULL;
 | 
						|
 | 
						|
    if (pdc->in_error)
 | 
						|
	return pdc_false;
 | 
						|
 | 
						|
    if (flags & PDC_ET_NOPREFIX)
 | 
						|
        name = strchr(apiname, '_');
 | 
						|
    if (name)
 | 
						|
        name++;
 | 
						|
    else
 | 
						|
        name = (char *) apiname;
 | 
						|
 | 
						|
    if (pdc->apiname)
 | 
						|
        pdc_free(pdc, pdc->apiname);
 | 
						|
    pdc->apiname = pdc_strdup(pdc, name);
 | 
						|
 | 
						|
    if (flags & PDC_ET_NOSUFFIX)
 | 
						|
    {
 | 
						|
        size_t len = strlen(pdc->apiname);
 | 
						|
        len--;
 | 
						|
        if (len && pdc->apiname[len] == '2')
 | 
						|
            pdc->apiname[len] = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    pdc->errnum = 0;
 | 
						|
    return pdc_true;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdc_set_warnings(pdc_core *pdc, pdc_bool on)
 | 
						|
{
 | 
						|
    pdc->warnings_enabled = on;
 | 
						|
}
 | 
						|
 | 
						|
pdc_bool
 | 
						|
pdc_in_error(pdc_core *pdc)
 | 
						|
{
 | 
						|
    return pdc->in_error;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* --------------------- error table management --------------------- */
 | 
						|
 | 
						|
static pdc_error_info	core_errors[] =
 | 
						|
{
 | 
						|
#define		pdc_genInfo	1
 | 
						|
#include	"pc_generr.h"
 | 
						|
};
 | 
						|
 | 
						|
#define N_CORE_ERRORS	(sizeof core_errors / sizeof (pdc_error_info))
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
pdc_panic(pdc_core *pdc, const char *fmt, ...)
 | 
						|
{
 | 
						|
    va_list ap;
 | 
						|
 | 
						|
    va_start(ap, fmt);
 | 
						|
    vsprintf(pdc->errbuf, fmt, ap);
 | 
						|
    va_end(ap);
 | 
						|
 | 
						|
    pdc->errnum = PDF_UnknownError;
 | 
						|
    (*pdc->errorhandler)(pdc->opaque, pdc->errnum, pdc->errbuf);
 | 
						|
} /* pdc_panic */
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
check_parms(pdc_core *pdc, pdc_error_info *ei)
 | 
						|
{
 | 
						|
    const char *msg = ei->errmsg;
 | 
						|
    const char *dollar;
 | 
						|
 | 
						|
    while ((dollar = strchr(msg, '$')) != (char *) 0)
 | 
						|
    {
 | 
						|
	if (isdigit((int) dollar[1]))
 | 
						|
	{
 | 
						|
	    int n = dollar[1] - '0';
 | 
						|
 | 
						|
	    if (ei->nparms < n || n < 1)
 | 
						|
		pdc_panic(pdc, "illegal parameter '$%d' in error message %d",
 | 
						|
				    n, ei->errnum);
 | 
						|
	}
 | 
						|
	else if (dollar[1] != '$')
 | 
						|
	{
 | 
						|
	    pdc_panic(pdc,
 | 
						|
		"illegal '$' in error message %d", ei->errnum);
 | 
						|
	}
 | 
						|
 | 
						|
	msg = dollar + 1;
 | 
						|
    }
 | 
						|
} /* check_parms */
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
pdc_register_errtab(pdc_core *pdc, int et, pdc_error_info *ei, int n_entries)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    int n = (et / 1000) - 1;
 | 
						|
 | 
						|
    if (n < 0 || N_ERRTABS <= n || et % 1000 != 0)
 | 
						|
	pdc_panic(pdc, "tried to register unknown error table %d", et);
 | 
						|
 | 
						|
    /* ignore multiple registrations of the same table.
 | 
						|
    */
 | 
						|
    if (pdc->err_tables[n].ei != (pdc_error_info *) 0)
 | 
						|
	return;
 | 
						|
 | 
						|
    pdc->err_tables[n].ei = ei;
 | 
						|
    pdc->err_tables[n].n_entries = n_entries;
 | 
						|
 | 
						|
    check_parms(pdc, &ei[0]);
 | 
						|
 | 
						|
    for (i = 1; i < n_entries; ++i)
 | 
						|
    {
 | 
						|
	if (ei[i].errnum <= ei[i-1].errnum)
 | 
						|
	{
 | 
						|
	    pdc_panic(pdc,
 | 
						|
		"duplicate or misplaced error number %d", ei[i].errnum);
 | 
						|
	}
 | 
						|
 | 
						|
	/* an error table may span several blocks.
 | 
						|
	*/
 | 
						|
	if ((ei[i].errnum / 1000) - 1 > n)
 | 
						|
	{
 | 
						|
	    pdc->err_tables[n].n_entries = i;	/* correct old block size */
 | 
						|
 | 
						|
	    n = (ei[i].errnum / 1000) - 1;	/* new block number */
 | 
						|
 | 
						|
	    if (N_ERRTABS <= n)
 | 
						|
		pdc_panic(pdc, "invalid error number %d", ei[i].errnum);
 | 
						|
 | 
						|
	    ei += i;				/* start of new block */
 | 
						|
	    n_entries -= i;			/* size of new block */
 | 
						|
	    i = 0;
 | 
						|
	    pdc->err_tables[n].ei = ei;
 | 
						|
	    pdc->err_tables[n].n_entries = n_entries;
 | 
						|
	}
 | 
						|
 | 
						|
	check_parms(pdc, &ei[i]);
 | 
						|
    }
 | 
						|
} /* pdc_register_errtab */
 | 
						|
 | 
						|
 | 
						|
/* pdc_init_core() never throws exceptions.
 | 
						|
** it returns NULL if there's not enough memory.
 | 
						|
*/
 | 
						|
pdc_core *
 | 
						|
pdc_init_core(
 | 
						|
    pdc_error_fp errorhandler,
 | 
						|
    pdc_alloc_fp allocproc,
 | 
						|
    pdc_realloc_fp reallocproc,
 | 
						|
    pdc_free_fp freeproc,
 | 
						|
    void *opaque)
 | 
						|
{
 | 
						|
    static const char fn[] = "pdc_init_core";
 | 
						|
 | 
						|
    pdc_core *pdc;
 | 
						|
    int i;
 | 
						|
 | 
						|
    /* if allocproc is NULL, we use pdc's default memory handling.
 | 
						|
    */
 | 
						|
    if (allocproc == (pdc_alloc_fp) 0)
 | 
						|
    {
 | 
						|
	allocproc	= default_malloc;
 | 
						|
	reallocproc	= default_realloc;
 | 
						|
	freeproc	= default_free;
 | 
						|
    }
 | 
						|
 | 
						|
    if (errorhandler == (pdc_error_fp) 0)
 | 
						|
	errorhandler = default_errorhandler;
 | 
						|
 | 
						|
    pdc = (pdc_core *) (*allocproc)(opaque, sizeof (pdc_core), fn);
 | 
						|
 | 
						|
    if (pdc == (pdc_core *) 0)
 | 
						|
	return (pdc_core *) 0;
 | 
						|
 | 
						|
    pdc->errorhandler	= errorhandler;
 | 
						|
    pdc->allocproc	= allocproc;
 | 
						|
    pdc->reallocproc	= reallocproc;
 | 
						|
    pdc->freeproc	= freeproc;
 | 
						|
    pdc->opaque		= opaque;
 | 
						|
 | 
						|
    pdc->tracestatus    = pdc_undef;
 | 
						|
    pdc->tracefilename	= NULL;
 | 
						|
    pdc->traceflush     = pdc_true;
 | 
						|
    pdc->tracefp        = NULL;
 | 
						|
    pdc->tracestrform   = strform_readable;
 | 
						|
    pdc->tracemaxchar   = 0;
 | 
						|
    memset(pdc->traceclasslist, 0, PDC_CLASSLIST_SIZE);
 | 
						|
    pdc->traceclasslist[trc_api] = 1;
 | 
						|
    pdc->traceclassapi  = pdc_true;
 | 
						|
 | 
						|
    pdc->floatdigits	= 4;
 | 
						|
#ifdef	PDC_DEBUG
 | 
						|
    pdc->hexdump	= pdc_true;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* initialize error & exception handling.
 | 
						|
    */
 | 
						|
    pdc->warnings_enabled = pdc_true;
 | 
						|
    pdc->in_error = pdc_false;
 | 
						|
    pdc->x_thrown = pdc_false;
 | 
						|
    pdc->epcount = 0;
 | 
						|
    pdc->errnum = 0;
 | 
						|
    pdc->apiname = NULL;
 | 
						|
    pdc->x_sp = -1;
 | 
						|
    pdc->x_ssize = PDC_XSTACK_INISIZE;
 | 
						|
 | 
						|
#ifdef PDC_ALIGN16
 | 
						|
    pdc->x_alias = (char *)
 | 
						|
	(*allocproc)(opaque, 16 + pdc->x_ssize * sizeof (pdc_xframe), fn);
 | 
						|
 | 
						|
    if (pdc->x_alias == (char *) 0)
 | 
						|
	pdc->x_stack = (pdc_xframe *) 0;
 | 
						|
    else
 | 
						|
	pdc->x_stack = (pdc_xframe *)
 | 
						|
	    (((unsigned long) pdc->x_alias + 16) & 0xFFFFFFFFFFFFFFF0);
 | 
						|
#else
 | 
						|
    pdc->x_stack = (pdc_xframe *)
 | 
						|
	(*allocproc)(opaque, pdc->x_ssize * sizeof (pdc_xframe), fn);
 | 
						|
#endif
 | 
						|
 | 
						|
    if (pdc->x_stack == (pdc_xframe *) 0)
 | 
						|
    {
 | 
						|
	(*freeproc)(opaque, pdc);
 | 
						|
	return (pdc_core *) 0;
 | 
						|
    }
 | 
						|
 | 
						|
    pdc_tmlist_init(&pdc->tm_list);
 | 
						|
 | 
						|
    /* initialize error tables.
 | 
						|
    */
 | 
						|
    for (i = 0; i < N_ERRTABS; ++i)
 | 
						|
	pdc->err_tables[i].ei = (pdc_error_info *) 0;
 | 
						|
 | 
						|
    pdc_register_errtab(pdc, PDC_ET_CORE, core_errors, N_CORE_ERRORS);
 | 
						|
 | 
						|
 | 
						|
    /* initialize private glyph table */
 | 
						|
    pdc->pglyphtab = NULL;
 | 
						|
 | 
						|
    return pdc;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdc_delete_core(pdc_core *pdc)
 | 
						|
{
 | 
						|
    pdc_time    ltime;
 | 
						|
 | 
						|
    pdc_localtime(<ime);
 | 
						|
    pdc_trace(pdc, "[%04d-%02d-%02d %02d:%02d:%02d]\n",
 | 
						|
        ltime.year + 1900, ltime.month + 1, ltime.mday,
 | 
						|
        ltime.hour, ltime.minute, ltime.second);
 | 
						|
 | 
						|
    if (pdc->apiname)
 | 
						|
        pdc_free(pdc, pdc->apiname);
 | 
						|
 | 
						|
    pdc_tmlist_cleanup(pdc, &pdc->tm_list);
 | 
						|
 | 
						|
    if (pdc->tm_list.capacity != 0)
 | 
						|
	pdc_free(pdc, pdc->tm_list.tmpmem);
 | 
						|
 | 
						|
#ifdef PDC_ALIGN16
 | 
						|
    pdc_free(pdc, pdc->x_alias);
 | 
						|
#else
 | 
						|
    pdc_free(pdc, pdc->x_stack);
 | 
						|
#endif
 | 
						|
 | 
						|
    pdc_cleanup_pglyphtab(pdc);
 | 
						|
    pdc->pglyphtab = NULL;
 | 
						|
 | 
						|
    if (pdc->tracefp != NULL && pdc->tracefp != stdout && pdc->tracefp !=stderr)
 | 
						|
        fclose(pdc->tracefp);
 | 
						|
    pdc->tracefp = NULL;
 | 
						|
    if (pdc->tracefilename)
 | 
						|
        pdc_free(pdc, pdc->tracefilename);
 | 
						|
    pdc->tracefilename = NULL;
 | 
						|
    pdc->tracestatus = pdc_false;
 | 
						|
 | 
						|
    pdc_free(pdc, pdc);
 | 
						|
}
 | 
						|
 | 
						|
/* --------------------------- memory management --------------------------- */
 | 
						|
 | 
						|
void *
 | 
						|
pdc_malloc(pdc_core *pdc, size_t size, const char *caller)
 | 
						|
{
 | 
						|
    void *ret;
 | 
						|
 | 
						|
    /* the behavior of malloc(0) is undefined in ANSI C, and may
 | 
						|
     * result in a NULL pointer return value which makes PDFlib bail out.
 | 
						|
     */
 | 
						|
    if (size == (size_t) 0 || (long) size < 0L) {
 | 
						|
	size = (size_t) 1;
 | 
						|
	pdc_warning(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    if ((ret = (*pdc->allocproc)(pdc->opaque, size, caller)) == (void *) 0)
 | 
						|
    {
 | 
						|
	pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    pdc_trace_protocol(pdc, 1, trc_memory,
 | 
						|
                       "\t%p malloced, size=%d, called from \"%s\"\n",
 | 
						|
                       ret, size, caller);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/* We cook up our own calloc routine, using the caller-supplied
 | 
						|
 * malloc and memset.
 | 
						|
 */
 | 
						|
void *
 | 
						|
pdc_calloc(pdc_core *pdc, size_t size, const char *caller)
 | 
						|
{
 | 
						|
    void *ret;
 | 
						|
 | 
						|
    if (size == (size_t) 0 || (long) size < 0L) {
 | 
						|
	size = (size_t) 1;
 | 
						|
	pdc_warning(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    if ((ret = (*pdc->allocproc)(pdc->opaque, size, caller)) == (void *) 0)
 | 
						|
    {
 | 
						|
	pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    pdc_trace_protocol(pdc, 1, trc_memory,
 | 
						|
                       "\t%p calloced, size=%d, called from \"%s\"\n",
 | 
						|
                       ret, size, caller);
 | 
						|
 | 
						|
    memset(ret, 0, size);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
void *
 | 
						|
pdc_realloc(pdc_core *pdc, void *mem, size_t size, const char *caller)
 | 
						|
{
 | 
						|
    void *ret;
 | 
						|
 | 
						|
    if (size == (size_t) 0 || (long) size < 0L) {
 | 
						|
        size = (size_t) 1;
 | 
						|
        pdc_warning(pdc, PDC_E_INT_ALLOC0, caller, 0, 0, 0);
 | 
						|
    }
 | 
						|
 | 
						|
    if ((ret = (*pdc->reallocproc)(pdc->opaque, mem, size, caller))
 | 
						|
         == (void *) 0)
 | 
						|
	pdc_error(pdc, PDC_E_MEM_OUT, caller, 0, 0, 0);
 | 
						|
 | 
						|
    pdc_trace_protocol(pdc, 1, trc_memory,
 | 
						|
                       "\t%p realloced to\n"
 | 
						|
                       "\t%p new, size=%d, called from \"%s\"\n",
 | 
						|
                       mem, ret, size, caller);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdc_free(pdc_core *pdc, void *mem)
 | 
						|
{
 | 
						|
    pdc_trace_protocol(pdc, 1, trc_memory, "\t%p freed\n", mem);
 | 
						|
 | 
						|
    /* just in case the freeproc() isn't that ANSI compatible...
 | 
						|
    */
 | 
						|
    if (mem != NULL)
 | 
						|
	(*pdc->freeproc)(pdc->opaque, mem);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/* -------------------- temporary free store management -------------------- */
 | 
						|
 | 
						|
static void
 | 
						|
pdc_tmlist_init(pdc_tmpmem_list *tm_list)
 | 
						|
{
 | 
						|
    tm_list->size = tm_list->capacity = 0;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
pdc_tmlist_grow(pdc_core *pdc, pdc_tmpmem_list *tm_list)
 | 
						|
{
 | 
						|
    static const char	fn[] = "pdc_tmlist_grow";
 | 
						|
    static const int	chunksize = 20;
 | 
						|
 | 
						|
    if (tm_list->capacity == 0)
 | 
						|
    {
 | 
						|
	tm_list->capacity = chunksize;
 | 
						|
	tm_list->tmpmem = (pdc_tmpmem *) pdc_malloc(pdc,
 | 
						|
	    (size_t) (tm_list->capacity * sizeof (pdc_tmpmem)), fn);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	tm_list->capacity += chunksize;
 | 
						|
	tm_list->tmpmem = (pdc_tmpmem *) pdc_realloc(pdc, tm_list->tmpmem,
 | 
						|
	    (size_t) (tm_list->capacity * sizeof (pdc_tmpmem)), fn);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
pdc_tmlist_cleanup(pdc_core *pdc, pdc_tmpmem_list *tm_list)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    for (i = 0; i < tm_list->size; ++i)
 | 
						|
    {
 | 
						|
	if (tm_list->tmpmem[i].destr)
 | 
						|
	    tm_list->tmpmem[i].destr(pdc, tm_list->tmpmem[i].mem);
 | 
						|
 | 
						|
	pdc_free(pdc, tm_list->tmpmem[i].mem);
 | 
						|
    }
 | 
						|
 | 
						|
    tm_list->size = 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdc_insert_mem_tmp(
 | 
						|
    pdc_core *          pdc,
 | 
						|
    void *              memory,
 | 
						|
    void *              opaque,
 | 
						|
    pdc_destructor      destr)
 | 
						|
{
 | 
						|
    pdc_tmpmem_list *tm_list = &pdc->tm_list;
 | 
						|
 | 
						|
    if (tm_list->size == tm_list->capacity)
 | 
						|
        pdc_tmlist_grow(pdc, tm_list);
 | 
						|
 | 
						|
    tm_list->tmpmem[tm_list->size].mem = memory;
 | 
						|
    tm_list->tmpmem[tm_list->size].destr = destr;
 | 
						|
    tm_list->tmpmem[tm_list->size].opaque = opaque;
 | 
						|
    ++tm_list->size;
 | 
						|
}
 | 
						|
 | 
						|
void *
 | 
						|
pdc_malloc_tmp(
 | 
						|
    pdc_core *          pdc,
 | 
						|
    size_t              size,
 | 
						|
    const char *        caller,
 | 
						|
    void *              opaque,
 | 
						|
    pdc_destructor      destr)
 | 
						|
{
 | 
						|
    void *memory = pdc_malloc(pdc, size, caller);
 | 
						|
 | 
						|
    pdc_insert_mem_tmp(pdc, memory, opaque, destr);
 | 
						|
 | 
						|
    return memory;
 | 
						|
}
 | 
						|
 | 
						|
void *
 | 
						|
pdc_calloc_tmp(
 | 
						|
    pdc_core *		pdc,
 | 
						|
    size_t		size,
 | 
						|
    const char *	caller,
 | 
						|
    void *		opaque,
 | 
						|
    pdc_destructor	destr)
 | 
						|
{
 | 
						|
    void *memory = pdc_calloc(pdc, size, caller);
 | 
						|
 | 
						|
    pdc_insert_mem_tmp(pdc, memory, opaque, destr);
 | 
						|
 | 
						|
    return memory;
 | 
						|
}
 | 
						|
 | 
						|
void *
 | 
						|
pdc_realloc_tmp(pdc_core *pdc, void *mem, size_t size, const char *caller)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    pdc_tmpmem_list *tm_list = &pdc->tm_list;
 | 
						|
 | 
						|
    for (i = tm_list->size - 1; 0 <= i; --i)
 | 
						|
	if (tm_list->tmpmem[i].mem == mem)
 | 
						|
	    return tm_list->tmpmem[i].mem = pdc_realloc(pdc, mem, size, caller);
 | 
						|
 | 
						|
    pdc_error(pdc, PDC_E_INT_REALLOC_TMP, caller, 0, 0, 0);
 | 
						|
    return (void *) 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdc_free_tmp(pdc_core *pdc, void *mem)
 | 
						|
{
 | 
						|
    int i, j;
 | 
						|
    pdc_tmpmem_list *tm_list = &pdc->tm_list;
 | 
						|
 | 
						|
    /* we search the list backwards since chances are good
 | 
						|
    ** that the most recently allocated items are freed first.
 | 
						|
    */
 | 
						|
    for (i = tm_list->size - 1; 0 <= i; --i)
 | 
						|
    {
 | 
						|
	if (tm_list->tmpmem[i].mem == mem)
 | 
						|
	{
 | 
						|
	    if (tm_list->tmpmem[i].destr)
 | 
						|
		tm_list->tmpmem[i].destr(
 | 
						|
		    tm_list->tmpmem[i].opaque, tm_list->tmpmem[i].mem);
 | 
						|
 | 
						|
	    pdc_free(pdc, tm_list->tmpmem[i].mem);
 | 
						|
	    tm_list->tmpmem[i].mem = (void *) 0;
 | 
						|
 | 
						|
            --tm_list->size;
 | 
						|
            for (j = i; j < tm_list->size; j++)
 | 
						|
                tm_list->tmpmem[j] = tm_list->tmpmem[j + 1];
 | 
						|
 | 
						|
	    return;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    pdc_error(pdc, PDC_E_INT_FREE_TMP, 0, 0, 0, 0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* --------------------------- exception handling --------------------------- */
 | 
						|
 | 
						|
const char *pdc_errprintf(pdc_core *pdc, const char *fmt, ...)
 | 
						|
{
 | 
						|
    va_list ap;
 | 
						|
 | 
						|
    if (pdc->epcount < 0 || pdc->epcount > 3)
 | 
						|
        pdc->epcount = 0;
 | 
						|
 | 
						|
    va_start(ap, fmt);
 | 
						|
    vsprintf(pdc->errparms[pdc->epcount], fmt, ap);
 | 
						|
    va_end(ap);
 | 
						|
 | 
						|
    return pdc->errparms[pdc->epcount++];
 | 
						|
}
 | 
						|
 | 
						|
static pdc_error_info *
 | 
						|
get_error_info(pdc_core *pdc, int errnum)
 | 
						|
{
 | 
						|
    int n = (errnum / 1000) - 1;
 | 
						|
 | 
						|
    if (0 <= n && n < N_ERRTABS && pdc->err_tables[n].ei != 0)
 | 
						|
    {
 | 
						|
	error_table *etab = &pdc->err_tables[n];
 | 
						|
	int i;
 | 
						|
 | 
						|
	/* LATER: binary search. */
 | 
						|
	for (i = 0; i < etab->n_entries; ++i)
 | 
						|
	{
 | 
						|
	    if (etab->ei[i].errnum == errnum)
 | 
						|
		return &etab->ei[i];
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    pdc_panic(pdc, "Internal error: unknown error number %d", errnum);
 | 
						|
 | 
						|
    return (pdc_error_info *) 0;	/* for the compiler */
 | 
						|
} /* get_error_info */
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
make_errmsg(
 | 
						|
    pdc_core *		pdc,
 | 
						|
    pdc_error_info *	ei,
 | 
						|
    const char *	parm1,
 | 
						|
    const char *	parm2,
 | 
						|
    const char *	parm3,
 | 
						|
    const char *	parm4)
 | 
						|
{
 | 
						|
    const char *src = ei->ce_msg ? ei->ce_msg : ei->errmsg;
 | 
						|
    char *	dst = pdc->errbuf;
 | 
						|
    const char *dollar;
 | 
						|
 | 
						|
    pdc->epcount = 0;
 | 
						|
 | 
						|
    /* copy *src to *dst, replacing "$N" with *parmN.
 | 
						|
    */
 | 
						|
    while ((dollar = strchr(src, '$')) != (char *) 0)
 | 
						|
    {
 | 
						|
	const char *parm = (const char *) 0;
 | 
						|
 | 
						|
	memcpy(dst, src, (size_t) (dollar - src));
 | 
						|
	dst += dollar - src;
 | 
						|
	src = dollar + 1;
 | 
						|
 | 
						|
	switch (*src)
 | 
						|
	{
 | 
						|
	    case '1':	parm = (parm1 ? parm1 : "?");	break;
 | 
						|
	    case '2':	parm = (parm2 ? parm2 : "?");	break;
 | 
						|
	    case '3':	parm = (parm3 ? parm3 : "?");	break;
 | 
						|
	    case '4':	parm = (parm4 ? parm4 : "?");	break;
 | 
						|
 | 
						|
	    case 0:	break;
 | 
						|
 | 
						|
	    default:	*(dst++) = *(src++);
 | 
						|
			break;
 | 
						|
	}
 | 
						|
 | 
						|
	if (parm != (const char *) 0)
 | 
						|
	{
 | 
						|
	    ++src;
 | 
						|
	    strcpy(dst, parm);
 | 
						|
	    dst += strlen(parm);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    strcpy(dst, src);
 | 
						|
} /* make_errmsg */
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
pdc_set_errmsg(
 | 
						|
    pdc_core *  pdc,
 | 
						|
    int         errnum,
 | 
						|
    const char *parm1,
 | 
						|
    const char *parm2,
 | 
						|
    const char *parm3,
 | 
						|
    const char *parm4)
 | 
						|
{
 | 
						|
    pdc_error_info *ei = get_error_info(pdc, errnum);
 | 
						|
 | 
						|
    make_errmsg(pdc, ei, parm1, parm2, parm3, parm4);
 | 
						|
    pdc->errnum = errnum;
 | 
						|
 | 
						|
    pdc_trace_protocol(pdc, 1, trc_warning,
 | 
						|
        "\tError %d: \"%s\"\n", pdc->errnum, pdc->errbuf);
 | 
						|
} /* pdc_set_errmsg */
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
pdc_error(
 | 
						|
    pdc_core *	pdc,
 | 
						|
    int		errnum,
 | 
						|
    const char *parm1,
 | 
						|
    const char *parm2,
 | 
						|
    const char *parm3,
 | 
						|
    const char *parm4)
 | 
						|
{
 | 
						|
    if (pdc->in_error)		/* avoid recursive errors. */
 | 
						|
	return;
 | 
						|
    else
 | 
						|
    {
 | 
						|
	pdc->in_error = pdc_true;
 | 
						|
	pdc->x_thrown = pdc_true;
 | 
						|
    }
 | 
						|
 | 
						|
    if (errnum != -1)
 | 
						|
    {
 | 
						|
	pdc_error_info *ei = get_error_info(pdc, errnum);
 | 
						|
 | 
						|
	make_errmsg(pdc, ei, parm1, parm2, parm3, parm4);
 | 
						|
	pdc->errnum = errnum;
 | 
						|
    }
 | 
						|
 | 
						|
    pdc_trace(pdc, "\n[+++ Exception %d in %s, %s +++]\n",
 | 
						|
        pdc->errnum, (pdc->errnum == 0 || !pdc->apiname) ? "" : pdc->apiname,
 | 
						|
	(pdc->x_sp == -1 ?  "Error handler active" : "try/catch active"));
 | 
						|
    pdc_trace(pdc, "[\"%s\"]\n\n", pdc->errbuf);
 | 
						|
 | 
						|
    if (pdc->x_sp == -1)
 | 
						|
    {
 | 
						|
	char errbuf[PDC_ERRBUF_SIZE];
 | 
						|
 | 
						|
	sprintf(errbuf, "[%d] %s: %s",
 | 
						|
	    pdc->errnum, pdc_get_apiname(pdc), pdc->errbuf);
 | 
						|
 | 
						|
	pdc->errorhandler(pdc->opaque, PDF_UnknownError, errbuf);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * The error handler must never return. If it does, it is severely
 | 
						|
	 * broken. We cannot remedy this, so we exit.
 | 
						|
	 */
 | 
						|
	 exit(99);
 | 
						|
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	longjmp(pdc->x_stack[pdc->x_sp].jbuf.jbuf, 1);
 | 
						|
    }
 | 
						|
 | 
						|
} /* pdc_error */
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
pdc_warning(
 | 
						|
    pdc_core *	pdc,
 | 
						|
    int		errnum,
 | 
						|
    const char *parm1,
 | 
						|
    const char *parm2,
 | 
						|
    const char *parm3,
 | 
						|
    const char *parm4)
 | 
						|
{
 | 
						|
    if (pdc->in_error)
 | 
						|
	return;
 | 
						|
 | 
						|
    if (pdc->warnings_enabled == pdc_false)
 | 
						|
    {
 | 
						|
        if (pdc_trace_protocol_is_enabled(pdc, 1, trc_warning))
 | 
						|
        {
 | 
						|
            if (errnum != -1)
 | 
						|
            {
 | 
						|
                pdc_error_info *ei = get_error_info(pdc, errnum);
 | 
						|
 | 
						|
                make_errmsg(pdc, ei, parm1, parm2, parm3, parm4);
 | 
						|
                pdc->errnum = errnum;
 | 
						|
            }
 | 
						|
 | 
						|
            pdc_trace(pdc, "\tWarning %d: \"%s\"\n", pdc->errnum, pdc->errbuf);
 | 
						|
        }
 | 
						|
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    pdc->in_error = pdc_true;
 | 
						|
    pdc->x_thrown = pdc_true;
 | 
						|
 | 
						|
    if (errnum != -1)
 | 
						|
    {
 | 
						|
	pdc_error_info *ei = get_error_info(pdc, errnum);
 | 
						|
 | 
						|
	make_errmsg(pdc, ei, parm1, parm2, parm3, parm4);
 | 
						|
	pdc->errnum = errnum;
 | 
						|
    }
 | 
						|
 | 
						|
    pdc_trace(pdc, "\n[+++ Warning %d in %s, %s +++]\n",
 | 
						|
        pdc->errnum, (pdc->errnum == 0 || !pdc->apiname) ? "" : pdc->apiname,
 | 
						|
	(pdc->x_sp == -1 ?  "Error handler active" : "try/catch active"));
 | 
						|
    pdc_trace(pdc, "[\"%s\"]\n\n", pdc->errbuf);
 | 
						|
 | 
						|
    if (pdc->x_sp == -1)
 | 
						|
    {
 | 
						|
	char errbuf[PDC_ERRBUF_SIZE];
 | 
						|
 | 
						|
	sprintf(errbuf, "[%d] %s: %s",
 | 
						|
	    pdc->errnum, pdc_get_apiname(pdc), pdc->errbuf);
 | 
						|
 | 
						|
	(*pdc->errorhandler)(pdc->opaque, PDF_NonfatalError, errbuf);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	longjmp(pdc->x_stack[pdc->x_sp].jbuf.jbuf, 1);
 | 
						|
    }
 | 
						|
 | 
						|
    /* a client-supplied error handler may return after a warning */
 | 
						|
    pdc->in_error = pdc_false;
 | 
						|
 | 
						|
} /* pdc_warning */
 | 
						|
 | 
						|
 | 
						|
pdc_jmpbuf *
 | 
						|
pdc_jbuf(pdc_core *pdc)
 | 
						|
{
 | 
						|
    static const char fn[] = "pdc_jbuf";
 | 
						|
 | 
						|
    if (++pdc->x_sp == pdc->x_ssize)
 | 
						|
    {
 | 
						|
	pdc_xframe *aux;
 | 
						|
 | 
						|
#ifdef PDC_ALIGN16
 | 
						|
	char *cp = (char *) (*pdc->allocproc)(pdc->opaque,
 | 
						|
			16 + 2 * pdc->x_ssize * sizeof (pdc_xframe), fn);
 | 
						|
 | 
						|
	if (cp == (char *) 0)
 | 
						|
	{
 | 
						|
	    aux = (pdc_xframe *) 0;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    pdc_free(pdc, pdc->x_alias);
 | 
						|
	    pdc->x_alias = cp;
 | 
						|
	    aux = (pdc_xframe *)
 | 
						|
		(((unsigned long) cp + 16) & 0xFFFFFFFFFFFFFFF0);
 | 
						|
 | 
						|
	    memcpy(aux, pdc->x_stack, pdc->x_ssize * sizeof (pdc_xframe));
 | 
						|
	}
 | 
						|
#else
 | 
						|
	aux = (pdc_xframe *) (*pdc->reallocproc)(
 | 
						|
			pdc->opaque, pdc->x_stack,
 | 
						|
			2 * pdc->x_ssize * sizeof (pdc_xframe), fn);
 | 
						|
#endif
 | 
						|
 | 
						|
	if (aux == (pdc_xframe *) 0)
 | 
						|
	{
 | 
						|
	    --pdc->x_sp;
 | 
						|
	    pdc->x_thrown = pdc_true;
 | 
						|
	    pdc->in_error = pdc_true;
 | 
						|
 | 
						|
            pdc->errnum = PDC_E_MEM_OUT;
 | 
						|
            if (pdc->apiname)
 | 
						|
                pdc_free(pdc, pdc->apiname);
 | 
						|
            pdc->apiname = NULL;
 | 
						|
	    sprintf(pdc->errbuf,
 | 
						|
                    "Out of memory in TRY function (nesting level: %d)",
 | 
						|
                    pdc->x_sp + 1);
 | 
						|
 | 
						|
	    longjmp(pdc->x_stack[pdc->x_sp].jbuf.jbuf, 1);
 | 
						|
	}
 | 
						|
 | 
						|
	pdc->x_stack = aux;
 | 
						|
	pdc->x_ssize *= 2;
 | 
						|
    }
 | 
						|
 | 
						|
    pdc->x_thrown = pdc_false;
 | 
						|
    return &pdc->x_stack[pdc->x_sp].jbuf;
 | 
						|
} /* pdc_jbuf */
 | 
						|
 | 
						|
void
 | 
						|
pdc_exit_try(pdc_core *pdc)
 | 
						|
{
 | 
						|
    if (pdc->x_sp == -1)
 | 
						|
    {
 | 
						|
	strcpy(pdc->errbuf, "exception stack underflow");
 | 
						|
	pdc->errnum = PDC_E_INT_XSTACK;
 | 
						|
	(*pdc->errorhandler)(pdc->opaque, PDF_UnknownError, pdc->errbuf);
 | 
						|
    }
 | 
						|
    else
 | 
						|
	--pdc->x_sp;
 | 
						|
} /* pdc_exit_try */
 | 
						|
 | 
						|
int
 | 
						|
pdc_catch_intern(pdc_core *pdc)
 | 
						|
{
 | 
						|
    pdc_bool result;
 | 
						|
 | 
						|
    if (pdc->x_sp == -1)
 | 
						|
    {
 | 
						|
	strcpy(pdc->errbuf, "exception stack underflow");
 | 
						|
	pdc->errnum = PDC_E_INT_XSTACK;
 | 
						|
	(*pdc->errorhandler)(pdc->opaque, PDF_UnknownError, pdc->errbuf);
 | 
						|
    }
 | 
						|
    else
 | 
						|
	--pdc->x_sp;
 | 
						|
 | 
						|
    result = pdc->x_thrown;
 | 
						|
    pdc->in_error = pdc_false;
 | 
						|
    pdc->x_thrown = pdc_false;
 | 
						|
 | 
						|
    return result;
 | 
						|
} /* pdc_catch_intern */
 | 
						|
 | 
						|
int
 | 
						|
pdc_catch_extern(pdc_core *pdc)
 | 
						|
{
 | 
						|
    pdc_bool result;
 | 
						|
 | 
						|
    if (pdc->x_sp == -1)
 | 
						|
    {
 | 
						|
	strcpy(pdc->errbuf, "exception stack underflow");
 | 
						|
	pdc->errnum = PDC_E_INT_XSTACK;
 | 
						|
	(*pdc->errorhandler)(pdc->opaque, PDF_UnknownError, pdc->errbuf);
 | 
						|
    }
 | 
						|
    else
 | 
						|
	--pdc->x_sp;
 | 
						|
 | 
						|
    result = pdc->x_thrown;
 | 
						|
    pdc->x_thrown = pdc_false;
 | 
						|
 | 
						|
    return result;
 | 
						|
} /* pdc_catch_extern */
 | 
						|
 | 
						|
void
 | 
						|
pdc_rethrow(pdc_core *pdc)
 | 
						|
{
 | 
						|
    pdc_error(pdc, -1, 0, 0, 0, 0);
 | 
						|
} /* pdc_rethrow */
 | 
						|
 | 
						|
 | 
						|
int
 | 
						|
pdc_get_errnum(pdc_core *pdc)
 | 
						|
{
 | 
						|
    return pdc->errnum;
 | 
						|
}
 | 
						|
 | 
						|
const char *
 | 
						|
pdc_get_errmsg(pdc_core *pdc)
 | 
						|
{
 | 
						|
    return (pdc->errnum == 0) ? "" : pdc->errbuf;
 | 
						|
}
 | 
						|
 | 
						|
const char *
 | 
						|
pdc_get_apiname(pdc_core *pdc)
 | 
						|
{
 | 
						|
    return (pdc->errnum == 0 || !pdc->apiname) ? "" : pdc->apiname;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* --------------------------- debug trace  --------------------------- */
 | 
						|
 | 
						|
void
 | 
						|
pdc_set_tracefile(pdc_core *pdc, const char *filename)
 | 
						|
{
 | 
						|
    if (!filename || !*filename)
 | 
						|
        return;
 | 
						|
 | 
						|
    if (pdc->tracefilename)
 | 
						|
        pdc_free(pdc, pdc->tracefilename);
 | 
						|
 | 
						|
    pdc->tracefilename = pdc_strdup(pdc, filename);
 | 
						|
    pdc->tracestatus = pdc_undef;
 | 
						|
}
 | 
						|
 | 
						|
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[] =
 | 
						|
{
 | 
						|
    {"other",      trc_other},
 | 
						|
    {"api",        trc_api},
 | 
						|
    {"optlist",    trc_optlist},
 | 
						|
    {"memory",     trc_memory},
 | 
						|
    {"warning",    trc_warning},
 | 
						|
    {"resource",   trc_resource},
 | 
						|
    {"filesearch", trc_filesearch},
 | 
						|
    {"encoding",   trc_encoding},
 | 
						|
    {"image",      trc_image},
 | 
						|
    {"font",       trc_font},
 | 
						|
    {NULL, 0}
 | 
						|
};
 | 
						|
 | 
						|
static const pdc_defopt pdc_trace_options[] =
 | 
						|
{
 | 
						|
    {"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, 1024, 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, PDF_MAXSTRINGSIZE, NULL},
 | 
						|
 | 
						|
    {"classes", pdc_stringlist, PDC_OPT_EVENNUM |PDC_OPT_SUBOPTLIST,
 | 
						|
      1, 2 * PDC_CLASSLIST_SIZE, 1.0, 64, NULL},
 | 
						|
 | 
						|
    PDC_OPT_TERMINATE
 | 
						|
};
 | 
						|
 | 
						|
pdc_bool
 | 
						|
pdc_set_trace_options(pdc_core *pdc, const char *optlist)
 | 
						|
{
 | 
						|
    pdc_resopt *resopts = NULL;
 | 
						|
    char **strlist, *keyword;
 | 
						|
    pdc_bool enable = pdc_true;
 | 
						|
    pdc_bool remfile = pdc_false;
 | 
						|
    pdc_char level;
 | 
						|
    int inum, i, pclass = 0, sumlevel = 0;
 | 
						|
 | 
						|
    if (optlist && strlen(optlist))
 | 
						|
    {
 | 
						|
        resopts = pdc_parse_optionlist(pdc, optlist, pdc_trace_options,
 | 
						|
                                       NULL, pdc_true);
 | 
						|
 | 
						|
        enable = pdc_true;
 | 
						|
        pdc_get_optvalues("enable", resopts, &enable, NULL);
 | 
						|
        if (pdc_get_optvalues("disable", resopts, &inum, NULL))
 | 
						|
            enable = !inum;
 | 
						|
 | 
						|
        pdc_get_optvalues("flush", resopts, &pdc->traceflush, NULL);
 | 
						|
 | 
						|
        pdc_get_optvalues("remove", resopts, &remfile, NULL);
 | 
						|
 | 
						|
        if (pdc_get_optvalues("filename", resopts, NULL, &strlist))
 | 
						|
            pdc_set_tracefile(pdc, strlist[0]);
 | 
						|
 | 
						|
        if (pdc_get_optvalues("stringformat", resopts, &inum, NULL))
 | 
						|
            pdc->tracestrform = (pdc_strform_kind) inum;
 | 
						|
 | 
						|
        pdc_get_optvalues("stringlimit", resopts, &pdc->tracemaxchar, 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(pdc->traceclasslist, (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);
 | 
						|
 | 
						|
                pdc->traceclasslist[pclass] = level;
 | 
						|
            }
 | 
						|
 | 
						|
            for (i = 0; i < PDC_CLASSLIST_SIZE; i++)
 | 
						|
                sumlevel += (int) pdc->traceclasslist[i];
 | 
						|
            pdc->traceclassapi =
 | 
						|
                (sumlevel == 1 && pdc->traceclasslist[trc_api]) ?
 | 
						|
                pdc_true : pdc_false;
 | 
						|
        }
 | 
						|
 | 
						|
        pdc_cleanup_optionlist(pdc, resopts);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!enable)
 | 
						|
        pdc_set_trace(pdc, NULL);
 | 
						|
 | 
						|
    if (pdc->tracefp != NULL && pdc->tracefp != stdout && pdc->tracefp !=stderr)
 | 
						|
        fclose(pdc->tracefp);
 | 
						|
    pdc->tracefp = NULL;
 | 
						|
 | 
						|
    if (enable)
 | 
						|
    {
 | 
						|
        if (pdc->tracefilename == NULL)
 | 
						|
            pdc->tracefilename = pdc_strdup(pdc, DEBUG_TRACE_FILE);
 | 
						|
 | 
						|
        if (remfile && strcmp(pdc->tracefilename, "-"))
 | 
						|
            remove(pdc->tracefilename);
 | 
						|
 | 
						|
        if (!pdc->traceflush)
 | 
						|
        {
 | 
						|
            if (!strcmp(pdc->tracefilename, "stdout"))
 | 
						|
                pdc->tracefp = stdout;
 | 
						|
            else if (!strcmp(pdc->tracefilename, "stderr"))
 | 
						|
                pdc->tracefp = stderr;
 | 
						|
            else
 | 
						|
                pdc->tracefp = fopen(pdc->tracefilename, APPENDMODE);
 | 
						|
            if (pdc->tracefp == NULL)
 | 
						|
            {
 | 
						|
                pdc->tracestatus = pdc_false;
 | 
						|
                pdc_error(pdc, PDC_E_IO_WROPEN, "log ", pdc->tracefilename,
 | 
						|
                          0, 0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return enable;
 | 
						|
}
 | 
						|
 | 
						|
const char *
 | 
						|
pdc_print_tracestring(pdc_core *pdc, const char *str, int len)
 | 
						|
{
 | 
						|
    if (pdc->tracestatus == pdc_true)
 | 
						|
        return pdc_strprint(pdc, str, len, pdc->tracemaxchar,
 | 
						|
                            pdc->tracestrform);
 | 
						|
    else
 | 
						|
        return "";
 | 
						|
}
 | 
						|
 | 
						|
/* trace function without any class level check and decorations
 | 
						|
 */
 | 
						|
static void
 | 
						|
pdc_trace_output(pdc_core *pdc, const char *fmt, va_list ap)
 | 
						|
{
 | 
						|
    if (pdc->traceflush)
 | 
						|
    {
 | 
						|
        FILE *fp = NULL;
 | 
						|
 | 
						|
        if (!strcmp(pdc->tracefilename, "stdout"))
 | 
						|
            fp = stdout;
 | 
						|
        else if (!strcmp(pdc->tracefilename, "stderr"))
 | 
						|
            fp = stderr;
 | 
						|
        else
 | 
						|
            fp = fopen(pdc->tracefilename, APPENDMODE);
 | 
						|
 | 
						|
        if (fp == NULL)
 | 
						|
        {
 | 
						|
            pdc->tracestatus = pdc_false;
 | 
						|
            pdc_error(pdc, PDC_E_IO_WROPEN, "log ", pdc->tracefilename,
 | 
						|
                      0, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        pdc_vfprintf(pdc, pdc_false, fp, fmt, ap);
 | 
						|
 | 
						|
        if (fp != stdout && fp != stderr)
 | 
						|
            fclose(fp);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        pdc_vfprintf(pdc, pdc_false, pdc->tracefp, fmt, ap);
 | 
						|
        fflush(pdc->tracefp);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdc_trace(pdc_core *pdc, const char *fmt, ...)
 | 
						|
{
 | 
						|
    if (pdc && pdc->tracestatus == pdc_true)
 | 
						|
    {
 | 
						|
        va_list ap;
 | 
						|
 | 
						|
        va_start(ap, fmt);
 | 
						|
        pdc_trace_output(pdc, fmt, ap);
 | 
						|
        va_end(ap);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* start or stop (client == NULL) a trace for the supplied client program
 | 
						|
 */
 | 
						|
void
 | 
						|
pdc_set_trace(pdc_core *pdc, const char *client)
 | 
						|
{
 | 
						|
    const char *separstr =
 | 
						|
         "[ --------------------------------------------------------- ]\n";
 | 
						|
 | 
						|
    pdc_bool	old_tracestatus = pdc->tracestatus;
 | 
						|
    pdc_time	ltime;
 | 
						|
 | 
						|
    pdc_localtime(<ime);
 | 
						|
 | 
						|
    if (old_tracestatus == pdc_true && client == NULL)
 | 
						|
    {
 | 
						|
        pdc_trace(pdc, "\n");
 | 
						|
        pdc_trace(pdc, separstr);
 | 
						|
    }
 | 
						|
 | 
						|
    pdc->tracestatus = client ? pdc_true : pdc_false;
 | 
						|
 | 
						|
    if (old_tracestatus == pdc_undef && pdc->tracestatus == pdc_true)
 | 
						|
    {
 | 
						|
        pdc_trace(pdc, separstr);
 | 
						|
        pdc_trace(pdc, "[ %s on %s (%s) ", client, PDF_PLATFORM,
 | 
						|
                  PDC_ISBIGENDIAN ? "be" : "le");
 | 
						|
        pdc_trace(pdc, "%04d-%02d-%02d %02d:%02d:%02d ]\n",
 | 
						|
            ltime.year + 1900, ltime.month + 1, ltime.mday,
 | 
						|
            ltime.hour, ltime.minute, ltime.second);
 | 
						|
 | 
						|
        if (pdc->traceclassapi)
 | 
						|
            pdc_trace(pdc, "[ Use  %%s/\\[[^]]*\\]//g  and  %%s/)$/);"
 | 
						|
                           "/  in vi to compile it ]\n");
 | 
						|
        pdc_trace(pdc, separstr);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* standard trace protocol functions for api function calls
 | 
						|
 */
 | 
						|
void
 | 
						|
pdc_trace_enter_api(pdc_core *pdc, const char *funame,
 | 
						|
                    const char *fmt, va_list args)
 | 
						|
{
 | 
						|
    if (pdc && pdc->tracestatus == pdc_true && pdc->traceclasslist[trc_api])
 | 
						|
    {
 | 
						|
        /* time stamp */
 | 
						|
        if (pdc->traceclasslist[trc_api] > 1)
 | 
						|
        {
 | 
						|
            pdc_time ltime;
 | 
						|
 | 
						|
            pdc_localtime(<ime);
 | 
						|
            pdc_trace(pdc, "[%02d:%02d:%02d] ",
 | 
						|
                      ltime.hour, ltime.minute, ltime.second);
 | 
						|
        }
 | 
						|
 | 
						|
        /* function name */
 | 
						|
        pdc_trace(pdc, "%s", funame);
 | 
						|
 | 
						|
        /* function arg list */
 | 
						|
        pdc_trace_output(pdc, fmt, args);
 | 
						|
 | 
						|
        /* linefeed if not only API calls */
 | 
						|
        if (!pdc->traceclassapi)
 | 
						|
            pdc_trace(pdc, "\n");
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdc_trace_exit_api(pdc_core *pdc, pdc_bool cleanup, const char *fmt, ...)
 | 
						|
{
 | 
						|
    if (pdc->tracestatus == pdc_true && pdc->traceclasslist[trc_api] &&
 | 
						|
        fmt != NULL)
 | 
						|
    {
 | 
						|
        va_list ap;
 | 
						|
 | 
						|
        va_start(ap, fmt);
 | 
						|
        pdc_trace_output(pdc, fmt, ap);
 | 
						|
        va_end(ap);
 | 
						|
    }
 | 
						|
 | 
						|
    if (cleanup)
 | 
						|
        pdc_tmlist_cleanup(pdc, &pdc->tm_list);
 | 
						|
}
 | 
						|
 | 
						|
/* general trace protocol functions
 | 
						|
 */
 | 
						|
pdc_bool
 | 
						|
pdc_trace_protocol_is_enabled(pdc_core *pdc, int level, int pclass)
 | 
						|
{
 | 
						|
    return pdc->tracestatus == pdc_true && level <= pdc->traceclasslist[pclass];
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdc_trace_protocol(pdc_core *pdc, int level, int pclass, const char *fmt, ...)
 | 
						|
{
 | 
						|
    if (pdc && pdc->tracestatus == pdc_true &&
 | 
						|
        level <= pdc->traceclasslist[pclass])
 | 
						|
    {
 | 
						|
        va_list ap;
 | 
						|
 | 
						|
        va_start(ap, fmt);
 | 
						|
        pdc_trace_output(pdc, fmt, ap);
 | 
						|
        va_end(ap);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* ------------ encoding handling ------------ */
 | 
						|
 | 
						|
void
 | 
						|
pdc_set_pglyphtab_ptr(pdc_core *pdc, void *pglyphtab_ptr)
 | 
						|
{
 | 
						|
    pdc->pglyphtab = pglyphtab_ptr;
 | 
						|
}
 | 
						|
 | 
						|
void *
 | 
						|
pdc_get_pglyphtab_ptr(pdc_core *pdc)
 | 
						|
{
 | 
						|
    return pdc->pglyphtab;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* ----------- service function to get PDF version string  -------------- */
 | 
						|
 | 
						|
const char *
 | 
						|
pdc_get_pdfversion(pdc_core *pdc, int compatibility)
 | 
						|
{
 | 
						|
    return pdc_errprintf(pdc, "%d.%d", compatibility / 10, compatibility % 10);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* --------------------------- float digits  --------------------------- */
 | 
						|
 | 
						|
void
 | 
						|
pdc_set_floatdigits(pdc_core *pdc, int val)
 | 
						|
{
 | 
						|
    pdc->floatdigits = val;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
pdc_get_floatdigits(pdc_core *pdc)
 | 
						|
{
 | 
						|
    return pdc->floatdigits;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#ifdef	PDC_DEBUG
 | 
						|
/* --------------------------- debug hexdump  --------------------------- */
 | 
						|
void
 | 
						|
pdc_enable_hexdump(pdc_core *pdc)
 | 
						|
{
 | 
						|
    pdc->hexdump = pdc_true;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdc_disable_hexdump(pdc_core *pdc)
 | 
						|
{
 | 
						|
    pdc->hexdump = pdc_false;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
pdc_hexdump(pdc_core *pdc, const char *msg, const char *text, int tlen)
 | 
						|
{
 | 
						|
    if (pdc->hexdump)
 | 
						|
    {
 | 
						|
	int i, k;
 | 
						|
 | 
						|
	if (tlen == 1)
 | 
						|
	{
 | 
						|
	    printf("%s: %02X '%c'\n", msg,
 | 
						|
			(unsigned char) text[0],
 | 
						|
			isprint(text[0]) ? text[0] : '.');
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    printf("%s:\n", msg);
 | 
						|
 | 
						|
	    for (i = 0; i < tlen; i += 16)
 | 
						|
	    {
 | 
						|
		for (k = 0; k < 16; ++k)
 | 
						|
		    if (i + k < tlen)
 | 
						|
			printf("%02X ", (unsigned char) text[i + k]);
 | 
						|
		    else
 | 
						|
			printf("   ");
 | 
						|
 | 
						|
		printf(" ");
 | 
						|
		for (k = 0; k < 16; ++k)
 | 
						|
		    if (i + k < tlen)
 | 
						|
			printf("%c", isprint(text[i + k]) ? text[i + k] : '.');
 | 
						|
		    else
 | 
						|
			printf("   ");
 | 
						|
 | 
						|
		printf("\n");
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#endif /* PDC_DEBUG */
 |