1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
/* scan.c, scan.h: scanning library
Daniel J. Bernstein, brnstnd@nyu.edu.
No dependencies.
No environment requirements.
7/18/91: Baseline. scan 1.0, public domain.
No known patent problems.
XXX: still need floating-point scanning
*/
#include "scan.h"
/* just to keep track of what special characters we're using */
#define zero '0'
#define plus '+'
#define minus '-'
#define alow 'a'
#define acap 'A'
#define space ' '
#define tab '\t'
#define xlow 'x'
#define xcap 'x'
/* Note that the digits here are defined as '0', '0' + 1, '0' + 2, etc. */
/* The letters are defined similarly, starting from 'a' and 'A'. */
/* This may produce unintuitive results with a weird character set. */
unsigned int scan_plusminus(s,sign) char *s; int *sign;
{
if (*s == plus) { *sign = 1; return 1; }
if (*s == minus) { *sign = -1; return 1; }
*sign = 1; return 0;
}
unsigned int scan_0x(s,base) char *s; unsigned int *base;
{
if (*s == zero)
{
if ((s[1] == xlow) || (s[1] == xcap))
{ *base = 16; return 2; }
*base = 8; return 1;
}
*base = 10; return 0;
}
unsigned int scan_ulong(s,u) char *s; unsigned long *u;
{
unsigned int pos; unsigned long result; unsigned long c;
pos = 0; result = 0;
while ((c = (unsigned long) (unsigned char) (s[pos] - zero)) < 10)
{ result = result * 10 + c; ++pos; }
*u = result; return pos;
}
unsigned int scan_xlong(s,u) char *s; unsigned long *u;
{
unsigned int pos; unsigned long result; unsigned long c;
pos = 0; result = 0;
while (((c = (unsigned long) (unsigned char) (s[pos] - zero)) < 10)
||(((c = (unsigned long) (unsigned char) (s[pos] - alow)) < 6)
&&(c = c + 10))
||(((c = (unsigned long) (unsigned char) (s[pos] - acap)) < 6)
&&(c = c + 10))
) /* XXX: this gets the job done */
{ result = result * 16 + c; ++pos; }
*u = result; return pos;
}
unsigned int scan_nbblong(s,n,base,bext,u)
char *s; unsigned int n; unsigned int base; unsigned int bext; unsigned long *u;
/* Note that n == 0 means scan forever. Hopefully this is a good choice. */
{
unsigned int pos; unsigned long result; unsigned long c;
pos = 0; result = 0;
while (((c = (unsigned long) (unsigned char) (s[pos] - zero)) < base)
||(((c = (unsigned long) (unsigned char) (s[pos] - alow)) < bext)
&&(c = c + base))
||(((c = (unsigned long) (unsigned char) (s[pos] - acap)) < bext)
&&(c = c + base))
) /* XXX: this gets the job done */
{ result = result * (base + bext) + c; ++pos; if (pos == n) break; }
*u = result; return pos;
}
unsigned int scan_uint(s,u) char *s; unsigned int *u;
{
unsigned int pos; unsigned long result;
pos = scan_ulong(s,&result);
*u = result; return pos;
}
unsigned int scan_xint(s,u) char *s; unsigned int *u;
{
unsigned int pos; unsigned long result;
pos = scan_xlong(s,&result);
*u = result; return pos;
}
unsigned int scan_nbbint(s,n,base,bext,u)
char *s; unsigned int n; unsigned int base; unsigned int bext; unsigned int *u;
{
unsigned int pos; unsigned long result;
pos = scan_nbblong(s,n,base,bext,&result);
*u = result; return pos;
}
unsigned int scan_ushort(s,u) char *s; unsigned short *u;
{
unsigned int pos; unsigned long result;
pos = scan_ulong(s,&result);
*u = result; return pos;
}
unsigned int scan_xshort(s,u) char *s; unsigned short *u;
{
unsigned int pos; unsigned long result;
pos = scan_xlong(s,&result);
*u = result; return pos;
}
unsigned int scan_nbbshort(s,n,base,bext,u)
char *s; unsigned int n; unsigned int base; unsigned int bext; unsigned short *u;
{
unsigned int pos; unsigned long result;
pos = scan_nbblong(s,n,base,bext,&result);
*u = result; return pos;
}
unsigned int scan_charsetnskip(s,chars,n) char *s; char *chars; unsigned int n;
{
unsigned int pos;
pos = 0;
while (chars[s[pos]]) /* user's responsibility to check for null */
if (++pos == n)
break;
return pos;
}
unsigned int scan_noncharsetnskip(s,chars,n) char *s; char *chars; unsigned int n;
{
unsigned int pos;
pos = 0;
while (!chars[s[pos]]) /* again, user's responsibility to check for null */
if (++pos == n)
break;
return pos;
}
unsigned int scan_whitenskip(s,n) char *s; unsigned int n;
{
unsigned int pos; char c;
pos = 0;
while (((c = s[pos]) == space) || (c == tab)) /* XXX: this is slow */
if (++pos == n)
break;
return pos;
}
unsigned int scan_nonwhitenskip(s,n) char *s; unsigned int n;
{
unsigned int pos; char c;
pos = 0;
/* This is the only function without ``str'' in its name where we
check specially for nulls. */
while ((c = s[pos]) && (c != space) && (c != tab)) /* XXX: this is slow */
if (++pos == n)
break;
return pos;
}
unsigned int scan_strncmp(s,t,n) char *s; char *t; unsigned int n;
{
unsigned int pos; char c;
pos = 0;
while ((c = s[pos]) && (c == t[pos]))
if (++pos == n)
break;
return pos;
}
unsigned int scan_memcmp(s,t,n) char *s; char *t; unsigned int n;
/* This is the only function where n == 0 means do nothing. */
{
unsigned int pos;
pos = 0;
while (n) if (s[pos] != t[pos]) break; else { --n; ++pos; }
return pos;
}
|