home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / CHBYTES.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  7KB  |  203 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /*
  4. **  CHBYTES.C - Change bytes in a file
  5. **
  6. **  This program searches a file for a sequence of bytes. If they are
  7. **  found, they are replaced with zeros. It was originally developed for
  8. **  a friend who needed a program to call from Paradox to remove printer
  9. **  control sequences from formatted print files. The requirements were
  10. **  1) since it is called by another program, all status has to be returned
  11. **  in the errorlevel with no screen messages allowed, and 2) The file must
  12. **  remain the same length, so the deleted sequences must only be replaced
  13. **  with ASCII NULs.
  14. **
  15. **  Syntax: CHBYTES filename pattern_1 [pattern_2 [...pattern_N]]
  16. **  where:  Each pattern is a comma-separated list of bytes, each of which
  17. **          may be of the following forms:
  18. **          C    - Any single character will be treated as literal.
  19. **          XXh  - "XX" will be interpreted as a hexadecimal number (both
  20. **                 1- and 2-digit hex numbers are allowed).
  21. **          NNNd - "NNN" will be interpreted as a decimal number (both
  22. **                 1-, 2-, and 3-digit decimal numbers are allowed).
  23. **
  24. **  e.g.    CHBYTES printer.fil 12d 1bh,[,3,x
  25. **          would zero out form feeds and the escape sequence "[3x"
  26. **
  27. **  Returns: 0 - Success
  28. **           1 - No filename
  29. **           2 - No arguments
  30. **           3 - Error opening file
  31. **           4 - Not enough memory
  32. **           5 - Bad argument
  33. **           6 - Error reading file
  34. **           7 - Error writing file
  35. **
  36. **  Public domain by Bob Stout
  37. */
  38.  
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <ctype.h>
  43. #include "sniptype.h"
  44.  
  45. #ifdef __ZTC__
  46.  int _okbigbuf = 0;
  47. #endif
  48.  
  49. #ifndef max
  50.  #define max(x,y) (((x) >= (y)) ? (x) : (y))
  51. #endif
  52.  
  53. int bufsize;
  54.  
  55. struct {
  56.       char pattern[40];                         /* pattern to find      */
  57.       int numbytes;                             /* length of pattern    */
  58. } search[40];
  59.  
  60. int main (int argc, char *argv[])
  61. {
  62.       FILE *fp  = NULL;
  63.       char *buf = NULL, *getbuf(void);
  64.       fpos_t rpos;
  65.       int i, patterns, max_bytes = 0;
  66.       Boolean_T hex2char(const char *, char *);
  67.  
  68.       if (2 > argc)                             /* no filename          */
  69.             return 1;
  70.       if (3 > argc)                             /* no argument          */
  71.             return 2;
  72.       if (NULL == (fp = fopen(argv[1], "r+b")))
  73.             return 3;                           /* file open error      */
  74.       if (NULL == (buf = getbuf()))
  75.             return 4;                           /* no memory for buffer */
  76.  
  77.       patterns = argc - 2;                      /* process arguments    */
  78.       for (i = 2; i < argc; ++i)
  79.       {
  80.             char *p, *ptr;
  81.  
  82.             if (NULL != (ptr = strtok(argv[i], ",")))
  83.             {
  84.                   p = search[i - 2].pattern;
  85.                   do
  86.                   {
  87.                         search[i - 2].numbytes++;
  88.                         if (1 == strlen(ptr))
  89.                         {
  90.                               *p++ = *ptr;
  91.                               continue;
  92.                         }
  93.                         switch (toupper(LAST_CHAR(ptr)))
  94.                         {
  95.                         case 'D':
  96.                               LAST_CHAR(ptr) = '\0';
  97.                               *p++ = (char)atoi(ptr);
  98.                               break;
  99.                         case 'H':
  100.                               LAST_CHAR(ptr) = '\0';
  101.                               if (Error_ == hex2char(ptr, p++))
  102.                                     return 5;
  103.                               break;
  104.                         default:
  105.                               return 5;
  106.                         }
  107.                   } while (NULL != (ptr = strtok(NULL, ",")));
  108.                   *p = '\0';
  109.                   max_bytes = max(max_bytes, search[i - 2].numbytes);
  110.             }
  111.             else  return 5;
  112.       }
  113.  
  114.       fgetpos(fp, &rpos);                       /* save where we are    */
  115.       while (1)
  116.       {
  117.             int bytes, n;
  118.             Boolean_T modified;
  119.  
  120.             if (max_bytes > (bytes = (int)fread(buf, 1, bufsize, fp)))
  121.             {
  122.                   if (0 == bytes && !feof(fp))
  123.                         return 6;               /* something's wrong!   */
  124.                   else  break;                  /* all done!            */
  125.             }
  126.             for (n = 0, modified = False_; n < patterns; ++n)
  127.             {
  128.                   /* check each pattern in turn                         */
  129.  
  130.                   for (i = 0; i < (bytes - max_bytes + 1); ++i)
  131.                   {
  132.                         int j;
  133.  
  134.                         if (buf[i] != *(search[n].pattern))
  135.                               continue;
  136.                         if (Success_ != strncmp(&buf[i],
  137.                               search[n].pattern, search[n].numbytes))
  138.                         {
  139.                               continue;
  140.                         }
  141.  
  142.                         /* found one! replace it in the buffer          */
  143.  
  144.                         for (j = 0; j < search[n].numbytes; ++j, ++i)
  145.                               buf[i] = '\0';
  146.                         modified = True_;
  147.                   }
  148.             }
  149.             if (modified)                       /* write changes, if any*/
  150.             {
  151.                   fpos_t wpos = rpos;
  152.  
  153.                   fsetpos(fp, &wpos);
  154.                   if (bytes != (int)fwrite(buf, 1, bytes, fp))
  155.                         return 7;
  156.                   fsetpos(fp, &rpos);
  157.             }
  158.             rpos += bytes - max_bytes + 1;      /* get another buffer   */
  159.             fsetpos(fp, &rpos);
  160.       }
  161.       fclose(fp);
  162.       return Success_;
  163. }
  164.  
  165. /*
  166. **  Allocate the largest buffer we can
  167. */
  168.  
  169. char *getbuf(void)
  170. {
  171.       register char *buffer;
  172.  
  173.       for (bufsize = 0x4000; bufsize >= 128; bufsize >>= 1)
  174.       {
  175.             if (NULL != (buffer = (char *) malloc(bufsize)))
  176.                   return buffer;
  177.       }
  178.       return NULL;
  179. }
  180.  
  181. /*
  182. **  Convert ASCII hex char to char
  183. */
  184.  
  185. #define xdigit(c) (toupper(c) - (((c) > '9') ? 'A' - 10 : '0'))
  186.  
  187. Boolean_T hex2char(const char *hex, char *buf)
  188. {
  189.       int ch = 0;
  190.       char *p = (char *)hex;
  191.  
  192.       while(*p)
  193.       {
  194.             if (!isxdigit(*p))
  195.                   return Error_;
  196.             ch <<= 4;
  197.             ch  += xdigit(*p);
  198.                 ++p;
  199.       }
  200.       *buf = (char)ch;
  201.       return Success_;
  202. }
  203.