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