Fix segfault in CVS head (sorry about that)
[asterisk/asterisk.git] / utils.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * See http://www.asterisk.org for more information about
7  * the Asterisk project. Please do not directly contact
8  * any of the maintainers of this project for assistance;
9  * the project provides a web site, mailing lists and IRC
10  * channels for your use.
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License Version 2. See the LICENSE file
14  * at the top of the source tree.
15  */
16
17 /*
18  *
19  * Utility functions
20  *
21  */
22
23 #include <ctype.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <stdarg.h>
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include "asterisk/lock.h"
41 #include "asterisk/io.h"
42 #include "asterisk/logger.h"
43 #include "asterisk/md5.h"
44 #include "asterisk/options.h"
45
46 #define AST_API_MODULE          /* ensure that inlinable API functions will be built in this module if required */
47 #include "asterisk/strings.h"
48
49 #define AST_API_MODULE          /* ensure that inlinable API functions will be built in this module if required */
50 #include "asterisk/time.h"
51
52 #define AST_API_MODULE          /* ensure that inlinable API functions will be built in this module if required */
53 #include "asterisk/utils.h"
54
55 static char base64[64];
56 static char b2a[256];
57
58 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
59
60 /* duh? ERANGE value copied from web... */
61 #define ERANGE 34
62 #undef gethostbyname
63
64 AST_MUTEX_DEFINE_STATIC(__mutex);
65
66 /* Recursive replacement for gethostbyname for BSD-based systems.  This
67 routine is derived from code originally written and placed in the public 
68 domain by Enzo Michelangeli <em@em.no-ip.com> */
69
70 static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
71                                 size_t buflen, struct hostent **result, 
72                                 int *h_errnop) 
73 {
74         int hsave;
75         struct hostent *ph;
76         ast_mutex_lock(&__mutex); /* begin critical area */
77         hsave = h_errno;
78
79         ph = gethostbyname(name);
80         *h_errnop = h_errno; /* copy h_errno to *h_herrnop */
81         if (ph == NULL) {
82                 *result = NULL;
83         } else {
84                 char **p, **q;
85                 char *pbuf;
86                 int nbytes=0;
87                 int naddr=0, naliases=0;
88                 /* determine if we have enough space in buf */
89
90                 /* count how many addresses */
91                 for (p = ph->h_addr_list; *p != 0; p++) {
92                         nbytes += ph->h_length; /* addresses */
93                         nbytes += sizeof(*p); /* pointers */
94                         naddr++;
95                 }
96                 nbytes += sizeof(*p); /* one more for the terminating NULL */
97
98                 /* count how many aliases, and total length of strings */
99                 for (p = ph->h_aliases; *p != 0; p++) {
100                         nbytes += (strlen(*p)+1); /* aliases */
101                         nbytes += sizeof(*p);  /* pointers */
102                         naliases++;
103                 }
104                 nbytes += sizeof(*p); /* one more for the terminating NULL */
105
106                 /* here nbytes is the number of bytes required in buffer */
107                 /* as a terminator must be there, the minimum value is ph->h_length */
108                 if(nbytes > buflen) {
109                         *result = NULL;
110                         ast_mutex_unlock(&__mutex); /* end critical area */
111                         return ERANGE; /* not enough space in buf!! */
112                 }
113
114                 /* There is enough space. Now we need to do a deep copy! */
115                 /* Allocation in buffer:
116                         from [0] to [(naddr-1) * sizeof(*p)]:
117                         pointers to addresses
118                         at [naddr * sizeof(*p)]:
119                         NULL
120                         from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
121                         pointers to aliases
122                         at [(naddr+naliases+1) * sizeof(*p)]:
123                         NULL
124                         then naddr addresses (fixed length), and naliases aliases (asciiz).
125                 */
126
127                 *ret = *ph;   /* copy whole structure (not its address!) */
128
129                 /* copy addresses */
130                 q = (char **)buf; /* pointer to pointers area (type: char **) */
131                 ret->h_addr_list = q; /* update pointer to address list */
132                 pbuf = buf + ((naddr+naliases+2)*sizeof(*p)); /* skip that area */
133                 for (p = ph->h_addr_list; *p != 0; p++) {
134                         memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
135                         *q++ = pbuf; /* the pointer is the one inside buf... */
136                         pbuf += ph->h_length; /* advance pbuf */
137                 }
138                 *q++ = NULL; /* address list terminator */
139
140                 /* copy aliases */
141                 ret->h_aliases = q; /* update pointer to aliases list */
142                 for (p = ph->h_aliases; *p != 0; p++) {
143                         strcpy(pbuf, *p); /* copy alias strings */
144                         *q++ = pbuf; /* the pointer is the one inside buf... */
145                         pbuf += strlen(*p); /* advance pbuf */
146                         *pbuf++ = 0; /* string terminator */
147                 }
148                 *q++ = NULL; /* terminator */
149
150                 strcpy(pbuf, ph->h_name); /* copy alias strings */
151                 ret->h_name = pbuf;
152                 pbuf += strlen(ph->h_name); /* advance pbuf */
153                 *pbuf++ = 0; /* string terminator */
154
155                 *result = ret;  /* and let *result point to structure */
156
157         }
158         h_errno = hsave;  /* restore h_errno */
159         ast_mutex_unlock(&__mutex); /* end critical area */
160
161         return (*result == NULL); /* return 0 on success, non-zero on error */
162 }
163
164
165 #endif
166
167 /* Re-entrant (thread safe) version of gethostbyname that replaces the 
168    standard gethostbyname (which is not thread safe)
169 */
170 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
171 {
172         int res;
173         int herrno;
174         int dots=0;
175         const char *s;
176         struct hostent *result = NULL;
177         /* Although it is perfectly legitimate to lookup a pure integer, for
178            the sake of the sanity of people who like to name their peers as
179            integers, we break with tradition and refuse to look up a
180            pure integer */
181         s = host;
182         res = 0;
183         while(s && *s) {
184                 if (*s == '.')
185                         dots++;
186                 else if (!isdigit(*s))
187                         break;
188                 s++;
189         }
190         if (!s || !*s) {
191                 /* Forge a reply for IP's to avoid octal IP's being interpreted as octal */
192                 if (dots != 3)
193                         return NULL;
194                 memset(hp, 0, sizeof(struct ast_hostent));
195                 hp->hp.h_addr_list = hp->buf;
196                 hp->hp.h_addr = hp->buf + sizeof(void *);
197                 if (inet_pton(AF_INET, host, hp->hp.h_addr) > 0)
198                         return &hp->hp;
199                 return NULL;
200                 
201         }
202 #ifdef SOLARIS
203         result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
204
205         if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
206                 return NULL;
207 #else
208         res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
209
210         if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
211                 return NULL;
212 #endif
213         return &hp->hp;
214 }
215
216
217 /* This is a regression test for recursive mutexes.
218    test_for_thread_safety() will return 0 if recursive mutex locks are
219    working properly, and non-zero if they are not working properly. */
220
221 AST_MUTEX_DEFINE_STATIC(test_lock);
222 AST_MUTEX_DEFINE_STATIC(test_lock2);
223 static pthread_t test_thread; 
224 static int lock_count = 0;
225 static int test_errors = 0;
226
227 static void *test_thread_body(void *data) 
228
229         ast_mutex_lock(&test_lock);
230         lock_count += 10;
231         if (lock_count != 10) 
232                 test_errors++;
233         ast_mutex_lock(&test_lock);
234         lock_count += 10;
235         if (lock_count != 20) 
236                 test_errors++;
237         ast_mutex_lock(&test_lock2);
238         ast_mutex_unlock(&test_lock);
239         lock_count -= 10;
240         if (lock_count != 10) 
241                 test_errors++;
242         ast_mutex_unlock(&test_lock);
243         lock_count -= 10;
244         ast_mutex_unlock(&test_lock2);
245         if (lock_count != 0) 
246                 test_errors++;
247         return NULL;
248
249
250 int test_for_thread_safety(void)
251
252         ast_mutex_lock(&test_lock2);
253         ast_mutex_lock(&test_lock);
254         lock_count += 1;
255         ast_mutex_lock(&test_lock);
256         lock_count += 1;
257         ast_pthread_create(&test_thread, NULL, test_thread_body, NULL); 
258         usleep(100);
259         if (lock_count != 2) 
260                 test_errors++;
261         ast_mutex_unlock(&test_lock);
262         lock_count -= 1;
263         usleep(100); 
264         if (lock_count != 1) 
265                 test_errors++;
266         ast_mutex_unlock(&test_lock);
267         lock_count -= 1;
268         if (lock_count != 0) 
269                 test_errors++;
270         ast_mutex_unlock(&test_lock2);
271         usleep(100);
272         if (lock_count != 0) 
273                 test_errors++;
274         pthread_join(test_thread, NULL);
275         return(test_errors);          /* return 0 on success. */
276 }
277
278 /*--- ast_md5_hash: Produce 16 char MD5 hash of value. ---*/
279 void ast_md5_hash(char *output, char *input)
280 {
281         struct MD5Context md5;
282         unsigned char digest[16];
283         char *ptr;
284         int x;
285
286         MD5Init(&md5);
287         MD5Update(&md5, (unsigned char *)input, strlen(input));
288         MD5Final(digest, &md5);
289         ptr = output;
290         for (x=0; x<16; x++)
291                 ptr += sprintf(ptr, "%2.2x", digest[x]);
292 }
293
294 int ast_base64decode(unsigned char *dst, const char *src, int max)
295 {
296         int cnt = 0;
297         unsigned int byte = 0;
298         unsigned int bits = 0;
299         int incnt = 0;
300 #if 0
301         unsigned char *odst = dst;
302 #endif
303         while(*src && (cnt < max)) {
304                 /* Shift in 6 bits of input */
305                 byte <<= 6;
306                 byte |= (b2a[(int)(*src)]) & 0x3f;
307                 bits += 6;
308 #if 0
309                 printf("Add: %c %s\n", *src, binary(b2a[(int)(*src)] & 0x3f, 6));
310 #endif
311                 src++;
312                 incnt++;
313                 /* If we have at least 8 bits left over, take that character 
314                    off the top */
315                 if (bits >= 8)  {
316                         bits -= 8;
317                         *dst = (byte >> bits) & 0xff;
318 #if 0
319                         printf("Remove: %02x %s\n", *dst, binary(*dst, 8));
320 #endif
321                         dst++;
322                         cnt++;
323                 }
324         }
325 #if 0
326         dump(odst, cnt);
327 #endif
328         /* Dont worry about left over bits, they're extra anyway */
329         return cnt;
330 }
331
332 int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
333 {
334         int cnt = 0;
335         unsigned int byte = 0;
336         int bits = 0;
337         int index;
338         int cntin = 0;
339 #if 0
340         char *odst = dst;
341         dump(src, srclen);
342 #endif
343         /* Reserve one bit for end */
344         max--;
345         while((cntin < srclen) && (cnt < max)) {
346                 byte <<= 8;
347 #if 0
348                 printf("Add: %02x %s\n", *src, binary(*src, 8));
349 #endif
350                 byte |= *(src++);
351                 bits += 8;
352                 cntin++;
353                 while((bits >= 6) && (cnt < max)) {
354                         bits -= 6;
355                         /* We want only the top */
356                         index = (byte >> bits) & 0x3f;
357                         *dst = base64[index];
358 #if 0
359                         printf("Remove: %c %s\n", *dst, binary(index, 6));
360 #endif
361                         dst++;
362                         cnt++;
363                 }
364         }
365         if (bits && (cnt < max)) {
366                 /* Add one last character for the remaining bits, 
367                    padding the rest with 0 */
368                 byte <<= (6 - bits);
369                 index = (byte) & 0x3f;
370                 *(dst++) = base64[index];
371                 cnt++;
372         }
373         *dst = '\0';
374         return cnt;
375 }
376
377 static void base64_init(void)
378 {
379         int x;
380         memset(b2a, -1, sizeof(b2a));
381         /* Initialize base-64 Conversion table */
382         for (x=0;x<26;x++) {
383                 /* A-Z */
384                 base64[x] = 'A' + x;
385                 b2a['A' + x] = x;
386                 /* a-z */
387                 base64[x + 26] = 'a' + x;
388                 b2a['a' + x] = x + 26;
389                 /* 0-9 */
390                 if (x < 10) {
391                         base64[x + 52] = '0' + x;
392                         b2a['0' + x] = x + 52;
393                 }
394         }
395         base64[62] = '+';
396         base64[63] = '/';
397         b2a[(int)'+'] = 62;
398         b2a[(int)'/'] = 63;
399 #if 0
400         for (x=0;x<64;x++) {
401                 if (b2a[(int)base64[x]] != x) {
402                         fprintf(stderr, "!!! %d failed\n", x);
403                 } else
404                         fprintf(stderr, "--- %d passed\n", x);
405         }
406 #endif
407 }
408
409 /*--- ast_uri_encode: Turn text string to URI-encoded %XX version ---*/
410 /*      At this point, we're converting from ISO-8859-x (8-bit), not UTF8
411         as in the SIP protocol spec 
412         If doreserved == 1 we will convert reserved characters also.
413         RFC 2396, section 2.4
414         outbuf needs to have more memory allocated than the instring
415         to have room for the expansion. Every char that is converted
416         is replaced by three ASCII characters.
417
418         Note: The doreserved option is needed for replaces header in
419         SIP transfers.
420 */
421 char *ast_uri_encode(char *string, char *outbuf, int buflen, int doreserved) 
422 {
423         char *reserved = ";/?:@&=+$, "; /* Reserved chars */
424
425         char *ptr  = string;    /* Start with the string */
426         char *out = NULL;
427         char *buf = NULL;
428
429         strncpy(outbuf, string, buflen);
430
431         /* If there's no characters to convert, just go through and don't do anything */
432         while (*ptr) {
433                 if (((unsigned char) *ptr) > 127 || (doreserved && strchr(reserved, *ptr)) ) {
434                         /* Oops, we need to start working here */
435                         if (!buf) {
436                                 buf = outbuf;
437                                 out = buf + (ptr - string) ;    /* Set output ptr */
438                         }
439                         out += sprintf(out, "%%%02x", (unsigned char) *ptr);
440                 } else if (buf) {
441                         *out = *ptr;    /* Continue copying the string */
442                         out++;
443                 } 
444                 ptr++;
445         }
446         if (buf)
447                 *out = '\0';
448         return outbuf;
449 }
450
451 /*--- ast_uri_decode: Decode SIP URI, URN, URL (overwrite the string)  ---*/
452 void ast_uri_decode(char *s) 
453 {
454         char *o;
455         unsigned int tmp;
456
457         for (o = s; *s; s++, o++) {
458                 if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
459                         /* have '%', two chars and correct parsing */
460                         *o = tmp;
461                         s += 2; /* Will be incremented once more when we break out */
462                 } else /* all other cases, just copy */
463                         *o = *s;
464         }
465         *o = '\0';
466 }
467
468 /*--- ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */
469 const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia)
470 {
471         return inet_ntop(AF_INET, &ia, buf, bufsiz);
472 }
473
474 int ast_utils_init(void)
475 {
476         base64_init();
477         return 0;
478 }
479
480 #ifndef __linux__
481 #undef pthread_create /* For ast_pthread_create function only */
482 #endif /* ! LINUX */
483
484 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize)
485 {
486         pthread_attr_t lattr;
487         if (!attr) {
488                 pthread_attr_init(&lattr);
489                 attr = &lattr;
490         }
491 #ifdef __linux__
492         /* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
493            which is kind of useless. Change this here to
494            PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
495            priority will propagate down to new threads by default.
496            This does mean that callers cannot set a different priority using
497            PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
498            the priority afterwards with pthread_setschedparam(). */
499         errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED);
500         if (errno)
501                 ast_log(LOG_WARNING, "pthread_attr_setinheritsched returned non-zero: %s\n", strerror(errno));
502 #endif
503
504         if (!stacksize)
505                 stacksize = AST_STACKSIZE;
506         errno = pthread_attr_setstacksize(attr, stacksize);
507         if (errno)
508                 ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
509         return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
510 }
511
512 int ast_wait_for_input(int fd, int ms)
513 {
514         struct pollfd pfd[1];
515         memset(pfd, 0, sizeof(pfd));
516         pfd[0].fd = fd;
517         pfd[0].events = POLLIN|POLLPRI;
518         return poll(pfd, 1, ms);
519 }
520
521 char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
522 {
523         char *e;
524         char *q;
525
526         s = ast_strip(s);
527         if ((q = strchr(beg_quotes, *s))) {
528                 e = s + strlen(s) - 1;
529                 if (*e == *(end_quotes + (q - beg_quotes))) {
530                         s++;
531                         *e = '\0';
532                 }
533         }
534
535         return s;
536 }
537
538 int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
539 {
540         int result;
541
542         if (!buffer || !*buffer || !space || !*space)
543                 return -1;
544
545         result = vsnprintf(*buffer, *space, fmt, ap);
546
547         if (result < 0)
548                 return -1;
549         else if (result > *space)
550                 result = *space;
551
552         *buffer += result;
553         *space -= result;
554         return 0;
555 }
556
557 int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
558 {
559         va_list ap;
560         int result;
561
562         va_start(ap, fmt);
563         result = ast_build_string_va(buffer, space, fmt, ap);
564         va_end(ap);
565
566         return result;
567 }
568
569 int ast_true(const char *s)
570 {
571         if (!s || ast_strlen_zero(s))
572                 return 0;
573
574         /* Determine if this is a true value */
575         if (!strcasecmp(s, "yes") ||
576             !strcasecmp(s, "true") ||
577             !strcasecmp(s, "y") ||
578             !strcasecmp(s, "t") ||
579             !strcasecmp(s, "1") ||
580             !strcasecmp(s, "on"))
581                 return -1;
582
583         return 0;
584 }
585
586 int ast_false(const char *s)
587 {
588         if (!s || ast_strlen_zero(s))
589                 return 0;
590
591         /* Determine if this is a false value */
592         if (!strcasecmp(s, "no") ||
593             !strcasecmp(s, "false") ||
594             !strcasecmp(s, "n") ||
595             !strcasecmp(s, "f") ||
596             !strcasecmp(s, "0") ||
597             !strcasecmp(s, "off"))
598                 return -1;
599
600         return 0;
601 }
602
603 #define ONE_MILLION     1000000
604 /*
605  * put timeval in a valid range. usec is 0..999999
606  * negative values are not allowed and truncated.
607  */
608 static struct timeval tvfix(struct timeval a)
609 {
610         if (a.tv_usec >= ONE_MILLION) {
611                 ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
612                         a.tv_sec, (long int) a.tv_usec);
613                 a.tv_sec += a.tv_usec % ONE_MILLION;
614                 a.tv_usec %= ONE_MILLION;
615         } else if (a.tv_usec < 0) {
616                 ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
617                                 a.tv_sec, (long int) a.tv_usec);
618                 a.tv_usec = 0;
619         }
620         return a;
621 }
622
623 struct timeval ast_tvadd(struct timeval a, struct timeval b)
624 {
625         /* consistency checks to guarantee usec in 0..999999 */
626         a = tvfix(a);
627         b = tvfix(b);
628         a.tv_sec += b.tv_sec;
629         a.tv_usec += b.tv_usec;
630         if (a.tv_usec >= ONE_MILLION) {
631                 a.tv_sec++;
632                 a.tv_usec -= ONE_MILLION;
633         }
634         return a;
635 }
636
637 struct timeval ast_tvsub(struct timeval a, struct timeval b)
638 {
639         /* consistency checks to guarantee usec in 0..999999 */
640         a = tvfix(a);
641         b = tvfix(b);
642         a.tv_sec -= b.tv_sec;
643         a.tv_usec -= b.tv_usec;
644         if (a.tv_usec < 0) {
645                 a.tv_sec-- ;
646                 a.tv_usec += ONE_MILLION;
647         }
648         return a;
649 }
650 #undef ONE_MILLION
651
652 #ifndef HAVE_STRCASESTR
653 static char *upper(const char *orig, char *buf, int bufsize)
654 {
655         int i = 0;
656
657         while (i < (bufsize - 1) && orig[i]) {
658                 buf[i] = toupper(orig[i]);
659                 i++;
660         }
661
662         buf[i] = '\0';
663
664         return buf;
665 }
666
667 char *strcasestr(const char *haystack, const char *needle)
668 {
669         char *u1, *u2;
670         int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
671
672         u1 = alloca(u1len);
673         u2 = alloca(u2len);
674         if (u1 && u2) {
675                 char *offset;
676                 if (u2len > u1len) {
677                         /* Needle bigger than haystack */
678                         return NULL;
679                 }
680                 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
681                 if (offset) {
682                         /* Return the offset into the original string */
683                         return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
684                 } else {
685                         return NULL;
686                 }
687         } else {
688                 ast_log(LOG_ERROR, "Out of memory\n");
689                 return NULL;
690         }
691 }
692 #endif
693
694 #ifndef HAVE_STRNLEN
695 size_t strnlen(const char *s, size_t n)
696 {
697         size_t len;
698
699         for (len=0; len < n; len++)
700                 if (s[len] == '\0')
701                         break;
702
703         return len;
704 }
705 #endif
706
707 #if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC)
708 char *strndup(const char *s, size_t n)
709 {
710         size_t len = strnlen(s, n);
711         char *new = malloc(len + 1);
712
713         if (!new)
714                 return NULL;
715
716         new[len] = '\0';
717         return memcpy(new, s, len);
718 }
719 #endif
720
721 #if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC)
722 int vasprintf(char **strp, const char *fmt, va_list ap)
723 {
724         int size;
725         va_list ap2;
726         char s;
727
728         *strp = NULL;
729         va_copy(ap2, ap);
730         size = vsnprintf(&s, 1, fmt, ap2);
731         va_end(ap2);
732         *strp = malloc(size + 1);
733         if (!*strp)
734                 return -1;
735         vsnprintf(*strp, size + 1, fmt, ap);
736
737         return size;
738 }
739 #endif
740
741 #ifndef HAVE_STRTOQ
742 #define LONG_MIN        (-9223372036854775807L-1L)
743                                          /* min value of a "long int" */
744 #define LONG_MAX        9223372036854775807L
745                                          /* max value of a "long int" */
746
747 /*
748  * Convert a string to a quad integer.
749  *
750  * Ignores `locale' stuff.  Assumes that the upper and lower case
751  * alphabets and digits are each contiguous.
752  */
753 uint64_t strtoq(const char *nptr, char **endptr, int base)
754 {
755          const char *s;
756          uint64_t acc;
757          unsigned char c;
758          uint64_t qbase, cutoff;
759          int neg, any, cutlim;
760
761          /*
762           * Skip white space and pick up leading +/- sign if any.
763           * If base is 0, allow 0x for hex and 0 for octal, else
764           * assume decimal; if base is already 16, allow 0x.
765           */
766          s = nptr;
767          do {
768                  c = *s++;
769          } while (isspace(c));
770          if (c == '-') {
771                  neg = 1;
772                  c = *s++;
773          } else {
774                  neg = 0;
775                  if (c == '+')
776                          c = *s++;
777          }
778          if ((base == 0 || base == 16) &&
779              c == '\0' && (*s == 'x' || *s == 'X')) {
780                  c = s[1];
781                  s += 2;
782                  base = 16;
783          }
784          if (base == 0)
785                  base = c == '\0' ? 8 : 10;
786
787          /*
788           * Compute the cutoff value between legal numbers and illegal
789           * numbers.  That is the largest legal value, divided by the
790           * base.  An input number that is greater than this value, if
791           * followed by a legal input character, is too big.  One that
792           * is equal to this value may be valid or not; the limit
793           * between valid and invalid numbers is then based on the last
794           * digit.  For instance, if the range for quads is
795           * [-9223372036854775808..9223372036854775807] and the input base
796           * is 10, cutoff will be set to 922337203685477580 and cutlim to
797           * either 7 (neg==0) or 8 (neg==1), meaning that if we have
798           * accumulated a value > 922337203685477580, or equal but the
799           * next digit is > 7 (or 8), the number is too big, and we will
800           * return a range error.
801           *
802           * Set any if any `digits' consumed; make it negative to indicate
803           * overflow.
804           */
805          qbase = (unsigned)base;
806          cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
807          cutlim = cutoff % qbase;
808          cutoff /= qbase;
809          for (acc = 0, any = 0;; c = *s++) {
810                  if (!isascii(c))
811                          break;
812                  if (isdigit(c))
813                          c -= '\0';
814                  else if (isalpha(c))
815                          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
816                  else
817                          break;
818                  if (c >= base)
819                          break;
820                  if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
821                          any = -1;
822                  else {
823                          any = 1;
824                          acc *= qbase;
825                          acc += c;
826                  }
827          }
828          if (any < 0) {
829                  acc = neg ? LONG_MIN : LONG_MAX;
830          } else if (neg)
831                  acc = -acc;
832          if (endptr != 0)
833                  *((const char **)endptr) = any ? s - 1 : nptr;
834          return acc;
835 }
836 #endif
837
838 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
839 {
840         char *dataPut = start;
841         int inEscape = 0;
842         int inQuotes = 0;
843
844         for (; *start; start++) {
845                 if (inEscape) {
846                         *dataPut++ = *start;       /* Always goes verbatim */
847                         inEscape = 0;
848                 } else {
849                         if (*start == '\\') {
850                                 inEscape = 1;      /* Do not copy \ into the data */
851                         } else if (*start == '\'') {
852                                 inQuotes = 1-inQuotes;   /* Do not copy ' into the data */
853                         } else {
854                                 /* Replace , with |, unless in quotes */
855                                 *dataPut++ = inQuotes ? *start : ((*start==find) ? replace_with : *start);
856                         }
857                 }
858         }
859         if (start != dataPut)
860                 *dataPut = 0;
861         return dataPut;
862 }