Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4973 right-hear 1
/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
2
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
3
#include 
4
#include 
5
#include 
6
#include 
7
#include 
8
#include 
9
 
10
#define	SPC	01
11
#define	STP	02
12
 
13
#define	SHORT	0
14
#define	REGULAR	1
15
#define	LONG	2
16
#define LONGDOUBLE 4
17
#define	INT	0
18
#define	FLOAT	1
19
 
20
static int _innum(void *ptr, int type, int len, int size, FILE *iop,
21
                  int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *),
22
                  int *eofptr);
23
static int _instr(char *ptr, int type, int len, FILE *iop,
24
                  int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *),
25
                  int *eofptr);
26
static const char *_getccl(const unsigned char *s);
27
 
28
static char _sctab[256] = {
29
	0,0,0,0,0,0,0,0,
30
	0,SPC,SPC,SPC,SPC,SPC,0,0,
31
	0,0,0,0,0,0,0,0,
32
	0,0,0,0,0,0,0,0,
33
	SPC,0,0,0,0,0,0,0,
34
	0,0,0,0,0,0,0,0,
35
	0,0,0,0,0,0,0,0,
36
	0,0,0,0,0,0,0,0,
37
};
38
 
39
static int nchars = 0;
40
 
41
int
42
_doscan(FILE *iop, const char *fmt, va_list argp)
43
{
44
  return(_doscan_low(iop, fgetc, ungetc, fmt, argp));
45
}
46
 
47
int
48
_doscan_low(FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *),
49
            const char *fmt, va_list argp)
50
{
51
  register int ch;
52
  int nmatch, len, ch1;
53
  void* ptr;
54
  int fileended, size;
55
 
56
  nchars = 0;
57
  nmatch = 0;
58
  fileended = 0;
59
  for (;;) switch (ch = *fmt++) {
60
  case '\0':
61
    return (nmatch);
62
  case '%':
63
    if ((ch = *fmt++) == '%')
64
      goto def;
65
    if (ch == 'n')
66
    {
67
      int* arg = va_arg(argp, int*);
68
      *arg = nchars;
69
      break;
70
    }
71
    if (fileended)
72
      return(nmatch? nmatch: -1);
73
    ptr = 0;
74
    if (ch != '*')
75
      ptr = va_arg(argp, void*);
76
    else
77
      ch = *fmt++;
78
    len = 0;
79
    size = REGULAR;
80
    while (isdigit(ch)) {
81
      len = len*10 + ch - '0';
82
      ch = *fmt++;
83
    }
84
    if (len == 0)
85
      len = 30000;
86
    if (ch=='l') {
87
      size = LONG;
88
      ch = *fmt++;
89
    } else if (ch=='h') {
90
      size = SHORT;
91
      ch = *fmt++;
92
    } else if (ch=='L') {
93
      size = LONGDOUBLE;
94
      ch = *fmt++;
95
    } else if (ch=='[')
96
      fmt = _getccl((const unsigned char *)fmt);
97
    if (isupper(ch)) {
98
      /* ch = tolower(ch);
99
	 gcc gives warning: ANSI C forbids braced
100
	 groups within expressions */
101
      ch += 'a' - 'A';
102
      size = LONG;
103
    }
104
    if (ch == '\0')
105
      return(-1);
106
    if (_innum(ptr, ch, len, size, iop, scan_getc, scan_ungetc,
107
	       &fileended) && ptr)
108
      nmatch++;
109
/* breaks %n */
110
/*    if (fileended) {
111
      return(nmatch? nmatch: -1);
112
    } */
113
    break;
114
  case ' ':
115
  case '\n':
116
  case '\t':
117
  case '\r':
118
  case '\f':
119
  case '\v':
120
    while (((nchars++, ch1 = scan_getc(iop))!=EOF) && (_sctab[ch1] & SPC))
121
      ;
122
    if (ch1 != EOF)
123
    {
124
      scan_ungetc(ch1, iop);
125
    }
126
    nchars--;
127
    break;
128
 
129
  default:
130
  def:
131
    ch1 = scan_getc(iop);
132
    if (ch1 != EOF) nchars++;
133
    if (ch1 != ch) {
134
      if (ch1==EOF)
135
	return(-1);
136
      scan_ungetc(ch1, iop);
137
      nchars--;
138
      return(nmatch);
139
    }
140
  }
141
}
142
 
