summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/fscanbin.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/fscanbin.c')
-rwxr-xr-xreference/C/CONTRIB/SNIP/fscanbin.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SNIP/fscanbin.c b/reference/C/CONTRIB/SNIP/fscanbin.c
new file mode 100755
index 0000000..9efa1c0
--- /dev/null
+++ b/reference/C/CONTRIB/SNIP/fscanbin.c
@@ -0,0 +1,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;
+}