bb3a3e561c85886653d8227b319ca3b21e04a519
[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         const char *s;
175         struct hostent *result = NULL;
176         /* Although it is perfectly legitimate to lookup a pure integer, for
177            the sake of the sanity of people who like to name their peers as
178            integers, we break with tradition and refuse to look up a
179            pure integer */
180         s = host;
181         res = 0;
182         while(s && *s) {
183                 if (!isdigit(*s))
184                         break;
185                 s++;
186         }
187         if (!s || !*s)
188                 return NULL;
189 #ifdef SOLARIS
190         result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
191
192         if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
193                 return NULL;
194 #else
195         res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
196
197         if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
198                 return NULL;
199 #endif
200         return &hp->hp;
201 }
202
203
204 /* This is a regression test for recursive mutexes.
205    test_for_thread_safety() will return 0 if recursive mutex locks are
206    working properly, and non-zero if they are not working properly. */
207
208 AST_MUTEX_DEFINE_STATIC(test_lock);
209 AST_MUTEX_DEFINE_STATIC(test_lock2);
210 static pthread_t test_thread; 
211 static int lock_count = 0;
212 static int test_errors = 0;
213
214 static void *test_thread_body(void *data) 
215
216         ast_mutex_lock(&test_lock);
217         lock_count += 10;
218         if (lock_count != 10) 
219                 test_errors++;
220         ast_mutex_lock(&test_lock);
221         lock_count += 10;
222         if (lock_count != 20) 
223                 test_errors++;
224         ast_mutex_lock(&test_lock2);
225         ast_mutex_unlock(&test_lock);
226         lock_count -= 10;
227         if (lock_count != 10) 
228                 test_errors++;
229         ast_mutex_unlock(&test_lock);
230         lock_count -= 10;
231         ast_mutex_unlock(&test_lock2);
232         if (lock_count != 0) 
233                 test_errors++;
234         return NULL;
235
236
237 int test_for_thread_safety(void)
238
239         ast_mutex_lock(&test_lock2);
240         ast_mutex_lock(&test_lock);
241         lock_count += 1;
242         ast_mutex_lock(&test_lock);
243         lock_count += 1;
244         ast_pthread_create(&test_thread, NULL, test_thread_body, NULL); 
245         usleep(100);
246         if (lock_count != 2) 
247                 test_errors++;
248         ast_mutex_unlock(&test_lock);
249         lock_count -= 1;
250         usleep(100); 
251         if (lock_count != 1) 
252                 test_errors++;
253         ast_mutex_unlock(&test_lock);
254         lock_count -= 1;
255         if (lock_count != 0) 
256                 test_errors++;
257         ast_mutex_unlock(&test_lock2);
258         usleep(100);
259         if (lock_count != 0) 
260                 test_errors++;
261         pthread_join(test_thread, NULL);
262         return(test_errors);          /* return 0 on success. */
263 }
264
265 /*--- ast_md5_hash: Produce 16 char MD5 hash of value. ---*/
266 void ast_md5_hash(char *output, char *input)
267 {
268         struct MD5Context md5;
269         unsigned char digest[16];
270         char *ptr;
271         int x;
272
273         MD5Init(&md5);
274         MD5Update(&md5, (unsigned char *)input, strlen(input));
275         MD5Final(digest, &md5);
276         ptr = output;
277         for (x=0; x<16; x++)
278                 ptr += sprintf(ptr, "%2.2x", digest[x]);
279 }
280
281 int ast_base64decode(unsigned char *dst, char *src, int max)
282 {
283         int cnt = 0;
284         unsigned int byte = 0;
285         unsigned int bits = 0;
286         int incnt = 0;
287 #if 0
288         unsigned char *odst = dst;
289 #endif
290         while(*src && (cnt < max)) {
291                 /* Shift in 6 bits of input */
292                 byte <<= 6;
293                 byte |= (b2a[(int)(*src)]) & 0x3f;
294                 bits += 6;
295 #if 0
296                 printf("Add: %c %s\n", *src, binary(b2a[(int)(*src)] & 0x3f, 6));
297 #endif
298                 src++;
299                 incnt++;
300                 /* If we have at least 8 bits left over, take that character 
301                    off the top */
302                 if (bits >= 8)  {
303                         bits -= 8;
304                         *dst = (byte >> bits) & 0xff;
305 #if 0
306                         printf("Remove: %02x %s\n", *dst, binary(*dst, 8));
307 #endif
308                         dst++;
309                         cnt++;
310                 }
311         }
312 #if 0
313         dump(odst, cnt);
314 #endif
315         /* Dont worry about left over bits, they're extra anyway */
316         return cnt;
317 }
318
319 int ast_base64encode(char *dst, unsigned char *src, int srclen, int max)
320 {
321         int cnt = 0;
322         unsigned int byte = 0;
323         int bits = 0;
324         int index;
325         int cntin = 0;
326 #if 0
327         char *odst = dst;
328         dump(src, srclen);
329 #endif
330         /* Reserve one bit for end */
331         max--;
332         while((cntin < srclen) && (cnt < max)) {
333                 byte <<= 8;
334 #if 0
335                 printf("Add: %02x %s\n", *src, binary(*src, 8));
336 #endif
337                 byte |= *(src++);
338                 bits += 8;
339                 cntin++;
340                 while((bits >= 6) && (cnt < max)) {
341                         bits -= 6;
342                         /* We want only the top */
343                         index = (byte >> bits) & 0x3f;
344                         *dst = base64[index];
345 #if 0
346                         printf("Remove: %c %s\n", *dst, binary(index, 6));
347 #endif
348                         dst++;
349                         cnt++;
350                 }
351         }
352         if (bits && (cnt < max)) {
353                 /* Add one last character for the remaining bits, 
354                    padding the rest with 0 */
355                 byte <<= (6 - bits);
356                 index = (byte) & 0x3f;
357                 *(dst++) = base64[index];
358                 cnt++;
359         }
360         *dst = '\0';
361         return cnt;
362 }
363
364 static void base64_init(void)
365 {
366         int x;
367         memset(b2a, -1, sizeof(b2a));
368         /* Initialize base-64 Conversion table */
369         for (x=0;x<26;x++) {
370                 /* A-Z */
371                 base64[x] = 'A' + x;
372                 b2a['A' + x] = x;
373                 /* a-z */
374                 base64[x + 26] = 'a' + x;
375                 b2a['a' + x] = x + 26;
376                 /* 0-9 */
377                 if (x < 10) {
378                         base64[x + 52] = '0' + x;
379                         b2a['0' + x] = x + 52;
380                 }
381         }
382         base64[62] = '+';
383         base64[63] = '/';
384         b2a[(int)'+'] = 62;
385         b2a[(int)'/'] = 63;
386 #if 0
387         for (x=0;x<64;x++) {
388                 if (b2a[(int)base64[x]] != x) {
389                         fprintf(stderr, "!!! %d failed\n", x);
390                 } else
391                         fprintf(stderr, "--- %d passed\n", x);
392         }
393 #endif
394 }
395
396 /*--- ast_uri_encode: Turn text string to URI-encoded %XX version ---*/
397 /*      At this point, we're converting from ISO-8859-x (8-bit), not UTF8
398         as in the SIP protocol spec 
399         If doreserved == 1 we will convert reserved characters also.
400         RFC 2396, section 2.4
401         outbuf needs to have more memory allocated than the instring
402         to have room for the expansion. Every char that is converted
403         is replaced by three ASCII characters.
404
405         Note: The doreserved option is needed for replaces header in
406         SIP transfers.
407 */
408 char *ast_uri_encode(char *string, char *outbuf, int buflen, int doreserved) 
409 {
410         char *reserved = ";/?:@&=+$, "; /* Reserved chars */
411
412         char *ptr  = string;    /* Start with the string */
413         char *out = NULL;
414         char *buf = NULL;
415
416         strncpy(outbuf, string, buflen);
417
418         /* If there's no characters to convert, just go through and don't do anything */
419         while (*ptr) {
420                 if (((unsigned char) *ptr) > 127 || (doreserved && strchr(reserved, *ptr)) ) {
421                         /* Oops, we need to start working here */
422                         if (!buf) {
423                                 buf = outbuf;
424                                 out = buf + (ptr - string) ;    /* Set output ptr */
425                         }
426                         out += sprintf(out, "%%%02x", (unsigned char) *ptr);
427                 } else if (buf) {
428                         *out = *ptr;    /* Continue copying the string */
429                         out++;
430                 } 
431                 ptr++;
432         }
433         if (buf)
434                 *out = '\0';
435         return outbuf;
436 }
437
438 /*--- ast_uri_decode: Decode SIP URI, URN, URL (overwrite the string)  ---*/
439 void ast_uri_decode(char *s) 
440 {
441         char *o;
442         unsigned int tmp;
443
444         for (o = s; *s; s++, o++) {
445                 if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
446                         /* have '%', two chars and correct parsing */
447                         *o = tmp;
448                         s += 2; /* Will be incremented once more when we break out */
449                 } else /* all other cases, just copy */
450                         *o = *s;
451         }
452         *o = '\0';
453 }
454
455 /*--- ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */
456 const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia)
457 {
458         return inet_ntop(AF_INET, &ia, buf, bufsiz);
459 }
460
461 int ast_utils_init(void)
462 {
463         base64_init();
464         return 0;
465 }
466
467 #ifndef __linux__
468 #undef pthread_create /* For ast_pthread_create function only */
469 #endif /* ! LINUX */
470
471 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize)
472 {
473         pthread_attr_t lattr;
474         if (!attr) {
475                 pthread_attr_init(&lattr);
476                 attr = &lattr;
477         }
478         if (!stacksize)
479                 stacksize = AST_STACKSIZE;
480         errno = pthread_attr_setstacksize(attr, stacksize);
481         if (errno)
482                 ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
483         return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
484 }
485
486 int ast_wait_for_input(int fd, int ms)
487 {
488         struct pollfd pfd[1];
489         memset(pfd, 0, sizeof(pfd));
490         pfd[0].fd = fd;
491         pfd[0].events = POLLIN|POLLPRI;
492         return poll(pfd, 1, ms);
493 }
494
495 char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
496 {
497         char *e;
498         char *q;
499
500         s = ast_strip(s);
501         if ((q = strchr(beg_quotes, *s))) {
502                 e = s + strlen(s) - 1;
503                 if (*e == *(end_quotes + (q - beg_quotes))) {
504                         s++;
505                         *e = '\0';
506                 }
507         }
508
509         return s;
510 }
511
512 int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
513 {
514         va_list ap;
515         int result;
516
517         if (!buffer || !*buffer || !space || !*space)
518                 return -1;
519
520         va_start(ap, fmt);
521         result = vsnprintf(*buffer, *space, fmt, ap);
522         va_end(ap);
523
524         if (result < 0)
525                 return -1;
526         else if (result > *space)
527                 result = *space;
528
529         *buffer += result;
530         *space -= result;
531         return 0;
532 }
533
534 int ast_true(const char *s)
535 {
536         if (!s || ast_strlen_zero(s))
537                 return 0;
538
539         /* Determine if this is a true value */
540         if (!strcasecmp(s, "yes") ||
541             !strcasecmp(s, "true") ||
542             !strcasecmp(s, "y") ||
543             !strcasecmp(s, "t") ||
544             !strcasecmp(s, "1") ||
545             !strcasecmp(s, "on"))
546                 return -1;
547
548         return 0;
549 }
550
551 int ast_false(const char *s)
552 {
553         if (!s || ast_strlen_zero(s))
554                 return 0;
555
556         /* Determine if this is a false value */
557         if (!strcasecmp(s, "no") ||
558             !strcasecmp(s, "false") ||
559             !strcasecmp(s, "n") ||
560             !strcasecmp(s, "f") ||
561             !strcasecmp(s, "0") ||
562             !strcasecmp(s, "off"))
563                 return -1;
564
565         return 0;
566 }
567
568 #define ONE_MILLION     1000000
569 /*
570  * put timeval in a valid range. usec is 0..999999
571  * negative values are not allowed and truncated.
572  */
573 static struct timeval tvfix(struct timeval a)
574 {
575         if (a.tv_usec >= ONE_MILLION) {
576                 ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
577                         a.tv_sec, (long int) a.tv_usec);
578                 a.tv_sec += a.tv_usec % ONE_MILLION;
579                 a.tv_usec %= ONE_MILLION;
580         } else if (a.tv_usec < 0) {
581                 ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
582                                 a.tv_sec, (long int) a.tv_usec);
583                 a.tv_usec = 0;
584         }
585         return a;
586 }
587
588 struct timeval ast_tvadd(struct timeval a, struct timeval b)
589 {
590         /* consistency checks to guarantee usec in 0..999999 */
591         a = tvfix(a);
592         b = tvfix(b);
593         a.tv_sec += b.tv_sec;
594         a.tv_usec += b.tv_usec;
595         if (a.tv_usec >= ONE_MILLION) {
596                 a.tv_sec++;
597                 a.tv_usec -= ONE_MILLION;
598         }
599         return a;
600 }
601
602 struct timeval ast_tvsub(struct timeval a, struct timeval b)
603 {
604         /* consistency checks to guarantee usec in 0..999999 */
605         a = tvfix(a);
606         b = tvfix(b);
607         a.tv_sec -= b.tv_sec;
608         a.tv_usec -= b.tv_usec;
609         if (a.tv_usec < 0) {
610                 a.tv_sec-- ;
611                 a.tv_usec += ONE_MILLION;
612         }
613         return a;
614 }
615 #undef ONE_MILLION
616
617 #ifndef HAVE_STRCASESTR
618 static char *upper(const char *orig, char *buf, int bufsize)
619 {
620         int i = 0;
621
622         while (i < (bufsize - 1) && orig[i]) {
623                 buf[i] = toupper(orig[i]);
624                 i++;
625         }
626
627         buf[i] = '\0';
628
629         return buf;
630 }
631
632 char *strcasestr(const char *haystack, const char *needle)
633 {
634         char *u1, *u2;
635         int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
636
637         u1 = alloca(u1len);
638         u2 = alloca(u2len);
639         if (u1 && u2) {
640                 char *offset;
641                 if (u2len > u1len) {
642                         /* Needle bigger than haystack */
643                         return NULL;
644                 }
645                 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
646                 if (offset) {
647                         /* Return the offset into the original string */
648                         return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
649                 } else {
650                         return NULL;
651                 }
652         } else {
653                 ast_log(LOG_ERROR, "Out of memory\n");
654                 return NULL;
655         }
656 }
657 #endif
658
659 #ifndef HAVE_STRNLEN
660 size_t strnlen(const char *s, size_t n)
661 {
662         size_t len;
663
664         for (len=0; len < n; len++)
665                 if (s[len] == '\0')
666                         break;
667
668         return len;
669 }
670 #endif
671
672 #if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC)
673 char *strndup(const char *s, size_t n)
674 {
675         size_t len = strnlen(s, n);
676         char *new = malloc(len + 1);
677
678         if (!new)
679                 return NULL;
680
681         new[len] = '\0';
682         return memcpy(new, s, len);
683 }
684 #endif
685
686 #if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC)
687 int vasprintf(char **strp, const char *fmt, va_list ap)
688 {
689         int size;
690         va_list ap2;
691         char s;
692
693         *strp = NULL;
694         va_copy(ap2, ap);
695         size = vsnprintf(&s, 1, fmt, ap2);
696         va_end(ap2);
697         *strp = malloc(size + 1);
698         if (!*strp)
699                 return -1;
700         vsnprintf(*strp, size + 1, fmt, ap);
701
702         return size;
703 }
704 #endif
705
706 #ifndef HAVE_STRTOQ
707 #define LONG_MIN        (-9223372036854775807L-1L)
708                                          /* min value of a "long int" */
709 #define LONG_MAX        9223372036854775807L
710                                          /* max value of a "long int" */
711
712 /*
713  * Convert a string to a quad integer.
714  *
715  * Ignores `locale' stuff.  Assumes that the upper and lower case
716  * alphabets and digits are each contiguous.
717  */
718 uint64_t strtoq(const char *nptr, char **endptr, int base)
719 {
720          const char *s;
721          uint64_t acc;
722          unsigned char c;
723          uint64_t qbase, cutoff;
724          int neg, any, cutlim;
725
726          /*
727           * Skip white space and pick up leading +/- sign if any.
728           * If base is 0, allow 0x for hex and 0 for octal, else
729           * assume decimal; if base is already 16, allow 0x.
730           */
731          s = nptr;
732          do {
733                  c = *s++;
734          } while (isspace(c));
735          if (c == '-') {
736                  neg = 1;
737                  c = *s++;
738          } else {
739                  neg = 0;
740                  if (c == '+')
741                          c = *s++;
742          }
743          if ((base == 0 || base == 16) &&
744              c == '\0' && (*s == 'x' || *s == 'X')) {
745                  c = s[1];
746                  s += 2;
747                  base = 16;
748          }
749          if (base == 0)
750                  base = c == '\0' ? 8 : 10;
751
752          /*
753           * Compute the cutoff value between legal numbers and illegal
754           * numbers.  That is the largest legal value, divided by the
755           * base.  An input number that is greater than this value, if
756           * followed by a legal input character, is too big.  One that
757           * is equal to this value may be valid or not; the limit
758           * between valid and invalid numbers is then based on the last
759           * digit.  For instance, if the range for quads is
760           * [-9223372036854775808..9223372036854775807] and the input base
761           * is 10, cutoff will be set to 922337203685477580 and cutlim to
762           * either 7 (neg==0) or 8 (neg==1), meaning that if we have
763           * accumulated a value > 922337203685477580, or equal but the
764           * next digit is > 7 (or 8), the number is too big, and we will
765           * return a range error.
766           *
767           * Set any if any `digits' consumed; make it negative to indicate
768           * overflow.
769           */
770          qbase = (unsigned)base;
771          cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
772          cutlim = cutoff % qbase;
773          cutoff /= qbase;
774          for (acc = 0, any = 0;; c = *s++) {
775                  if (!isascii(c))
776                          break;
777                  if (isdigit(c))
778                          c -= '\0';
779                  else if (isalpha(c))
780                          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
781                  else
782                          break;
783                  if (c >= base)
784                          break;
785                  if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
786                          any = -1;
787                  else {
788                          any = 1;
789                          acc *= qbase;
790                          acc += c;
791                  }
792          }
793          if (any < 0) {
794                  acc = neg ? LONG_MIN : LONG_MAX;
795          } else if (neg)
796                  acc = -acc;
797          if (endptr != 0)
798                  *((const char **)endptr) = any ? s - 1 : nptr;
799          return acc;
800 }
801 #endif
802
803 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
804 {
805         char *dataPut = start;
806         int inEscape = 0;
807         int inQuotes = 0;
808
809         for (; *start; start++) {
810                 if (inEscape) {
811                         *dataPut++ = *start;       /* Always goes verbatim */
812                         inEscape = 0;
813                 } else {
814                         if (*start == '\\') {
815                                 inEscape = 1;      /* Do not copy \ into the data */
816                         } else if (*start == '\'') {
817                                 inQuotes = 1-inQuotes;   /* Do not copy ' into the data */
818                         } else {
819                                 /* Replace , with |, unless in quotes */
820                                 *dataPut++ = inQuotes ? *start : ((*start==find) ? replace_with : *start);
821                         }
822                 }
823         }
824         if (start != dataPut)
825                 *dataPut = 0;
826         return dataPut;
827 }