summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/chbytes.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/chbytes.c')
-rwxr-xr-xreference/C/CONTRIB/SNIP/chbytes.c203
1 files changed, 203 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#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;
+}