typedef enum { Nop=100000, /* ; do nothing */ New1, /* ; reset and begin new test */ Open, /* ; open test file */ Read, /* [askfor] [get] ; read bytes into buffer */ Write, /* [expect] [bytestream] ; write to file (expect 0 = ignore)*/ Compare, /* [bytestream] ; compare buffer to given bytes */ Verify, /* [bytestream] ; compare file to given bytes */ Seek, /* [offset] [whence] ; seek in file */ Tell, /* [offset] ; compare file positions */ BufSize, /* [size] ; change the stdio buffer size */ Flush, /* ; flush the stdio stream */ Text, /* ; switch file to text mode */ Binary, /* ; switch file to binary mode */ Rep, /* [count] ; repeat 'R' bytes (used in bytestream) */ Fill, /* [posn] ; fill 'F' until given byte position */ Start, /* ; for Seek */ Current, /* ; for Seek */ End, /* ; for Seek, or end of byte stream */ Max } Opcode; #define New New1,__LINE__ /* Byte streams are just inserted into the command stream, and must end in an End code. */ int commands[] = { #ifndef __DJGPP__ New, Write, 1605, Rep, 1600, 'h', 'e', 'l', 'l', 'o', End, Tell, 1605, Open, BufSize, 16, Read, 1605, 1605, Compare, Rep, 1600, 'h', 'e', 'l', 'l', 'o', End, Tell, 1605, Flush, Tell, 1605, Seek, 1000, Start, Tell, 1000, New, Text, Write, 2, 'x', 10, End, Verify, 'x', 13, 10, End, New, Binary, Write, 2, 'x', 10, End, Verify, 'x', 10, End, BufSize, 16, New, Binary, Write, 0, Fill, 15, 13, 10, 'x', End, Text, Open, Read, 17, 17, Compare, Fill, 15, 10, 'x', End, Tell, 18, New, Binary, Write, 0, Fill, 14, 13, 10, 'x', End, Text, Open, Read, 16, 16, Compare, Fill, 14, 10, 'x', End, Tell, 17, New, Binary, Write, 0, 13, 10, 'a', 'b', End, Text, Open, Read, 2, 2, Compare, 10, 'a', End, Tell, 3, New, Binary, Write, 0, 10, 'a', 'b', End, Text, Open, Read, 2, 2, Compare, 10, 'a', End, Tell, 2, New, Binary, Write, 0, 13, 'a', 'b', End, Text, Open, Read, 2, 2, Compare, 13, 'a', End, Tell, 2, New, Binary, Write, 0, 13, 13, 10, 'a', End, Text, Open, Read, 2, 2, Compare, 13, 10, End, Tell, 3, New, Binary, Write, 0, 13, 10, 'a', 13, End, Text, Open, Read, 2, 2, Compare, 10, 'a', End, Tell, 3, New, Binary, Write, 0, 13, 10, 'a', 10, End, Text, Open, Read, 2, 2, Compare, 10, 'a', End, Tell, 3, New, Binary, Write, 0, 13, 13, 13, 10, 'a', 10, 10, 10, End, Text, Open, Read, 4, 4, Compare, 13, 13, 10, 'a', End, Tell, 5, #endif New, Binary, Write, 0, 13, 13, 13, 10, 'a', 'b', 13, 10, 13, 10, End, Text, Open, Read, 4, 4, Compare, 13, 13, 10, 'a', End, Tell, 5, }; /*==========================================================================*/ #include #include #include #include #include #include #include #include #ifndef O_BINARY #define O_BINARY 0 #endif #ifndef O_TEXT #define O_TEXT 0 #endif int errors = 0; #define num_commands (sizeof(commands)/sizeof(commands[0])) int pc; int askfor, get, expect, count, posn, whence, size; typedef struct { unsigned char *bytes; int max, count; } Buffer; Buffer rw_buf={0,0,0}, cmp_buf={0,0,0}, vfy_buf={0,0,0}; void expand_buf(Buffer *buf, int len) { if (buf->max < len) { buf->max = len+20; if (buf->bytes) buf->bytes = (unsigned char *)realloc(buf->bytes, buf->max); else buf->bytes = (unsigned char *)malloc(buf->max); } } void get_bytestream(Buffer *buf) { int tpc; int len = 0, rep, byte; unsigned char *bp; for (tpc = pc+1; tpc < num_commands && commands[tpc] != End; tpc++) { switch (commands[tpc]) { case Rep: len += commands[tpc+1]; tpc ++; break; case Fill: if (len < commands[tpc+1]) len = commands[tpc+1]; tpc ++; break; default: len ++; break; } } expand_buf(buf, len); len = 0; bp = buf->bytes; for (tpc = pc+1; tpc < num_commands && commands[tpc] != End; tpc++) { switch (commands[tpc]) { case Rep: rep = commands[++tpc]; byte = 'R'; while (rep--) *bp++ = byte; break; case Fill: rep = commands[++tpc]; byte = 'F'; while (bp-buf->bytes < rep) *bp++ = byte; break; default: *bp++ = commands[tpc]; break; } } buf->count = bp - buf->bytes; pc = tpc; } char dataname[] = "crlf.dat"; int verbose=1; void v(char *fmt, ...) { va_list ap; if (!verbose) return; va_start(ap, fmt); vfprintf(stdout, fmt, ap); va_end(ap); printf("\n"); } void vp(char *fmt, ...) { va_list ap; if (!verbose) return; printf("%08x: ", pc); va_start(ap, fmt); vfprintf(stdout, fmt, ap); va_end(ap); printf("\n"); } void errorq(int use_errno, char *fmt, ...) { va_list ap; fprintf(stderr, "crlf: Error at pc=%d: ", pc); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); if (use_errno) perror("The error was"); errors++; } void error(int use_errno, char *fmt, ...) { va_list ap; fprintf(stderr, "crlf: Error at pc=%d: ", pc); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); if (use_errno) perror("The error was"); fprintf(stderr, "FAIL\n"); exit(1); } void display_buf(char *which, Buffer *buf, int ofs) { int i; fprintf(stderr, "%s %04x:", which, ofs); for (i=0; i<8; i++) if (i+ofs < buf->count) { unsigned char b = buf->bytes[i+ofs]; fprintf(stderr, " %02x", b); if (isgraph(b)) fprintf(stderr, " %c ", b); else fprintf(stderr, " ", b); } fprintf(stderr, "\n"); } void compare_bufs(char *name, Buffer *actual, Buffer *expected) { int i, got_one=0; for (i=0; icount && icount; i++) if (actual->bytes[i] != expected->bytes[i]) { errorq(0, "%s: byte mismatch at offset 0x%x", name, i); got_one = 1; break; } if (!got_one) { if (actual->count < expected->count) errorq(0, "%s: too few bytes (0x%x vs 0x%x)", name, actual->count, expected->count); else if (actual->count > expected->count) errorq(0, "%s: too many bytes (0x%x vs 0x%x)", name, actual->count, expected->count); else return; } i -= 4; if (i<0) i = 0; display_buf("Actual ", actual, i); display_buf("Expected", expected, i); } int main(int argc, char **argv) { char *readmode = "rb"; char *writemode = "wb"; FILE *file = 0; int i, fd; struct stat st; char *str; while (argc > 1 && argv[1][0] == '-') { if (strcmp(argv[1], "-v") == 0) verbose++; argc--; argv++; } size = 0; for (pc=0; pc