#define ctrl(letter) ('letter' & 077)
int fnum
, no_intty
, no_tty
, slow_tty
;
int dum_opt
, dlines
, onquit(), end_it();
int inwait
, pause
, errors
;
int within
; /* true if we are within a file,
false if we are between files */
int hard
, dumb
, noscroll
, hardtabs
;
char obuf
[BUFSIZ
]; /* stdout buffer */
int Lpp
= 24; /* lines per page */
char *Clear
; /* clear screen */
char *eraseln
; /* erase line */
char *Senter
, *Sexit
;/* enter and exit standout mode */
int Mcol
= 80; /* number of columns */
int Wrap
= 1; /* set if automargins */
extern char PC
; /* pad character */
/* Put terminal setup stuff in separate procedure ?? (From here...) */
if (!(no_tty
= gtty(1, &otty
))) {
if (tgetent(buf
, getenv("TERM")) <= 0) {
if (((Lpp
= tgetnum("li")) < 0) || tgetflag("hc")) {
hard
++; /* Hard copy terminal */
if (!hard
&& tgetflag("ns"))
if ((Mcol
= tgetnum("co")) < 0)
eraseln
= tgetstr("ce",&clearptr
);
Clear
= tgetstr("cl", &clearptr
);
Senter
= tgetstr("so", &clearptr
);
Sexit
= tgetstr("se", &clearptr
);
PC
= *tgetstr("pc", &clearptr
);
if ((shell
= getenv("SHELL")) == NULL
)
no_intty
= gtty(0, &otty
);
slow_tty
= ospeed
< B1200
;
hardtabs
= !(otty
.sg_flags
& XTABS
);
if (MBIT
== CBREAK
|| !slow_tty
)
/* ... until here or so */
if ((ch
= (*++fnames
)[0]) == '-') {
for (s
= fnames
[0] + 1, dlines
= 0; *s
!= '\0'; s
++)
dlines
= dlines
*10 + *s
- '0';
for (++s
, p
= initbuf
; p
< initbuf
+ 79 && *s
!= '\0';)
for (initline
= 0; *s
!= '\0'; s
++)
initline
= initline
*10 + *s
-'0';
if (!no_intty
&& nfiles
== 0) {
fputs(" [-dn] name1 name2 ...\n",stderr
);
search (initbuf
, stdin
, 1);
skiplns (initline
, stdin
);
if ((f
= checkf (fnames
[fnum
])) != NULL
) {
if (firstf
) setjmp (restore
);
else if (fnum
< nfiles
&& !no_tty
) {
left
= command (fnames
[fnum
], f
);
pr("\n::::::::::::::\n");
** Check whether the file named by fs is an ASCII file which the user may
** access. If it is, return the opened file. Otherwise return NULL.
int space
[3]; /* Why doesn't libretro have a V7 stat? */
if (stat (fs
, &stbuf
) == -1) {
if (stbuf
.st_mode
& S_IFDIR
) {
pr(": directory ***\n\n");
if ((f
=fopen(fs
, "r")) == NULL
) {
/* Try to see whether it is an ASCII file */
switch ((c
| *f
->_ptr
<< 8) & 0177777) {
pr(": Not a text file ********\n\n");
** A real function, for the tputs routine in termlib
** Print out the contents of the file f, one screenful at a time.
while (num_lines
> 0 && !pause
) {
if ((nchars
= getline (f
)) == EOF
)
if (Senter
&& *Senter
== ' ' && promptlen
> 0)
erase (nchars
); /* erase () sets promptlen to 0 */
if ((c
= getc(f
)) == EOF
) {
if ((num_lines
= command (NULL
, f
)) == 0)
** Come here if a quit signal is received
signal(SIGQUIT
, SIG_IGN
);
else if (!dum_opt
&& notell
) {
write (2, "[Use q or Q to quit]", 20);
** Clean up terminal state and exit. Also come here if interrupt signal received
while ((c
= getc(f
)) != EOF
)
static char bell
= ctrl(G
);
tputs (Senter
, 1, putch
);
promptlen
+= 13 + strlen(filename
);
pr("[Hit space to continue, Rubout to abort]");
if (colflg
&& c
== '\n') c
= getc (f
);
for (i
= 1; i
< LINSIZ
; i
++) {
if (hardtabs
&& column
< promptlen
&& !hard
) {
tputs (eraseln
, 1, putch
);
for (--p
; column
& 7; column
++)
if (column
>= promptlen
) promptlen
= 0;
column
= 1 + (column
| 7);
else if (c
== '\f' && stop_opt
) {
if (column
>= Mcol
) break;
if (Mcol
> 0 && column
>= Mcol
) {
colflg
= (column
== Mcol
) || c
== '\f';
if (c
== '\f' && stop_opt
)
** Erase the rest of the prompt, assuming we are starting column col.
if (hard
|| promptlen
== 0)
tputs (eraseln
, 1, putch
);
for (col
= promptlen
- col
; col
> 0; col
--)
** Erase the current line entirely
if (!eraseln
|| dumb
) putchar ('\r');
** Read a command and do it. A command consists of an optional integer
** argument followed by the command character. Return the number of lines
** to display in the next screenful. If there is nothing more to display
** in the current file, zero is returned.
char comchar
, cmdbuf
[80], *p
;
#define ret(val) retval=val;done++;break
if (MBIT
== RAW
&& slow_tty
) {
nlines
= number (&comchar
);
if (nlines
== 0) nlines
= dlines
;
else if (comchar
== 'z') dlines
= nlines
;
if (nlines
== 0) nlines
++;
while ((c
= getc (f
)) != '\n')
if (nlines
== 0) nlines
++;
search (cmdbuf
, f
, nlines
);
while ((id
= fork ()) < 0)
execl (shell
, shell
, "-c", cmdbuf
, 0);
write (2, "exec failed\n", 12);
signal (SIGINT
, SIG_IGN
);
signal (SIGQUIT
, SIG_IGN
);
signal (SIGQUIT
, onquit
);
pr ("----------\n(continue)\n");
if (MBIT
== RAW
&& slow_tty
) {
** Read a decimal number from the terminal. Set cmd to the non-digit which
** terminates the number.
i
= 0; ch
= otty
.sg_kill
;
if (ch
>= '0' && ch
<= '9')
else if (ch
== otty
.sg_kill
)
** Skip n lines in the file f
while ((c
= getc (f
)) != '\n')
** Skip nskip files in the file list (from the command line). Nskip may be
else if (fnum
> nfiles
- 1)
pr (nskip
> 0 ? "to file " : "back to file ");
while (sptr
- buf
< nmax
) {
if (promptlen
> maxlen
) maxlen
= promptlen
;
else if (ch
== otty
.sg_erase
&& !slash
) {
if (*sptr
< ' ' && *sptr
!= '\n') {
if (!eraseln
) promptlen
= maxlen
;
else if (ch
== otty
.sg_kill
&& !slash
) {
if (slash
&& (ch
== otty
.sg_kill
|| ch
== otty
.sg_erase
)) {
if (ch
< ' ' && ch
!= '\n' && ch
!= ESC
) {
if (ch
!= '\n' && ch
!= ESC
) {
if (!eraseln
) promptlen
= maxlen
;
if (sptr
- buf
>= nmax
- 1)
** Search for nth ocurrence of regular expression contained in buf in the file
long startline
= ftell (file
);
register long line1
= startline
;
register long line2
= startline
;
register long line3
= startline
;
if (lncount
> 3 || (lncount
> 1 && no_intty
))
file
->_flag
&= ~_IOEOF
; /* why doesn't fseek do this ??!!??! */
fseek (file
, startline
, 0);
pr ("\nPattern not found\n");
error ("Pattern not found");
* The following are adapted from the editor
* Internal form of regular expressions.
#define CBRA 1 /* left \( bracket */
#define CCHR 2 /* a particular character */
#define CDOT 4 /* any char (.) */
#define CCL 6 /* begin class ([) */
#define NCCL 8 /* begin not class ([^) */
#define CDOL 10 /* end of line ($) */
#define CEOF 11 /* end of pattern */
#define CKET 12 /* right \) bracket */
#define CBACK 14 /* repeat previous match (\1, etc on lhs) */
#define STAR 01 /* or'ed with some symbols to indicate * suffix */
#define NBRA 5 /* max # of \( \) pairs */
* compile: convert typed in regular expression into internal form.
* eof is the char that delimits the r.e.
* General structure of compiled r.e. in expbuf: A sequence of codes
* from #defines above (CCHR, CDOT, etc). Some of these take arguments
* which follow in line (e.g. CCHR is followed by the particular character
* it is required to match.) CEOF terminates the r.e.
register char *bp
= inbuf
;
char bracket
[NBRA
], *bracketp
;
/* comerr: compilation error. Don't leave half baked r.e. around. */
#define comerr(msg) {expbuf[0] = 0; nbra = 0; error(msg); }
if ((c
= *bp
++) == '\0') {
/* null r.e.: just re-use last r.e., which is still there */
error("No previous regular expression");
/* circfl: true if have ^ (anchored search). */
for (;;) { /* for each character in the r.e. */
if (ep
>= &expbuf
[BUFSIZ
])
/* Hit trailing delim: clean up and quit */
/* \(: start of subexpression */
comerr("too many \\(\\) pairs");
if (c
>='1' && c
<'1'+NBRA
) {
/* \1, \2, ...: rematch previous subexp */
/* Otherwise just force that char, not specially */
/* Newlines can't possibly be in lines */
comerr("multi line r.e. not allowed");
/* .: match any character */
/* *: Repeat last char indefinitely */
if (lastep
==0 || *lastep
==CBRA
|| *lastep
==CKET
)
/* Not that smart, so treat * as nonspecial */
/* $: match end of line */
/* $ only special at end of r.e. */
* [...]: any of chars enclosed in brackets.
* Compiled form: CCL or NCCL, # of possible chars,
* then each char. -'s are expanded.
if ((c
= *bp
++) == '^') {
/* [^...]: reverse sense of match */
do { /* for each char in brackets */
if (c
== '-' && ep
[-1] != 0) {
/* form ...a-z... but [- not special */
if ((c
= *bp
++) == ']') {
/* -] not special either */
/* insert all chars between */
if (ep
>= &expbuf
[BUFSIZ
])
} while ((c
= *bp
++) != ']');
lastep
[1] = cclcnt
; /* backpatch count */
* An ordinary char or one treated as ordinary.
* Store CCHR followed by that char, rather than
* just the char. This causes most r.e.'s to take
* up about twice the space you would expect.
* On the other hand, it makes r.e.'s beautifully
* portable, even though the codes could be real
* execute: look for the compiled r.e. on line addr.
* gf is 0 if this is the first time on this line, otherwise nonzero.
* If not first, start looking at locs, otherwise at beg of linebuf.
* loc1 and loc2 are set to the ends of the pattern found, if any.
* 1 is returned if successful, otherwise 0.
/* anchored search (^): just try one advance. */
/* fast check for first character */
/* regular algorithm, try advance starting at each char position. */
* advance: does an anchored search for expression starting at ep,
* looking in line starting at lp. Returns 1 if matches, else 0.
* If found, loc2 is set to end of pattern.
for (;;) switch (*ep
++) { /* for each code in r.e., look at it..*/
if (cclass(ep
, *lp
++, 1)) {
if (cclass(ep
, *lp
++, 0)) {
if (braelist
[i
= *ep
++]==0)
error("bad back reference");
lp
+= braelist
[i
] - braslist
[i
];
if (braelist
[i
= *ep
++] == 0)
error("bad back reference");
lp
+= braelist
[i
] - braslist
[i
];
lp
-= braelist
[i
] - braslist
[i
];
while (cclass(ep
, *lp
++, ep
[-1]==(CCL
|STAR
)))
* star: special treatment. We have found as many of them
* as there are to find. Maybe this was too many, as dictated
* by what follows in the pattern. Try, starting from the
* end, to recursively advance after each char found,
* and return after first successful advance (thus finding
* largest possible string that matches).
/* star failed at all attempts, so whole pattern fails. */
* backref: checks to see that text starting at lp matches previous
* sub-expression #i. Returns 1 if successful, else 0. (Used for \k
* cclass: check to see if character c is in class starting at set.
* ([...] construction on lhs of r.e.) af is sense of success/failure:
* af=1 is normal (success returns 1), af=0 is reversed for [^ (success
promptlen
+= strlen (mess
);
tputs (Senter
, 1, putch
);
while ((c
= getc (f
)) != '\n' && c
!= EOF
&& p
- Line
< LINSIZ
- 1)