1 /*---------------------------------------------------------------------------*
2  |              PDFlib - A library for generating PDF on the fly             |
3  +---------------------------------------------------------------------------+
4  | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
5  +---------------------------------------------------------------------------+
6  |                                                                           |
7  |    This software is subject to the PDFlib license. It is NOT in the       |
8  |    public domain. Extended versions and commercial licenses are           |
9  |    available, please check http://www.pdflib.com.                         |
10  |                                                                           |
11  *---------------------------------------------------------------------------*/
12 
13 /* $Id: pc_util.c,v 1.209.2.69 2010/04/21 18:58:46 kurt Exp $
14  *
15  * PDFlib various utility routines
16  *
17  */
18 
19 #include <errno.h>
20 
21 #include "pc_util.h"
22 #include "pc_file.h"
23 #include "pc_ctype.h"
24 
25 #ifdef AS400
26 #include <qp0z1170.h>   /* for getenv() emulation */
27 #endif
28 
29 #ifdef __sun
30 #include <ieeefp.h>     /* for finite */
31 #endif
32 
33 #if defined (isfinite)
34 #define PDC_ISFINITE isfinite
35 #else /* isfinite */
36 
37 #if defined(WIN32)
38 #if !defined(_UNICODE)
39 #define UNICODE
40 #endif
41 #include <windows.h>
42 #include <float.h>
43 #include <wchar.h>
44 #define PDC_ISFINITE _finite
45 #else /* WIN32 */
46 
47 #ifdef OS_ZOS_SASC
48 #define PDC_ISFINITE isfinite
49 #else /* OS_ZOS_SASC */
50 
51 #define PDC_ISFINITE finite
52 #endif
53 #endif
54 #endif
55 
56 
57 /* ---------------------- finite() workarounds -------------------------- */
58 
59 
60 
61 /*
62  * pdc_check_number checks whether a floating-point number
63  * is valid and within the specified range. If not, an exception
64  * will be thrown.
65  */
66 void
pdc_check_number_limits(pdc_core * pdc,const char * paramname,double dz,double dmin,double dmax)67 pdc_check_number_limits(pdc_core *pdc, const char *paramname, double dz,
68                         double dmin, double dmax)
69 {
70     if (!PDC_ISFINITE(dz))
71     {
72         pdc_error(pdc, PDC_E_ILLARG_FLOAT_NAN, paramname, 0, 0, 0);
73     }
74     else if (dz < dmin)
75     {
76         pdc_error(pdc, PDC_E_ILLARG_FLOAT_TOOSMALL, paramname,
77                   pdc_errprintf(pdc, "%f", dz),
78                   pdc_errprintf(pdc, "%f", dmin), 0);
79     }
80     else if (dz > dmax)
81     {
82         pdc_error(pdc, PDC_E_ILLARG_FLOAT_TOOLARGE, paramname,
83                   pdc_errprintf(pdc, "%f", dz),
84                   pdc_errprintf(pdc, "%f", dmax), 0);
85     }
86 }
87 
88 void
pdc_check_number(pdc_core * pdc,const char * paramname,double dz)89 pdc_check_number(pdc_core *pdc, const char *paramname, double dz)
90 {
91     pdc_check_number_limits(pdc, paramname, dz, PDC_FLOAT_MIN, PDC_FLOAT_MAX);
92 }
93 
94 void
pdc_check_number_zero(pdc_core * pdc,const char * paramname,double dz)95 pdc_check_number_zero(pdc_core *pdc, const char *paramname, double dz)
96 {
97     pdc_check_number_limits(pdc, paramname, dz, PDC_FLOAT_MIN, PDC_FLOAT_MAX);
98 
99     if (PDC_FLOAT_ISNULL(dz))
100     {
101         pdc_error(pdc, PDC_E_ILLARG_FLOAT_ZERO, paramname,
102                   pdc_errprintf(pdc, "%f", dz), 0, 0);
103     }
104 }
105 
106 int
pdc_check_text_length(pdc_core * pdc,const char ** text,int len,int maxlen)107 pdc_check_text_length(pdc_core *pdc, const char **text, int len, int maxlen)
108 {
109     if (*text == NULL)
110     {
111         len = 0;
112         *text = "";
113     }
114     else if (len == 0)
115     {
116         len = (int) strlen(*text);
117     }
118 
119     if (len < 0 || len > maxlen)
120     {
121         pdc_error(pdc, PDC_E_ILLARG_STRINGLEN,
122                   pdc_errprintf(pdc, "%d", len),
123                   pdc_errprintf(pdc, "%d", maxlen), 0, 0);
124     }
125 
126     return len;
127 }
128 
129 
130 /* ---------------- "unsupported feature" error message ------------------ */
131 
132 void
pdc_set_unsupp_error(pdc_core * pdc,int err_config,int err_lite,pdc_bool warning)133 pdc_set_unsupp_error(pdc_core *pdc, int err_config, int err_lite,
134                      pdc_bool warning)
135 {
136     (void) err_config;
137     (void) err_lite;
138 
139 /* this feature is sufficient for non public version */
140     if (warning)
141         pdc_warning(pdc, err_lite, 0, 0, 0, 0);
142     else
143         pdc_error(pdc, err_lite, 0, 0, 0, 0);
144 }
145 
146 
147 /* ---------------- error message with ASCII strings -------------------- */
148 
149 void
pdc_ascii_error(pdc_core * pdc,int errnum,int flags,const char * parm1,const char * parm2,const char * parm3,const char * parm4)150 pdc_ascii_error(pdc_core *pdc, int errnum, int flags, const char *parm1,
151                 const char *parm2, const char *parm3, const char *parm4)
152 {
153     if (flags & (1<<0))
154     {
155         parm1 = pdc_errprintf(pdc, "%a", parm1);
156     }
157 
158     if (flags & (1<<1))
159     {
160         parm2 = pdc_errprintf(pdc, "%a", parm2);
161     }
162 
163     if (flags & (1<<2))
164     {
165         parm3 = pdc_errprintf(pdc, "%a", parm3);
166     }
167 
168     if (flags & (1<<3))
169     {
170         parm4 = pdc_errprintf(pdc, "%a", parm4);
171     }
172 
173     pdc_error(pdc, errnum, parm1, parm2, parm3, parm4);
174 }
175 
176 
177 /* -------------------------- Time functions ------------------------------ */
178 
179 #ifndef WINCE
180 #ifndef __USE_POSIX
181 #define __USE_POSIX
182 #endif
183 #include <time.h>
184 #else
185 #include <winbase.h>
186 #endif
187 
188 /* our private localtime() function. this one circumvents platform
189 ** quirks we found on WINCE and Solaris, and perhaps some more in
190 ** the future.
191 */
192 void
pdc_localtime(pdc_time * t)193 pdc_localtime(pdc_time *t)
194 {
195 #ifdef WINCE
196 
197     SYSTEMTIME  st;
198 
199     GetLocalTime (&st);
200 
201     t->second = st.wSecond;
202     t->minute = st.wMinute;
203     t->hour = st.wHour;
204     t->mday = st.wDay;
205     t->wday = st.wDayOfWeek;
206     t->month = st.wMonth;
207     t->year = st.wYear;
208 
209 #else
210 
211     time_t      timer;
212     struct tm   ltime;
213 
214     time(&timer);
215 
216 #if defined(PDC_NEEDS_R_FUNCTIONS)
217 
218     /* the localtime() function isn't thread safe on this platform.
219     ** a thread safe variant must be used instead.
220     */
221     (void) localtime_r(&timer, &ltime);
222 
223 #else
224 
225     ltime = *localtime(&timer);
226 
227 #endif /* !PDC_NEEDS_R_FUNCTIONS */
228 
229     t->second = ltime.tm_sec;
230     t->minute = ltime.tm_min;
231     t->hour = ltime.tm_hour;
232     t->mday = ltime.tm_mday;
233     t->wday = ltime.tm_wday;
234     t->month = ltime.tm_mon;
235     t->year = ltime.tm_year;
236 
237 #endif /* !WINCE */
238 }
239 
240 static void
pdc_localtime_r(const time_t * timer,struct tm * res)241 pdc_localtime_r(const time_t *timer, struct tm *res)
242 {
243 #if defined(PDC_NEEDS_R_FUNCTIONS)
244     (void) localtime_r(timer, res);
245 #else
246     *res = *localtime(timer);
247 #endif
248 }
249 
250 static void
pdc_gmtime_r(const time_t * timer,struct tm * res)251 pdc_gmtime_r(const time_t *timer, struct tm *res)
252 {
253 #if defined(PDC_NEEDS_R_FUNCTIONS)
254     (void) gmtime_r(timer, res);
255 #else
256     *res = *gmtime(timer);
257 #endif
258 }
259 
260 void
pdc_get_timestr(char * str,pdc_bool ktoascii)261 pdc_get_timestr(char *str, pdc_bool ktoascii)
262 {
263 #ifndef WINCE
264     time_t      timer, gtimer;
265     struct tm   ltime;
266     double      diffminutes;
267     int         utcoffset;
268 #else
269     SYSTEMTIME  st;
270 #endif
271 
272     (void) ktoascii;
273 
274 #ifndef WINCE
275     time(&timer);
276 
277 #if !defined(I370)
278     pdc_gmtime_r(&timer, &ltime);
279     gtimer = mktime(&ltime);
280     pdc_localtime_r(&timer, &ltime);
281     ltime.tm_isdst = 0;
282     diffminutes = difftime(mktime(&ltime), gtimer) / 60;
283     if (diffminutes >= 0)
284         utcoffset = (int)(diffminutes + 0.5);
285     else
286         utcoffset = (int)(diffminutes - 0.5);
287 #else
288         utcoffset = 0;
289 #endif
290 
291     /* Get local time again, previous data is damaged by mktime(). */
292     pdc_localtime_r(&timer, &ltime);
293 
294     if (utcoffset > 0)
295         sprintf(str, "D:%04d%02d%02d%02d%02d%02d+%02d'%02d'",
296             ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
297             ltime.tm_hour, ltime.tm_min, ltime.tm_sec,
298             utcoffset / 60, utcoffset % 60);
299     else if (utcoffset < 0)
300         sprintf(str, "D:%04d%02d%02d%02d%02d%02d-%02d'%02d'",
301             ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
302             ltime.tm_hour, ltime.tm_min, ltime.tm_sec,
303             abs(utcoffset) / 60, abs(utcoffset) % 60);
304     else
305         sprintf(str, "D:%04d%02d%02d%02d%02d%02dZ",
306             ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
307             ltime.tm_hour, ltime.tm_min, ltime.tm_sec);
308 
309 #else
310     GetLocalTime (&st);
311     sprintf(str, "D:%04d%02d%02d%02d%02d%02d",
312             st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
313 #endif  /* !WINCE */
314 
315 
316 }
317 
318 
319 /* -------------------------- Environment ------------------------------ */
320 
321 char *
pdc_getenv(pdc_core * pdc,const char * envname)322 pdc_getenv(pdc_core *pdc, const char *envname)
323 {
324     char *envvalue = NULL;
325 
326     (void) pdc;
327     (void) envname;
328 
329 #ifdef HAVE_ENVVARS
330     envvalue = getenv(envname);
331     if (envvalue != NULL)
332     {
333         pdc_logg_cond(pdc, 1, trc_filesearch,
334             "\tEnvironment variable \"%s=%s\"\n", envname, envvalue);
335     }
336 #endif /* HAVE_ENVVARS */
337 
338     return envvalue;
339 }
340 
341 char *
pdc_getenv_filename(pdc_core * pdc,const char * envname)342 pdc_getenv_filename(pdc_core *pdc, const char *envname)
343 {
344     static const char fn[] = "pdc_getenv_filename";
345     char *envvalue = NULL;
346     int flags = PDC_CONV_TMPALLOC;
347 
348 #if defined(WIN32)
349 
350     size_t len = strlen(envname), wlen;
351     const wchar_t *wenvvalue;
352     wchar_t *wenvname;
353 
354     DWORD nSize = PDC_FILENAMELEN;
355 
356     wlen = 2 * (len + 1);
357     wenvname = (wchar_t *) pdc_calloc(pdc, wlen, fn);
358     pdc_inflate_ascii(envname, (int) len, (char *) wenvname, pdc_utf16);
359 
360     wenvvalue = _wgetenv(wenvname);
361     pdc_free(pdc, wenvname);
362 
363     if (wenvvalue != NULL && pdc_wstrlen((char *) wenvvalue))
364     {
365         wlen = 2 * wcslen(wenvvalue);
366         pdc_logg_cond(pdc, 1, trc_filesearch,
367             "\tEnvironment variable \"%s=%T\"\n", envname, wenvvalue, wlen);
368 
369         if (pdc_logg_is_enabled(pdc, 3, trc_filesearch))
370             flags |= PDC_CONV_LOGGING;
371 
372         envvalue = pdc_convert_name(pdc, (char *) wenvvalue, wlen, flags);
373     }
374 
375 #else /* WIN32 */
376 
377     envvalue = pdc_getenv(pdc, envname);
378     if (envvalue != NULL && strlen(envvalue))
379     {
380         envvalue = pdc_strdup_ext(pdc, envvalue, flags, fn);
381     }
382 
383 #endif /* !WIN32 */
384 
385     return envvalue;
386 }
387 
388 
389 
390 /* ------------------------ Language Code ------------------------------ */
391 
392 /* ISO 639 Windows and Mac Language codes */
393 static const char lang_codes_ISO639[] =
394     "ab aa af sq am ar hy as ay az ba eu bn dz bh bi br bg my be km ca zh co"
395     "hr cs da nl en eo et fo fa fj fi fr fy gl gd gv ka de el kl gn gu ha he"
396     "hi hu is id ia ie iu ik ga it ja jv kn ks kk rw ky rn ko ku lo la lv li"
397     "ln lt mk mg ms ml mt mi mr mo mn na ne no oc or om ps pl pt pa qu rm ro"
398     "ru sm sg sa sr sh st tn sn sd si ss sk sl so es su sw sv tl tg ta tt te"
399     "th bo ti to ts tr tk tw ug uk ur uz vi vo cy wo xh yi yo zu"
400     "pt-br en-gb en-us de-de de-ch";
401 
402 pdc_bool
pdc_check_lang_code(pdc_core * pdc,const char * lang_code)403 pdc_check_lang_code(pdc_core *pdc, const char* lang_code)
404 {
405     pdc_bool valid = pdc_false;
406     int     i;
407     char*   country_code;
408     char*   language;
409 
410     if ((lang_code != NULL) && *lang_code)
411     {
412         /* do not check for IANA or private languages */
413         if (!(valid = ((lang_code[0] == 'i') || (lang_code[0] == 'x'))))
414         {
415             language = pdc_strdup(pdc, lang_code);
416             for (i = 0; i < (int)strlen(language); i++)
417             {
418                 if (pdc_isupper(language[i]))
419                 {
420                     language[i] = (char) pdc_tolower((int)language[i]);
421                 }
422             }
423 
424 
425             country_code = (char *)strstr(lang_codes_ISO639, language);
426             valid = (country_code != NULL);
427 
428             if (!valid && (strlen(language) > 2))
429             {
430                 country_code = strchr(language, '-');
431                 if (country_code != NULL)
432                 {
433                     country_code[0] = '\0';
434 
435                     country_code = (char *)strstr(lang_codes_ISO639, language);
436                     valid = (country_code != NULL);
437 
438                     if (!valid)
439                     {
440                         pdc_warning(pdc, PDC_E_ILLARG_LANG_CODE,
441                                     lang_code, 0, 0, 0);
442                     }
443                 }
444             }
445 
446             pdc_free(pdc, language);
447         }
448     }
449 
450     return valid;
451 }
452 
453 
454 /* -------------------------- Bit arryas ------------------------------ */
455 
456 /* set bit right to left within a byte */
457 void
pdc_setbit(char * bitarr,int bit)458 pdc_setbit(char *bitarr, int bit)
459 {
460     bitarr[bit/8] |= (char) (1<<(bit%8));
461 }
462 
463 /* set bit left to right within a byte */
464 void
pdc_setbit_l2r(char * bitarr,int bit)465 pdc_setbit_l2r(char *bitarr, int bit)
466 {
467     bitarr[bit/8] |= (char) (0x80>>(bit%8));
468 }
469 
470 pdc_bool
pdc_getbit(const char * bitarr,int bit)471 pdc_getbit(const char *bitarr, int bit)
472 {
473     return (pdc_bool) (bitarr[bit/8] & (1<<(bit%8)));
474 }
475 
476 void
pdc_setbit_text(char * bitarr,const pdc_byte * text,int len,int nbits,int size)477 pdc_setbit_text(char *bitarr, const pdc_byte *text, int len,
478                 int nbits, int size)
479 {
480     int i, bit;
481     pdc_ushort *ustext = (pdc_ushort *) text;
482 
483     for (i = 0; i < len; i += size)
484     {
485         if (size == sizeof(pdc_byte))
486             bit = (int) text[i];
487         else
488             bit = ustext[i/size];
489         if (bit < nbits) pdc_setbit(bitarr, bit);
490     }
491 }
492 
493 
494 /* ---------- Get functions of integer binary data types --------------- */
495 
496 pdc_short
pdc_get_le_short(const pdc_byte * data)497 pdc_get_le_short(const pdc_byte *data)
498 {
499     return (pdc_short) ((pdc_short) (data[1] << 8) | data[0]);
500 }
501 
502 pdc_ushort
pdc_get_le_ushort(const pdc_byte * data)503 pdc_get_le_ushort(const pdc_byte *data)
504 {
505     return (pdc_ushort) ((data[1] << 8) | data[0]);
506 }
507 
508 pdc_uint32
pdc_get_le_ulong3(const pdc_byte * data)509 pdc_get_le_ulong3(const pdc_byte *data)
510 {
511     return (pdc_uint32) (((((data[2]) << 8) | data[1]) << 8) | data[0]);
512 }
513 
514 pdc_sint32
pdc_get_le_long(const pdc_byte * data)515 pdc_get_le_long(const pdc_byte *data)
516 {
517     return ((pdc_sint32)
518          (((((data[3] << 8) | data[2]) << 8) | data[1]) << 8) | data[0]);
519 }
520 
521 pdc_uint32
pdc_get_le_ulong(const pdc_byte * data)522 pdc_get_le_ulong(const pdc_byte *data)
523 {
524     return (pdc_uint32)
525          ((((((data[3] << 8) | data[2]) << 8) | data[1]) << 8) | data[0]);
526 }
527 
528 pdc_short
pdc_get_be_short(const pdc_byte * data)529 pdc_get_be_short(const pdc_byte *data)
530 {
531     return (pdc_short) ((pdc_short) (data[0] << 8) | data[1]);
532 }
533 
534 pdc_ushort
pdc_get_be_ushort(const pdc_byte * data)535 pdc_get_be_ushort(const pdc_byte *data)
536 {
537     return (pdc_ushort) ((data[0] << 8) | data[1]);
538 }
539 
540 pdc_uint32
pdc_get_be_ulong3(const pdc_byte * data)541 pdc_get_be_ulong3(const pdc_byte *data)
542 {
543     return (pdc_uint32) (((((data[0]) << 8) | data[1]) << 8) | data[2]);
544 }
545 
546 pdc_sint32
pdc_get_be_long(const pdc_byte * data)547 pdc_get_be_long(const pdc_byte *data)
548 {
549     return ((pdc_sint32)
550          (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3]);
551 }
552 
553 pdc_uint32
pdc_get_be_ulong(const pdc_byte * data)554 pdc_get_be_ulong(const pdc_byte *data)
555 {
556     return (pdc_uint32)
557         ((((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3]);
558 }
559 
560 
561 /* ----------------- String handling for Unicode too ------------------- */
562 
563 /* strlen() for wide character strings, which are double null terminated.
564  * pdc_wstrlen() returns the number of bytes in the Unicode string,
565  * NOT including the two terminating null bytes.
566  */
567 size_t
pdc_wstrlen(const char * str)568 pdc_wstrlen(const char *str)
569 {
570     size_t len = 0;
571 
572     while(str[len] != 0 || str[len+1] != 0)
573     {
574         len += 2;
575     }
576 
577     return len;
578 }
579 
580 /*
581  * This function returns the length in bytes for C and Unicode strings.
582  */
583 size_t
pdc_strlen(const char * str)584 pdc_strlen(const char *str)
585 {
586     if (pdc_is_utf16be_unicode(str) || pdc_is_utf16le_unicode(str))
587         return pdc_wstrlen(str);
588     else
589         return strlen(str);
590 }
591 
592 
593 /* Allocate a local buffer and copy the string including
594  * the terminating sentinel. If the string starts with the Unicode BOM
595  * it is considered a Unicode string, and must be terminated by
596  * two null bytes. Otherwise it is considered a plain C string and
597  * must be terminated by a single null byte.
598  * The caller is responsible for freeing the buffer.
599  *
600  * The special functions pdc_strdup, pdc_strdup_tmp and pdc_strdup_withbom
601  * should be replaced by the more sophisticated function pdc_strdup_ext.
602  * There: flags (see pc_unicode.h):
603  *
604  * PDC_CONV_TMPALLOC, PDC_CONV_EBCDIC, PDC_CONV_ASCII,
605  * PDC_CONV_WITHBOM, PDC_CONV_NOBOM, PDC_CONV_MAXSTRLEN
606  *
607  */
608 char *
pdc_strdup_ext(pdc_core * pdc,const char * text,int flags,const char * fn)609 pdc_strdup_ext(pdc_core *pdc, const char *text, int flags, const char *fn)
610 {
611     char *buf = NULL;
612 
613     if (text != NULL)
614     {
615         size_t len = pdc_strlen(text) + 1;
616         size_t is = 0, it = 0;
617 
618         if ((flags & PDC_CONV_MAXSTRLEN) && len > PDC_ERR_MAXSTRLEN)
619             len = PDC_ERR_MAXSTRLEN;
620 
621         if ((flags & PDC_CONV_NOBOM) && pdc_is_utf8_bytecode(text))
622             is = 3;
623 
624         if ((flags & PDC_CONV_WITHBOM) && !pdc_is_utf8_bytecode(text))
625             it = 3;
626 
627         len += it - is;
628         if (flags & PDC_CONV_TMPALLOC)
629             buf = (char *) pdc_malloc_tmp(pdc, len + 1, fn, NULL, NULL);
630         else
631             buf = (char *) pdc_malloc(pdc, len + 1, fn);
632 
633         memcpy(&buf[it], &text[is], len - it);
634         buf[len] = 0;
635 
636 
637         if (it == 3)
638             pdc_copy_utf8_bom(buf);
639 
640     }
641 
642     return buf;
643 }
644 
645 /* Convenience functions
646 */
647 char *
pdc_strdup_tmp(pdc_core * pdc,const char * text)648 pdc_strdup_tmp(pdc_core *pdc, const char *text)
649 {
650     static const char fn[] = "pdc_strdup_tmp";
651 
652     return pdc_strdup_ext(pdc, text, PDC_CONV_TMPALLOC, fn);
653 }
654 
655 char *
pdc_strdup_withbom(pdc_core * pdc,const char * text)656 pdc_strdup_withbom(pdc_core *pdc, const char *text)
657 {
658     static const char fn[] = "pdc_strdup_withbom";
659 
660     return pdc_strdup_ext(pdc, text, PDC_CONV_WITHBOM, fn);
661 }
662 
663 /* Rapid function
664 */
665 char *
pdc_strdup(pdc_core * pdc,const char * text)666 pdc_strdup(pdc_core *pdc, const char *text)
667 {
668     char *buf = NULL;
669     static const char fn[] = "pdc_strdup";
670 
671     if (text != NULL)
672     {
673         size_t len = pdc_strlen(text) + 1;
674 
675         buf = (char *) pdc_malloc(pdc, len + 1, fn);
676         memcpy(buf, text, len);
677         buf[len] = 0;
678     }
679 
680     return buf;
681 }
682 
683 char *
pdc_strdup2(pdc_core * pdc,const char * text,size_t len)684 pdc_strdup2(pdc_core *pdc, const char *text, size_t len)
685 {
686     char *buf = NULL;
687     static const char fn[] = "pdc_strdup2";
688 
689     if (text != NULL)
690     {
691         buf = (char *) pdc_malloc(pdc, len + 1, fn);
692         memcpy(buf, text, len);
693         buf[len] = 0;
694     }
695 
696     return buf;
697 }
698 
699 /* Convert Pascal string to a null terminated C string.
700  * Size of C string: at least 256 bytes
701  */
702 int
pdc_convert_pascal_str(const char * pstr,char * cstr)703 pdc_convert_pascal_str(const char *pstr, char *cstr)
704 {
705     int len = (int) *((pdc_byte *) pstr);
706 
707     memcpy(cstr, pstr + 1, (size_t) len);
708     cstr[len] = 0;
709 
710     return len;
711 }
712 
713 char *
pdc_strdup_convert(pdc_core * pdc,pdc_encoding encto,pdc_encoding encfrom,const char * text,int flags,const char * fn)714 pdc_strdup_convert(pdc_core *pdc, pdc_encoding encto, pdc_encoding encfrom,
715                    const char *text, int flags, const char *fn)
716 {
717     pdc_encodingvector *evfrom, *evto;
718     char *buf;
719     size_t len;
720     int i;
721 
722     evto = pdc_get_encoding_vector(pdc, encto);
723     evfrom = pdc_get_encoding_vector(pdc, encfrom);
724     buf = pdc_strdup_ext(pdc, text, flags, fn);
725     len = strlen(buf);
726 
727     for (i = 0; i < (int) len; i++)
728         buf[i] = (char) pdc_transform_bytecode(pdc, evto, evfrom,
729                                                (pdc_byte) text[i]);
730 
731     return buf;
732 }
733 
734 pdc_bool
pdc_logg_isprint(int c)735 pdc_logg_isprint(int c)
736 {
737     if (c < 0x20 || (c >= 0x7F && c < 0xA0))
738         return pdc_false;
739     return pdc_true;
740 }
741 
742 
743 /*
744  * Put out an arbitrary string.
745  *
746  * strform = readable:  Direct byte output with replacing not
747  *                      printable bytes by their octal codes.
748  *         = readable0: Like readable, but byte 0 will be displayed as space.
749  *         = octal:     All bytes will be put out as octal.
750  *         = hexa:      All bytes will be put out as hexadecimal value.
751  *         = java:      Like readable, but Unicode strings and not printable
752  *                      bytes will be put out in Java notation \uxxxx,
753  *
754  * Output string is temporarily allocated.
755  *
756  */
757 char *
pdc_strprint(pdc_core * pdc,const char * str,int leni,int maxchar,pdc_strform_kind strform)758 pdc_strprint(pdc_core *pdc, const char *str, int leni, int maxchar,
759              pdc_strform_kind strform)
760 {
761     static const char fn[] = "pdc_strprint";
762 
763     if (str != NULL)
764     {
765         pdc_bool isunicode = pdc_false;
766         int len = leni;
767 
768         if (!leni)
769             len = (int) strlen(str);
770 
771         if (len)
772         {
773             pdc_strform_kind sf = strform;
774             char *ts, *tmpstr;
775             pdc_byte c = ' ', cp = '.';
776             pdc_ushort *ush = (pdc_ushort *) str;
777             int i, im;
778 
779             /* because of strform_java: \uxxxx: factor 6 */
780             tmpstr = (char *) pdc_calloc_tmp(pdc, (size_t) (6 * (len + 4)), fn,
781                                              NULL, NULL);
782             ts = tmpstr;
783 
784             if (strform == strform_java)
785             {
786                 if (leni && !(leni % 2))
787                     isunicode = pdc_true;
788                 else
789                     strform = strform_readable;
790             }
791 
792             if (maxchar <= 0)
793                 maxchar = len;
794             im = (maxchar < len) ? maxchar : len;
795             if (isunicode)
796                 im = im/2;
797             for (i = 0; i < im; i++)
798             {
799                 if (isunicode)
800                 {
801                     if (ush[i] > PDC_UNICODE_MAXLATIN1)
802                     {
803                         sf = strform_java;
804                     }
805                     else
806                     {
807                         c = (pdc_byte) ush[i];
808                         sf = strform;
809                     }
810                 }
811                 else
812                 {
813                     c = (pdc_byte) str[i];
814                     sf = strform;
815                 }
816 
817                 switch (sf)
818                 {
819                     case strform_hexa:
820                     ts += sprintf(ts, "\\x%02X", c);
821                     break;
822 
823                     case strform_octal:
824                     ts += sprintf(ts, "\\%03o", c);
825                     break;
826 
827                     case strform_java:
828                     ts += sprintf(ts, "\\u%04X", ush[i]);
829                     break;
830 
831                     default:
832                     if (c == 0x00 && sf == strform_readable0)
833                     {
834                         c = 0x20;
835 
836                         *ts = (char) c;
837                         ts++;
838                     }
839                     else
840                     {
841                         if (!pdc_logg_isprint((int) c))
842                         {
843                             if (isunicode)
844                                 ts += sprintf(ts, "\\u%04X", c);
845                             else
846                                 ts += sprintf(ts, "\\%03o", c);
847                         }
848                         else
849                         {
850                             if (c == '"')
851                             {
852                                 *ts = '\\';
853                                 ts++;
854                             }
855 
856                             *ts = (char) c;
857                             ts++;
858                         }
859 
860                     }
861                 }
862             }
863 
864             if (maxchar < len)
865             {
866                 switch (strform)
867                 {
868                     case strform_hexa:
869                     ts += sprintf(ts, "\\x%02X\\x%02X\\x%02X", cp, cp, cp);
870                     break;
871 
872                     case strform_octal:
873                     ts += sprintf(ts, "\\%03o\\%03o\\%03o", cp, cp, cp);
874                     break;
875 
876                     case strform_java:
877                     ts += sprintf(ts, "\\u%04X\\u%04X\\u%04X", cp, cp, cp);
878                     break;
879 
880                     default:
881                     ts += sprintf(ts, "%c%c%c", cp, cp, cp);
882                     break;
883                 }
884             }
885 
886             return tmpstr;
887         }
888     }
889 
890     return (char *) pdc_calloc_tmp(pdc, 1, fn, NULL, NULL);
891 }
892 
893 /*
894  * Returned string is temporary allocated.
895  */
896 const char *
pdc_utf8strprint(pdc_core * pdc,const char * str)897 pdc_utf8strprint(pdc_core *pdc, const char *str)
898 {
899     static const char fn[] = "pdc_utf8strprint";
900 
901     return pdc_strdup_ext(pdc, str,
902                   PDC_CONV_TMPALLOC | PDC_CONV_NOBOM | PDC_CONV_MAXSTRLEN, fn);
903 }
904 
905 /*
906  * Split a given text string into single strings which are separated by
907  * arbitrary characters. This characters must be specified in a string.
908  * If this string is NULL, " \f\n\r\t\v" (standard white spaces) is assumed.
909  *
910  * There is the convention that text inside braces {} will be taken verbatim.
911  * Inside brace expressions braces must exist only in pairs. Braces are
912  * masked by backslash.
913  *
914  * The caller is responsible for freeing the resultated string list
915  * by calling the function pdc_cleanup_stringlist.
916  *
917  * Not for unicode strings.
918  *
919  * Return value: Number of strings.
920  *               If braces aren't balanced the number is negative.
921  *
922  */
923 int
pdc_split_stringlist(pdc_core * pdc,const char * text,const char * i_separstr,int flags,char *** stringlist)924 pdc_split_stringlist(pdc_core *pdc, const char *text, const char *i_separstr,
925                      int flags, char ***stringlist)
926 {
927     static const char fn[] = "pdc_split_stringlist";
928     const char *separstr = " \f\n\r\t\v";
929     const char *oldtext;
930     char **strlist = NULL, *newtext = NULL;
931     int it, len, jt = 0, jtb = 0, maxk = 0, count = 0, inside = 0;
932     int ns, nbs = 0, nbss;
933 
934     if (stringlist)
935         *stringlist = NULL;
936     if (i_separstr)
937         separstr = i_separstr;
938 
939     if (text == NULL)
940         return 0;
941 
942     /* check for empty string */
943     ns = (int) strspn(text, separstr);
944     oldtext = &text[ns];
945     len = (int) strlen(oldtext);
946     if (!len)
947         return 0;
948 
949     /* check for UTF-8-BOM */
950     if (pdc_is_utf8_bytecode(oldtext))
951     {
952         oldtext = &text[ns + 3];
953         len -= 3;
954         ns = (int) strspn(oldtext, separstr);
955         oldtext = &oldtext[ns];
956         len -= ns;
957         if (!len)
958             return 0;
959     }
960 
961     /* new string */
962     if (stringlist != NULL)
963         newtext = (char *) pdc_malloc(pdc, (size_t) (len + 1), fn);
964     for (it = 0; it <= len; it++)
965     {
966         /* check for separators */
967         if (it == len)
968             ns = 1;
969         else if (inside <= 0)
970             ns = (int) strspn(&oldtext[it], separstr);
971         else
972             ns = 0;
973 
974         /* close text part */
975         if (ns)
976         {
977             if (stringlist != NULL)
978             {
979                 newtext[jt] = 0;
980                 if (count == maxk)
981                 {
982                     maxk += 16;
983                     strlist = (char **) pdc_realloc(pdc, strlist,
984                                                     maxk * sizeof(char *), fn);
985                 }
986                 strlist[count] = &newtext[jtb];
987             }
988             count++;
989 
990             /* Exit */
991             it += ns;
992             if (it >= len ) break;
993 
994             /* new text part */
995             jt++;
996             jtb = jt;
997         }
998 
999         /* option list */
1000         if (flags & PDC_SPLIT_ISOPTLIST)
1001         {
1002             /* save backslash counter */
1003             nbss = nbs;
1004 
1005             /* backslash */
1006             if (oldtext[it] == '\\')
1007             {
1008                 nbs++;
1009                 if (!(nbs % 2) && inside <= 1)
1010                     continue;
1011             }
1012             else
1013             {
1014                 nbs = 0;
1015             }
1016 
1017             /* open and close brace */
1018             if (oldtext[it] == '{')
1019             {
1020                 if (!(nbss % 2))
1021                 {
1022                     inside++;
1023                     if (inside == 1)
1024                         continue;
1025                 }
1026                 else if (inside <= 1)
1027                 {
1028                     jt--;
1029                 }
1030             }
1031             else if (oldtext[it] == '}')
1032             {
1033                 if (!(nbss % 2))
1034                 {
1035                     inside--;
1036                     if (inside == 0)
1037                         continue;
1038                 }
1039                 else if (inside <= 1)
1040                 {
1041                     jt--;
1042                 }
1043             }
1044         }
1045 
1046         /* argument list */
1047         else if (flags & PDC_SPLIT_ISARGLIST)
1048         {
1049             /* save backslash counter */
1050             nbss = nbs;
1051 
1052             /* backslash */
1053             if (oldtext[it] == '\\')
1054             {
1055                 nbs++;
1056                 if (!(nbs % 2))
1057                     continue;
1058             }
1059             else
1060             {
1061                 nbs = 0;
1062             }
1063 
1064             /* open and close quotation mark */
1065             if (oldtext[it] == '"')
1066             {
1067                 if (!(nbss % 2))
1068                 {
1069                     inside = 1 - inside;
1070                     continue;
1071                 }
1072                 else
1073                 {
1074                     jt--;
1075                 }
1076             }
1077         }
1078 
1079         /* save character */
1080         if (stringlist != NULL)
1081         {
1082             newtext[jt] = oldtext[it];
1083             jt++;
1084         }
1085     }
1086 
1087     if (stringlist != NULL)
1088         *stringlist = strlist;
1089 
1090     return inside ? -count : count;
1091 }
1092 
1093 void
pdc_cleanup_stringlist(pdc_core * pdc,char ** stringlist)1094 pdc_cleanup_stringlist(pdc_core *pdc, char **stringlist)
1095 {
1096     if(stringlist != NULL)
1097     {
1098         if(stringlist[0] != NULL)
1099             pdc_free(pdc, stringlist[0]);
1100 
1101         pdc_free(pdc, stringlist);
1102     }
1103 }
1104 
1105 
1106 /*
1107  * Substitute a list of variables in a string by its values recursively.
1108  * A variable begins with the character 'vchar' and ends at a character
1109  * in 'delimiters' or at the end of string resp..
1110  *
1111  * The character 'vchar' must be masked by 'vchar'.
1112  *
1113  * If at least one of a variable was substituted, a new allocated null
1114  * terminated string is returned. Otherwise the original pointer.
1115  *
1116  * The caller is responsible for freeing the new string.
1117  *
1118  *   string     null terminated string with variables
1119  *   vchar      begin character for a variable
1120  *   delimiters string with characters delimiting a variable name
1121  *   varslist   list of variable names
1122  *   valslist   list of variable values
1123  *   nvars      number of variables
1124  *   errind[2]  contains index and length of an unkown variable in string
1125  *
1126  */
1127 
1128 static char *
substitute_variables(pdc_core * pdc,char * string,int ibeg,int * level,const char ** varslist,const char ** valslist,int nvars,char vchar,const char * separstr,int * errind)1129 substitute_variables(pdc_core *pdc, char *string, int ibeg, int *level,
1130     const char **varslist, const char **valslist, int nvars, char vchar,
1131     const char *separstr, int *errind)
1132 {
1133     static const char fn[] = "substitue_variables";
1134     int i, j, l;
1135 
1136     j = ibeg;
1137     for (i = ibeg; string[i] != 0; i++)
1138     {
1139         if (string[i] == vchar)
1140         {
1141             if (string[i + 1] == vchar)
1142                 i++;
1143             else
1144                 break;
1145         }
1146 
1147         string[j] = string[i];
1148         j++;
1149     }
1150 
1151     if (string[i] != 0)
1152     {
1153         char *s = &string[i + 1];
1154         size_t n = strcspn(s, separstr);
1155 
1156         for (l = 0; l < nvars; l++)
1157         {
1158             if (n == strlen(varslist[l]) && !strncmp(s, varslist[l], n))
1159             {
1160                 char *newstring;
1161                 int k = (int) (i + n + 1);
1162                 size_t nv = strlen(valslist[l]);
1163                 size_t nr = strlen(&string[k]);
1164                 size_t nb = (size_t) j +  nv + nr + 1;
1165 
1166                 newstring = (char *) pdc_malloc(pdc, nb, fn);
1167                 strncpy(newstring, string, (size_t) j);
1168                 strncpy(&newstring[j], valslist[l], nv);
1169                 strcpy(&newstring[j + nv], &string[k]);
1170 
1171                 pdc_free(pdc, string);
1172                 (*level)++;
1173 
1174                 string = substitute_variables(pdc, newstring, j, level,
1175                                varslist, valslist, nvars, vchar, separstr,
1176                                errind);
1177                 break;
1178             }
1179         }
1180         if (l == nvars)
1181         {
1182             errind[0] = i;
1183             errind[1] = (int) (n + 1);
1184         }
1185     }
1186     else
1187     {
1188         string[j] = 0;
1189     }
1190     return string;
1191 }
1192 
1193 char *
pdc_substitute_variables(pdc_core * pdc,const char * string,char vchar,const char * delimiters,const char ** varslist,const char ** valslist,int nvars,int * errind)1194 pdc_substitute_variables(pdc_core *pdc, const char *string, char vchar,
1195     const char *delimiters, const char **varslist,
1196     const char **valslist, int nvars, int *errind)
1197 {
1198     static const char fn[] = "pdc_substitue_variables";
1199     char *subststr, *newstring, separstr[64];
1200     int level = 0;
1201 
1202     newstring = pdc_strdup_ext(pdc, string, 0, fn);
1203 
1204     separstr[0] = vchar;
1205     separstr[1] = 0;
1206     strcat(separstr, delimiters);
1207 
1208     errind[0] = -1;
1209     errind[1] = 0;
1210     subststr = substitute_variables(pdc, newstring, 0, &level,
1211                          varslist, valslist, nvars, vchar, separstr, errind);
1212 
1213     return subststr;
1214 }
1215 
1216 /*
1217  * Compares its arguments and returns an integer less than,
1218  * equal to, or greater than zero, depending on whether s1
1219  * is lexicographically less than, equal to, or greater than s2.
1220  * Null pointer values for s1 and s2 are treated the same as pointers
1221  * to empty strings.
1222  *
1223  * Presupposition: basic character set
1224  *
1225  * Return value:  < 0  s1 <  s2;
1226  *                = 0  s1 == s2;
1227  *                > 0  s1 >  s2;
1228  *
1229  */
1230 int
pdc_strcmp(const char * s1,const char * s2)1231 pdc_strcmp(const char *s1, const char *s2)
1232 {
1233     if (s1 == s2) return (0);
1234     if (s1 == NULL) return (-1);
1235     if (s2 == NULL) return (1);
1236 
1237     return strcmp(s1, s2);
1238 }
1239 
1240 int
pdc_stricmp(const char * s1,const char * s2)1241 pdc_stricmp(const char *s1, const char *s2)
1242 {
1243     if (s1 == s2) return (0);
1244     if (s1 == NULL) return (-1);
1245     if (s2 == NULL) return (1);
1246 
1247     for (; *s1; ++s1, ++s2)
1248     {
1249         if (pdc_tolower(*s1) != pdc_tolower(*s2))
1250             break;
1251     }
1252 
1253     return (pdc_tolower(*s1) - pdc_tolower(*s2));
1254 }
1255 
1256 int
pdc_stricmp_a(const char * s1,const char * s2)1257 pdc_stricmp_a(const char *s1, const char *s2)
1258 {
1259     if (s1 == s2) return (0);
1260     if (s1 == NULL) return (-1);
1261     if (s2 == NULL) return (1);
1262 
1263     for (; *s1; ++s1, ++s2)
1264     {
1265         if (pdc_tolower_a(*s1) != pdc_tolower_a(*s2))
1266             break;
1267     }
1268 
1269     return (pdc_tolower_a(*s1) - pdc_tolower_a(*s2));
1270 }
1271 
1272 /*
1273  * Same like pdc_strcmp, except that the strings can be
1274  * wide character strings with nulls and double null terminated.
1275  */
1276 int
pdc_wstrcmp(const char * s1,const char * s2)1277 pdc_wstrcmp(const char *s1, const char *s2)
1278 {
1279     size_t len1, len2, len;
1280     int res;
1281 
1282     if (s1 == s2) return (0);
1283     if (s1 == NULL) return (-1);
1284     if (s2 == NULL) return (1);
1285 
1286     len1 = pdc_strlen(s1);
1287     len2 = pdc_strlen(s2);
1288     len = MIN(len1, len2);
1289 
1290     res = memcmp(s1, s2, len);
1291 
1292     if (!res && len1 != len2)
1293         res = (len1 < len2) ? -1 : 1;
1294 
1295     return res;
1296 }
1297 
1298 /*
1299  * Compares its arguments and returns an integer less than,
1300  * equal to, or greater than zero, depending on whether s1
1301  * is lexicographically less than, equal to, or greater than s2.
1302  * But only up to n characters compared (n less than or equal
1303  * to zero yields equality).Null pointer values for s1 and s2
1304  * are treated the same as pointers to empty strings.
1305  *
1306  * Presupposition: basic character set
1307  *
1308  * Return value:  < 0  s1 <  s2;
1309  *                = 0  s1 == s2;
1310  *                > 0  s1 >  s2;
1311  *
1312  */
1313 int
pdc_strincmp(const char * s1,const char * s2,int n)1314 pdc_strincmp(const char *s1, const char *s2, int n)
1315 {
1316     int i;
1317 
1318     if (s1 == s2)   return (0);
1319     if (s1 == NULL) return (-1);
1320     if (s2 == NULL) return (1);
1321 
1322     for (i = 0; i < n && *s1 && *s2; ++i, ++s1, ++s2)
1323     {
1324         if (pdc_tolower(*s1) != pdc_tolower(*s2))
1325             break;
1326     }
1327 
1328     return (i == n) ? 0 : (pdc_tolower(*s1) - pdc_tolower(*s2));
1329 }
1330 
1331 /*
1332  * pdc_strtrim removes trailing white space characters from an input string.
1333  * pdc_str2trim removes leading and trailing white space characters from an
1334  * input string..
1335  */
1336 char *
pdc_strtrim(char * str)1337 pdc_strtrim(char *str)
1338 {
1339     int i, n;
1340 
1341     n = (int) strlen(str);
1342     for (i = n - 1; i >= 0; i--)
1343         if (!pdc_isspace(str[i])) break;
1344     str[i + 1] = '\0';
1345 
1346     return str;
1347 }
1348 
1349 char *
pdc_str2trim(char * str)1350 pdc_str2trim(char *str)
1351 {
1352     int i, n;
1353 
1354     n = (int) strlen(str);
1355     for (i = n - 1; i >= 0; i--)
1356         if (!pdc_isspace(str[i])) break;
1357     str[i + 1] = '\0';
1358 
1359     for (i = 0; ; i++)
1360         if (!pdc_isspace(str[i])) break;
1361     if (i > 0)
1362         memmove(str, &str[i], strlen(&str[i]) + 1);
1363 
1364     return str;
1365 }
1366 
1367 char *
pdc_strtoupper(char * str)1368 pdc_strtoupper(char *str)
1369 {
1370     int i, n;
1371 
1372     n = (int) strlen(str);
1373     for (i = 0; i < n; i++)
1374         str[i] = (char) pdc_toupper(str[i]);
1375 
1376     return str;
1377 }
1378 
1379 char *
pdc_strtolower(char * str)1380 pdc_strtolower(char *str)
1381 {
1382     int i, n;
1383 
1384     n = (int) strlen(str);
1385     for (i = 0; i < n; i++)
1386         str[i] = (char) pdc_tolower(str[i]);
1387 
1388     return str;
1389 }
1390 
1391 void
pdc_swap_bytes2(const char * instring,int inlen,char * outstring)1392 pdc_swap_bytes2(const char *instring, int inlen, char *outstring)
1393 {
1394     pdc_ushort *inp, *outp;
1395     int i;
1396 
1397     if (instring == NULL)
1398         return;
1399 
1400     if (outstring == NULL)
1401         outstring = (char *) instring;
1402 
1403     inp = (pdc_ushort *) instring;
1404     outp = (pdc_ushort *) outstring;
1405 
1406     inlen /= sizeof(pdc_ushort);
1407     for (i = 0; i < inlen; i++)
1408     {
1409         outp[i] = (pdc_ushort) (((inp[i] & (pdc_ushort)0x00FFu) << 8) |
1410                                 ((inp[i] & (pdc_ushort)0xFF00u) >> 8));
1411     }
1412 }
1413 
1414 void
pdc_swap_bytes4(const char * instring,int inlen,char * outstring)1415 pdc_swap_bytes4(const char *instring, int inlen, char *outstring)
1416 {
1417     pdc_uint32 *inp, *outp;
1418     int i;
1419 
1420     if (instring == NULL)
1421         return;
1422 
1423     if (outstring == NULL)
1424         outstring = (char *) instring;
1425 
1426     inp = (pdc_uint32 *) instring;
1427     outp = (pdc_uint32 *) outstring;
1428 
1429     inlen /= sizeof(pdc_uint32);
1430     for (i = 0; i < inlen; i++)
1431     {
1432         outp[i] = (pdc_uint32) (((inp[i] & (pdc_uint32)0x000000FFu) << 24) |
1433                                 ((inp[i] & (pdc_uint32)0x0000FF00u) <<  8) |
1434                                 ((inp[i] & (pdc_uint32)0x00FF0000u) >>  8) |
1435                                 ((inp[i] & (pdc_uint32)0xFF000000u) >> 24));
1436     }
1437 }
1438 
1439 void
pdc_inflate_ascii(const char * instring,int inlen,char * outstring,pdc_text_format textformat)1440 pdc_inflate_ascii(const char *instring, int inlen, char *outstring,
1441                   pdc_text_format textformat)
1442 {
1443     int i, j;
1444     pdc_bool is_bigendian = (textformat == pdc_utf16be) ||
1445                             (textformat == pdc_utf16 && PDC_ISBIGENDIAN);
1446 
1447     j = 0;
1448     for (i = 0; i < inlen; i++)
1449     {
1450         if (is_bigendian)
1451         {
1452             outstring[j] = 0;
1453             j++;
1454             outstring[j] = instring[i];
1455         }
1456         else
1457         {
1458             outstring[j] = instring[i];
1459             j++;
1460             outstring[j] = 0;
1461         }
1462         j++;
1463     }
1464 }
1465 
1466 /*
1467  *  pdc_stresc --
1468  *      Remove from a string containing escaped non-printable cha-
1469  *      racters. The string must follows the C-standard escape
1470  *      mechanism: an escaped character is preceeded by an escape
1471  *      character which is a backslash '\' character and followed
1472  *      by one or more characters to define the non-printable
1473  *      character to be inserted here. The supported escapes are
1474  *
1475  *            \a              bell            (ASCII/EBCDIC-BEL)
1476  *            \b              backspace       (ASCII/EBCDIC-BS)
1477  *            \e              escape charater (ASCII/EBCDIC-ESC)
1478  *            \f              formfeed        (ASCII/EBCDIC-FF)
1479  *            \n              linefeed        (ASCII/EBCDIC-LF)
1480  *            \r              return          (ASCII/EBCDIC-CR)
1481  *            \t              tab character   (ASCII/EBCDIC-TAB)
1482  *            \v              vertical tab    (ASCII/EBCDIC-VT)
1483  *            \\              the slash itself
1484  *            \xnn            two hex digits n to define a
1485  *                            character numerically as ASCII/EBCDIC value.
1486  *            \nnn            three octal digits n to define a
1487  *                            character numerically as ASCII/EBCDIC value.
1488  *
1489  *      For example: \x0A, \x0a or \012 has the same effect in ASCII
1490  *      as \n (i.e linefeed).
1491  *      Note, if the last character in a string is the backslash
1492  *      then the backslash is illegal.
1493  *      The special characters a,b,e,f, and so on are recognized in
1494  *      lower case only.
1495  *
1496  *      textformat:
1497  *      pdc_bytes:      Latin1 or EBCDIC bytes on EBCDIC platforms
1498  *      pdc_utf8:       Latin1
1499  *      pdc_ebcdicutf8: EBCDIC - only on EBCDIC platforms
1500  *      pdc_utf16:      2 bytes Latin1
1501  *
1502  *      If a illegal escaped sequence was detected an exception will
1503  *      be thrown (verbose == pdc_true) or the sequence will be taken
1504  *      as it (verbose == pdc_false).
1505  *
1506 */
1507 
1508 static const pdc_keyconn pdc_ascii_escape_keylist[] =
1509 {
1510     {"\\",   0x5C},
1511     {"a",    0x07},
1512     {"b",    0x08},
1513     {"e",    0x1B},
1514     {"f",    0x0C},
1515     {"n",    0x0A},
1516     {"r",    0x0D},
1517     {"t",    0x09},
1518     {"v",    0x0B},
1519     {"x",    0x78},
1520     {NULL, 0}
1521 };
1522 
1523 pdc_ushort
pdc_get_string_value(pdc_byte * str,int i,int charlen)1524 pdc_get_string_value(pdc_byte *str, int i, int charlen)
1525 {
1526     pdc_ushort retval = 0;
1527 
1528     if (charlen == 1)
1529     {
1530         retval = (pdc_ushort) str[i];
1531     }
1532     else
1533     {
1534         pdc_ushort *ustr = (pdc_ushort *) str;
1535 
1536         retval = ustr[i];
1537     }
1538 
1539     return retval;
1540 }
1541 
1542 /* return value: length of new string. -1: error
1543 */
1544 int
pdc_subst_backslash(pdc_core * pdc,pdc_byte * str,int len,pdc_encodingvector * ev,pdc_text_format textformat,pdc_bool verbose)1545 pdc_subst_backslash(pdc_core *pdc, pdc_byte *str, int len,
1546                     pdc_encodingvector *ev, pdc_text_format textformat,
1547                     pdc_bool verbose)
1548 {
1549     pdc_ushort *ustr = (pdc_ushort *) str;
1550     int charlen = (textformat == pdc_utf16) ? 2 : 1;
1551     pdc_byte bschar = '\\';
1552     pdc_ushort uv;
1553     int i, j, k, code;
1554 
1555     if (ev != NULL)
1556     {
1557         code = pdc_get_encoding_bytecode(pdc, ev, PDC_UNICODE_BACKSLASH);
1558         if (code != -1)
1559             bschar = (pdc_byte) code;
1560     }
1561 
1562 
1563     j = 0;
1564     len /= charlen;
1565     for (i = 0; i < len; i++)
1566     {
1567         uv = pdc_get_string_value(str, i, charlen);
1568         if (uv > PDC_UNICODE_MAXLATIN1)
1569         {
1570             ustr[j] = uv;
1571             j++;
1572             continue;
1573         }
1574 
1575         /* backslash found */
1576         if (uv == bschar)
1577         {
1578             pdc_byte escseq[4], stemp[6];
1579             pdc_bool kerror = pdc_false;
1580 
1581             i++;
1582             if (i < len)
1583             {
1584                 uv = pdc_get_string_value(str, i, charlen);
1585                 if (uv > PDC_UNICODE_MAXLATIN1)
1586                     goto PDC_OVERFLOW_EXIT;
1587 
1588                 escseq[0] = (pdc_byte) uv;
1589                 escseq[1] = 0;
1590 
1591                 code = pdc_get_keycode((char *) escseq,
1592                                        pdc_ascii_escape_keylist);
1593                 if (code != PDC_KEY_NOTFOUND)
1594                 {
1595                     /* hex number */
1596                     if (code == 0x78)
1597                     {
1598                         for (k = 0; k < 2; k++)
1599                         {
1600                             i++;
1601                             if (i < len)
1602                             {
1603                                 uv = pdc_get_string_value(str, i, charlen);
1604                                 if (uv > PDC_UNICODE_MAXLATIN1)
1605                                     goto PDC_OVERFLOW_EXIT;
1606                             }
1607                             else
1608                             {
1609                                 uv = 0;
1610                             }
1611                             escseq[k] = (pdc_byte) uv;
1612                         }
1613                         escseq[k] = 0;
1614                         if (i >= len ||
1615                             !pdc_str2integer((char *) escseq, PDC_INT_UNICODE,
1616                                              &uv))
1617                         {
1618                             strcpy((char *) stemp, "\\x");
1619                             strcat((char *) stemp, (char *) escseq);
1620                             kerror = pdc_true;
1621                         }
1622                     }
1623                     else
1624                     {
1625                         pdc_char c = (pdc_char) code;
1626                         uv = (pdc_ushort) (pdc_byte) c;
1627                     }
1628                 }
1629                 else
1630                 {
1631                     /* octal number */
1632                     for (k = 0; k < 3; k++)
1633                     {
1634                         if (k) i++;
1635                         if (i < len)
1636                         {
1637                             uv = pdc_get_string_value(str, i, charlen);
1638                             if (uv > PDC_UNICODE_MAXLATIN1)
1639                                 goto PDC_OVERFLOW_EXIT;
1640                         }
1641                         else
1642                         {
1643                             uv = 0;
1644                         }
1645                         escseq[k] = (pdc_byte) uv;
1646                     }
1647                     escseq[k] = 0;
1648                     if (i >= len ||
1649                         !pdc_str2integer((char *) escseq,
1650                                         PDC_INT_SHORT |
1651                                         PDC_INT_UNSIGNED |
1652                                         PDC_INT_OCTAL,
1653                                         &uv) ||
1654                         (charlen == 1 && uv > 0xFF))
1655                     {
1656                         strcpy((char *) stemp, "\\");
1657                         strcat((char *) stemp, (char *) escseq);
1658                         kerror = pdc_true;
1659                     }
1660                 }
1661             }
1662             else
1663             {
1664                 strcpy((char *) stemp, "\\");
1665                 kerror = pdc_true;
1666             }
1667 
1668             /* error message */
1669             if (kerror)
1670             {
1671                 pdc_set_errmsg(pdc, PDC_E_STR_ILL_ESCSEQ, (char *) stemp,
1672                                0, 0, 0);
1673 
1674                 if (verbose)
1675                     pdc_error(pdc, -1, 0, 0, 0, 0);
1676 
1677                 return -1;
1678             }
1679         }
1680 
1681         if (charlen == 1)
1682             str[j] = (pdc_byte) uv;
1683         else
1684             ustr[j] = uv;
1685 
1686         j++;
1687     }
1688 
1689     if (charlen == 1)
1690         str[j] = 0;
1691     else
1692         ustr[j] = 0;
1693 
1694     return charlen * j;
1695 
1696     PDC_OVERFLOW_EXIT:
1697 
1698     pdc_set_errmsg(pdc, PDC_E_STR_ILL_UNIESCSEQ,
1699                    pdc_errprintf(pdc, "%04X", uv), 0, 0, 0);
1700 
1701     if (verbose)
1702         pdc_error(pdc, -1, 0, 0, 0, 0);
1703 
1704     return -1;
1705 }
1706 
1707 
1708 /* ----------------------- number converting ----------------------- */
1709 
1710 /*
1711  * pdc_str2double converts a null terminated and trimmed string
1712  * to a double precision number
1713  */
1714 pdc_bool
pdc_str2double(const char * string,double * o_dz)1715 pdc_str2double(const char *string, double *o_dz)
1716 {
1717     const char *s = string;
1718     double dz = 0;
1719     int is = 1, isd = 0;
1720 
1721     *o_dz = 0;
1722 
1723     /* sign */
1724     if (*s == '-')
1725     {
1726         is = -1;
1727         s++;
1728     }
1729     else if (*s == '+')
1730         s++;
1731 
1732     if (!*s)
1733         return pdc_false;
1734 
1735     /* places before decimal point */
1736     isd = pdc_isdigit(*s);
1737     if (isd)
1738     {
1739         do
1740         {
1741             dz = 10 * dz + *s - '0';
1742             s++;
1743         }
1744         while (pdc_isdigit(*s));
1745     }
1746 
1747     /* decimal point */
1748     if (*s == '.' || *s == ',')
1749     {
1750         const char *sa;
1751         double adz = 0;
1752 
1753         s++;
1754         isd = pdc_isdigit(*s);
1755         if (!isd)
1756             return pdc_false;
1757 
1758         /* places after decimal point */
1759         sa = s;
1760         do
1761         {
1762             adz = 10 * adz + *s - '0';
1763             s++;
1764         }
1765         while (pdc_isdigit(*s));
1766         dz += adz / pow(10.0, (double)(s - sa));
1767     }
1768 
1769     /* power sign */
1770     if (*s == 'e' || *s == 'E')
1771     {
1772         s++;
1773         if (!isd)
1774             return pdc_false;
1775 
1776         /* sign */
1777         if (!*s)
1778         {
1779             dz *= 10;
1780         }
1781         else
1782         {
1783             int isp = 1;
1784             double pdz = 0, pdl = log10(dz);
1785 
1786             if (*s == '-')
1787             {
1788                 isp = -1;
1789                 s++;
1790             }
1791             else if (*s == '+')
1792                 s++;
1793 
1794             if (!pdc_isdigit(*s))
1795                 return pdc_false;
1796             do
1797             {
1798                 pdz = 10 * pdz + *s - '0';
1799                 s++;
1800             }
1801             while (pdc_isdigit(*s));
1802 
1803 
1804             if (*s || fabs(pdl + pdz) > 300.0)
1805                 return pdc_false;
1806 
1807             dz *= pow(10.0, isp * pdz);
1808         }
1809     }
1810     else if(*s)
1811     {
1812         return pdc_false;
1813     }
1814 
1815     *o_dz = is * dz;
1816     return pdc_true;
1817 }
1818 
1819 /*
1820  * pdc_str2integer converts a null terminated and trimmed string
1821  * to an hexadecimal or decimal integer number of arbitrary size
1822  */
1823 pdc_bool
pdc_str2integer(const char * string,int flags,void * o_iz)1824 pdc_str2integer(const char *string, int flags, void *o_iz)
1825 {
1826     const char *s = string;
1827     double dz = 0;
1828     pdc_char cz = 0;
1829     pdc_short sz = 0;
1830     pdc_sint32 lz = 0;
1831     pdc_byte ucz = 0;
1832     pdc_ushort usz = 0;
1833     pdc_uint32 ulz = 0;
1834     int is = 1, lzd;
1835 
1836     if (flags & PDC_INT_CHAR)
1837         memcpy(o_iz, &cz, sizeof(pdc_char));
1838     else if (flags & PDC_INT_SHORT)
1839         memcpy(o_iz, &sz, sizeof(pdc_short));
1840     else
1841         memcpy(o_iz, &lz, sizeof(pdc_sint32));
1842 
1843     /* sign */
1844     if (*s == '-')
1845     {
1846         if (flags & PDC_INT_UNSIGNED)
1847             return pdc_false;
1848         is = -1;
1849         s++;
1850     }
1851     else if (*s == '+')
1852         s++;
1853 
1854     if (!*s)
1855         return pdc_false;
1856 
1857     /* hexadecimal test */
1858     if (!(flags & PDC_INT_DEC))
1859     {
1860         const char *ss = s;
1861 
1862         if (*s == '<')
1863             s += 1;
1864         else if (*s == 'x' || *s == 'X')
1865             s += 1;
1866         else if (!strncmp(s, "0x", 2) || !strncmp(s, "0X", 2))
1867             s += 2;
1868         if (s > ss)
1869         {
1870             if (!*s)
1871                 return pdc_false;
1872             flags |= PDC_INT_HEXADEC;
1873         }
1874     }
1875 
1876     /* hexadecimal */
1877     if (flags & PDC_INT_HEXADEC)
1878     {
1879         while (pdc_isxdigit(*s))
1880         {
1881             if (pdc_isalpha(*s))
1882                 lzd = (pdc_isupper(*s) ? 'A' : 'a') - 10;
1883             else
1884                 lzd = '0';
1885             dz = 16 * dz + *s - lzd;
1886             s++;
1887         }
1888         if (*string == '<')
1889         {
1890             if (*s == '>')
1891                 s += 1;
1892             else
1893                 return pdc_false;
1894         }
1895     }
1896 
1897     /* octal */
1898     if (flags & PDC_INT_OCTAL)
1899     {
1900         while (pdc_isdigit(*s) && *s < '8')
1901         {
1902             dz = 8 * dz + *s - '0';
1903             s++;
1904         }
1905     }
1906 
1907     /* decimal */
1908     else
1909     {
1910         while (pdc_isdigit(*s))
1911         {
1912             dz = 10 * dz + *s - '0';
1913             s++;
1914         }
1915     }
1916     if (*s)
1917         return pdc_false;
1918 
1919     dz *= is;
1920     if (flags & PDC_INT_CHAR)
1921     {
1922         if (flags & PDC_INT_UNSIGNED)
1923         {
1924             if (dz > PDC_UCHAR_MAX)
1925                 return pdc_false;
1926             ucz = (pdc_byte) dz;
1927             memcpy(o_iz, &ucz, sizeof(pdc_byte));
1928         }
1929         else
1930         {
1931             if (dz < PDC_SCHAR_MIN || dz > PDC_SCHAR_MAX)
1932                 return pdc_false;
1933             cz = (pdc_char) dz;
1934             memcpy(o_iz, &cz, sizeof(pdc_char));
1935         }
1936     }
1937     else if (flags & PDC_INT_SHORT)
1938     {
1939         if (flags & PDC_INT_UNSIGNED)
1940         {
1941             if (dz > PDC_USHRT_MAX)
1942                 return pdc_false;
1943             usz = (pdc_ushort) dz;
1944             memcpy(o_iz, &usz, sizeof(pdc_ushort));
1945         }
1946         else
1947         {
1948             if (dz < PDC_SHRT_MIN || dz > PDC_SHRT_MAX)
1949                 return pdc_false;
1950             sz = (pdc_short) dz;
1951             memcpy(o_iz, &sz, sizeof(pdc_short));
1952         }
1953     }
1954     else
1955     {
1956         if (flags & PDC_INT_UNSIGNED)
1957         {
1958             if (dz > PDC_UINT_MAX)
1959                 return pdc_false;
1960             ulz = (pdc_uint32) dz;
1961             memcpy(o_iz, &ulz, sizeof(pdc_uint32));
1962         }
1963         else
1964         {
1965             if (dz < PDC_INT_MIN || dz > PDC_INT_MAX)
1966                 return pdc_false;
1967             lz = (pdc_sint32) dz;
1968             memcpy(o_iz, &lz, sizeof(pdc_sint32));
1969         }
1970     }
1971 
1972     return pdc_true;
1973 }
1974 
1975 
1976 pdc_bool
pdc_str2integer_ext(pdc_core * pdc,const char * string,int len,int dupflags,int flags,void * o_iz)1977 pdc_str2integer_ext(pdc_core *pdc, const char *string, int len,
1978                     int dupflags, int flags, void *o_iz)
1979 {
1980     static const char fn[] = "pdc_str2integer_ext";
1981     char *dupstr;
1982     pdc_bool retval;
1983 
1984     dupstr = pdc_strdup_ext(pdc, string, dupflags, fn);
1985     dupstr[len] = 0;
1986     retval = pdc_str2integer(dupstr, flags, o_iz);
1987     pdc_free(pdc, dupstr);
1988     return retval;
1989 }
1990 
1991 
1992 static const char digits[] = "0123456789ABCDEF";
1993 
1994 static char *
pdc_ltoa(char * buf,long n,int width,char pad,int base)1995 pdc_ltoa(char *buf, long n, int width, char pad, int base)
1996 {
1997     char        aux[100];
1998     int         k, i = sizeof aux;
1999     char *      dest = buf;
2000     pdc_bool    sign;
2001 
2002     if (n == 0)
2003     {
2004         if (width == 0)
2005             width = 1;
2006 
2007         for (k = 0; k < width; ++k)
2008             *(dest++) = '0';
2009 
2010         return dest;
2011     }
2012 
2013     if (n < 0 && base == 10)
2014     {
2015         --width;
2016         sign = pdc_true;
2017         aux[--i] = digits[- (n % base)];
2018         n = n / -base;
2019     }
2020     else
2021     {
2022         sign = pdc_false;
2023         aux[--i] = digits[n % base];
2024         n = n / base;
2025     }
2026 
2027     while (0 < n)
2028     {
2029         aux[--i] = digits[n % base];
2030         n = n / base;
2031     }
2032 
2033     width -= (int) (sizeof aux) - i;
2034     for (k = 0; k < width; ++k)
2035         *(dest++) = pad;
2036 
2037     if (sign)
2038         *(dest++) = '-';
2039 
2040     memcpy(dest, &aux[i], sizeof aux - i);
2041     return dest + sizeof aux - i;
2042 } /* pdc_ltoa */
2043 
2044 
2045 static char *
pdc_uoff_t2a(char * buf,pdc_uoff_t n,int width,char pad,int base,pdc_bool left_justify)2046 pdc_uoff_t2a(
2047     char *	buf,
2048     pdc_uoff_t	n,
2049     int		width,
2050     char	pad,
2051     int		base,
2052     pdc_bool	left_justify)
2053 {
2054     char        aux[100];
2055     int         k, i = sizeof aux;
2056     char *      dest = buf;
2057 
2058     while (0 < n)
2059     {
2060         aux[--i] = digits[n % base];
2061         n = n / base;
2062     }
2063 
2064     width -= (int) (sizeof aux) - i;
2065 
2066     if (!left_justify)
2067     {
2068 	for (k = 0; k < width; ++k)
2069 	    *(dest++) = pad;
2070     }
2071 
2072     memcpy(dest, &aux[i], sizeof aux - i);
2073     dest += sizeof aux - i;
2074 
2075     if (left_justify)
2076     {
2077 	for (k = 0; k < width; ++k)
2078 	    *(dest++) = pad;
2079     }
2080 
2081     return dest;
2082 } /* pdc_uoff_t2a */
2083 
2084 
2085 static char *
pdc_off_t2a(char * buf,pdc_off_t n,int width,char pad,pdc_bool left_justify,pdc_bool pos_sign)2086 pdc_off_t2a(
2087     char *	buf,
2088     pdc_off_t	n,
2089     int		width,
2090     char	pad,
2091     pdc_bool	left_justify,
2092     pdc_bool	pos_sign)
2093 {
2094     char        aux[100];
2095     int         k, i = sizeof aux;
2096     char *      dest = buf;
2097     pdc_bool    sign;
2098 
2099     if (n < 0)
2100     {
2101         --width;
2102         sign = pdc_true;
2103         aux[--i] = digits[- (n % 10)];
2104         n = n / -10;
2105     }
2106     else
2107     {
2108 	if (pos_sign)
2109 	    --width;
2110 
2111         sign = pdc_false;
2112         aux[--i] = digits[n % 10];
2113         n = n / 10;
2114     }
2115 
2116     while (0 < n)
2117     {
2118         aux[--i] = digits[n % 10];
2119         n = n / 10;
2120     }
2121 
2122     width -= (int) (sizeof aux) - i;
2123 
2124     if (!left_justify)
2125     {
2126 	for (k = 0; k < width; ++k)
2127 	    *(dest++) = pad;
2128     }
2129 
2130     if (sign)
2131     {
2132         *(dest++) = '-';
2133     }
2134     else if (pos_sign)
2135     {
2136         *(dest++) = '+';
2137     }
2138 
2139     memcpy(dest, &aux[i], sizeof aux - i);
2140     dest += sizeof aux - i;
2141 
2142     if (left_justify)
2143     {
2144 	for (k = 0; k < width; ++k)
2145 	    *(dest++) = pad;
2146     }
2147 
2148     return dest;
2149 } /* pdc_off_t2a */
2150 
2151 
2152 /*
2153  * pdc_ftoa converts a floating point number to string
2154  *
2155  * Because of historical reason "%f" = "%.12g".
2156  *
2157  * The function calls sprintf() and replaces
2158  * decimal comma by decimal point.
2159  *
2160  * If the number is infinite or not a number
2161  * "nan" will be set.
2162  *
2163  */
2164 
2165 static char *
pdc_ftoa(pdc_core * pdc,const char * format,char * buf,double x)2166 pdc_ftoa(pdc_core *pdc, const char *format, char *buf, double x)
2167 {
2168     char *dest = buf;
2169     char *cd;
2170     int n;
2171 
2172     (void) pdc;
2173 
2174     /* check whether the number is valid */
2175     if (!PDC_ISFINITE(x))
2176     {
2177         strcpy(dest, "nan");
2178         return dest + 3;
2179     }
2180 
2181     /* standard C convert */
2182     if (!strcmp(format, "%f"))
2183         n = sprintf(dest, "%.12g", x);
2184     else
2185         n = sprintf(dest, format, x);
2186 
2187     /* normalized to decimal point */
2188     cd = strchr(dest, ',');
2189     if (cd != NULL)
2190         *cd = '.';
2191 
2192     return dest + n;
2193 } /* pdc_ftoa */
2194 
2195 /*
2196  * pdc_ftoa_pdfconf converts a floating point number to string
2197  * PDF conforming
2198  *
2199  */
2200 
2201 static char *
pdc_ftoa_pdfconf(pdc_core * pdc,char * buf,double x)2202 pdc_ftoa_pdfconf(pdc_core *pdc, char *buf, double x)
2203 {
2204     static const long pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };
2205     char *      dest = buf;
2206     double      integ, fract, powd;
2207     int         ifd;
2208     long        f;
2209 
2210     /* check whether the number is valid */
2211     if (!PDC_ISFINITE(x))
2212         pdc_error(pdc, PDC_E_INT_ILLFLOAT, 0, 0, 0, 0);
2213 
2214     /* small number will be mapped to 0 */
2215     if (x < PDF_SMALLREAL && x > -PDF_SMALLREAL)
2216     {
2217         *dest = '0';
2218         return dest + 1;
2219     }
2220 
2221     /* negative number */
2222     if (x < 0)
2223     {
2224         x = -x;
2225         *(dest++) = '-';
2226     }
2227 
2228     /* large number is invalid or will be mapped to integer */
2229     if (x >= PDF_BIGREAL)
2230     {
2231         if (x > PDF_BIGINT)
2232             pdc_error(pdc, PDC_E_INT_FLOATTOOLARGE,
2233                       pdc_errprintf(pdc, "%f", x), 0, 0, 0);
2234 
2235         return pdc_ltoa(dest, (long) (x + 0.5), 0, ' ', 10);
2236     }
2237 
2238     ifd = pdc->floatdigits;
2239     powd = pow10[ifd];
2240 
2241     /* number <= 1/powd will be mappepd to 1/powd */
2242     if (x <= 1 / powd)
2243     {
2244         *(dest++) = '0';
2245         *(dest++) = '.';
2246         while (--ifd)
2247             *(dest++) = '0';
2248         *(dest++) = '1';
2249         return dest;
2250     }
2251 
2252     fract = modf(x, &integ);
2253     f = (long) (fract * powd + 0.5);
2254 
2255     if (f == powd)
2256     {
2257         integ += 1.0;
2258         f = 0;
2259     }
2260 
2261     if (integ == 0 && f == 0)   /* avoid "-0" */
2262         dest = buf;
2263 
2264     dest = pdc_ltoa(dest, (long) integ, 0, ' ', 10);
2265 
2266     if (f != 0)
2267     {
2268         char *  aux;
2269         long    rem;
2270 
2271         *(dest++) = '.';
2272 
2273         do      /* avoid trailing zeros */
2274         {
2275             rem = f % 10;
2276             f = f / 10;
2277             --ifd;
2278         } while (rem == 0);
2279 
2280         aux = dest + ifd + 1;
2281         dest[ifd--] = digits[rem];
2282 
2283         for (; 0 <= ifd; --ifd)
2284         {
2285             dest[ifd] = digits[f % 10];
2286             f = f / 10;
2287         }
2288 
2289         return aux;
2290     }
2291 
2292     return dest;
2293 } /* pdc_ftoa_pdfconf */
2294 
2295 
2296 /* flags for formatting function pdc_vxprintf()
2297 */
2298 typedef enum
2299 {
2300     pdc_form_nolimit,   /* no buffer limit supplied, no overflow check */
2301     pdc_form_fixlimit,  /* fix buffer limit, buffer overflow causes exception */
2302     pdc_form_varlimit   /* buffer overflow causes string truncation */
2303 }
2304 pdc_limitkind;
2305 
2306 /* write to string or file
2307 */
2308 static char *
write_sf(pdc_core * pdc,FILE * fp,pdc_limitkind ltd,char * dst,char * limit,const char * src,int n)2309 write_sf(
2310     pdc_core *pdc,
2311     FILE *fp,
2312     pdc_limitkind ltd,
2313     char *dst,
2314     char *limit,
2315     const char *src,
2316     int n)
2317 {
2318     if (fp != (FILE *) 0)
2319     {
2320 	pdc_fwrite_ascii(pdc, src, (size_t) n, fp);
2321     }
2322     else
2323     {
2324         if (ltd != pdc_form_nolimit)
2325         {
2326             int avail = (int) (limit - dst);
2327 
2328             if (avail < n)
2329             {
2330                 if (ltd == pdc_form_fixlimit)
2331                 {
2332                     pdc_error(pdc, PDC_E_INT_FORMOVERFLOW, 0, 0, 0, 0);
2333                 }
2334                 else
2335                 {
2336                     n = MAX(avail, 0);
2337                 }
2338             }
2339         }
2340 
2341         if (n > 0)
2342         {
2343             memcpy(dst, src, (size_t) n);
2344             dst += n;
2345         }
2346     }
2347 
2348     return dst;
2349 } /* write2buf */
2350 
2351 static int
pdc_vxprintf(pdc_core * pdc,pdc_bool pdfconf,pdc_limitkind ltd,char * cp,size_t size,FILE * fp,const char * format,va_list args)2352 pdc_vxprintf(
2353     pdc_core *pdc,
2354     pdc_bool pdfconf,
2355     pdc_limitkind ltd,
2356     char *cp,
2357     size_t size,
2358     FILE *fp,
2359     const char *format,
2360     va_list args)
2361 {
2362     static const char fn[] = "pdc_vxprintf";
2363 
2364     char buf[1024];
2365     char *dest = buf;
2366     int result = 0;
2367     char *limit = (char *) 0;
2368 
2369     if (cp != (char *) 0 && ltd != pdc_form_nolimit)
2370 	limit = cp + (int) (size - 1);
2371 
2372     for (/* */ ; /* */ ; /* */)
2373     {
2374         int             width = 0;	/* = no width specified		*/
2375         int             prec = -1;	/* = no precision specified	*/
2376         char            pad = ' ';
2377         pdc_bool        left_justify = pdc_false;
2378         pdc_bool        pos_sign = pdc_false;
2379 
2380 	char		fbuf[100];	/* format buffer for %f and %g	*/
2381 	char *		fscan = fbuf;
2382 
2383         /* as long as there is no '%', just print.
2384         */
2385         while (*format != 0 && *format != '%')
2386             *(dest++) = *(format++);
2387 
2388 	if (dest > buf)
2389 	{
2390 	    int inbuf = (int) (dest - buf);
2391 
2392 	    cp = write_sf(pdc, fp, ltd, cp, limit, buf, inbuf);
2393 	    result += inbuf;
2394 	    dest = buf;
2395 	}
2396 
2397         if (*format == 0)
2398         {
2399             if (cp != (char *) 0)
2400                 *cp = 0;
2401 
2402             return result;
2403         }
2404 
2405 	*(fscan++) = *(format++);	/* '%' */
2406 
2407         /* get the "flags", if any.
2408         */
2409 	while (*format && strchr("+- #0", *format))
2410 	{
2411 	    switch (*format)
2412 	    {
2413 		case '-':	left_justify = pdc_true;
2414 				break;
2415 
2416 		case '+':	pos_sign = pdc_true;
2417 				break;
2418 
2419 		case '0':	pad = '0';
2420 				break;
2421 
2422 		default:	break;
2423 	    }
2424 
2425 	    *(fscan++) = *(format++);
2426 	}
2427 
2428         /* get the "width", if present.
2429         */
2430         if (*format == '*')
2431         {
2432             width = va_arg(args, int);
2433             ++format;
2434 
2435 	    if (width < 0)
2436 	    {
2437 		width = -width;
2438 
2439 		if (!left_justify)
2440 		{
2441 		    *(fscan++) = '-';
2442 		    left_justify = pdc_true;
2443 		}
2444 	    }
2445 
2446 	    fscan += sprintf(fscan, "%d", width);
2447         }
2448         else
2449         {
2450             while (pdc_isdigit(*format))
2451 	    {
2452                 width = 10 * width + *format - '0';
2453 		*(fscan++) = *(format++);
2454 	    }
2455         }
2456 
2457 	if (left_justify)
2458 	    pad = ' ';
2459 
2460         /* get the "precision", if present.
2461         */
2462         if (*format == '.')
2463         {
2464             ++format;
2465 
2466             if (*format == '*')
2467             {
2468                 prec = va_arg(args, int);
2469                 ++format;
2470 
2471 		if (prec >= 0)		/* ignore negative precision */
2472 		{
2473 		    fscan += sprintf(fscan, ".%d", prec);
2474 		}
2475             }
2476             else if (pdc_isdigit(*format))
2477             {
2478 		prec = 0;
2479 		*(fscan++) = '.';
2480 
2481 		do
2482 		{
2483                     prec = 10 * prec + *format - '0';
2484 		    *(fscan++) = *(format++);
2485 		} while (pdc_isdigit(*format));
2486             }
2487         }
2488 
2489 	*(fscan++) = *format;
2490 	*fscan = 0;
2491 
2492         switch (*format)
2493         {
2494             case 'x':
2495             case 'X':
2496                 dest = pdc_uoff_t2a(
2497                         dest, (pdc_uoff_t) va_arg(args, pdc_uint),
2498                         width, pad, 16, left_justify);
2499                 break;
2500 
2501             case 'c':
2502                 *(dest++) = (char) va_arg(args, int);
2503                 break;
2504 
2505             case 'd':
2506                 dest = pdc_off_t2a(dest, (pdc_off_t) va_arg(args, int),
2507                                    width, pad, left_justify, pos_sign);
2508                 break;
2509 
2510             case 'u':
2511                 dest = pdc_uoff_t2a(
2512                         dest, (pdc_uoff_t) va_arg(args, pdc_uint),
2513                         width, pad, 10, left_justify);
2514                 break;
2515 
2516             case 'g':
2517             case 'f':
2518                 if (pdfconf)
2519                 {
2520                     dest = pdc_ftoa_pdfconf(pdc, dest, va_arg(args, double));
2521                 }
2522                 else
2523                 {
2524                     dest = pdc_ftoa(pdc, fbuf, dest, va_arg(args, double));
2525                 }
2526                 break;
2527 
2528             case 'l':
2529             {
2530                 pdc_off_t	n = 0;
2531                 pdc_uoff_t	u = 0;
2532 		pdc_bool	ll = pdc_false;
2533 
2534                 if (*(++format) == 'l')
2535                 {
2536 		    ll = pdc_true;
2537                     ++format;
2538                 }
2539 
2540 		if (strchr("xXu", *format))
2541 		{
2542 		    if (ll)
2543 			u = va_arg(args, pdc_uoff_t);
2544 		    else
2545 			u = va_arg(args, pdc_ulong);
2546 		}
2547 		else if (*format == 'd')
2548 		{
2549 		    if (ll)
2550 			n = va_arg(args, pdc_off_t);
2551 		    else
2552 			n = va_arg(args, long);
2553 		}
2554 		else
2555 		{
2556 		    pdc_error(pdc, PDC_E_INT_BADFORMAT,
2557 			pdc_errprintf(pdc, "l%c",
2558 			    pdc_isprint((int) *format) ? *format : '?'),
2559 			pdc_errprintf(pdc, "0x%02X", *format),
2560 			0, 0);
2561 		}
2562 
2563                 switch (*format)
2564                 {
2565                     case 'x':
2566                     case 'X':
2567                         dest = pdc_uoff_t2a(
2568 				    dest, u, width, pad, 16, left_justify);
2569                         break;
2570 
2571                     case 'd':
2572                         dest = pdc_off_t2a(dest, n, width, pad,
2573 					    left_justify, pos_sign);
2574                         break;
2575 
2576                     case 'u':
2577                         dest = pdc_uoff_t2a(
2578 				    dest, u, width, pad, 10, left_justify);
2579                         break;
2580 
2581                     default:
2582 			break;
2583                 }
2584 
2585                 break;
2586             }
2587 
2588             case 'p':
2589             {
2590 	        char tmp[64];
2591                 void *ptr = va_arg(args, void *);
2592 
2593 		sprintf(tmp, "%p", ptr);
2594 #if defined(AIX)
2595 		if (strncmp(tmp, "0x", 2))
2596 		    dest += sprintf(dest, "0x");
2597 #endif
2598                 dest += sprintf(dest, "%s", tmp);
2599                 break;
2600             }
2601 
2602             case 'a':
2603             case 's':
2604             case 'T':
2605             {
2606                 char *str = va_arg(args, char *);
2607                 const char *cstr = str;
2608                 pdc_bool tobefree = pdc_false;
2609                 size_t len;
2610                 int llen;
2611 
2612                 if (str != 0)
2613                 {
2614                     if (*format == 'T')
2615                     {
2616                         llen = va_arg(args, int);
2617                         cstr = pdc_print_loggstring(pdc, str, llen);
2618                     }
2619                     else if (*format == 'a')
2620                     {
2621                         cstr = pdc_strdup_ext(pdc, str, PDC_CONV_EBCDIC, fn);
2622                         tobefree = pdc_true;
2623                     }
2624                 }
2625                 else
2626                 {
2627                     cstr = "(NULL)";
2628                     if (*format == 'T')
2629                         llen = va_arg(args, int);
2630                 }
2631 
2632 		len = strlen(cstr);
2633 
2634                 if (prec != -1 && prec < (int) len)
2635 		{
2636 		    len = prec;
2637 		}
2638 
2639                 if (!left_justify && len < (size_t) width)
2640                 {
2641 		    int inbuf = (int) (width - len);
2642 
2643                     memset(buf, pad, (size_t) inbuf);
2644                     cp = write_sf(pdc, fp, ltd, cp, limit, buf, inbuf);
2645 		    result += inbuf;
2646                 }
2647 
2648                 if (len != 0)
2649                 {
2650 		    result += (int) len;
2651 
2652                     if (fp != (FILE *) 0)
2653                     {
2654                         pdc_fwrite_ascii(pdc, cstr, len, fp);
2655                     }
2656                     else if (ltd == pdc_form_nolimit || result < (int) size)
2657                     {
2658                         memcpy(cp, cstr, len);
2659                         cp += (int) len;
2660                     }
2661                     else if (ltd == pdc_form_fixlimit)
2662                     {
2663                         pdc_error(pdc, PDC_E_INT_FORMOVERFLOW, 0, 0, 0, 0);
2664                     }
2665                     else if (cp < limit)
2666                     {
2667                         memcpy(cp, cstr, (size_t) (limit - cp));
2668                         cp = limit;
2669                     }
2670 
2671                     if (tobefree)
2672                         pdc_free(pdc, (char *) cstr);
2673                 }
2674 
2675                 if (left_justify && len < (size_t) width)
2676                 {
2677 		    int inbuf = (int) (width - len);
2678 
2679                     memset(buf, pad, (size_t) inbuf);
2680                     cp = write_sf(pdc, fp, ltd, cp, limit, buf, inbuf);
2681 		    result += inbuf;
2682                 }
2683 
2684                 break;
2685             }
2686 
2687             case '%':
2688                 *(dest++) = '%';
2689                 break;
2690 
2691             default:
2692                 pdc_error(pdc, PDC_E_INT_BADFORMAT,
2693                     pdc_errprintf(pdc, "%c", pdc_isprint((int) *format) ?
2694                                   *format : '?'),
2695                     pdc_errprintf(pdc, "0x%02X", *format),
2696                     0, 0);
2697         } /* switch */
2698 
2699         ++format;
2700     } /* loop */
2701 } /* pdc_vxprintf */
2702 
2703 
2704 /* ----------------------- formatted output ----------------------- */
2705 
2706 /*
2707  * formatted output to file
2708  */
2709 int
pdc_vfprintf(pdc_core * pdc,pdc_bool pdfconf,FILE * fp,const char * format,va_list args)2710 pdc_vfprintf(pdc_core *pdc, pdc_bool pdfconf, FILE *fp,
2711              const char *format, va_list args)
2712 {
2713     return pdc_vxprintf(pdc, pdfconf, pdc_form_nolimit,
2714                         NULL, 0, fp, format, args);
2715 } /* pdc_vfprintf */
2716 
2717 int
pdc_fprintf(pdc_core * pdc,pdc_bool pdfconf,FILE * fp,const char * format,...)2718 pdc_fprintf(pdc_core *pdc, pdc_bool pdfconf, FILE *fp,
2719             const char *format, ...)
2720 {
2721     int result;
2722     va_list ap;
2723 
2724     va_start(ap, format);
2725     result = pdc_vxprintf(pdc, pdfconf, pdc_form_nolimit,
2726                           NULL, 0, fp, format, ap);
2727     va_end(ap);
2728 
2729     return result;
2730 } /* pdc_fprintf */
2731 
2732 
2733 /*
2734  * formatted output to character string
2735  */
2736 int
pdc_vsprintf(pdc_core * pdc,pdc_bool pdfconf,char * buf,const char * format,va_list args)2737 pdc_vsprintf(pdc_core *pdc, pdc_bool pdfconf, char *buf,
2738              const char *format, va_list args)
2739 {
2740     return pdc_vxprintf(pdc, pdfconf, pdc_form_fixlimit,
2741                         buf, PDC_GEN_BUFSIZE, NULL, format, args);
2742 } /* pdc_vsprintf */
2743 
2744 int
pdc_sprintf(pdc_core * pdc,pdc_bool pdfconf,char * buf,const char * format,...)2745 pdc_sprintf(pdc_core *pdc, pdc_bool pdfconf, char *buf,
2746             const char *format, ...)
2747 {
2748     int result;
2749     va_list ap;
2750 
2751     va_start(ap, format);
2752     result = pdc_vxprintf(pdc, pdfconf, pdc_form_nolimit,
2753                           buf, 0, NULL, format, ap);
2754     va_end(ap);
2755 
2756     return result;
2757 } /* pdc_sprintf */
2758 
2759 int
pdc_vsnprintf(pdc_core * pdc,char * buf,size_t size,const char * format,va_list args)2760 pdc_vsnprintf(pdc_core *pdc, char *buf, size_t size,
2761               const char *format, va_list args)
2762 {
2763     return pdc_vxprintf(pdc, pdc_false, pdc_form_varlimit,
2764                         buf, size, NULL, format, args);
2765 } /* pdc_vsnprintf */
2766 
2767 
2768 /* --------------------- name tree handling ----------------------- */
2769 
2770 struct pdc_branch_s
2771 {
2772     char        *name;     /* name - must be allocated pointer */
2773     void        *data;     /* private data - must be allocated pointer */
2774     int          nalloc;   /* number of allocated kid structs */
2775     int          nkids;    /* number of kids */
2776     pdc_branch **kids;     /* kids */
2777     pdc_branch  *parent;   /* parent branch */
2778 };
2779 
2780 pdc_branch *
pdc_init_tree(pdc_core * pdc)2781 pdc_init_tree(pdc_core *pdc)
2782 {
2783     return pdc_create_treebranch(pdc, NULL, "__tree__root__",
2784                                  NULL, 0, 0, NULL, NULL);
2785 }
2786 
2787 pdc_branch *
pdc_create_treebranch(pdc_core * pdc,pdc_branch * root,const char * pathname,void * data,int flags,int size,pdc_branch_error * errcode,const char ** name_p)2788 pdc_create_treebranch(pdc_core *pdc, pdc_branch *root, const char *pathname,
2789                       void *data, int flags, int size,
2790                       pdc_branch_error *errcode, const char **name_p)
2791 {
2792     static const char fn[] = "pdc_create_branch";
2793     char *name = NULL;
2794     pdc_branch *branch = NULL;
2795     pdc_branch *kid = NULL;
2796     pdc_branch *parent = NULL;
2797     char **namelist;
2798     int i, j, k, nnames, nkids;
2799 
2800     if (errcode) *errcode = tree_ok;
2801     if (name_p) *name_p = "";
2802 
2803     if (root)
2804     {
2805         /* search for parent branch */
2806         parent = root;
2807         nnames = pdc_split_stringlist(pdc, pathname, PDC_NAME_SEPARSTRG, 0,
2808                                       &namelist);
2809         for (i = 0; i < nnames; i++)
2810         {
2811             /* parent branch must not be a leaf branch */
2812             if (!parent->nalloc)
2813             {
2814                 if (errcode) *errcode = tree_isleaf;
2815                 pdc_cleanup_stringlist(pdc, namelist);
2816                 return NULL;
2817             }
2818             if (i == nnames - 1)
2819                 break;
2820 
2821             name = namelist[i];
2822             if (name_p)
2823             {
2824                 *name_p = pdc_utf8strprint(pdc, name);
2825             }
2826 
2827             nkids = parent->nkids;
2828             for (j = 0; j < nkids; j++)
2829             {
2830                 kid = parent->kids[j];
2831                 k = pdc_is_utf8_bytecode(kid->name) ? 3 : 0;
2832                 if (!strcmp(&kid->name[k], name))
2833                 {
2834                     parent = kid;
2835                     break;
2836                 }
2837             }
2838             if (j == nkids)
2839             {
2840                 if (errcode) *errcode = tree_notfound;
2841                 pdc_cleanup_stringlist(pdc, namelist);
2842                 return NULL;
2843             }
2844         }
2845 
2846         if (pdc_is_utf8_bytecode(pathname))
2847             name = pdc_strdup_withbom(pdc, namelist[nnames - 1]);
2848         else
2849             name = pdc_strdup(pdc, namelist[nnames - 1]);
2850         pdc_cleanup_stringlist(pdc, namelist);
2851 
2852         /* kids must have different names */
2853         for (j = 0; j < parent->nkids; j++)
2854         {
2855             kid = parent->kids[j];
2856             if (!strcmp(kid->name, name))
2857             {
2858                 if (errcode) *errcode = tree_nameexists;
2859                 if (name_p) *name_p = pdc_utf8strprint(pdc, name);
2860 
2861                 pdc_free(pdc, name);
2862                 return NULL;
2863             }
2864         }
2865     }
2866     else
2867     {
2868         parent = NULL;
2869         name = pdc_strdup(pdc, pathname);
2870     }
2871 
2872     branch = (pdc_branch *) pdc_malloc(pdc, sizeof(pdc_branch), fn);
2873     branch->name = name;
2874     branch->data = data;
2875     if (flags & PDC_TREE_ISLEAF)
2876     {
2877         branch->nalloc = 0;
2878         branch->nkids = 0;
2879         branch->kids = NULL;
2880     }
2881     else
2882     {
2883         branch->nalloc = PDC_KIDS_CHUNKSIZE;
2884         branch->nkids = 0;
2885         branch->kids = (pdc_branch **) pdc_malloc(pdc,
2886                             branch->nalloc * sizeof(pdc_branch *), fn);
2887     }
2888     branch->parent = parent;
2889 
2890     /* insert kid */
2891     if (parent)
2892     {
2893         if (parent->nkids == parent->nalloc)
2894         {
2895             parent->nalloc *= 2;
2896             parent->kids = (pdc_branch **) pdc_realloc(pdc, parent->kids,
2897                                 parent->nalloc * sizeof(pdc_branch *), fn);
2898         }
2899         parent->kids[parent->nkids] = branch;
2900         (parent->nkids)++;
2901 
2902         if ((flags & PDC_TREE_INHERIT) && parent->data)
2903             memcpy(branch->data, parent->data, (size_t) size);
2904     }
2905 
2906     return branch;
2907 }
2908 
2909 void
pdc_deactivate_name_treebranch(pdc_core * pdc,pdc_branch * branch)2910 pdc_deactivate_name_treebranch(pdc_core *pdc, pdc_branch *branch)
2911 {
2912     static const char fn[] = "pdc_deactivate_name_treebranch";
2913     size_t len = strlen(branch->name);
2914 
2915     branch->name = (char *) pdc_realloc(pdc, branch->name, len + 2, fn);
2916     branch->name[len] = PDC_NAME_SEPARSIGN;
2917     branch->name[len+1] = 0;
2918 }
2919 
2920 char *
pdc_get_name_treebranch(pdc_branch * branch)2921 pdc_get_name_treebranch(pdc_branch *branch)
2922 {
2923     return branch->name;
2924 }
2925 
2926 pdc_branch *
pdc_get_parent_treebranch(pdc_branch * branch)2927 pdc_get_parent_treebranch(pdc_branch *branch)
2928 {
2929     return branch->parent;
2930 }
2931 
2932 void *
pdc_get_data_treebranch(pdc_branch * branch)2933 pdc_get_data_treebranch(pdc_branch *branch)
2934 {
2935     return branch->data;
2936 }
2937 
2938 pdc_branch **
pdc_get_kids_treebranch(pdc_branch * branch,int * nkids)2939 pdc_get_kids_treebranch(pdc_branch *branch, int *nkids)
2940 {
2941     *nkids = branch->nkids;
2942     return branch->kids;
2943 }
2944 
2945 void
pdc_cleanup_treebranch(pdc_core * pdc,pdc_branch * branch)2946 pdc_cleanup_treebranch(pdc_core *pdc, pdc_branch *branch)
2947 {
2948     int i;
2949 
2950     if (branch->name)
2951         pdc_free(pdc, branch->name);
2952 
2953     if (branch->data)
2954         pdc_free(pdc, branch->data);
2955 
2956     if (branch->kids)
2957     {
2958         for(i = 0; i < branch->nkids; i++)
2959             pdc_cleanup_treebranch(pdc, branch->kids[i]);
2960         pdc_free(pdc, branch->kids);
2961     }
2962 
2963     pdc_free(pdc, branch);
2964 }
2965 
2966 /***************************** memory pools *****************************/
2967 
2968 /* the data structures and functions in this section are more than
2969 ** confusing. the funny "mp_item" structure below makes them more
2970 ** readable, believe it or not.
2971 */
2972 typedef struct mp_item_s mp_item;
2973 
2974 struct mp_item_s
2975 {
2976     mp_item *   next;
2977 };
2978 
2979 struct pdc_mempool_s
2980 {
2981     pdc_core *  pdc;
2982 
2983     char **     pool_tab;
2984     mp_item *   free_list;
2985 
2986     size_t      pool_incr;      /* pool growth chunk size (items)       */
2987 
2988     size_t      ptab_cap;       /* total # of slots in pool_tab         */
2989     size_t      ptab_size;      /* used # of slots in pool_tab          */
2990     size_t      ptab_incr;      /* pool_tab growth chunk size (slots)   */
2991 
2992     size_t      item_size;      /* size of a single item (bytes)        */
2993 };
2994 
2995 #undef  COMMENT
2996 #ifdef  COMMENT
2997 
2998     pool_incr   = 5
2999     ptab_incr   = 4
3000     ptab_cap    = 4     (1 * ptab_incr)
3001 
3002 
3003     +------+
3004     | free |
3005     +------+         +----------------------------------+
3006     | free |    +--> |      |      |      | free | free |
3007     +------+    |    +----------------------------------+
3008     |      | ---+
3009     +------+         +----------------------------------+
3010     |      | ------> |      |      |      |      |      |
3011     +------+         +----------------------------------+
3012 
3013     pool_tab
3014 
3015 #endif  /* COMMENT */
3016 
3017 
3018 pdc_mempool *
3019 pdc_mp_new(pdc_core *pdc, size_t item_size)
3020 {
3021     static const char fn[] = "pdc_mp_new";
3022 
3023     int m;
3024     pdc_mempool *mp = (pdc_mempool *)
3025         pdc_malloc(pdc, sizeof (pdc_mempool), fn);
3026 
3027     if (mp != (pdc_mempool *) 0)
3028     {
3029         /* round up 'item_size' to a multiple of 'sizeof (mp_item)'
3030         ** to ensure proper alignment.
3031         */
3032         if ((m = (int) (item_size % sizeof (mp_item))) != 0)
3033             item_size += sizeof (mp_item) - m;
3034 
3035         mp->pdc = pdc;
3036 
3037         mp->pool_tab = (char **) 0;
3038         mp->free_list = (mp_item *) 0;
3039         mp->pool_incr = 1000;
3040 
3041         mp->ptab_cap = 0;
3042         mp->ptab_size = 0;
3043         mp->ptab_incr = 100;
3044 
3045         mp->item_size = item_size;
3046     }
3047 
3048     return mp;
3049 } /* pdc_mp_new */
3050 
3051 
3052 void
pdc_mp_delete(pdc_mempool * mp)3053 pdc_mp_delete(pdc_mempool *mp)
3054 {
3055     /* TODO: exception if there are still alloc'd items in the pool?    */
3056     /* or, the other way round, call destructors?                       */
3057 
3058     pdc_core *  pdc = mp->pdc;
3059     int         i;
3060 
3061     for (i = 0; i < (int) mp->ptab_size; ++i)
3062         pdc_free(pdc, mp->pool_tab[i]);
3063 
3064     if (mp->pool_tab)
3065         pdc_free(pdc, mp->pool_tab);
3066 
3067     pdc_free(pdc, mp);
3068 } /* pdc_mp_delete */
3069 
3070 
3071 void *
pdc_mp_alloc(pdc_mempool * mp)3072 pdc_mp_alloc(pdc_mempool *mp)
3073 {
3074     static const char fn[] = "pdc_mp_alloc";
3075 
3076     pdc_core *  pdc = mp->pdc;
3077     mp_item *   result;
3078 
3079     if (!mp->free_list)
3080     {
3081         char *  new_chunk;
3082         int     i;
3083 
3084         if (mp->ptab_size == mp->ptab_cap)
3085         {
3086             mp->ptab_cap += mp->ptab_incr;
3087 
3088             mp->pool_tab = (char **) pdc_realloc(pdc,
3089                 mp->pool_tab, mp->ptab_cap * sizeof (char **), fn);
3090         }
3091 
3092         new_chunk = mp->pool_tab[mp->ptab_size] = (char *)
3093             pdc_malloc(pdc, mp->pool_incr * mp->item_size, fn);
3094 
3095         ++mp->ptab_size;
3096         mp->free_list = (mp_item *) new_chunk;
3097         mp->free_list->next = (mp_item *) 0;
3098 
3099         for (i = 1; i < (int) mp->pool_incr; ++i)
3100         {
3101             mp_item *scan = (mp_item *) (new_chunk + i * mp->item_size);
3102 
3103             scan->next = mp->free_list;
3104             mp->free_list = scan;
3105         }
3106     }
3107 
3108     result = mp->free_list;
3109     mp->free_list = result->next;
3110 
3111     return (void *) result;
3112 } /* pdc_mp_alloc */
3113 
3114 
3115 void
pdc_mp_free(pdc_mempool * mp,void * item)3116 pdc_mp_free(pdc_mempool *mp, void *item)
3117 {
3118     mp_item *mpi = (mp_item *) item;
3119 
3120     mpi->next = mp->free_list;
3121     mp->free_list = mpi;
3122 } /* pdc_mp_free */
3123 
3124 
3125 /***************************** miscellaneous ****************************/
3126 
3127 /* search a sorted (strcmp order) array "names" of size "size"
3128 ** for string "name". return the index if found, otherwise -1.
3129 */
3130 int
pdc_name2idx(const char ** names,int size,const char * name)3131 pdc_name2idx(const char **names, int size, const char *name)
3132 {
3133     int lo = 0, hi = size;
3134 
3135     while (lo != hi)
3136     {
3137         int idx = (lo + hi) / 2;
3138         int cmp = strcmp(name, names[idx]);
3139 
3140         if (cmp == 0)
3141             return idx;
3142 
3143         if (cmp < 0)
3144             hi = idx;
3145         else
3146             lo = idx + 1;
3147     }
3148 
3149     return -1;
3150 } /* pdc_name2idx */
3151 
3152 
3153 /* linear search; see man page LSEARCH(3).
3154 */
3155 void *
pdc_lfind(const void * key,const void * base,size_t * nmemb,size_t size,int (* compar)(const void *,const void *))3156 pdc_lfind(
3157     const void *key,
3158     const void *base,
3159     size_t *    nmemb,
3160     size_t      size,
3161     int       (*compar)(const void *, const void *))
3162 {
3163     size_t i;
3164 
3165     for (i = 0; i < *nmemb; ++i)
3166     {
3167         const char *cp = (const char *) base + i * size;
3168 
3169         if (compar(key, (void *) cp) == 0)
3170             return (void *) cp;
3171     }
3172 
3173     return (void *) 0;
3174 } /* pdc_lfind */
3175 
3176 
3177 /********************* pseudo random numbers *********************/
3178 
3179 int
pdc_rand(pdc_core * pdc)3180 pdc_rand(pdc_core *pdc)
3181 {
3182     pdc->last_rand = pdc->last_rand * 1103515245 + 12345;
3183 
3184     return (pdc_uint)(pdc->last_rand / 65536) % 32768;
3185 } /* pdc_rand */
3186 
3187 void
pdc_srand(pdc_core * pdc,pdc_uint seed)3188 pdc_srand(pdc_core *pdc, pdc_uint seed)
3189 {
3190     pdc->last_rand = seed;
3191 } /* pdc_srand */
3192 
3193