xref: /original-bsd/lib/libc/stdlib/strtol.c (revision 74d2fb93)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #if defined(LIBC_SCCS) && !defined(lint)
19 static char sccsid[] = "@(#)strtol.c	5.1 (Berkeley) 07/23/88";
20 #endif /* LIBC_SCCS and not lint */
21 
22 #include <ctype.h>
23 
24 long
25 strtol(ascii, endp, base)
26 	register char *ascii;
27 	char **endp;
28 	register int base;
29 {
30 	register long val;
31 	register int c;
32 	int negative;
33 
34 	for (; isascii(*ascii) && isspace(*ascii); ++ascii);
35 
36 	negative = 0;
37 	if (*ascii == '+')
38 		++ascii;
39 	else if (*ascii == '-') {
40 		negative = 1;
41 		++ascii;
42 	}
43 
44 	/*
45 	 * ``If base is positive, but not greater than 36, it is used as
46 	 * the base for the conversion.''
47 	 *	-- The UNIX System User's Manual, 1986
48 	 */
49 	if ((unsigned int)base > 36)
50 		base = 10;
51 	else if (base == 0)
52 		if (*ascii == '0') {
53 			++ascii;
54 			if (*ascii == 'X' || *ascii == 'x') {
55 				++ascii;
56 				base = 16;
57 			}
58 			else
59 				base = 8;
60 		}
61 		else
62 			base = 10;
63 	else if (base == 16 && *ascii == '0' &&
64 	    (*++ascii == 'X' || *ascii == 'x'))
65 			++ascii;
66 
67 	for (val = 0; isascii(c = *ascii) && isalnum(c); ++ascii) {
68 		if (isdigit(c))
69 			c -= '0';
70 		else {
71 			if (isupper(c))
72 				c = tolower(c);
73 			c = c - 'a' + 10;
74 		}
75 		if (c >= base)
76 			break;
77 		val = val * base + c;
78 	}
79 	if (endp)
80 		*endp = ascii;
81 	return(negative ? -val : val);
82 }
83