143
static int
144
_innum(void *ptr, int type, int len, int size, FILE *iop,
145
       int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
146
{
147
  register char *np;
148
  char numbuf[64];
149
  register c, base;
150
  int expseen, scale, negflg, c1, ndigit;
151
  long lcval;
152
  int cpos;
153
 
154
  if (type=='c' || type=='s' || type=='[')
155
    return(_instr(ptr, type, len,
156
		  iop, scan_getc, scan_ungetc, eofptr));
157
  lcval = 0;
158
  ndigit = 0;
159
  scale = INT;
160
  if (type=='e'||type=='f'||type=='g')
161
    scale = FLOAT;
162
  base = 10;
163
  if (type=='o')
164
    base = 8;
165
  else if (type=='x')
166
    base = 16;
167
  np = numbuf;
168
  expseen = 0;
169
  negflg = 0;
170
  while (((nchars++, c = scan_getc(iop)) != EOF) && (_sctab[c] & SPC))
171
    ;
172
  if (c == EOF) nchars--;
173
  if (c=='-') {
174
    negflg++;
175
    *np++ = c;
176
    c = scan_getc(iop);
177
    nchars++;
178
    len--;
179
  } else if (c=='+') {
180
    len--;
181
    c = scan_getc(iop);
182
    nchars++;
183
  }
184
  cpos = 0;
185
  for ( ; --len>=0; *np++ = c, c = scan_getc(iop), nchars++) {
186
    cpos++;
187
    if (c == '0' && cpos == 1 && type == 'i')
188
      base = 8;
189
    if ((c == 'x' || c == 'X') && (type == 'i' || type == 'x')
190
	&& cpos == 2 && lcval == 0)
191
    {
192
      base = 16;
193
      continue;
194
    }
195
    if (isdigit(c)
196
	|| (base==16 && (('a'<=c && c<='f') || ('A'<=c && c<='F')))) {
197
      ndigit++;
198
      if (base==8)
199
	lcval <<=3;
200
      else if (base==10)
201
	lcval = ((lcval<<2) + lcval)<<1;
202
      else
203
	lcval <<= 4;
204
      c1 = c;
205
      if (isdigit(c))
206
	c -= '0';
207
      else if ('a'<=c && c<='f')
208
	c -= 'a'-10;
209
      else
210
	c -= 'A'-10;
211
      lcval += c;
212
      c = c1;
213
      continue;
214
    } else if (c=='.') {
215
      if (base!=10 || scale==INT)
216
	break;
217
      ndigit++;
218
      continue;
219
    } else if ((c=='e'||c=='E') && expseen==0) {
220
      if (base!=10 || scale==INT || ndigit==0)
221
	break;
222
      expseen++;
223
      *np++ = c;
224
      c = scan_getc(iop);
225
      nchars++;
226
      if (c!='+'&&c!='-'&&('0'>c||c>'9'))
227
	break;
228
    } else
229
      break;
230
  }
231
  if (negflg)
232
    lcval = -lcval;
233
  if (c != EOF) {
234
    scan_ungetc(c, iop);
235
    *eofptr = 0;
236
  } else
237
    *eofptr = 1;
238
  nchars--;
239
  if (ptr==NULL || np==numbuf || (negflg && np==numbuf+1) ) /* gene dykes*/
240
    return(0);
241
  *np++ = 0;
242
  switch((scale<<4) | size) {
243
 
244
  case (FLOAT<<4) | SHORT:
245
  case (FLOAT<<4) | REGULAR:
246
    *(float *)ptr = atof(numbuf);
247
    break;
248
 
249
  case (FLOAT<<4) | LONG:
250
    *(double *)ptr = atof(numbuf);
251
    break;
252
 
253
  case (FLOAT<<4) | LONGDOUBLE:
254
    *(long double *)ptr = _atold(numbuf);
255
    break;
256
 
257
  case (INT<<4) | SHORT:
258
    *(short *)ptr = (short)lcval;
259
    break;
260
 
261
  case (INT<<4) | REGULAR:
262
    *(int *)ptr = (int)lcval;
263
    break;
264
 
265
  case (INT<<4) | LONG:
266
  case (INT<<4) | LONGDOUBLE:
267
    *(long *)ptr = lcval;
268
    break;
269
  }
270
  return(1);
271
}
272
 
273
static int
274
_instr(char *ptr, int type, int len, FILE *iop,
275
       int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr)
276
{
277
  register ch;
278
  register char *optr;
279
  int ignstp;
280
 
281
  *eofptr = 0;
282
  optr = ptr;
283
  if (type=='c' && len==30000)
284
    len = 1;
285
  ignstp = 0;
286
  if (type=='s')
287
    ignstp = SPC;
288
  while ((nchars++, ch = scan_getc(iop)) != EOF && _sctab[ch] & ignstp)
289
    ;
290
  ignstp = SPC;
291
  if (type=='c')
292
    ignstp = 0;
293
  else if (type=='[')
294
    ignstp = STP;
295
  while (ch!=EOF && (_sctab[ch]&ignstp)==0) {
296
    if (ptr)
297
      *ptr++ = ch;
298
    if (--len <= 0)
299
      break;
300
    ch = scan_getc(iop);
301
    nchars++;
302
  }
303
  if (ch != EOF) {
304
    if (len > 0)
305
    {
306
      scan_ungetc(ch, iop);
307
      nchars--;
308
    }
309
    *eofptr = 0;
310
  } else
311
  {
312
    nchars--;
313
    *eofptr = 1;
314
  }
315
  if (ptr && ptr!=optr) {
316
    if (type!='c')
317
      *ptr++ = '\0';
318
    return(1);
319
  }
320
  return(0);
321
}
322
 
323
static const char *
324
_getccl(const unsigned char *s)
325
{
326
  register c, t;
327
 
328
  t = 0;
329
  if (*s == '^') {
330
    t++;
331
    s++;
332
  }
333
  for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++)
334
    if (t)
335
      _sctab[c] &= ~STP;
336
    else
337
      _sctab[c] |= STP;
338
  if ((c = *s) == ']' || c == '-') { /* first char is special */
339
    if (t)
340
      _sctab[c] |= STP;
341
    else
342
      _sctab[c] &= ~STP;
343
    s++;
344
  }
345
  while ((c = *s++) != ']') {
346
    if (c==0)
347
      return((const char *)--s);
348
    else if (c == '-' && *s != ']' && s[-2] < *s) {
349
      for (c = s[-2] + 1; c < *s; c++)
350
	if (t)
351
	  _sctab[c] |= STP;
352
	else
353
	  _sctab[c] &= ~STP;
354
    } else if (t)
355
      _sctab[c] |= STP;
356
    else
357
      _sctab[c] &= ~STP;
358
  }
359
  return((const char *)s);
360
}