Annotation of os2sdk/demos/apps/cpgrep/cpgrep.c, revision 1.1.1.1

1.1       root        1: /* cpgrep
                      2: *
                      3: * HISTORY:
                      4: * 23-Mar-87     danl    exit(x) -> DOSEXIT(1, x)
                      5: *
                      6: */
                      7: 
                      8: #include               <stdio.h>
                      9: #include               <fcntl.h>
                     10: #include               <ctype.h>
                     11: 
                     12: int far pascal         DOSCREATETHREAD(void (far *)(),int far *,int far *);
                     13: int far pascal         DOSGETMACHINEMODE(char far *);
                     14: int far pascal         DOSQHANDTYPE(int,int far *,int far *);
                     15: int far pascal         DOSREAD(int,char far *,int,int far *);
                     16: int far pascal         DOSSEMCLEAR(long far *);
                     17: int far pascal         DOSSEMREQUEST(long far *,long);
                     18: int far pascal         DOSSEMSET(long far *);
                     19: int far pascal         DOSSEMWAIT(long far *,long);
                     20: int far pascal         DOSSLEEP(long);
                     21: int far pascal         DOSWRITE(int,char far *,int,int far *);
                     22: int far pascal         DOSEXIT(int, int);
                     23: 
                     24: #define        BEGLINE         0x40
                     25: #define        DEBUG           0x08
                     26: #define        ENDLINE         0x80
                     27: #define        FILBUFLEN       (SECTORLEN*30)
                     28: #define        FILNAMLEN       80
                     29: #define        INVERT          0x10
                     30: #define        ISCOT           0x0002
                     31: #define        LG2SECLEN       9
                     32: #define        LINELEN         128
                     33: #define        LINENOS         0x04
                     34: #define        LNOLEN          8
                     35: #define        MAXSTRLEN       128
                     36: #define        NAMEONLY        0x02
                     37: #define        OUTBUFLEN       (SECTORLEN*4)
                     38: #define        SECTORLEN       (1 << LG2SECLEN)
                     39: #define        SHOWNAME        0x01
                     40: #define        STKLEN          256
                     41: #define        TIMER           0x20
                     42: #define        TRTABLEN        256
                     43: #define        s_text(x)       (((char *)(x)) - ((x)->s_must))
                     44: 
                     45: typedef struct stringnode
                     46:   {
                     47:     struct stringnode  *s_alt;         /* List of alternates */
                     48:     struct stringnode  *s_suf;         /* List of suffixes */
                     49:     int                        s_must;         /* Length of portion that must match */
                     50:   }
                     51:                        STRINGNODE;
                     52: 
                     53: char                   filbuf[(FILBUFLEN + 2)*2];
                     54: char                   *bufptr[] = { filbuf, filbuf + FILBUFLEN + 2 };
                     55: char                   outbuf[OUTBUFLEN*2];
                     56: char                   *obuf[] = { outbuf, outbuf + OUTBUFLEN };
                     57: char                   *optr[] = { outbuf, outbuf + OUTBUFLEN };
                     58: int                    ocnt[] = { OUTBUFLEN, OUTBUFLEN };
                     59: int                    oi = 0;
                     60: char                   transtab[TRTABLEN] = { 0 };
                     61: STRINGNODE             *stringlist[TRTABLEN/2];
                     62: int                    arrc;           /* I/O return code for DOSREAD */
                     63: int                    awrc;           /* I/O return code for DOSWRITE */
                     64: int                    casesen = 1;    /* Assume case-sensitivity */
                     65: int                    cbread;         /* Bytes read by DOSREAD */
                     66: int                    cbwrite;        /* Bytes written by DOSWRITE */
                     67: int                    clists = 1;     /* One is first available index */
                     68: int                    flags;          /* Flags */
                     69: int                    lineno;         /* Current line number */
                     70: char                   pmode;          /* Protected mode flag */
                     71: long                   readdone;       /* Async read done semaphore */
                     72: long                   readpending;    /* Async read pending semaphore */
                     73: int                    status = 1;     /* Assume failure */
                     74: char                   *t2buf;         /* Async read buffer */
                     75: int                    t2buflen;       /* Async read buffer length */
                     76: int                    t2fd;           /* Async read file */
                     77: char                   *t3buf;         /* Async write buffer */
                     78: int                    t3buflen;       /* Async write buffer length */
                     79: int                    t3fd;           /* Async write file */
                     80: long                   writedone;      /* Async write done semaphore */
                     81: long                   writepending;   /* Async write pending semaphore */
                     82: char                   target[MAXSTRLEN];
                     83:                                        /* Last string added */
                     84: int                    targetlen;      /* Length of last string added */
                     85: 
                     86: int                    countlines();   /* See CPGREPSB.ASM */
                     87: int                    countmatched(); /* See CPGREPSB.ASM */
                     88: char                   *findlist();    /* See CPGREPSB.ASM */
                     89: char                   *findone();     /* See CPGREPSB.ASM */
                     90: void                   flush1buf();    /* See below */
                     91: int                    grepbuffer();   /* See below */
                     92: int                    revfind();      /* See CPGREPSB.ASM */
                     93: void                   write1buf();    /* See below */
                     94: char                   *(*find)() = findlist;
                     95: void                   (*flush1)() = flush1buf;
                     96: int                    (*grep)() = grepbuffer;
                     97: void                   (*write1)() = write1buf;
                     98: 
                     99: void                   freenode(x)
                    100: register STRINGNODE    *x;             /* Pointer to node to free */
                    101:   {
                    102:     register STRINGNODE        *y;             /* Pointer to next node in list */
                    103: 
                    104:     while(x != NULL)                   /* While not at end of list */
                    105:       {
                    106:        if(x->s_suf != NULL) freenode(x->s_suf);
                    107:                                        /* Free suffix list */
                    108:        y = x;                          /* Save pointer */
                    109:        x = x->s_alt;                   /* Move down the list */
                    110:        free(y);                        /* Free the node */
                    111:       }
                    112:   }
                    113: 
                    114: 
                    115: STRINGNODE             *newnode(s,n)
                    116: char                   *s;             /* String */
                    117: int                    n;              /* Length of string */
                    118:   {
                    119:     register STRINGNODE        *new;           /* Pointer to new node */
                    120:     char               *t;             /* String pointer */
                    121:     char               *malloc();      /* Storage allocator */
                    122: 
                    123:     if((t = malloc(sizeof(STRINGNODE) + n + (n & 1))) == NULL)
                    124:       {                                        /* If allocation fails */
                    125:        fprintf(stderr,"Out of memory\n");
                    126:        DOSEXIT(1, 2);                        /* Print error message and die */
                    127:       }
                    128:     if(n & 1) ++t;                     /* END of string word-aligned */
                    129:     strncpy(t,s,n);                    /* Copy string text */
                    130:     new = (STRINGNODE *)(t + n);       /* Set pointer to node */
                    131:     new->s_alt = NULL;                 /* No alternates yet */
                    132:     new->s_suf = NULL;                 /* No suffixes yet */
                    133:     new->s_must = n;                   /* Set string length */
                    134:     return(new);                       /* Return pointer to new node */
                    135:   }
                    136: 
                    137: 
                    138: void                   reallocnode(node,s,n)
                    139: register STRINGNODE    *node;          /* Pointer to node */
                    140: char                   *s;             /* String */
                    141: register int           n;              /* Length of string */
                    142:   {
                    143:     if(n > node->s_must)               /* If node must grow */
                    144:       {
                    145:        fprintf(stderr,"Internal error\n");
                    146:                                        /* Error message */
                    147:        DOSEXIT(1, 2);                        /* Error exit */
                    148:       }
                    149:     node->s_must = n;                  /* Set new length */
                    150:     memcpy(s_text(node),s,n);          /* Copy new text */
                    151:   }
                    152: 
                    153: 
                    154: void                   addstring(s,n)
                    155: char                   *s;             /* String to add */
                    156: int                    n;              /* Length of string */
                    157:   {
                    158:     register STRINGNODE        *cur;           /* Current string */
                    159:     register STRINGNODE        **pprev;        /* Pointer to previous link */
                    160:     STRINGNODE         *new;           /* New string */
                    161:     int                        i;              /* Index */
                    162:     int                        j;              /* Count */
                    163:     int                        k;              /* Count */
                    164: 
                    165:     if(n <= 0 || n > 127) return;      /* Should never happen */
                    166:     i = transtab[*s];                  /* Get current index */
                    167:     if(i == 0)                         /* If no existing list */
                    168:       {
                    169:        /*
                    170:         *  We have to start a new list
                    171:         */
                    172:        if((i = clists++) >= TRTABLEN/2)
                    173:          {                             /* If too many string lists */
                    174:            fprintf(stderr,"Too many string lists\n");
                    175:                                        /* Error message */
                    176:            DOSEXIT(1, 2);                    /* Die */
                    177:          }
                    178:        stringlist[i] = NULL;           /* Initialize */
                    179:        transtab[*s] = i;               /* Set pointer to new list */
                    180:        if(!casesen && isalpha(*s)) transtab[*s ^ '\x20'] = i;
                    181:                                        /* Set pointer for other case */
                    182:       }
                    183:     else if(stringlist[i] == NULL) return;
                    184:                                        /* Check for existing 1-byte string */
                    185:     if(--n == 0)                       /* If 1-byte string */
                    186:       {
                    187:        freenode(stringlist[i]);        /* Free any existing stuff */
                    188:        stringlist[i] = NULL;           /* No record here */
                    189:        return;                         /* Done */
                    190:       }
                    191:     ++s;                               /* Skip first char */
                    192:     pprev = stringlist + i;            /* Get pointer to link */
                    193:     cur = *pprev;                      /* Get pointer to node */
                    194:     while(cur != NULL)                 /* Loop to traverse match tree */
                    195:       {
                    196:        i = (n > cur->s_must)? cur->s_must: n;
                    197:                                        /* Find minimum of string lengths */
                    198:        matchstrings(s,s_text(cur),i,&j,&k);
                    199:                                        /* Compare the strings */
                    200:        if(j == 0)                      /* If complete mismatch */
                    201:          {
                    202:            if(k < 0) break;            /* Break if insertion point found */
                    203:            pprev = &(cur->s_alt);      /* Get pointer to alternate link */
                    204:            cur = *pprev;               /* Follow the link */
                    205:          }
                    206:        else if(i == j)                 /* Else if strings matched */
                    207:          {
                    208:            if(i == n)                  /* If new is prefix of current */
                    209:              {
                    210:                reallocnode(cur,s_text(cur),n);
                    211:                                        /* Shorten text of node */
                    212:                if(cur->s_suf != NULL)  /* If there are suffixes */
                    213:                  {
                    214:                    freenode(cur->s_suf);
                    215:                                        /* Suffixes no longer needed */
                    216:                    cur->s_suf = NULL;
                    217:                  }
                    218:                return;                 /* All done */
                    219:              }
                    220:            pprev = &(cur->s_suf);      /* Get pointer to suffix link */
                    221:            if((cur = *pprev) == NULL) return;
                    222:                                        /* Done if current is prefix of new */
                    223:            s += i;                     /* Skip matched portion */
                    224:            n -= i;
                    225:          }
                    226:        else                            /* Else partial match */
                    227:          {
                    228:            /*
                    229:             *  We must split an existing node.
                    230:             *  This is the trickiest case.
                    231:             */
                    232:            new = newnode(s_text(cur) + j,cur->s_must - j);
                    233:                                        /* Unmatched part of current string */
                    234:            reallocnode(cur,s_text(cur),j);
                    235:                                        /* Set length to matched portion */
                    236:            new->s_suf = cur->s_suf;    /* Current string's suffixes */
                    237:            if(k < 0)                   /* If new preceded current */
                    238:              {
                    239:                cur->s_suf = newnode(s + j,n - j);
                    240:                                        /* FIrst suffix is new string */
                    241:                cur->s_suf->s_alt = new;/* Alternate is part of current */
                    242:              }
                    243:            else                        /* Else new followed current */
                    244:              {
                    245:                new->s_alt = newnode(s + j,n - j);
                    246:                                        /* Unmatched new string is alternate */
                    247:                cur->s_suf = new;       /* New suffix list */
                    248:              }
                    249:            return;
                    250:          }
                    251:       }
                    252:     *pprev = newnode(s,n);             /* Set pointer to new node */
                    253:     (*pprev)->s_alt = cur;             /* Attach alternates */
                    254:   }
                    255: 
                    256: 
                    257: int                    addfancy(buffer,buflen,seplist)
                    258: register char          *buffer;        /* Buffer */
                    259: int                    buflen;         /* Length of buffer */
                    260: char                   *seplist;       /* List of separators */
                    261:   {
                    262:     register char      *bufend;        /* Pointer to end of buffer */
                    263:     int                        strcnt = 0;     /* String count */
                    264:     int                        len;            /* String length */
                    265:     char               c;              /* One char buffer */
                    266: 
                    267:     bufend = buffer + buflen;          /* Set end pointer */
                    268:     while(buffer < bufend)             /* Loop through all strings */
                    269:       {
                    270:        len = strncspn(buffer,seplist,bufend - buffer);
                    271:                                        /* Length of string */
                    272:        if(flags & ENDLINE)             /* If match must be at end of line */
                    273:          {
                    274:            c = buffer[len];            /* Save 1st character past string */
                    275:            buffer[len++] = '\r';       /* Carriage return marks end of line */
                    276:          }
                    277:        if(findlist(buffer,buffer + len) == NULL)
                    278:          {                             /* If no match within string */
                    279:            addstring(buffer,len);      /* Add string to list */
                    280:            if(strcnt++ == 0)           /* If first string */
                    281:              {
                    282:                memcpy(target,buffer,len);
                    283:                                        /* Save first string in buffer */
                    284:                targetlen = len;        /* Remember length */
                    285:              }
                    286:          }
                    287:        buffer += len;                  /* Skip over string */
                    288:        if(flags & ENDLINE) (--buffer)[0] = c;
                    289:                                        /* Restore saved character */
                    290:        buffer += strnspn(buffer,seplist,bufend - buffer);
                    291:                                        /* Skip over trailing separators */
                    292:       }
                    293:     return(strcnt);                    /* Return string count */
                    294:   }
                    295: 
                    296: 
                    297: int                    addplain(buffer,buflen,seplist)
                    298: register char          *buffer;        /* String list buffer */
                    299: int                    buflen;         /* Buffer length */
                    300: char                   *seplist;       /* List of separators */
                    301:   {
                    302:     int                        strcnt;         /* String count */
                    303:     register int       len;            /* String length */
                    304:     char               c;              /* One char buffer */
                    305: 
                    306:     strcnt = 0;
                    307:     while((len = strncspn(buffer,seplist,buflen)) > 0)
                    308:       {                                        /* While not at end of input list */
                    309:        if(flags & ENDLINE)             /* If match must be at end of line */
                    310:          {
                    311:            c = buffer[len];            /* Save 1st character past string */
                    312:            buffer[len++] = '\r';       /* Carriage return marks end of line */
                    313:          }
                    314:        if(strcnt == 0)                 /* Save first string */
                    315:          {
                    316:            strncpy(target,buffer,len); /* Save string in buffer */
                    317:            targetlen = len;            /* Save string length */
                    318:          }
                    319:        addstring(buffer,len);          /* Add the string to the table */
                    320:        if(flags & ENDLINE) buffer[--len] = c;
                    321:                                        /* Restore saved character */
                    322:        buffer += len;                  /* Skip the string */
                    323:        buflen -= len;
                    324:        len = strnspn(buffer,seplist,buflen);
                    325:                                        /* Skip separators */
                    326:        buffer += len;
                    327:        buflen -= len;
                    328:        ++strcnt;                       /* Increment string count */
                    329:       }
                    330:     return(strcnt);                    /* Return string count */
                    331:   }
                    332: 
                    333: 
                    334: void                   dumplist(node,indent)
                    335: register STRINGNODE    *node;          /* Pointer to list to dump */
                    336: int                    indent;         /* Current length of buffer */
                    337:   {
                    338:     int                        i;              /* Counter */
                    339: 
                    340:     while(node != NULL)                        /* While not at end of list */
                    341:       {
                    342:        for(i = 0; i < indent; ++i) fputc(' ',stderr);
                    343:        fwrite(s_text(node),sizeof(char),node->s_must,stderr);
                    344:        fprintf(stderr,"\n");
                    345:        if(node->s_suf != NULL)
                    346:          dumplist(node->s_suf,indent + node->s_must);
                    347:                                        /* Recurse to do suffixes */
                    348:        node = node->s_alt;             /* Do next alternate in list */
                    349:       }
                    350:   }
                    351: 
                    352: 
                    353: void                   dumpstrings()
                    354:   {
                    355:     int                        i;              /* Index */
                    356: 
                    357:     for(i = 0; i < TRTABLEN; ++i)      /* Loop through translation table */
                    358:       {
                    359:        if(transtab[i] == 0) continue;  /* Skip null entries */
                    360:        fprintf(stderr,"%c\n",i);       /* Print the first byte */
                    361:        dumplist(stringlist[transtab[i]],1);
                    362:                                        /* Dump the list */
                    363:       }
                    364:   }
                    365: 
                    366: 
                    367: int                    openfile(name)
                    368: char                   *name;          /* File name */
                    369:   {
                    370:     int                        fd;             /* File descriptor */
                    371: 
                    372:     if((fd = open(name,0)) == -1)      /* If error opening file */
                    373:       {
                    374:        fprintf(stderr,"Cannot open %s\r\n",name);
                    375:                                        /* Print error message */
                    376:       }
                    377:     return(fd);                                /* Return file descriptor */
                    378:   }
                    379: 
                    380: 
                    381: void far               thread2()       /* Read thread */
                    382:   {
                    383:     while(DOSSEMREQUEST((long far *) &readpending,-1L) == 0)
                    384:       {                                        /* While there is work to do */
                    385:        arrc = DOSREAD(t2fd,(char far *) t2buf,t2buflen,(int far *) &cbread);
                    386:                                        /* Do the read */
                    387:        DOSSEMCLEAR((long far *) &readdone);
                    388:                                        /* Signal read completed */
                    389:       }
                    390:     fprintf(stderr,"Thread 2: DOSSEMREQUEST failed\n");
                    391:                                        /* Print error message */
                    392:     DOSEXIT(1, 2);                           /* Die */
                    393:   }
                    394: 
                    395: 
                    396: void far               thread3()       /* Write thread */
                    397:   {
                    398:     while(DOSSEMREQUEST((long far *) &writepending,-1L) == 0)
                    399:       {                                        /* While there is work to do */
                    400:        awrc = DOSWRITE(t3fd,(char far *) t3buf,t3buflen,(int far *) &cbwrite);
                    401:                                        /* Do the write */
                    402:        DOSSEMCLEAR((long far *) &writedone);
                    403:                                        /* Signal write completed */
                    404:       }
                    405:     fprintf(stderr,"Thread 3: DOSSEMREQUEST failed\n");
                    406:                                        /* Print error message */
                    407:     DOSEXIT(1, 2);                           /* Die */
                    408:   }
                    409: 
                    410: 
                    411: void                   startread(fd,buffer,buflen)
                    412: int                    fd;             /* File handle */
                    413: char                   *buffer;        /* Buffer */
                    414: int                    buflen;         /* Buffer length */
                    415:   {
                    416:     if(pmode)                          /* If protected mode */
                    417:       {
                    418:        if(DOSSEMREQUEST((long far *) &readdone,-1L) != 0)
                    419:          {                             /* If we fail to get the semaphore */
                    420:            fprintf(stderr,"DOSSEMREQUEST failed\n");
                    421:                                        /* Error message */
                    422:            DOSEXIT(1, 2);                    /* Die */
                    423:          }
                    424:        t2fd = fd;                      /* Set parameters for read */
                    425:        t2buf = buffer;
                    426:        t2buflen = buflen;
                    427:        DOSSEMCLEAR((long far *) &readpending);
                    428:                                        /* Wake thread 2 for read */
                    429:        DOSSLEEP(0L);                   /* Yield the CPU */
                    430:       }
                    431:     else arrc = DOSREAD(fd,(char far *) buffer,buflen,(int far *) &cbread);
                    432:   }
                    433: 
                    434: 
                    435: int                    finishread()
                    436:   {
                    437:     if(pmode && DOSSEMWAIT((long far *) &readdone,-1L) != 0)
                    438:       {                                        /* If protected mode and wait fails */
                    439:        fprintf(stderr,"DOSSEMWAIT failed\n");
                    440:                                        /* Print error message */
                    441:        DOSEXIT(1, 2);                        /* Die */
                    442:       }
                    443:     return((arrc == 0)? cbread: -1);   /* Return number of bytes read */
                    444:   }
                    445: 
                    446: 
                    447: void                   startwrite(fd,buffer,buflen)
                    448: int                    fd;             /* File handle */
                    449: char                   *buffer;        /* Buffer */
                    450: int                    buflen;         /* Buffer length */
                    451:   {
                    452:     if(pmode)                          /* If protected mode */
                    453:       {
                    454:        if(DOSSEMREQUEST((long far *) &writedone,-1L) != 0)
                    455:          {                             /* If we fail to get the semaphore */
                    456:            fprintf(stderr,"DOSSEMREQUEST failed\n");
                    457:                                        /* Error message */
                    458:            DOSEXIT(1, 2);                    /* Die */
                    459:          }
                    460:        t3fd = fd;                      /* Set parameters for write */
                    461:        t3buf = buffer;
                    462:        t3buflen = buflen;
                    463:        DOSSEMCLEAR((long far *) &writepending);
                    464:                                        /* Wake thread 3 for read */
                    465:        DOSSLEEP(0L);                   /* Yield the CPU */
                    466:       }
                    467:     else awrc = DOSWRITE(fd,(char far *) buffer,buflen,(int far *) &cbwrite);
                    468:   }
                    469: 
                    470: 
                    471: int                    finishwrite()
                    472:   {
                    473:     if(pmode && DOSSEMWAIT((long far *) &writedone,-1L) != 0)
                    474:       {                                        /* If protected mode and wait fails */
                    475:        fprintf(stderr,"DOSSEMWAIT failed\n");
                    476:                                        /* Print error message */
                    477:        DOSEXIT(1, 2);                        /* Die */
                    478:       }
                    479:     return((awrc == 0)? cbwrite: -1);  /* Return number of bytes written */
                    480:   }
                    481: 
                    482: 
                    483: void                   write1nobuf(buffer,buflen)
                    484: char                   *buffer;        /* Buffer */
                    485: register int           buflen;         /* Buffer length */
                    486:   {
                    487:     int                        cb;             /* Count of bytes written */
                    488: 
                    489:     if(DOSWRITE(1,(char far *) buffer,buflen,(int far *) &cb) != 0 ||
                    490:       cb != buflen)                    /* If write fails */
                    491:       {
                    492:        fprintf(stderr,"write error %d\n",awrc);
                    493:                                        /* Print error message */
                    494:        DOSEXIT(1, 2);                        /* Die */
                    495:       }
                    496:   }
                    497: 
                    498: 
                    499: void                   write1buf(buffer,buflen)
                    500: char                   *buffer;        /* Buffer */
                    501: register int           buflen;         /* Buffer length */
                    502:   {
                    503:     register int       cb;             /* Byte count */
                    504: 
                    505:     while(buflen > 0)                  /* While bytes remain */
                    506:       {
                    507:        if(awrc != 0)                   /* If previous write failed */
                    508:          {
                    509:            fprintf(stderr,"write error %d\n",awrc);
                    510:                                        /* Print error message */
                    511:            DOSEXIT(1, 2);                    /* Die */
                    512:          }
                    513:        if((cb = ocnt[oi]) == 0)        /* If buffer full */
                    514:          {
                    515:            startwrite(1,obuf[oi],OUTBUFLEN);
                    516:                                        /* Write the buffer */
                    517:            ocnt[oi] = OUTBUFLEN;       /* Reset count and pointer */
                    518:            optr[oi] = obuf[oi];
                    519:            oi ^= 1;                    /* Switch buffers */
                    520:            cb = ocnt[oi];              /* Get space remaining */
                    521:          }
                    522:        if(cb > buflen) cb = buflen;    /* Get minimum */
                    523:        memcpy(optr[oi],buffer,cb);     /* Copy bytes to buffer */
                    524:        ocnt[oi] -= cb;                 /* Update buffer length and pointers */
                    525:        optr[oi] += cb;
                    526:        buflen -= cb;
                    527:        buffer += cb;
                    528:       }
                    529:   }
                    530: 
                    531: 
                    532: void                   flush1nobuf()
                    533:   {
                    534:   }
                    535: 
                    536: 
                    537: void                   flush1buf()
                    538:   {
                    539:     int                        cb;             /* Byte count */
                    540: 
                    541:     if((cb = OUTBUFLEN - ocnt[oi]) > 0)        /* If buffer not empty */
                    542:       {
                    543:        startwrite(1,obuf[oi],cb);      /* Start write */
                    544:        if(finishwrite() != cb)         /* If write failed */
                    545:          {
                    546:            fprintf(stderr,"write error %d\n",awrc);
                    547:                                        /* Print error message */
                    548:            DOSEXIT(1, 2);                    /* Die */
                    549:          }
                    550:       }
                    551:   }
                    552: 
                    553: 
                    554: int                    grepnull(cp,endbuf,name)
                    555: register char          *cp;            /* Buffer pointer */
                    556: char                   *endbuf;        /* End of buffer */
                    557: char                   *name;          /* File name */
                    558:   {
                    559:     return(0);                         /* Do nothing */
                    560:   }
                    561: 
                    562: 
                    563: int                    grepbuffer(startbuf,endbuf,name)
                    564: char                   *startbuf;      /* Start of buffer */
                    565: char                   *endbuf;        /* End of buffer */
                    566: char                   *name;          /* File name */
                    567:   {
                    568:     register char      *cp;            /* Buffer pointer */
                    569:     char               *lastmatch;     /* Last matching line */
                    570:     int                        linelen;        /* Line length */
                    571:     int                        namlen = 0;     /* Length of name */
                    572:     char               lnobuf[LNOLEN]; /* Line number buffer */
                    573:     char               nambuf[LINELEN];/* Name buffer */
                    574: 
                    575:     cp = startbuf;                     /* Initialize to start of buffer */
                    576:     lastmatch = cp;                    /* No previous match yet */
                    577:     while((cp = (*find)(cp,endbuf)) != NULL)
                    578:       {                                        /* While matches are found */
                    579:        if((flags & BEGLINE) && cp[-1] != '\n' && cp > startbuf)
                    580:          {                             /* If begin line conditions not met */
                    581:            ++cp;                       /* Skip first char of match */
                    582:            continue;                   /* Keep looking */
                    583:          }
                    584:        status = 0;                     /* Match found */
                    585:        if(flags & NAMEONLY)            /* If filename only wanted */
                    586:          {
                    587:            (*write1)(nambuf,sprintf(nambuf,"%s\r\n",name));
                    588:                                        /* Print the name */
                    589:            return(1);                  /* Punt remainder of buffer */
                    590:          }
                    591:        cp -= revfind(cp,'\n',cp - startbuf);
                    592:                                        /* Point at last linefeed */
                    593:        if(*cp == '\n') ++cp;           /* Point at start of line */
                    594:        if(flags & SHOWNAME)            /* If name wanted */
                    595:          {
                    596:            if(namlen == 0) namlen = sprintf(nambuf,"%s:",name);
                    597:                                        /* Format name if not done already */
                    598:            (*write1)(nambuf,namlen);   /* Show name */
                    599:          }
                    600:        if(flags & LINENOS)             /* If line number wanted */
                    601:          {
                    602:            lineno += countlines(lastmatch,cp);
                    603:                                        /* Count lines since last match */
                    604:            (*write1)(lnobuf,sprintf(lnobuf,"%d:",lineno));
                    605:                                        /* Print line number */
                    606:            lastmatch = cp;             /* New last match */
                    607:          }
                    608:        linelen = strncspn(cp,"\n",endbuf - cp) + 1;
                    609:                                        /* Calculate line length */
                    610:        (*write1)(cp,linelen);          /* Print the line */
                    611:        cp += linelen;                  /* Skip the line */
                    612:       }
                    613:     if(flags & LINENOS) lineno += countlines(lastmatch,endbuf);
                    614:                                        /* Count remaining lines in buffer */
                    615:     return(0);                         /* Keep searching */
                    616:   }
                    617: 
                    618: 
                    619: void                   showv(name,lastmatch,thismatch)
                    620: char                   *name;
                    621: register char          *lastmatch;
                    622: char                   *thismatch;
                    623:   {
                    624:     register int       linelen;
                    625:     int                        namlen = 0;     /* Length of name */
                    626:     char               lnobuf[LNOLEN]; /* Line number buffer */
                    627:     char               nambuf[LINELEN];/* Name buffer */
                    628: 
                    629:     if(flags & (SHOWNAME | LINENOS))
                    630:       {
                    631:        while(lastmatch < thismatch)
                    632:          {
                    633:            if(flags & SHOWNAME)        /* If name wanted */
                    634:              {
                    635:                if(namlen == 0) namlen = sprintf(nambuf,"%s:",name);
                    636:                                        /* Format name if not done already */
                    637:                (*write1)(nambuf,namlen);
                    638:                                        /* Write the name */
                    639:              }
                    640:            if(flags & LINENOS)
                    641:              {
                    642:                (*write1)(lnobuf,sprintf(lnobuf,"%d:",lineno++));
                    643:              }
                    644:            linelen = strncspn(lastmatch,"\n",thismatch - lastmatch) + 1;
                    645:            (*write1)(lastmatch,linelen);
                    646:            lastmatch += linelen;
                    647:          }
                    648:       }
                    649:     else (*write1)(lastmatch,thismatch - lastmatch);
                    650:   }
                    651: 
                    652: 
                    653: int                    grepvbuffer(startbuf,endbuf,name)
                    654: char                   *startbuf;      /* Start of buffer */
                    655: char                   *endbuf;        /* End of buffer */
                    656: char                   *name;          /* File name */
                    657:   {
                    658:     register char      *cp;            /* Buffer pointer */
                    659:     register char      *lastmatch;     /* Pointer to line after last match */
                    660: 
                    661:     cp = startbuf;                     /* Initialize to start of buffer */
                    662:     lastmatch = cp;
                    663:     while((cp = (*find)(cp,endbuf)) != NULL)
                    664:       {
                    665:        if((flags & BEGLINE) && cp[-1] != '\n' && cp > startbuf)
                    666:          {                             /* If begin line conditions not met */
                    667:            ++cp;                       /* Skip first char of match */
                    668:            continue;                   /* Keep looking */
                    669:          }
                    670:        status = 1;                     /* Match found */
                    671:        if(flags & NAMEONLY) return(1); /* Skip rest of file if NAMEONLY */
                    672:        cp -= revfind(cp,'\n',cp - startbuf);
                    673:                                        /* Point at last linefeed */
                    674:        if(*cp == '\n') ++cp;           /* Point at start of line */
                    675:        showv(name,lastmatch,cp);       /* Show from last match to this */
                    676:        cp += strncspn(cp,"\n",endbuf - cp) + 1;
                    677:                                        /* Skip over line with match */
                    678:        lastmatch = cp;                 /* New "last" match */
                    679:        ++lineno;                       /* Increment line count */
                    680:       }
                    681:     if(!(flags & NAMEONLY)) showv(name,lastmatch,endbuf);
                    682:                                        /* Show buffer tail if not NAMEONLY */
                    683:     return(0);                         /* Keep searching file */
                    684:   }
                    685: 
                    686: 
                    687: void                   qgrep(name,fd)
                    688: char                   *name;          /* File name */
                    689: int                    fd;             /* File descriptor */
                    690:   {
                    691:     register int       cb;             /* Byte count */
                    692:     register char      *cp;            /* Buffer pointer */
                    693:     char               *endbuf;        /* End of buffer */
                    694:     int                        taillen;        /* Length of buffer tail */
                    695:     int                        bufi;           /* Buffer index */
                    696:     char               line[LINELEN];  /* Line buffer */
                    697: 
                    698:     lineno = 1;                                /* File starts on line 1 */
                    699:     taillen = 0;                       /* No buffer tail yet */
                    700:     bufi = 0;                          /* Initialize buffer index */
                    701:     cp = bufptr[0];                    /* Initialize to start of buffer */
                    702:     finishread();                      /* Make sure no I/O activity */
                    703:     arrc = DOSREAD(fd,(char far *) cp,FILBUFLEN,(int far *) &cbread);
                    704:                                        /* Do first read synchronously */
                    705:     while((cb = finishread()) + taillen > 0)
                    706:       {                                        /* While search incomplete */
                    707:        if(cb == 0)                     /* If buffer tail is all that's left */
                    708:          {
                    709:            taillen = 0;                /* Set tail length to zero */
                    710:            *cp++ = '\r';               /* Add end of line sequence */
                    711:            *cp++ = '\n';
                    712:            endbuf = cp;                /* Note end of buffer */
                    713:          }
                    714:        else                            /* Else start next read */
                    715:          {
                    716:            taillen = revfind(cp + cb - 1,'\n',cb);
                    717:                                        /* Find length of partial line */
                    718:            endbuf = cp + cb - taillen; /* Get pointer to end of buffer */
                    719:            cp = bufptr[bufi ^ 1];      /* Pointer to other buffer */
                    720:            memcpy(cp,endbuf,taillen);  /* Copy tail to head of other buffer */
                    721:            cp += taillen;              /* Skip over tail */
                    722:            startread(fd,cp,(FILBUFLEN - taillen) & (~0 << LG2SECLEN));
                    723:                                        /* Start next read */
                    724:          }
                    725:        if((*grep)(bufptr[bufi],endbuf,name)) return;
                    726:                                        /* Done if NAMEONLY and match found */
                    727:        bufi ^= 1;                      /* Switch buffers */
                    728:       }
                    729:     if((flags & (NAMEONLY | INVERT)) == (NAMEONLY | INVERT))
                    730:       (*write1)(line,sprintf(line,"%s\r\n",name));
                    731:                                        /* Write name if -lv */
                    732:   }
                    733: 
                    734: 
                    735: void                   usage(verbose)
                    736: int                    verbose;        /* Verbose message flag */
                    737:   {
                    738:     static char                *opts[] =
                    739:       {
                    740:        "-? - print this message",
                    741:        "-B - match pattern if at beginning of line",
                    742:        "-E - match pattern if at end of line",
                    743:        "-l - print only file name if file contains match",
                    744:        "-n - print line number before each matching line",
                    745:        "-v - print only lines not containing a match",
                    746:        "-x - print lines that match exactly (-BE)",
                    747:        "-y - treat upper and lower case as equivalent",
                    748:        "-e - treat next argument as the search string",
                    749:        "-f - read search strings from file named by next argument",
                    750:        "-i - read file list from file named by next argument",
                    751:        0
                    752:       };
                    753:     register char      **opt = opts;   /* Option list */
                    754: 
                    755:     fprintf(stderr,"usage: CPGREP [-?BElnvxy][-e][-f <file>][-i <file>][<strings>][<files>]\n");
                    756:     if(verbose)                                /* If verbose message wanted */
                    757:       {
                    758:        while(*opt != 0) fprintf(stderr,"%s\n",*opt++);
                    759:                                        /* Print option list */
                    760:       }
                    761:     DOSEXIT(1, 2);                           /* Error exit */
                    762:   }
                    763: 
                    764: 
                    765: void                   main(argc,argv)
                    766: int                    argc;
                    767: char                   **argv;
                    768:   {
                    769:     register char      *cp;
                    770:     int                        fd;
                    771:     FILE               *fi;
                    772:     char               filnam[FILNAMLEN];
                    773:     int                        i;
                    774:     char               *inpfile = NULL;
                    775:     int                        j;
                    776:     char               *seplist = " \t";
                    777:     int                        strcnt;
                    778:     char               *strfile = NULL;
                    779:     long               start;          /* Start time */
                    780:     int                        (*add)();
                    781:     int                        t2stk[STKLEN];  /* Read thread stack */
                    782:     int                        t3stk[STKLEN];  /* Write thread stack */
                    783:     long               time();         /* Time and date in seconds */
                    784: 
                    785:     DOSGETMACHINEMODE((char far *) &pmode);
                    786:     flags = 0;
                    787:     for(i = 1; i < argc && argv[i][0] == '-'; ++i)
                    788:       {
                    789:        switch(argv[i][1])
                    790:          {
                    791:            case 'f':
                    792:            case 'i':
                    793:              if(i == argc - 1)
                    794:                {
                    795:                  fprintf(stderr,"File name missing after -%c\n",argv[i][1]);
                    796:                  DOSEXIT(1, 2);
                    797:                }
                    798:              if(argv[i++][1] == 'i') inpfile = argv[i];
                    799:              else strfile = argv[i];
                    800:              break;
                    801: 
                    802:            case '?':
                    803:            case 'B':
                    804:            case 'E':
                    805:            case 'N':
                    806:            case 'S':
                    807:            case 'd':
                    808:            case 'l':
                    809:            case 'n':
                    810:            case 't':
                    811:            case 'v':
                    812:            case 'x':
                    813:            case 'y':
                    814:              for(cp = &argv[i][1]; *cp != '\0'; ++cp)
                    815:                {
                    816:                  switch(*cp)
                    817:                    {
                    818:                      case '?':
                    819:                        usage(1);       /* Verbose usage message */
                    820: 
                    821:                      case 'B':
                    822:                        flags |= BEGLINE;
                    823:                        break;
                    824: 
                    825:                      case 'E':
                    826:                        flags |= ENDLINE;
                    827:                        break;
                    828: 
                    829:                      case 'N':
                    830:                        grep = grepnull;
                    831:                        break;
                    832: 
                    833:                      case 'S':
                    834:                        pmode = 0;      /* Force synchronous I/O */
                    835:                        break;
                    836: 
                    837:                      case 'd':
                    838:                        flags |= DEBUG;
                    839:                        break;
                    840: 
                    841:                      case 'l':
                    842:                        flags |= NAMEONLY;
                    843:                        break;
                    844: 
                    845:                      case 'n':
                    846:                        flags |= LINENOS;
                    847:                        break;
                    848: 
                    849:                      case 't':
                    850:                        flags |= TIMER;
                    851:                        break;
                    852: 
                    853:                      case 'v':
                    854:                        status = 0;     /* Assume success */
                    855:                        flags |= INVERT;
                    856:                        grep = grepvbuffer;
                    857:                        break;
                    858: 
                    859:                      case 'x':
                    860:                        flags |= BEGLINE | ENDLINE;
                    861:                        break;
                    862: 
                    863:                      case 'y':
                    864:                        casesen = 0;
                    865:                        break;
                    866: 
                    867:                      default:
                    868:                        fprintf(stderr,"-%c ignored\n",*cp);
                    869:                        break;
                    870:                    }
                    871:                }
                    872:              break;
                    873: 
                    874:            case 'e':
                    875:              if(strfile == NULL)
                    876:                {
                    877:                  ++i;
                    878:                  seplist = "";         /* Allow anything in string */
                    879:                  goto endfor0;
                    880:                }
                    881:              /* Drop through to "default" */
                    882: 
                    883:            default:
                    884:              fprintf(stderr,"%s ignored\n",argv[i]);
                    885:              break;
                    886:          }
                    887:       }
                    888:     endfor0:
                    889: 
                    890:     if(i == argc && strfile == NULL) usage(0);
                    891:                                        /* Simple usage message if arg error */
                    892:     if(flags & TIMER) start = time(NULL);
                    893:                                        /* Get start time if timer on */
                    894:     if(pmode)                          /* Initialize semaphores and threads */
                    895:       {
                    896:        DOSSEMCLEAR((long far *) &readdone);
                    897:        DOSSEMCLEAR((long far *) &writedone);
                    898:        DOSSEMSET((long far *) &readpending);
                    899:        DOSSEMSET((long far *) &writepending);
                    900:        if(DOSCREATETHREAD(thread2,(int far *) &fd,
                    901:          (int far *) t2stk + STKLEN) != 0 ||
                    902:          DOSCREATETHREAD(thread3,(int far *) &fd,
                    903:          (int far *) t3stk + STKLEN) != 0)
                    904:          {                             /* If thread creation fails */
                    905:            fprintf(stderr,"Failed to create child threads\n");
                    906:                                        /* Print error message */
                    907:            DOSEXIT(1, 2);                    /* Die */
                    908:          }
                    909:       }
                    910:     setmode(fileno(stdout),O_BINARY);
                    911:     add = addplain;                    /* Assume plain string adds */
                    912:     if(strfile != NULL)                        /* If strings from file */
                    913:       {
                    914:        if(!(flags & BEGLINE)) add = addfancy;
                    915:                                        /* Try to add intelligently */
                    916:        if((fd = open(strfile,0)) == -1)
                    917:          {                             /* If open fails */
                    918:            fprintf(stderr,"Cannot read strings from %s\n",strfile);
                    919:            DOSEXIT(1, 2);                    /* Print message and die */
                    920:          }
                    921:        for(cp = filbuf, j = 0; (j = read(fd,cp,FILBUFLEN*2 - j)) > 0; cp += j);
                    922:                                        /* Read strings file into buffer */
                    923:        j = cp - filbuf;                /* Get total length of buffer */
                    924:        close(fd);                      /* Close strings file */
                    925:        filbuf[j] = '\0';               /* Null-terminate the buffer */
                    926:        cp = filbuf;                    /* Set pointer to string list */
                    927:        seplist = "\r\n";               /* Only '\r' and '\n' are separators */
                    928:       }
                    929:     else                               /* Else strings on command line */
                    930:       {
                    931:        cp = argv[i++];                 /* Set pointer to strings */
                    932:        j = strlen(cp);                 /* Get length of strings */
                    933:       }
                    934:     if((strcnt = (*add)(cp,j,seplist)) == 0)
                    935:       {                                        /* If no strings */
                    936:        fprintf(stderr,"No search strings\n");
                    937:        DOSEXIT(1, 2);                        /* Print error message and die */
                    938:       }
                    939: 
                    940:     /*
                    941:      *  Check type of handle for std. out.
                    942:      */
                    943:     if(DOSQHANDTYPE(fileno(stdout),(int far *) &j,(int far *) &fd) != 0)
                    944:       {                                        /* If error */
                    945:        fprintf(stderr,"Standard output bad handle\n");
                    946:                                        /* Print error message */
                    947:        DOSEXIT(1, 2);                        /* Die */
                    948:       }
                    949:     if(j != 0 && (fd & ISCOT))         /* If handle is console output */
                    950:       {
                    951:        write1 = write1nobuf;           /* Use unbuffered output */
                    952:        flush1 = flush1nobuf;
                    953:       }
                    954: 
                    955:     if(strcnt > 1)                     /* If more than one string */
                    956:       {
                    957:        if(flags & DEBUG)               /* Print debug info maybe */
                    958:          {
                    959:            fprintf(stderr,"Here are the strings:\n");
                    960:            dumpstrings();
                    961:          }
                    962:       }
                    963:     else if(casesen) find = findone;   /* Else use findone() */
                    964:     if(inpfile != NULL)                        /* If file list from file */
                    965:       {
                    966:        flags |= SHOWNAME;              /* Always show name of file */
                    967:        if((fi = fopen(inpfile,"r")) == NULL)
                    968:          {                             /* If open fails */
                    969:            fprintf(stderr,"Cannot read file list from %s\r\n",inpfile);
                    970:                                        /* Error message */
                    971:            DOSEXIT(1, 2);                    /* Error exit */
                    972:          }
                    973:        while(fgets(filnam,FILNAMLEN,fi) != NULL)
                    974:          {                             /* While there are names */
                    975:            filnam[strcspn(filnam,"\r\n")] = '\0';
                    976:                                        /* Null-terminate the name */
                    977:            if((fd = openfile(filnam)) == -1) continue;
                    978:                                        /* Skip file if it cannot be opened */
                    979:            qgrep(filnam,fd);           /* Do the work */
                    980:            close(fd);                  /* Close the file */
                    981:          }
                    982:        fclose(fi);                     /* Close the list file */
                    983:       }
                    984:     else if(i == argc)
                    985:       {
                    986:        flags &= ~(NAMEONLY | SHOWNAME);
                    987:        setmode(fileno(stdin),O_BINARY);
                    988:        qgrep(NULL,fileno(stdin));
                    989:       }
                    990:     if(argc > i + 1) flags |= SHOWNAME;
                    991:     for(; i < argc; ++i)
                    992:       {
                    993:        if((fd = openfile(argv[i])) == -1) continue;
                    994:        qgrep(argv[i],fd);
                    995:        close(fd);
                    996:       }
                    997:     (*flush1)();
                    998:     if(flags & TIMER) fprintf(stderr,"%ld seconds\n",time(NULL) - start);
                    999:                                        /* Print elapsed time if timer on */
                   1000:     DOSEXIT(1, status);
                   1001:   }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.