More utility cleanups
[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, const 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, const 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 #ifdef __linux__
479         /* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
480            which is kind of useless. Change this here to
481            PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
482            priority will propagate down to new threads by default.
483            This does mean that callers cannot set a different priority using
484            PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
485            the priority afterwards with pthread_setschedparam(). */
486         errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED);
487         if (errno)
488                 ast_log(LOG_WARNING, "pthread_attr_setinheritsched returned non-zero: %s\n", strerror(errno));
489 #endif
490
491         if (!stacksize)
492                 stacksize = AST_STACKSIZE;
493         errno = pthread_attr_setstacksize(attr, stacksize);
494         if (errno)
495                 ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
496         return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
497 }
498
499 int ast_wait_for_input(int fd, int ms)
500 {
501         struct pollfd pfd[1];
502         memset(pfd, 0, sizeof(pfd));
503         pfd[0].fd = fd;
504         pfd[0].events = POLLIN|POLLPRI;
505         return poll(pfd, 1, ms);
506 }
507
508 char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
509 {
510         char *e;
511         char *q;
512
513         s = ast_strip(s);
514         if ((q = strchr(beg_quotes, *s))) {
515                 e = s + strlen(s) - 1;
516                 if (*e == *(end_quotes + (q - beg_quotes))) {
517                         s++;
518                         *e = '\0';
519                 }
520         }
521
522         return s;
523 }
524
525 int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
526 {
527         int result;
528
529         if (!buffer || !*buffer || !space || !*space)
530                 return -1;
531
532         result = vsnprintf(*buffer, *space, fmt, ap);
533
534         if (result < 0)
535                 return -1;
536         else if (result > *space)
537                 result = *space;
538
539         *buffer += result;
540         *space -= result;
541         return 0;
542 }
543
544 int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
545 {
546         va_list ap;
547         int result;
548
549         va_start(ap, fmt);
550         result = ast_build_string_va(buffer, space, fmt, ap);
551         va_end(ap);
552
553         return result;
554 }
555
556 int ast_true(const char *s)
557 {
558         if (!s || ast_strlen_zero(s))
559                 return 0;
560
561         /* Determine if this is a true value */
562         if (!strcasecmp(s, "yes") ||
563             !strcasecmp(s, "true") ||
564             !strcasecmp(s, "y") ||
565             !strcasecmp(s, "t") ||
566             !strcasecmp(s, "1") ||
567             !strcasecmp(s, "on"))
568                 return -1;
569
570         return 0;
571 }
572
573 int ast_false(const char *s)
574 {
575         if (!s || ast_strlen_zero(s))
576                 return 0;
577
578         /* Determine if this is a false value */
579         if (!strcasecmp(s, "no") ||
580             !strcasecmp(s, "false") ||
581             !strcasecmp(s, "n") ||
582             !strcasecmp(s, "f") ||
583             !strcasecmp(s, "0") ||
584             !strcasecmp(s, "off"))
585                 return -1;
586
587         return 0;
588 }
589
590 #define ONE_MILLION     1000000
591 /*
592  * put timeval in a valid range. usec is 0..999999
593  * negative values are not allowed and truncated.
594  */
595 static struct timeval tvfix(struct timeval a)
596 {
597         if (a.tv_usec >= ONE_MILLION) {
598                 ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
599                         a.tv_sec, (long int) a.tv_usec);
600                 a.tv_sec += a.tv_usec % ONE_MILLION;
601                 a.tv_usec %= ONE_MILLION;
602         } else if (a.tv_usec < 0) {
603                 ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
604                                 a.tv_sec, (long int) a.tv_usec);
605                 a.tv_usec = 0;
606         }
607         return a;
608 }
609
610 struct timeval ast_tvadd(struct timeval a, struct timeval b)
611 {
612         /* consistency checks to guarantee usec in 0..999999 */
613         a = tvfix(a);
614         b = tvfix(b);
615         a.tv_sec += b.tv_sec;
616         a.tv_usec += b.tv_usec;
617         if (a.tv_usec >= ONE_MILLION) {
618                 a.tv_sec++;
619                 a.tv_usec -= ONE_MILLION;
620         }
621         return a;
622 }
623
624 struct timeval ast_tvsub(struct timeval a, struct timeval b)
625 {
626         /* consistency checks to guarantee usec in 0..999999 */
627         a = tvfix(a);
628         b = tvfix(b);
629         a.tv_sec -= b.tv_sec;
630         a.tv_usec -= b.tv_usec;
631         if (a.tv_usec < 0) {
632                 a.tv_sec-- ;
633                 a.tv_usec += ONE_MILLION;
634         }
635         return a;
636 }
637 #undef ONE_MILLION
638
639 #ifndef HAVE_STRCASESTR
640 static char *upper(const char *orig, char *buf, int bufsize)
641 {
642         int i = 0;
643
644         while (i < (bufsize - 1) && orig[i]) {
645                 buf[i] = toupper(orig[i]);
646                 i++;
647         }
648
649         buf[i] = '\0';
650
651         return buf;
652 }
653
654 char *strcasestr(const char *haystack, const char *needle)
655 {
656         char *u1, *u2;
657         int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
658
659         u1 = alloca(u1len);
660         u2 = alloca(u2len);
661         if (u1 && u2) {
662                 char *offset;
663                 if (u2len > u1len) {
664                         /* Needle bigger than haystack */
665                         return NULL;
666                 }
667                 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
668                 if (offset) {
669                         /* Return the offset into the original string */
670                         return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1)));
671                 } else {
672                         return NULL;
673                 }
674         } else {
675                 ast_log(LOG_ERROR, "Out of memory\n");
676                 return NULL;
677         }
678 }
679 #endif
680
681 #ifndef HAVE_STRNLEN
682 size_t strnlen(const char *s, size_t n)
683 {
684         size_t len;
685
686         for (len=0; len < n; len++)
687                 if (s[len] == '\0')
688                         break;
689
690         return len;
691 }
692 #endif
693
694 #if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC)
695 char *strndup(const char *s, size_t n)
696 {
697         size_t len = strnlen(s, n);
698         char *new = malloc(len + 1);
699
700         if (!new)
701                 return NULL;
702
703         new[len] = '\0';
704         return memcpy(new, s, len);
705 }
706 #endif
707
708 #if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC)
709 int vasprintf(char **strp, const char *fmt, va_list ap)
710 {
711         int size;
712         va_list ap2;
713         char s;
714
715         *strp = NULL;
716         va_copy(ap2, ap);
717         size = vsnprintf(&s, 1, fmt, ap2);
718         va_end(ap2);
719         *strp = malloc(size + 1);
720         if (!*strp)
721                 return -1;
722         vsnprintf(*strp, size + 1, fmt, ap);
723
724         return size;
725 }
726 #endif
727
728 #ifndef HAVE_STRTOQ
729 #define LONG_MIN        (-9223372036854775807L-1L)
730                                          /* min value of a "long int" */
731 #define LONG_MAX        9223372036854775807L
732                                          /* max value of a "long int" */
733
734 /*
735  * Convert a string to a quad integer.
736  *
737  * Ignores `locale' stuff.  Assumes that the upper and lower case
738  * alphabets and digits are each contiguous.
739  */
740 uint64_t strtoq(const char *nptr, char **endptr, int base)
741 {
742          const char *s;
743          uint64_t acc;
744          unsigned char c;
745          uint64_t qbase, cutoff;
746          int neg, any, cutlim;
747
748          /*
749           * Skip white space and pick up leading +/- sign if any.
750           * If base is 0, allow 0x for hex and 0 for octal, else
751           * assume decimal; if base is already 16, allow 0x.
752           */
753          s = nptr;
754          do {
755                  c = *s++;
756          } while (isspace(c));
757          if (c == '-') {
758                  neg = 1;
759                  c = *s++;
760          } else {
761                  neg = 0;
762                  if (c == '+')
763                          c = *s++;
764          }
765          if ((base == 0 || base == 16) &&
766              c == '\0' && (*s == 'x' || *s == 'X')) {
767                  c = s[1];
768                  s += 2;
769                  base = 16;
770          }
771          if (base == 0)
772                  base = c == '\0' ? 8 : 10;
773
774          /*
775           * Compute the cutoff value between legal numbers and illegal
776           * numbers.  That is the largest legal value, divided by the
777           * base.  An input number that is greater than this value, if
778           * followed by a legal input character, is too big.  One that
779           * is equal to this value may be valid or not; the limit
780           * between valid and invalid numbers is then based on the last
781           * digit.  For instance, if the range for quads is
782           * [-9223372036854775808..9223372036854775807] and the input base
783           * is 10, cutoff will be set to 922337203685477580 and cutlim to
784           * either 7 (neg==0) or 8 (neg==1), meaning that if we have
785           * accumulated a value > 922337203685477580, or equal but the
786           * next digit is > 7 (or 8), the number is too big, and we will
787           * return a range error.
788           *
789           * Set any if any `digits' consumed; make it negative to indicate
790           * overflow.
791           */
792          qbase = (unsigned)base;
793          cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX;
794          cutlim = cutoff % qbase;
795          cutoff /= qbase;
796          for (acc = 0, any = 0;; c = *s++) {
797                  if (!isascii(c))
798                          break;
799                  if (isdigit(c))
800                          c -= '\0';
801                  else if (isalpha(c))
802                          c -= isupper(c) ? 'A' - 10 : 'a' - 10;
803                  else
804                          break;
805                  if (c >= base)
806                          break;
807                  if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
808                          any = -1;
809                  else {
810                          any = 1;
811                          acc *= qbase;
812                          acc += c;
813                  }
814          }
815          if (any < 0) {
816                  acc = neg ? LONG_MIN : LONG_MAX;
817          } else if (neg)
818                  acc = -acc;
819          if (endptr != 0)
820                  *((const char **)endptr) = any ? s - 1 : nptr;
821          return acc;
822 }
823 #endif
824
825 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
826 {
827         char *dataPut = start;
828         int inEscape = 0;
829         int inQuotes = 0;
830
831         for (; *start; start++) {
832                 if (inEscape) {
833                         *dataPut++ = *start;       /* Always goes verbatim */
834                         inEscape = 0;
835                 } else {
836                         if (*start == '\\') {
837                                 inEscape = 1;      /* Do not copy \ into the data */
838                         } else if (*start == '\'') {
839                                 inQuotes = 1-inQuotes;   /* Do not copy ' into the data */
840                         } else {
841                                 /* Replace , with |, unless in quotes */
842                                 *dataPut++ = inQuotes ? *start : ((*start==find) ? replace_with : *start);
843                         }
844                 }
845         }
846         if (start != dataPut)
847                 *dataPut = 0;
848         return dataPut;
849 }