|
|
1.1 ! root 1: /* look.c - look for matching lines of text in a sorted file. ! 2: */ ! 3: #include <stdio.h> ! 4: #include <ctype.h> ! 5: ! 6: #define TRUE 1 ! 7: #define FALSE 0 ! 8: #define EQ 1 ! 9: #define LESS 0 ! 10: #define GREATER 2 ! 11: #define TAB ' ' ! 12: #define BSIZ 512 ! 13: ! 14: extern long ftell() ; ! 15: ! 16: /* Globals ! 17: */ ! 18: ! 19: int d_mode, f_mode ; ! 20: long top, bottom ; ! 21: long fsiz ; ! 22: FILE *fildes ; ! 23: char stbuf[BSIZ], rbuf[BSIZ] ; ! 24: char *rbufp ; ! 25: ! 26: /* getx - Get the nex character from the character buffer. ! 27: * If the buffer is empty get the next block. ! 28: */ ! 29: ! 30: /* getx() ! 31: * { ! 32: * if (rbufp < &rbuf[BSIZ]) ! 33: * return(*rbufp++) ; ! 34: * else { ! 35: * gnb() ; ! 36: * return(getx()) ; ! 37: * } ! 38: * } ! 39: */ ! 40: ! 41: #ifdef FIXED /* Bug in 8086 compiler */ ! 42: #define getx() ((rbuf < &rbuf[BSIZ]) ? *rbufp++ : (gnb(), *rbufp++)) ! 43: #else ! 44: getx() ! 45: { ! 46: if (rbufp >= &rbuf[BSIZ]) ! 47: gnb(); ! 48: return (*rbufp++); ! 49: } ! 50: #endif ! 51: ! 52: /* order - Order relation for characters. Returns GREATER, LESS or EQ. ! 53: */ ! 54: ! 55: /* order(a, b) ! 56: * { ! 57: * if (a > b) ! 58: * return(GREATER) ; ! 59: * else if (a < b) ! 60: * return(LESS) ; ! 61: * return(EQ) ; ! 62: * } ! 63: */ ! 64: ! 65: #define order(a, b) ((a > b) ? GREATER : ((a < b) ? LESS : EQ)) ! 66: ! 67: /* isdict - Test for a dictionary character. From the class : ! 68: * [a-zA-Z0-9 ]. ! 69: */ ! 70: ! 71: /* isdict(ch) ! 72: * { ! 73: * if (isalnum(ch) || (ch == ' ')) ! 74: * return(1) ; ! 75: * return(0) ; ! 76: * } ! 77: */ ! 78: ! 79: #define isdict(ch) ((isalnum(ch) || (ch == ' ')) ? 1 : 0) ! 80: ! 81: /* main - Get args, set flags and get the ball rolling. ! 82: */ ! 83: ! 84: main(argc, argv) ! 85: register char *argv[] ; ! 86: { ! 87: ++argv ; ! 88: switch (argc) { ! 89: ! 90: case 4 : ! 91: case 3 : ! 92: if (setop(argv[0])) { ! 93: ++argv ; ! 94: --argc ; ! 95: } else ! 96: if (argc == 4) { ! 97: form() ; ! 98: break ; ! 99: } ! 100: case 2 : ! 101: if (argc == 3) ! 102: gfile(argv[1]) ; ! 103: else ! 104: gfile(NULL) ; ! 105: if (gstring(argv[0])) { ! 106: look() ; ! 107: exit(0) ; ! 108: break ; ! 109: } ! 110: default : ! 111: form() ; ! 112: } ! 113: exit(1) ; ! 114: } ! 115: ! 116: /* setop - set option flags d_mode and f_mode. d_mode marks an occurance ! 117: * of -d[f] or -[f]d and f_mode marks an occurance of -f[d] or ! 118: * -[d]f. ! 119: */ ! 120: ! 121: setop(fp) ! 122: register char *fp ; ! 123: { ! 124: register int i ; ! 125: ! 126: d_mode = FALSE ; ! 127: f_mode = FALSE ; ! 128: ! 129: if (*fp++ != '-') ! 130: return(0) ; ! 131: else { ! 132: for (i = 0; i < 2; i++) { ! 133: switch (*fp++) { ! 134: ! 135: case 'd' : ! 136: d_mode = TRUE ; ! 137: break ; ! 138: case 'f' : ! 139: f_mode = TRUE ; ! 140: break ; ! 141: case '\0' : ! 142: --fp ; ! 143: return(1) ; ! 144: default : ! 145: return(0) ; ! 146: } ! 147: } ! 148: if (*fp != '\0') ! 149: return(0) ; ! 150: return(1) ; ! 151: } ! 152: } ! 153: ! 154: /* gstring - gets the match string <string> and places it in the ! 155: * stbuf buffer after conforming it to the d_mode and ! 156: * f_mode options (That will make the compare routine ! 157: * faster). Returns the number of characters in stbuf. ! 158: */ ! 159: ! 160: gstring(fp) ! 161: register char *fp ; ! 162: { ! 163: register int nc ; ! 164: register char *st ; ! 165: ! 166: nc = 0 ; ! 167: st = stbuf ; ! 168: while ((nc++ < BSIZ) && (*fp != '\0')) { ! 169: if (d_mode && !isdict(*fp)) { ! 170: fp++ ; ! 171: nc-- ; ! 172: continue ; ! 173: } ! 174: if (f_mode && islower(*fp)) { ! 175: *st++ = toupper(*fp++) ; ! 176: continue ; ! 177: } ! 178: *st++ = *fp++ ; ! 179: } ! 180: if (nc >= BSIZ) ! 181: return(0) ; ! 182: return(nc) ; ! 183: } ! 184: ! 185: ! 186: /* gfile - Gets the specified file and opens it for reading. ! 187: * If no file is specified /usr/dict/words is opened. ! 188: */ ! 189: ! 190: gfile(fp) ! 191: register char *fp ; ! 192: { ! 193: register char *file ; ! 194: ! 195: if (fp == NULL) { ! 196: file = "/usr/dict/words" ; ! 197: d_mode = TRUE ; ! 198: f_mode = TRUE ; ! 199: } else ! 200: file = fp ; ! 201: ! 202: if ((fildes = fopen(file, "r")) == NULL) { ! 203: aww("look : Cannot open file") ; ! 204: exit(1) ; ! 205: } ! 206: ! 207: bottom = 0 ; ! 208: if (fseek(fildes, 0L, 2) == -1) { ! 209: aww("look : Cannot seek on file") ; ! 210: exit(1) ; ! 211: } ! 212: ! 213: top = ftell(fildes) ; ! 214: top -= 2 ; ! 215: fsiz = top ; ! 216: ! 217: ! 218: return(1) ; ! 219: } ! 220: ! 221: /* aww - Error condition. Prints out the passed string. ! 222: */ ! 223: ! 224: aww(sp) ! 225: char *sp ; ! 226: { ! 227: fprintf(stderr, "%s\n", sp) ; ! 228: } ! 229: ! 230: /* form - Prints out a Usage message. ! 231: */ ! 232: ! 233: form() ! 234: { ! 235: fprintf(stderr, "Usage : look [-df] string [file]\n") ; ! 236: } ! 237: ! 238: /* look - Binary search looking for a string match. If a match ! 239: * is found (the EQ case) all the strings that match ! 240: * are printed and then we quit else the window is ! 241: * decreased and the test goes on. ! 242: */ ! 243: ! 244: look() ! 245: { ! 246: register int nmove ; ! 247: long mid1, mid2 ; ! 248: long gll() ; ! 249: long gteol() ; ! 250: ! 251: while (top != bottom) { ! 252: mid1 = (top - bottom)/2 + bottom ; ! 253: mid2 = gll(mid1) ; ! 254: nmove = comstr() ; ! 255: switch (nmove) { ! 256: ! 257: case EQ : ! 258: wstr(mid2) ; ! 259: return(1) ; ! 260: case GREATER : ! 261: bottom = gteol(mid1) ; ! 262: break ; ! 263: case LESS : ! 264: top = mid2 - 2 ; ! 265: break ; ! 266: } ! 267: if (top < bottom) ! 268: top = bottom ; ! 269: } ! 270: } ! 271: ! 272: ! 273: /* wstr - We found a string that matches but we are not sure that ! 274: * this is the only occurance of a matched string and hence ! 275: * we must back up until we find a non match and print ! 276: * forward till we find a non match in the other direction. ! 277: */ ! 278: ! 279: wstr(seek) ! 280: long seek ; ! 281: { ! 282: long temp1, temp2 ; ! 283: long gll() ; ! 284: ! 285: if (seek != 0) { ! 286: temp2 = seek ; ! 287: temp1 = gll(seek - 2) ; ! 288: while (comstr() == EQ) { ! 289: temp2 = temp1 ; ! 290: if (temp1 == 0) ! 291: break ; ! 292: else ! 293: temp1 = gll(temp1 - 2) ; ! 294: } ! 295: } else ! 296: temp2 = 0 ; ! 297: fseek(fildes, temp2, 0) ; ! 298: while (ftell(fildes) <= seek) { ! 299: fgets(rbuf, BSIZ, fildes) ; ! 300: fputs(rbuf, stdout) ; ! 301: } ! 302: fgets(rbuf, BSIZ, fildes) ; ! 303: rbufp = rbuf ; ! 304: while (comstr() == EQ) { ! 305: fputs(rbuf, stdout) ; ! 306: fgets(rbuf, BSIZ, fildes) ; ! 307: rbufp = rbuf ; ! 308: } ! 309: return(1) ; ! 310: } ! 311: ! 312: /* comstr - Compare the base string to the input line. ! 313: * Returns a stat telling what the difference between the ! 314: * two strings is. EQ is equal, GREATER implies the base string ! 315: * is greater then the input string and LESS is vice versa. ! 316: */ ! 317: ! 318: comstr() ! 319: { ! 320: register int state ; ! 321: register int ch ; ! 322: register char *sp ; ! 323: ! 324: sp = stbuf ; ! 325: while (*sp != '\0') { ! 326: ch = getx() ; ! 327: if (ch == '\n') ! 328: return(GREATER) ; ! 329: if (d_mode && !isdict(ch)) { ! 330: continue ; ! 331: } ! 332: if (f_mode && islower(ch)) ! 333: ch = toupper(ch) ; ! 334: if ((state = order(*sp, ch)) != EQ) { ! 335: return(state) ; ! 336: } ! 337: ++sp ; ! 338: } ! 339: return(EQ) ; ! 340: } ! 341: ! 342: /* gll - Get last line. Using the seek variable, returns a pointer to ! 343: * the beginning of the last line of text. If neccesary ! 344: * gll will wind back seek a block at a time looking for ! 345: * the last line. ! 346: */ ! 347: ! 348: long ! 349: gll(seek) ! 350: long seek ; ! 351: { ! 352: register char *cp ; ! 353: register int tmp ; ! 354: ! 355: if (seek == 0) { ! 356: rbufp = rbuf ; ! 357: return(0) ; ! 358: } ! 359: ! 360: if (seek < BSIZ) { ! 361: cp = &rbuf[(int) seek] ; ! 362: seek = 0 ; ! 363: fseek(fildes, 0L, 0) ; ! 364: } else { ! 365: cp = &rbuf[BSIZ - 1] ; ! 366: seek -= BSIZ ; ! 367: fseek(fildes, seek, 0) ; ! 368: } ! 369: fread(rbuf, sizeof(*cp), BSIZ, fildes) ; ! 370: ! 371: while (cp >= rbuf) { ! 372: if (*cp == '\n') ! 373: break ; ! 374: --cp ; ! 375: } ! 376: ! 377: if (*cp == '\n') { ! 378: rbufp = ++cp ; ! 379: tmp = cp - rbuf ; ! 380: seek += (long) tmp ; ! 381: if (seek > fsiz) ! 382: return(-1) ; ! 383: fseek(fildes, seek, 0) ; ! 384: fread(rbuf, sizeof(*rbufp), BSIZ, fildes) ; ! 385: rbufp = rbuf ; ! 386: return(seek) ; ! 387: } else ! 388: return(gll(seek)) ; ! 389: } ! 390: ! 391: /* gnb - Get the next block from the file and adjust the ! 392: * character buffer pointer. ! 393: */ ! 394: ! 395: gnb() ! 396: { ! 397: fseek(fildes, 512L, 1) ; ! 398: fread(rbuf, sizeof(*rbufp), BSIZ, fildes) ; ! 399: rbufp = rbuf ; ! 400: return(1) ; ! 401: } ! 402: ! 403: /* gteol - Go to end of line. Returns the seek adress of the end of line. ! 404: */ ! 405: ! 406: long ! 407: gteol(seek) ! 408: long seek ; ! 409: { ! 410: if (seek >= fsiz) ! 411: return(fsiz) ; ! 412: fseek(fildes, seek, 0) ; ! 413: while (fgetc(fildes) != '\n') ! 414: ; ! 415: return(ftell(fildes)) ; ! 416: } ! 417:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.