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
|
/* fscanbin.c -- scan binary fields via format string
**
** public domain by Ray Gardner Englewood, Colorado 11/29/89
**
** Usage: fscanbin(FILE *fp, char *format, ...)
**
** where format string contains specifiers:
** -ddd means skip ddd bytes
** i means read a 16-bit int
** l means read a 32-bit int
** sddd means read a character string of up to ddd bytes
** reads up to a nul byte if ddd is zero or missing
** cnnn means read a character field of nnn bytes (not nul-terminated)
** reads one byte if nnn is zero or missing
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
typedef unsigned short int16;
typedef unsigned long int32;
#define int16swap(n) (*n = (*n << 8) | (*n >> 8))
#define int32swap(n) (\
int16swap(&((int16 *)n)[0]),\
int16swap(&((int16 *)n)[1]),\
*n = (*n << 16) | (*n >> 16)\
)
#define maxk 32767
int fscanbin (FILE *fp, char *format, ...)
{
va_list argp;
unsigned char *p;
unsigned k;
int c;
char *charp;
int16 *int16p;
int32 *int32p;
int bytes_read;
bytes_read = 0;
va_start(argp, format);
for ( p = (unsigned char *)format; *p; )
{
switch( *p & 0xFF )
{
case '-':
for ( k = 0, c = *++p; isdigit(c); c = *++p )
k = 10 * k + c - '0';
if ( k == 0 )
k = 1;
if ( fseek(fp, (long)k, SEEK_CUR) )
return -2; /* i/o error */
bytes_read += k;
break;
case 'i':
int16p = va_arg(argp, int16 *);
if ( fread((void *)int16p, sizeof(int16), 1, fp) != 1 )
return -2; /* i/o error */
#if SWAP16
int16swap(int16p);
#endif
p++;
bytes_read += sizeof(int16);
break;
case 'l':
int32p = va_arg(argp, int32 *);
if ( fread((void *)int32p, sizeof(int32), 1, fp) != 1 )
return -2; /* i/o error */
#if SWAP32
int32swap(int32p);
#endif
p++;
bytes_read += sizeof(int32);
break;
case 's':
charp = va_arg(argp, char *);
for ( k = 0, c = *++p; isdigit(c); c = *++p )
k = 10 * k + c - '0';
do
{
c = getc(fp);
if ( c == EOF )
return -2;
*charp++ = (char)c;
bytes_read++;
} while ( c && (k == 0 || --k) );
break;
case 'c':
charp = va_arg(argp, char *);
for ( k = 0, c = *++p; isdigit(c); c = *++p )
k = 10 * k + c - '0';
if ( k == 0 )
k = 1;
if ( fread((void *)charp, sizeof(char), k, fp) != k )
return -2; /* i/o error */
bytes_read += k;
break;
default:
return -1; /* bad format */
}
}
va_end(argp);
return bytes_read;
}
|