From 7e0f021a9aec35fd8e6725e87e3313b101d26f5e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 27 Jan 2008 11:37:44 +0100 Subject: Initial import (2.0.2-6) --- reference/C/CONTRIB/SNIP/chbytes.c | 203 +++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100755 reference/C/CONTRIB/SNIP/chbytes.c (limited to 'reference/C/CONTRIB/SNIP/chbytes.c') diff --git a/reference/C/CONTRIB/SNIP/chbytes.c b/reference/C/CONTRIB/SNIP/chbytes.c new file mode 100755 index 0000000..b1c21f2 --- /dev/null +++ b/reference/C/CONTRIB/SNIP/chbytes.c @@ -0,0 +1,203 @@ +/* +** CHBYTES.C - Change bytes in a file +** +** This program searches a file for a sequence of bytes. If they are +** found, they are replaced with zeros. It was originally developed for +** a friend who needed a program to call from Paradox to remove printer +** control sequences from formatted print files. The requirements were +** 1) since it is called by another program, all status has to be returned +** in the errorlevel with no screen messages allowed, and 2) The file must +** remain the same length, so the deleted sequences must only be replaced +** with ASCII NULs. +** +** Syntax: CHBYTES filename pattern_1 [pattern_2 [...pattern_N]] +** where: Each pattern is a comma-separated list of bytes, each of which +** may be of the following forms: +** C - Any single character will be treated as literal. +** XXh - "XX" will be interpreted as a hexidecimal number (both +** 1- and 2-digit hex numbers are allowed). +** NNNd - "NNN" will be interpreted as a decimal number (both +** 1-, 2-, and 3-digit decimal numbers are allowed). +** +** e.g. CHBYTES printer.fil 12d 1bh,[,3,x +** would zero out form feeds and the escape sequence "[3x" +** +** Returns: 0 - Success +** 1 - No filename +** 2 - No arguments +** 3 - Error opening file +** 4 - Not enough memory +** 5 - Bad argument +** 6 - Error reading file +** 7 - Error writing file +** +** Public domain by Bob Stout +*/ + +#include +#include +#include +#include + +#ifdef __ZTC__ + int _okbigbuf = 0; +#endif + +#define LAST_CHAR(s) (((char *)(s))[strlen((char *)(s)) - 1]) + +#ifndef max + #define max(x,y) (((x) >= (y)) ? (x) : (y)) +#endif + +typedef enum {ERROR = -1, SUCCESS, FALSE = 0, TRUE} LOGICAL; + +int bufsize; + +struct { + char pattern[40]; /* pattern to find */ + int numbytes; /* length of pattern */ +} search[40]; + +int main (int argc, char *argv[]) +{ + FILE *fp = NULL; + char *buf = NULL, *getbuf(void); + fpos_t rpos; + int i, patterns, max_bytes = 0; + LOGICAL hex2char(const char *, char *); + + if (2 > argc) /* no filename */ + return 1; + if (3 > argc) /* no argument */ + return 2; + if (NULL == (fp = fopen(argv[1], "r+b"))) + return 3; /* file open error */ + if (NULL == (buf = getbuf())) + return 4; /* no memory for buffer */ + + patterns = argc - 2; /* process arguments */ + for (i = 2; i < argc; ++i) + { + char *p, *ptr; + + if (NULL != (ptr = strtok(argv[i], ","))) + { + p = search[i - 2].pattern; + do + { + search[i - 2].numbytes++; + if (1 == strlen(ptr)) + { + *p++ = *ptr; + continue; + } + switch (toupper(LAST_CHAR(ptr))) + { + case 'D': + LAST_CHAR(ptr) = '\0'; + *p++ = (char)atoi(ptr); + break; + case 'H': + LAST_CHAR(ptr) = '\0'; + if (ERROR == hex2char(ptr, p++)) + return 5; + break; + default: + return 5; + } + } while (NULL != (ptr = strtok(NULL, ","))); + *p = '\0'; + max_bytes = max(max_bytes, search[i - 2].numbytes); + } + else return 5; + } + + fgetpos(fp, &rpos); /* save where we are */ + while (1) + { + int bytes, n; + LOGICAL modified; + + if (max_bytes > (bytes = (int)fread(buf, 1, bufsize, fp))) + { + if (0 == bytes && !feof(fp)) + return 6; /* something's wrong! */ + else break; /* all done! */ + } + for (n = 0, modified = FALSE; n < patterns; ++n) + { + /* check each pattern in turn */ + + for (i = 0; i < (bytes - max_bytes + 1); ++i) + { + int j; + + if (buf[i] != *(search[n].pattern)) + continue; + if (SUCCESS != strncmp(&buf[i], + search[n].pattern, search[n].numbytes)) + { + continue; + } + + /* found one! replace it in the buffer */ + + for (j = 0; j < search[n].numbytes; ++j, ++i) + buf[i] = '\0'; + modified = TRUE; + } + } + if (modified) /* write changes, if any*/ + { + fpos_t wpos = rpos; + + fsetpos(fp, &wpos); + if (bytes != (int)fwrite(buf, 1, bytes, fp)) + return 7; + fsetpos(fp, &rpos); + } + rpos += bytes - max_bytes + 1; /* get another buffer */ + fsetpos(fp, &rpos); + } + fclose(fp); + return SUCCESS; +} + +/* +** Allocate the largest buffer we can +*/ + +char *getbuf(void) +{ + register char *buffer; + + for (bufsize = 0x4000; bufsize >= 128; bufsize >>= 1) + { + if (NULL != (buffer = (char *) malloc(bufsize))) + return buffer; + } + return NULL; +} + +/* +** Convert ASCII hex char to char +*/ + +#define xdigit(c) (toupper(c) - (((c) > '9') ? 'A' - 10 : '0')) + +LOGICAL hex2char(const char *hex, char *buf) +{ + int ch = 0; + char *p = (char *)hex; + + while(*p) + { + if (!isxdigit(*p)) + return ERROR; + ch <<= 4; + ch += xdigit(*p); + ++p; + } + *buf = (char)ch; + return SUCCESS; +} -- cgit v1.2.3-54-g00ecf