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

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

unix.superglobalmegacorp.com

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