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, <ime);
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, <ime);
279 gtimer = mktime(<ime);
280 pdc_localtime_r(&timer, <ime);
281 ltime.tm_isdst = 0;
282 diffminutes = difftime(mktime(<ime), 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, <ime);
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