00001
00002
00003 # ifndef lint
00004 static char rcsid[] = "$Header: /opt/proj/minix/cvsroot/src/commands/yap/getline.c,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $";
00005 # endif
00006
00007 # define _GETLINE_
00008
00009 # include <errno.h>
00010 # include "in_all.h"
00011 # include "getline.h"
00012 # include "options.h"
00013 # include "process.h"
00014 # include "term.h"
00015 # include "main.h"
00016 # include "display.h"
00017 # include "output.h"
00018 # include "assert.h"
00019
00020 extern int errno;
00021
00022 # define BLOCKSIZE 2048
00023 # define CHUNK 50
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 struct block {
00037 int b_flags;
00038 # define DUMPED 01
00039 # define PARTLY 02
00040 int b_next;
00041 long b_end;
00042 char * b_info;
00043 int * b_offs;
00044 long b_foff;
00045 };
00046
00047 static struct block * blocklist,
00048 * maxblocklist,
00049 * topblocklist;
00050 static int b_head,
00051 b_tail;
00052 static int tfdes, ifdes;
00053 static long lastreadline;
00054 static int ENDseen;
00055
00056 STATIC VOID readblock();
00057 STATIC VOID nextblock();
00058 STATIC char *re_alloc();
00059
00060 STATIC struct block *
00061 new_block()
00062 {
00063 register struct block *pblock = maxblocklist - 1;
00064
00065 if (!maxblocklist || !(pblock->b_flags & PARTLY)) {
00066
00067
00068
00069
00070 register int siz;
00071
00072 pblock = blocklist;
00073 if (maxblocklist == topblocklist) {
00074
00075
00076
00077 siz = topblocklist - pblock;
00078 blocklist = pblock = (struct block *)
00079 re_alloc((char *) pblock,
00080 (unsigned) (siz * sizeof(*pblock)),
00081 (unsigned) ((siz + CHUNK) * sizeof(*pblock)));
00082 pblock += siz;
00083 topblocklist = pblock + CHUNK;
00084 maxblocklist = pblock;
00085 for (; pblock < topblocklist; pblock++) {
00086 pblock->b_end = 0;
00087 pblock->b_info = 0;
00088 pblock->b_flags = 0;
00089 }
00090 if (!siz) {
00091
00092
00093
00094 maxblocklist++;
00095 }
00096 }
00097 pblock = maxblocklist++;
00098 }
00099 nextblock(pblock);
00100 return pblock;
00101 }
00102
00103
00104
00105
00106
00107
00108
00109 STATIC struct block *
00110 getblock(n, disable_interrupt) register long n; {
00111 register struct block * pblock;
00112
00113 if (stdf < 0) {
00114
00115
00116
00117 return 0;
00118 }
00119 pblock = maxblocklist - 1;
00120 if (n < lastreadline ||
00121 (n == lastreadline && !(pblock->b_flags & PARTLY))) {
00122
00123
00124
00125
00126
00127 register struct block *min, *mid;
00128
00129 min = blocklist + 1;
00130 do {
00131 mid = min + (pblock - min) / 2;
00132 if (n > mid->b_end) {
00133 min = mid + 1;
00134 }
00135 else pblock = mid;
00136 } while (min < pblock);
00137
00138 if (!pblock->b_info) readblock(pblock);
00139 return pblock;
00140 }
00141
00142
00143
00144
00145 for (;;) {
00146 if (interrupt && !disable_interrupt) return 0;
00147 pblock = new_block();
00148 if (pblock->b_end >= n) {
00149 return pblock;
00150 }
00151 if (pblock->b_flags & PARTLY) {
00152
00153
00154
00155
00156 return 0;
00157 }
00158 }
00159
00160 }
00161
00162 char *
00163 getline(n, disable_interrupt) long n; {
00164 register struct block *pblock;
00165
00166 if (!(pblock = getblock(n, disable_interrupt))) {
00167 return (char *) 0;
00168 }
00169 return pblock->b_info + pblock->b_offs[n - ((pblock-1)->b_end + 1)];
00170 }
00171
00172
00173
00174
00175
00176 long
00177 to_lastline() {
00178
00179 for (;;) {
00180 if (!getline(lastreadline + 1, 0)) {
00181
00182
00183
00184
00185
00186 if (interrupt) return -1L;
00187 return lastreadline;
00188 }
00189 }
00190
00191 }
00192
00193 #if MAXNBLOCKS
00194 int nblocks;
00195 #endif
00196
00197
00198
00199
00200
00201
00202 char *
00203 alloc(size, isblock) unsigned size; {
00204
00205 register char *pmem;
00206 register struct block *pblock, *bllist;
00207 char *malloc();
00208 long lseek();
00209 register long i;
00210
00211 bllist = blocklist;
00212 while (
00213 #if MAXNBLOCKS
00214 (isblock && nblocks >= MAXNBLOCKS) ||
00215 #endif
00216 !(pmem = malloc(size))
00217 ) {
00218 if (b_tail == 0) {
00219
00220
00221
00222 panic("No core");
00223 }
00224 #if MAXNBLOCKS
00225 nblocks--;
00226 #endif
00227 pblock = bllist + b_tail;
00228 b_tail = pblock->b_next;
00229 if (!nopipe && !(pblock->b_flags & DUMPED)) {
00230
00231
00232
00233 if (!tfdes) {
00234
00235
00236
00237 tfdes = opentemp(0);
00238 ifdes = opentemp(1);
00239 }
00240 pblock->b_flags |= DUMPED;
00241
00242
00243
00244 i = (pblock-1)->b_end * sizeof(int);
00245 (VOID) lseek(tfdes,
00246 ((long) BLOCKSIZE * (pblock - bllist)), 0);
00247 if (write(tfdes, pblock->b_info, BLOCKSIZE)
00248 != BLOCKSIZE) {
00249 panic("write failed");
00250 }
00251
00252
00253
00254 (VOID) lseek(ifdes, i, 0);
00255 i = pblock->b_end * sizeof(int) - i;
00256 if (write(ifdes, (char *) pblock->b_offs, (int) i)
00257 != (int) i) {
00258 panic("Write failed");
00259 }
00260 }
00261
00262
00263
00264
00265 free((char *) pblock->b_offs);
00266 free(pblock->b_info);
00267 pblock->b_info = (char *) 0;
00268 }
00269 #if MAXNBLOCKS
00270 if (isblock) nblocks++;
00271 #endif
00272 return pmem;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282 STATIC char *
00283 re_alloc(ptr,oldsize, newsize)
00284 char *ptr; unsigned oldsize; unsigned newsize; {
00285 register char *pmem;
00286 register char *c1, *c2;
00287
00288
00289
00290
00291
00292
00293
00294 pmem = alloc(newsize, 0);
00295 if (oldsize) {
00296
00297
00298
00299 c1 = pmem;
00300 c2 = ptr;
00301 if (newsize > oldsize) {
00302 newsize = oldsize;
00303 }
00304 while (newsize--) {
00305 *c1++ = *c2++;
00306 }
00307 free(ptr);
00308 }
00309 return pmem;
00310 }
00311
00312
00313
00314
00315
00316
00317 STATIC VOID
00318 addtolist(pblock) register struct block *pblock; {
00319 register struct block *bllist = blocklist;
00320
00321 pblock->b_next = 0;
00322 (bllist + b_head)->b_next = pblock - bllist;
00323 b_head = pblock - bllist;
00324 if (!b_tail) {
00325
00326
00327
00328 b_tail = b_head;
00329 }
00330 }
00331
00332 static char *saved;
00333 static long filldegree;
00334
00335
00336
00337
00338
00339 STATIC VOID
00340 nextblock(pblock) register struct block *pblock; {
00341 register char *c,
00342 *c1;
00343 register int *poff;
00344 register int cnt;
00345 register unsigned siz;
00346 static unsigned savedsiz;
00347 static int *savedpoff;
00348 static char *savedc1;
00349
00350 if (pblock->b_flags & PARTLY) {
00351
00352
00353
00354
00355 poff = savedpoff;
00356 siz = savedsiz;
00357 pblock->b_flags = 0;
00358 c1 = savedc1;
00359 if (c1 == pblock->b_info || *(c1 - 1)) {
00360
00361
00362
00363
00364
00365 poff--;
00366 --lastreadline;
00367 }
00368 }
00369 else {
00370 if (nopipe) pblock->b_foff = lseek(stdf, 0L, 1);
00371 if (saved) {
00372
00373
00374
00375 pblock->b_info = saved;
00376 if (nopipe) pblock->b_foff -= savedc1 - saved;
00377 c1 = savedc1;
00378 saved = 0;
00379 }
00380 else {
00381 pblock->b_info = c1 = alloc(BLOCKSIZE + 1, 1);
00382 }
00383
00384
00385
00386 pblock->b_offs = poff = (int *)
00387 alloc((unsigned) (100 * sizeof(int)), 0);
00388 siz = 99;
00389 *poff++ = 0;
00390 }
00391 c = c1;
00392 for (;;) {
00393
00394
00395
00396 cnt = read(stdf, c1, BLOCKSIZE - (c1 - pblock->b_info));
00397 if (cnt < 0) {
00398
00399
00400
00401 if (errno == EINTR) continue;
00402 error("Could not read input file");
00403 cnt = 0;
00404 }
00405 c1 += cnt;
00406 if (c1 != pblock->b_info + BLOCKSIZE) {
00407 ENDseen = 1;
00408 pblock->b_flags |= PARTLY;
00409 }
00410 break;
00411 }
00412 assert(c <= c1);
00413 while (c < c1) {
00414
00415
00416
00417 *c &= 0177;
00418 if (*c == '\n') {
00419
00420
00421
00422
00423 *c = 0;
00424 lastreadline++;
00425
00426
00427
00428 if (poff == pblock->b_offs + siz) {
00429
00430
00431
00432 pblock->b_offs = (int *)
00433 re_alloc((char *) pblock->b_offs,
00434 (siz+1) * sizeof(int),
00435 (siz + 51) * sizeof(int));
00436 poff = pblock->b_offs + siz;
00437 siz += 50;
00438 }
00439 *poff++ = c - pblock->b_info + 1;
00440 }
00441 else if (*c == '\0') {
00442
00443
00444
00445
00446 *c = 0200;
00447 }
00448 c++;
00449 }
00450 assert(c==c1);
00451 *c = 0;
00452 if (c != pblock->b_info && *(c-1) != 0) {
00453
00454
00455
00456 lastreadline++;
00457 *poff++ = c - pblock->b_info + 1;
00458 if (!(pblock->b_flags & PARTLY) && *(poff - 2) != 0) {
00459
00460
00461
00462
00463 saved = c1 = alloc(BLOCKSIZE + 1, 1);
00464 c = pblock->b_info + *(--poff - 1);
00465 while (*c) *c1++ = *c++;
00466 c = pblock->b_info + *(poff - 1);
00467 savedc1 = c1;
00468 --lastreadline;
00469 }
00470 }
00471 pblock->b_end = lastreadline;
00472 if (pblock->b_flags & PARTLY) {
00473
00474
00475
00476
00477 savedsiz = siz;
00478 savedpoff = poff;
00479 savedc1 = c;
00480 if (c == pblock->b_info) {
00481 lastreadline++;
00482 pblock->b_end = 0;
00483 }
00484 }
00485 else {
00486
00487
00488
00489
00490 addtolist(pblock);
00491 cnt = pblock - blocklist;
00492 filldegree = ((c-pblock->b_info) + (cnt-1) * filldegree) / cnt;
00493 }
00494 assert(pblock->b_end - (pblock-1)->b_end <= poff - pblock->b_offs);
00495 }
00496
00497
00498
00499
00500
00501
00502 STATIC VOID
00503 readblock(pblock) register struct block *pblock; {
00504
00505 register int size;
00506 register long i;
00507
00508
00509
00510
00511 pblock->b_info = alloc(BLOCKSIZE + 1, 1);
00512 i = (pblock - 1)->b_end * sizeof(int);
00513 size = (int) (pblock->b_end * sizeof(int) - i);
00514 pblock->b_offs = (int *) alloc((unsigned) size, 0);
00515 if (nopipe) {
00516 register char *c;
00517 register int line_index;
00518 int cnt;
00519 long l = lseek(stdf, 0L, 1);
00520
00521 (VOID) lseek(stdf, pblock->b_foff, 0);
00522 cnt = read(stdf, pblock->b_info, BLOCKSIZE);
00523 (VOID) lseek(stdf, l, 0);
00524 c = pblock->b_info;
00525 pblock->b_offs[0] = 0;
00526 line_index = 1;
00527 size /= sizeof(int);
00528 while (c < pblock->b_info + cnt) {
00529 *c &= 0177;
00530 if (*c == '\n') {
00531 *c = '\0';
00532 if (line_index < size)
00533 pblock->b_offs[line_index++] =
00534 (c - pblock->b_info) + 1;
00535 }
00536 else if (*c == '\0') *c = 0200;
00537 c++;
00538 }
00539 *c = '\0';
00540 }
00541 else {
00542 (VOID) lseek(tfdes, (long) ((long) BLOCKSIZE * (pblock - blocklist)),0);
00543 if (read(tfdes, pblock->b_info,BLOCKSIZE) != BLOCKSIZE) {
00544 panic("read error");
00545 }
00546
00547
00548
00549 (VOID) lseek(ifdes, i, 0);
00550 if (read(ifdes, (char *) pblock->b_offs, size) != size) {
00551 panic("read error");
00552 }
00553 pblock->b_info[BLOCKSIZE] = '\0';
00554 }
00555
00556
00557
00558 addtolist(pblock);
00559 }
00560
00561
00562
00563
00564
00565
00566 VOID
00567 do_clean() {
00568
00569 register struct block *pblock;
00570 register char *p;
00571
00572 for (pblock = blocklist; pblock < maxblocklist; pblock++) {
00573 if (p = pblock->b_info) {
00574 free(p);
00575 free((char *) pblock->b_offs);
00576 }
00577 }
00578 if (p = (char *) blocklist) {
00579 free(p);
00580 }
00581 blocklist = 0;
00582 maxblocklist = 0;
00583 topblocklist = 0;
00584 lastreadline = 0;
00585 filldegree = 0;
00586 ENDseen = 0;
00587 if (p = saved) free(p);
00588 saved = 0;
00589 b_head = 0;
00590 b_tail = 0;
00591 # if MAXNBLOCKS
00592 nblocks = 0;
00593 # endif
00594 }
00595
00596
00597
00598
00599
00600 STATIC VOID
00601 cls(file) {
00602 if (file) (VOID) close(file);
00603 }
00604
00605
00606
00607
00608
00609 VOID
00610 cls_files() {
00611
00612 cls(tfdes);
00613 cls(ifdes);
00614 cls(stdf);
00615 }
00616
00617
00618
00619
00620
00621 int
00622 getch() {
00623 # if USG_OPEN
00624 # include <fcntl.h>
00625 # include <sys/stat.h>
00626
00627 register int i,j;
00628 struct stat buf;
00629 # else
00630 # ifdef FIONREAD
00631 # include <sys/stat.h>
00632
00633 struct stat buf;
00634 long i;
00635 # endif
00636 # endif
00637
00638 char c;
00639 int retval;
00640
00641 flush();
00642 if (startcomm) {
00643
00644
00645
00646 if (*startcomm) return *startcomm++;
00647 return '\n';
00648 }
00649 # if USG_OPEN
00650 if (stdf >= 0) {
00651
00652
00653
00654
00655 i = fcntl(0,F_GETFL,0);
00656 if (i != -1 && fcntl(0, F_SETFL, i|O_NDELAY) != -1) {
00657 j = 0;
00658 while (! ENDseen &&
00659 ((j = read(0,&c,1)) == 0
00660 #ifdef EWOULDBLOCK
00661 || (j < 0 && errno == EWOULDBLOCK)
00662 #endif
00663 )
00664 &&
00665 (nopipe ||
00666 (fstat(stdf,&buf) >= 0 && buf.st_size > 0))) {
00667
00668
00669
00670
00671 new_block();
00672 }
00673 (VOID) fcntl(0,F_SETFL,i);
00674 if (j < 0) {
00675
00676
00677
00678
00679
00680 return -1;
00681 }
00682 if (j > 0) return c;
00683 }
00684 }
00685 # else
00686 # ifdef FIONREAD
00687 if (stdf >= 0) {
00688
00689
00690
00691
00692 while (! ENDseen &&
00693 ( ioctl(0, FIONREAD, (char *) &i) >= 0 && i == 0) &&
00694 ( nopipe || fstat(stdf,&buf) >= 0 && buf.st_size > 0)) {
00695
00696
00697
00698
00699 if (interrupt) return -1;
00700 new_block();
00701 }
00702 }
00703 # endif
00704 # endif
00705 if (read(0,&c,1) <= 0) retval = -1; else retval = c & 0177;
00706 return retval;
00707 }
00708
00709
00710
00711
00712
00713 long
00714 getpos(ln) long ln; {
00715 register struct block *pblock;
00716 register long i;
00717
00718 pblock = getblock(ln,1);
00719 assert(pblock != 0);
00720 i = filldegree * (pblock - blocklist);
00721 return i - (filldegree - pblock->b_offs[ln - (pblock-1)->b_end]);
00722 }