home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / TEXT / UTILITY / UNEEK101.ZIP / UNEEK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-22  |  7.8 KB  |  276 lines

  1. /*
  2.    ****************************  NOTICE!  **************************
  3.    *   Contrary to the current trend  in  MS-DOS  software  this   *
  4.    *   program,  for  whatever  it is worth,  is NOT copyrighted   *
  5.    *   (with the exception of the runtime library  from  Borland   *
  6.    *   International's  Turbo  C)!  The program,  in whole or in   *
  7.    *   part,  may be used freely in any fashion  or  environment   *
  8.    *   desired.  If  you  find this program to be useful to you,   *
  9.    *   do NOT send any contribution to the author;  in the words   *
  10.    *   of  Rick  Conn,   'Enjoy!'  However,   if  you  make  any   *
  11.    *   improvements,  I would enjoy  receiving  a  copy  of  the   *
  12.    *   modified  source.  I  can  be reached,  usually within 24   *
  13.    *   hours,  by  messages  on  any  of  the  Phoenix  systems,   *
  14.    *   particularly:                                               *
  15.    *                                                               *
  16.    *               Bob's Answering Machine [OPUS]                  *
  17.    *                   (602) 242-3158   1200/2400 bps              *
  18.    *               Radioactive West        [PCBOARD]               *
  19.    *                   (602) 873-0810   1200/2400 bps              *
  20.    *               The Tool Shop BBS       [PCBOARD]               *
  21.    *                   (602) 279-2673   1200/2400/9600 bps         *
  22.    *                   (Good luck trying!  VERY BUSY!)             *
  23.    *               Technoids Anonymous     [PCBOARD]               *
  24.    *                   (602) 899-4876   300/1200/2400 bps          *
  25.    *                                                               *
  26.    *   All can be reached through PC Pursuit.                      *
  27.    *                                                               *
  28.    *   or:                                                         *
  29.    *                on GEnie, mail address: DON-WILL               *
  30.    *                on CompuServ:           75410,543              *
  31.    *                                                               *
  32.    *   Every  effort has been made to avoid error and moderately   *
  33.    *   extensive testing has been  performed  on  this  program,   *
  34.    *   however, the author does not warrant it to be fit for any   *
  35.    *   purpose  or  to  be  free  from  error  and disclaims any   *
  36.    *   liability for actual or any other damage arising from the   *
  37.    *   use of this program.                                        *
  38.    *****************************************************************
  39. */
  40.  
  41. #include <stdlib.h>
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <ctype.h>
  45.  
  46. #include "queue.h"
  47.  
  48. #define LINE_LENGTH 256
  49. #define OFF 0
  50. #define ON  1
  51.  
  52. struct KeyEntry {
  53.     int Begin;
  54.     int Len;
  55.     char Case;
  56.     };
  57.  
  58. void GetArgs (int argc, char *argv[]);
  59. void InvalArgu (char *Msg);
  60. int KeyComp (char *Str1, char *Str2, QUE_DEF *Q);
  61. void Usage (void);
  62.  
  63. char InName[65] = "";
  64. FILE *F1 = NULL;
  65. FILE *F2;
  66. QUE_DEF *Keys;
  67.  
  68.  void
  69. main (int argc, char *argv[]) {
  70.     char BakName[65];
  71.     char IntName[65];
  72.     char Line[LINE_LENGTH + 3];
  73.     char *OldLine = NULL;
  74.     char *p;
  75.     struct KeyEntry *t;
  76.     int Lnno = 0;
  77.  
  78.     fprintf(stderr, "UNEEK- Version 1.0.0  May 21, 1990\n");
  79.     if (argc < 2) Usage();
  80.     Keys = malloc(sizeof(QUE_DEF));
  81.     InitQueue(Keys);
  82.     GetArgs(argc, argv);
  83.  
  84.     if (F1 == NULL) {
  85.         if (InName[0] == '\0') {
  86.             fprintf(stderr, "You must supply an input file name.\n");
  87.             Usage();
  88.             }
  89.         strcpy(BakName, InName);
  90.         if ( (p = strrchr(BakName, '.')) != NULL) *p = '\0';
  91.         strcat(BakName, ".BAK");
  92.         strcpy(IntName, InName);
  93.         if ( (p = strrchr(IntName, '\\')) == NULL) p = IntName;
  94.         else ++p;
  95.         strcpy(p, "UNIQUE.$$$");
  96.  
  97.         if ( (F1 = fopen(InName, "r")) == NULL) {
  98.             fprintf(stderr, "I can't open input file: %s", InName);
  99.             perror("");
  100.             exit(1);
  101.             }
  102.         setvbuf(F1, NULL, _IOFBF, 16384);
  103.         if ( (F2 = fopen(IntName, "w")) == NULL) {
  104.             fprintf(stderr, "I can't create output file: %s", IntName);
  105.             perror("");
  106.             exit(1);
  107.             }
  108.         setvbuf(F2, NULL, _IOFBF, 16384);
  109.         }
  110.  
  111.     if (Keys->Count == 0) {
  112.         t = malloc(sizeof(struct KeyEntry));
  113.         t->Begin = 0;
  114.         t->Len = 0;
  115.         Enque(Keys, t);
  116.         }
  117.  
  118.     while (fgets(Line, LINE_LENGTH, F1) != NULL) {
  119.         Lnno++;
  120.         if (Line[strlen(Line)-1] != '\n') {
  121.             fprintf(stderr, "File: %s Line #%d too long - truncated.\n",
  122.                     InName, Lnno);
  123.             strcat(Line, "\n");
  124.             while (fgetc(F1) != '\n');
  125.             }
  126.         if (OldLine == NULL) OldLine = malloc(LINE_LENGTH + 3);
  127.         else {
  128.             if (KeyComp(OldLine, Line, Keys)) fputs(OldLine, F2);
  129.             }
  130.         strcpy(OldLine, Line);
  131.         }
  132.  
  133.     fputs(OldLine, F2);
  134.     if (F1 != stdin) {
  135.         fclose(F1); fclose(F2);
  136.         unlink(BakName);
  137.         if (rename(InName, BakName)) {
  138.             fprintf(stderr, "Rename of file: %s failed", InName);
  139.             perror("");
  140.             }
  141.         if (rename(IntName, InName)) {
  142.             fprintf(stderr, "Rename of file: %s failed", IntName);
  143.             perror("");
  144.             }
  145.         }
  146.     }
  147.  
  148.  
  149.  
  150.  void
  151. GetArgs (int argc, char *argv[]) {
  152.     int i;
  153.     char *p1, *p2;
  154.     struct KeyEntry *t;
  155.  
  156.     for (i=1; i < argc; ++i) {
  157.         if (argv[i][0] != '-') continue;
  158.         if (!strcmp(argv[i], "-")) {
  159.             F1 = stdin;
  160.             F2 = stdout;
  161.             continue;
  162.             }
  163.         switch (tolower(argv[i][1])) {
  164.             default:
  165.                 fprintf(stderr, "Invalid option: %s\n", argv[i]);
  166.                 Usage();
  167.             }
  168.         }
  169.  
  170.     for (i=1; i < argc; ++i) {
  171.         if (argv[i][0] == '-') continue;
  172.         if ( (F1 == NULL) && (InName[0] == '\0') ) {
  173.             if (InName[0] == '\0') {
  174.                 strcpy(InName, argv[i]);
  175.                 continue;
  176.                 }
  177.             }
  178.         p1 = argv[i];
  179.         if ( !isdigit(p1[0]) ) InvalArgu(argv[i]);
  180.         p2 = &p1[strspn(p1, "0123456789")];
  181.         t =malloc( sizeof(struct KeyEntry) );
  182.         t->Case = OFF;
  183.         t->Begin = atoi(p1) -1;
  184.         if (*p2 == ':') t->Len = atoi(++p2);
  185.         else if (*p2 == '-') t->Len = atoi(++p2) - t->Begin;
  186.         else InvalArgu(argv[i]);
  187.         p1 = p2;
  188.         p2 = &p1[strspn(p1, "0123456789")];
  189.         if (*p2 == ':') {
  190.             p1 = ++p2;
  191.             while (*p1 != '\0') {
  192.                 switch (tolower(*p1++)) {
  193.                     case 'i':
  194.                         t->Case = OFF;
  195.                         break;
  196.                     case 'c':
  197.                         t->Case = ON;
  198.                         break;
  199.                     default:
  200.                         InvalArgu(argv[i]);
  201.                     }
  202.                 }
  203.             }
  204.         else if (*p2 != '\0') InvalArgu(argv[i]);
  205.         Enque(Keys, t);
  206.         }
  207.     }
  208.  
  209.  
  210.  
  211.  void
  212. InvalArgu (char *Msg) {
  213.     fprintf(stderr, "Invalid argument: %s.\n", Msg);
  214.     Usage();
  215.     }
  216.  
  217.  
  218.  
  219.  int
  220. KeyComp (char *Str1, char *Str2, QUE_DEF *Q) {
  221.     int Result, La, Lb;
  222.     QUE_ENTRY *t;
  223.     struct KeyEntry *p;
  224.     char *S1, *S2, HoldA, HoldB;
  225.  
  226.     La = strlen(Str1); Lb = strlen(Str2);
  227.     for (Result=0, t = Q->Head; (Result == 0) && (t != NULL); t = t->Next) {
  228.         p = t->Body;
  229.         if (p->Len == 0) {
  230.             if (p->Case == OFF) Result = stricmp(Str1, Str2);
  231.             else Result = strcmp(Str1, Str2);
  232.             break;
  233.             }
  234.         else {
  235.             if (p->Begin > La) S1 = "";
  236.             else S1 = &Str1[p->Begin];
  237.             if (p->Begin > Lb) S2 = "";
  238.             else S2 = &Str2[p->Begin];
  239.             if (S1[0] != '\0') {
  240.                 if (p->Begin + p->Len < La) {
  241.                     HoldA = S1[p->Len];
  242.                     S1[p->Len] = '\0';
  243.                     }
  244.                 }
  245.             if (S2[0] != '\0') {
  246.                 if (p->Begin + p->Len < Lb) {
  247.                     HoldB = S2[p->Len];
  248.                     S2[p->Len] = '\0';
  249.                     }
  250.                 }
  251.  
  252.             if (p->Case == OFF) Result = stricmp(S1, S2);
  253.             else Result = strcmp(S1, S2);
  254.             if ( (S1[0] != '\0') && (p->Begin + p->Len < La) )
  255.                 S1[p->Len] = HoldA;
  256.             if ( (S2[0] != '\0') && (p->Begin + p->Len < Lb) )
  257.                 S2[p->Len] = HoldB;
  258.             }
  259.         }
  260.     return(Result);
  261.     }
  262.  
  263.  
  264.  
  265.  void
  266. Usage (void) {
  267.     fprintf(stderr, "USAGE: unique [- | file_name] [field_spec ...]\n");
  268.     fprintf(stderr, "    field_spec = b:l[:o] or b-e[:o] where b is the beginning\n");
  269.     fprintf(stderr, "    character position of the field and l is the length\n");
  270.     fprintf(stderr, "    in characters or e is the ending character position\n");
  271.     fprintf(stderr, "    of the field (inclusive).  o, if supplied is 'i' for\n");
  272.     fprintf(stderr, "    a case insensitive match (default) or 'c' for a case\n");
  273.     fprintf(stderr, "    sensitive match.\n");
  274.     exit(1);
  275.     }
  276.