📄 getline.c
字号:
* last time we tried. Undo this increment */ poff--; --lastreadline; } } else { if (nopipe) pblock->b_foff = lseek(stdf, 0L, 1); if (saved) { /* * There were leftovers from the previous block */ pblock->b_info = saved; if (nopipe) pblock->b_foff -= savedc1 - saved; c1 = savedc1; saved = 0; } else { /* Allocate new block */ pblock->b_info = c1 = alloc(BLOCKSIZE + 1, 1); } /* * Allocate some space for line-offsets */ pblock->b_offs = poff = (int *) alloc((unsigned) (100 * sizeof(int)), 0); siz = 99; *poff++ = 0; } c = c1; for (;;) { /* * Read loop */ cnt = read(stdf, c1, BLOCKSIZE - (c1 - pblock->b_info)); if (cnt < 0) { /* * Interrupted read */ if (errno == EINTR) continue; error("Could not read input file"); cnt = 0; } c1 += cnt; if (c1 != pblock->b_info + BLOCKSIZE) { ENDseen = 1; pblock->b_flags |= PARTLY; } break; } assert(c <= c1); while (c < c1) { /* * Now process the block */ *c &= 0177; /* Most significant bit ignored */ if (*c == '\n') { /* * Newlines are replaced by '\0', so that "getline" * can deliver one line at a time */ *c = 0; lastreadline++; /* * Remember the line-offset */ if (poff == pblock->b_offs + siz) { /* * No space for it, allocate some more */ pblock->b_offs = (int *) re_alloc((char *) pblock->b_offs, (siz+1) * sizeof(int), (siz + 51) * sizeof(int)); poff = pblock->b_offs + siz; siz += 50; } *poff++ = c - pblock->b_info + 1; } else if (*c == '\0') { /* * 0-bytes are replaced by 0200, because newlines are * replaced by 0, and 0200 & 0177 gives again 0 ... */ *c = 0200; } c++; } assert(c==c1); *c = 0; if (c != pblock->b_info && *(c-1) != 0) { /* * The last line read does not end with a newline, so add one */ lastreadline++; *poff++ = c - pblock->b_info + 1; if (!(pblock->b_flags & PARTLY) && *(poff - 2) != 0) { /* * Save the started line; it will be in the next block. * Remove the newline we added just now. */ saved = c1 = alloc(BLOCKSIZE + 1, 1); c = pblock->b_info + *(--poff - 1); while (*c) *c1++ = *c++; c = pblock->b_info + *(poff - 1); savedc1 = c1; --lastreadline; } } pblock->b_end = lastreadline; if (pblock->b_flags & PARTLY) { /* * Take care, that we can call "nextblock" again, to fill in * the rest of this block */ savedsiz = siz; savedpoff = poff; savedc1 = c; if (c == pblock->b_info) { lastreadline++; pblock->b_end = 0; } } else { /* * Not completely read blocks are not in the linked list, * so can never be "swapped out". */ addtolist(pblock); cnt = pblock - blocklist; filldegree = ((c-pblock->b_info) + (cnt-1) * filldegree) / cnt; } assert(pblock->b_end - (pblock-1)->b_end <= poff - pblock->b_offs);}/* * Allocate core for the block, and read it back from * the temporary file. */STATIC VOIDreadblock(pblock) register struct block *pblock; { register int size; register long i; /* * Find out where the block is, and read it */ pblock->b_info = alloc(BLOCKSIZE + 1, 1); i = (pblock - 1)->b_end * sizeof(int); size = (int) (pblock->b_end * sizeof(int) - i); pblock->b_offs = (int *) alloc((unsigned) size, 0); if (nopipe) { register char *c; register int line_index; int cnt; long l = lseek(stdf, 0L, 1); (VOID) lseek(stdf, pblock->b_foff, 0); cnt = read(stdf, pblock->b_info, BLOCKSIZE); (VOID) lseek(stdf, l, 0); c = pblock->b_info; pblock->b_offs[0] = 0; line_index = 1; size /= sizeof(int); while (c < pblock->b_info + cnt) { *c &= 0177; if (*c == '\n') { *c = '\0'; if (line_index < size) pblock->b_offs[line_index++] = (c - pblock->b_info) + 1; } else if (*c == '\0') *c = 0200; c++; } *c = '\0'; } else { (VOID) lseek(tfdes, (long) ((long) BLOCKSIZE * (pblock - blocklist)),0); if (read(tfdes, pblock->b_info,BLOCKSIZE) != BLOCKSIZE) { panic("read error"); } /* * Find out where the line-offset list is, and read it */ (VOID) lseek(ifdes, i, 0); if (read(ifdes, (char *) pblock->b_offs, size) != size) { panic("read error"); } pblock->b_info[BLOCKSIZE] = '\0'; } /* * Add this block to the list of incore blocks */ addtolist(pblock);}/* * Called after processing a file. * Free all core. */VOIDdo_clean() { register struct block *pblock; register char *p; for (pblock = blocklist; pblock < maxblocklist; pblock++) { if (p = pblock->b_info) { free(p); free((char *) pblock->b_offs); } } if (p = (char *) blocklist) { free(p); } blocklist = 0; maxblocklist = 0; topblocklist = 0; lastreadline = 0; filldegree = 0; ENDseen = 0; if (p = saved) free(p); saved = 0; b_head = 0; b_tail = 0;# if MAXNBLOCKS nblocks = 0;# endif}/* * Close a file with file-descriptor "file", if it indeed is one */STATIC VOIDcls(file) { if (file) (VOID) close(file);}/* * Close all files */VOIDcls_files() { cls(tfdes); cls(ifdes); cls(stdf);}/* * Get a character. If possible, do some workahead. */intgetch() {# if USG_OPEN# include <fcntl.h># include <sys/stat.h> register int i,j; struct stat buf;# else# ifdef FIONREAD# include <sys/stat.h> struct stat buf; long i;# endif# endif char c; int retval; flush(); if (startcomm) { /* * Command line option command */ if (*startcomm) return *startcomm++; return '\n'; }# if USG_OPEN if (stdf >= 0) { /* * Make reads from the terminal non-blocking, so that * we can see if the user typed something */ i = fcntl(0,F_GETFL,0); if (i != -1 && fcntl(0, F_SETFL, i|O_NDELAY) != -1) { j = 0; while (! ENDseen && ((j = read(0,&c,1)) == 0#ifdef EWOULDBLOCK || (j < 0 && errno == EWOULDBLOCK)#endif ) && (nopipe || (fstat(stdf,&buf) >= 0 && buf.st_size > 0))) { /* * Do some read ahead, after making sure there * is input and the user did not type a command */ new_block(); } (VOID) fcntl(0,F_SETFL,i); if (j < 0) { /* * Could this have happened? * I'm not sure, because the read is * nonblocking. Can it be interrupted then? */ return -1; } if (j > 0) return c; } }# else# ifdef FIONREAD if (stdf >= 0) { /* * See if there are any characters waiting in the terminal input * queue. If there are not, read ahead. */ while (! ENDseen && ( ioctl(0, FIONREAD, (char *) &i) >= 0 && i == 0) && ( nopipe || fstat(stdf,&buf) >= 0 && buf.st_size > 0)) { /* * While the user does'nt type anything, and there is * input to be processed, work ahead */ if (interrupt) return -1; new_block(); } }# endif# endif if (read(0,&c,1) <= 0) retval = -1; else retval = c & 0177; return retval;}/* * Get the position of line "ln" in the file. */longgetpos(ln) long ln; { register struct block *pblock; register long i; pblock = getblock(ln,1); assert(pblock != 0); i = filldegree * (pblock - blocklist); return i - (filldegree - pblock->b_offs[ln - (pblock-1)->b_end]);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -