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