home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 14
/
CD_ASCQ_14_0694.iso
/
maj
/
653
/
chbytes.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-03
|
7KB
|
204 lines
/*
** 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;
}