📄 pg.c
字号:
"[] imbalance", 49, "Regular expression overflow", 50, "Bad regular expression", 0 }; for (j = 0; re_errmsg[j].number != 0; j++ ) if (re_errmsg[j].number == i ) break; error(re_errmsg[j].message); longjmp(restore,1); /* restore to search() */}/* * Search for nth ocurrence of regular expression contained in buf in the file * negative n implies backward search * n 'guaranteed' non-zero */char expbuf[BUFSIZ];search (buf, n)char buf[];register int n;{ register int direction; char *endbuf; int END_COND; endbuf = buf + strlen(buf)-2; if(*endbuf++ != '\\' && *endbuf == '$') { *endbuf++ = '\\'; *endbuf++ = 'n'; *endbuf = '\0'; } if (setjmp(restore) == 0) { compile(buf,expbuf,expbuf+BUFSIZ,NULL); if (n < 0) { /* search back */ direction = -1; find(0,old_ss.first_line); END_COND = BOF; } else { direction = 1; find(0,old_ss.last_line); END_COND = EOF; } while (find(1,direction) != END_COND){ if (brk_hit) break; if (step(Line,expbuf)) if ((n -= direction) == 0) { switch(leave_search) { case 't': new_ss.first_line = find(1,0); new_ss.last_line = new_ss.first_line + window - 1; break; case 'b': new_ss.last_line = find(1,0); new_ss.first_line = new_ss.last_line - window + 1; break; case 'm': new_ss.first_line =find(1,0) - (window - 1)/2; new_ss.last_line = new_ss.first_line + window - 1; break; } return(1); } } re_error(1); /* Pattern not found */ } BEEP(); return(0);}/* * find -- find line in file f, subject to certain constraints. * * This is the reason for all the funny stuff with sign and nlines. * We need to be able to differentiate between relative and abosolute * address specifications. * * So...there are basically three cases that this routine * handles. Either line is zero, which means there is to be * no motion (because line numbers start at one), or * how and line specify a number, or line itself is negative, * which is the same as having how == -1 and line == abs(line). * * Then, figure where exactly it is that we are going (an absolute * line number). Find out if it is within what we have read, * if so, go there without further ado. Otherwise, do some * magic to get there, saving all the intervening lines, * in case the user wants to see them some time later. * * In any case, return the line number that we end up at. * (This is used by search() and screen()). If we go past EOF, * return EOF. * This EOF will go away eventually, as pg is expanded to * handle multiple files as one huge one. Then EOF will * mean we have run off the file list. * If the requested line number is too far back, return BOF. */find(how,line) /* find the line and seek there */short how;short line;{ /* no compacted memory yet */ register FILE *f = in_file; register short where; int c; /* used to check for end of file */ if (how == 0) where = line; else if (dot == zero - 1) where = how * line; else where = how * line + dot->l_no; /* now, where is either at, before, or after dol */ /* most likely case is after, so do it first */ eoflag = 0; if (where >= dol->l_no) { if (doliseof) { dot = dol; eoflag++; return(EOF); } if (pipe_in) in_file = f = stdin; else fseek(f, dol->l_addr, 0); dot = dol - 1; while ((nchars = getline(f)) != EOF) { dot++; newdol(f); if ( where == dot->l_no || brk_hit) break; } if (nchars != EOF) return(dot->l_no); else { /* EOF */ dot = dol; eoflag++; doliseof++; eofl_no = dol->l_no; return(EOF); } } else { /* where < dol->l_no */ if (pipe_in) { fflush(tmp_fou); in_file = f = tmp_fin; } if (where < zero->l_no){ fseek(f, zero->l_addr, 0); dot = zero - 1; return(BOF); } else { dot = zero + where - 1; fseek(f, dot->l_addr, 0); nchars = getline(f); return(dot->l_no); } }}/* * Get a logical line */getline(f)register FILE *f;{ register int c; register char *p; register int column; register int i; register int (*rdchar)(); int fgetc(); int fgetputc(); static int colflg; /* true if received \f or a long line */ if (pipe_in && f == stdin) rdchar = fgetputc; else rdchar = fgetc; for (i = 1, column = 0, p = Line; i < LINSIZ - 1; i++, p++) { *p = c = (*rdchar)(f); switch(c) { case EOF: clearerr(f); if (p > Line) { /* last line doesn't have '\n', */ *p++ = '\n'; *p = '\0'; /* print it any way */ return(column); } return(EOF); case '\n': break; case '\t': /* just a guess */ column = 1 + (column | 7); break; case '\b': if (column > 0) column--; break; case '\r': column = 0; break; default: if (c >= ' ') column++; break; } if (c == '\n') { p++; break; } if (column >= columns && !fflag) { p++; break; } } if (c != '\n') { /* We're stopping in the middle of the line */ if (column != columns || !auto_right_margin) *p++ = '\n'; /* for the display */ /* peek at the next character */ c = fgetc(f); if (c == '\n') { ungetc(c,f); c = (*rdchar)(f); /* gobble and copy it */ } else if (c == EOF) /* get it next time */ clearerr(f); else ungetc(c,f); } *p = 0; return(column);}save_input(f)register FILE f;{ if (pipe_in) { save_pipe(); in_file = tmp_fin; pipe_in = 0; } fseek(in_file,0L,0); copy_file(in_file,f);}save_pipe(){ if (!doliseof) while (fgetputc(stdin) != EOF) if (brk_hit) { brk_hit = 0; error("Piped input only partially saved"); break; } fclose(tmp_fou);}fgetputc(f) /* copy anything read from a pipe to tmp_fou */register FILE *f;{ register int c; if ((c = getc(f)) != EOF) putc(c,tmp_fou); return(c);}lineset(how) /* initialize line memory */int how;{ if (zero == NULL) { nlall = 128; zero = (LINE *) malloc(nlall * sizeof (LINE)); } dol = contig = zero; zero->l_no = 1; zero->l_addr = 0l; if (how == BOF) { dot = zero - 1; eoflag = 0; doliseof = 0; eofl_no = -1; } else { dot = dol; eoflag = 1; doliseof = 1; eofl_no = 1; } return;}newdol(f) /* add address of new 'dol' */ /* assumes that f is currently at beginning of said line */ /* updates dol */register FILE *f;{ register int diff; if ((dol - zero) + 1 >= nlall){ LINE *ozero = zero; nlall += 512; free ((char *) zero); if ((zero = (LINE *) realloc ((char *) zero, (unsigned)(nlall * sizeof(LINE)))) == NULL){ zero = ozero; compact(); } diff = (char *)zero - (char *)ozero; dot = (LINE *)((char *)dot + diff); dol = (LINE *)((char *)dol + diff); contig = (LINE *)((char *)contig + diff); } dol++; if (!pipe_in) dol->l_addr = ftell(f); else { fflush(tmp_fou); dol->l_addr = ftell(tmp_fou); } dol->l_no = (dol-1)->l_no + 1;}compact(){ fprintf(stderr, "pg: no more memory - line %d\n",dol->l_no); end_it();}terminit() /* set up terminal dependencies from termlib */{ int err_ret; struct termio ntty; if ((freopen("/dev/tty","r+",stdout)) == NULL) { fprintf(stderr,"pg: cannot reopen stdout\n"); exit(1); } setupterm(0,fileno(stdout),&err_ret); if (err_ret != 1) setupterm("dumb",fileno(stdout),&err_ret); if (err_ret != 1) { fprintf(stderr,"pg: cannot find terminal type\n"); exit(1); } /* there must be a better way using "curses" */ ioctl(fileno(stdout),TCGETA,&ntty); /* ntty.c_lflag &= ~(ECHONL | ECHO | ICANON); Changed to echo responses (gray) */ ntty.c_lflag |= (ECHONL | ECHO | ICANON); ntty.c_cc[VMIN] = 1; ntty.c_cc[VTIME] = 1; ioctl(fileno(stdout),TCSETA,&ntty); saveterm(); resetterm(); if (lines <= 0 || hard_copy) { hard_copy = 1; lines = 24; } if (columns <= 0) columns = 80; if (clropt && !clear_screen) clropt = 0; if ((shell = getenv("SHELL")) == NULL) shell = "/bin/sh";}error(mess)char *mess;{ kill_line(); sopr(mess,1); prompt((char *) NULL); errors++;}prompt(filename)char *filename;{ char outstr[PROMPTSIZE+6]; int pagenum; if (filename != NULL) { sopr("(Next file: ",1); sopr(filename,1); sopr(")",1); } else { if ((pagenum=(int)((new_ss.last_line-2)/(window-1)+1)) > 999999) pagenum = 999999; sprintf(outstr,promptstr,pagenum); } sopr(outstr,1); fflush(stdout);}/* * sopr puts out the message (please no \n's) surrounded by standout * begins and ends */sopr(m,count) char *m; short count;{ if (count) promptlen += strlen(m); if (soflag && enter_standout_mode && exit_standout_mode) { pr(enter_standout_mode); pr(m); pr(exit_standout_mode); } else pr(m);}pr(s)char *s;{ fputs(s,stdout);}doclear(){ if (clear_screen) putp(clear_screen); putchar('\r'); /* this resets the terminal drivers character */ /* count in case it is trying to expand tabs */}kill_line(){ erase_line(0); if (!clr_eol) putchar ('\r');}/* erase from after col to end of prompt */erase_line(col)register int col;{ if (promptlen == 0) return; if (hard_copy) putchar('\n'); else { if (col == 0) putchar('\r'); if (clr_eol) { putp(clr_eol); putchar('\r'); /* for the terminal driver again */ } else for (col = promptlen - col; col > 0; col--) putchar (' '); } promptlen = 0;}/* * Come here if a quit or interrupt signal is received */voidon_brk(sno) int sno; /* signal number generated */{ signal(sno, on_brk); if (!inwait) { BEEP(); brk_hit = 1; } else { brk_hit = 0; longjmp(restore,1); }}/* * Clean up terminal state and exit. */voidend_it (){ if (out_is_tty) { kill_line(); resetterm(); system("/usr/ucb/reset"); } if (tmp_fin) fclose(tmp_fin); if (tmp_fou) fclose(tmp_fou); if (tmp_fou || tmp_fin) unlink(tmp_name); exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -