version 1.14, 2014/10/17 21:27:10 |
version 1.15, 2015/05/08 12:30:27 |
|
|
int l_needs_sort; /* set if chars went in out of order */ |
int l_needs_sort; /* set if chars went in out of order */ |
}; |
}; |
|
|
|
void addto_lineno(int *, int); |
LINE *alloc_line(void); |
LINE *alloc_line(void); |
void dowarn(int); |
void dowarn(int); |
void flush_line(LINE *); |
void flush_line(LINE *); |
|
|
LINE *lines; |
LINE *lines; |
int compress_spaces; /* if doing space -> tab conversion */ |
int compress_spaces; /* if doing space -> tab conversion */ |
int fine; /* if `fine' resolution (half lines) */ |
int fine; /* if `fine' resolution (half lines) */ |
int max_bufd_lines; /* max # lines to keep in memory */ |
int max_bufd_lines; /* max # of half lines to keep in memory */ |
int nblank_lines; /* # blanks after last flushed line */ |
int nblank_lines; /* # blanks after last flushed line */ |
int no_backspaces; /* if not to output any backspaces */ |
int no_backspaces; /* if not to output any backspaces */ |
|
|
|
|
int adjust, opt, warned; |
int adjust, opt, warned; |
const char *errstr; |
const char *errstr; |
|
|
max_bufd_lines = 128; |
max_bufd_lines = 256; |
compress_spaces = 1; /* compress spaces into tabs */ |
compress_spaces = 1; /* compress spaces into tabs */ |
while ((opt = getopt(argc, argv, "bfhl:x")) != -1) |
while ((opt = getopt(argc, argv, "bfhl:x")) != -1) |
switch (opt) { |
switch (opt) { |
|
|
compress_spaces = 1; |
compress_spaces = 1; |
break; |
break; |
case 'l': /* buffered line count */ |
case 'l': /* buffered line count */ |
max_bufd_lines = strtonum(optarg, 1, INT_MAX, &errstr); |
max_bufd_lines = strtonum(optarg, 1, |
|
(INT_MAX - BUFFER_MARGIN) / 2, &errstr) * 2; |
if (errstr != NULL) |
if (errstr != NULL) |
errx(1, "bad -l argument, %s: %s", errstr, |
errx(1, "bad -l argument, %s: %s", errstr, |
optarg); |
optarg); |
|
|
if (optind != argc) |
if (optind != argc) |
usage(); |
usage(); |
|
|
/* this value is in half lines */ |
|
max_bufd_lines *= 2; |
|
|
|
adjust = extra_lines = warned = 0; |
adjust = extra_lines = warned = 0; |
cur_col = 0; |
cur_col = 0; |
cur_line = max_line = nflushd_lines = this_line = 0; |
cur_line = max_line = nflushd_lines = this_line = 0; |
|
|
case ESC: /* just ignore EOF */ |
case ESC: /* just ignore EOF */ |
switch(getchar()) { |
switch(getchar()) { |
case RLF: |
case RLF: |
cur_line -= 2; |
addto_lineno(&cur_line, -2); |
break; |
break; |
case RHLF: |
case RHLF: |
cur_line--; |
addto_lineno(&cur_line, -1); |
break; |
break; |
case FHLF: |
case FHLF: |
cur_line++; |
addto_lineno(&cur_line, 1); |
if (cur_line > max_line) |
if (cur_line > max_line) |
max_line = cur_line; |
max_line = cur_line; |
} |
} |
continue; |
continue; |
case NL: |
case NL: |
cur_line += 2; |
addto_lineno(&cur_line, 2); |
if (cur_line > max_line) |
if (cur_line > max_line) |
max_line = cur_line; |
max_line = cur_line; |
cur_col = 0; |
cur_col = 0; |
|
|
++cur_col; |
++cur_col; |
continue; |
continue; |
case VT: |
case VT: |
cur_line -= 2; |
addto_lineno(&cur_line, -2); |
continue; |
continue; |
} |
} |
continue; |
continue; |
} |
} |
|
|
/* Must stuff ch in a line - are we at the right one? */ |
/* Must stuff ch in a line - are we at the right one? */ |
if (cur_line != this_line - adjust) { |
if (cur_line + adjust != this_line) { |
LINE *lnew; |
LINE *lnew; |
int nmove; |
|
|
|
adjust = 0; |
/* round up to next line */ |
nmove = cur_line - this_line; |
adjust = !fine && (cur_line & 1); |
if (!fine) { |
|
/* round up to next line */ |
if (cur_line + adjust < this_line) { |
if (cur_line & 1) { |
while (cur_line + adjust < this_line && |
adjust = 1; |
l->l_prev != NULL) { |
nmove++; |
|
} |
|
} |
|
if (nmove < 0) { |
|
for (; nmove < 0 && l->l_prev; nmove++) |
|
l = l->l_prev; |
l = l->l_prev; |
if (nmove) { |
this_line--; |
|
} |
|
if (cur_line + adjust < this_line) { |
if (nflushd_lines == 0) { |
if (nflushd_lines == 0) { |
/* |
/* |
* Allow backup past first |
* Allow backup past first |
* line if nothing has been |
* line if nothing has been |
* flushed yet. |
* flushed yet. |
*/ |
*/ |
for (; nmove < 0; nmove++) { |
while (cur_line + adjust |
|
< this_line) { |
lnew = alloc_line(); |
lnew = alloc_line(); |
l->l_prev = lnew; |
l->l_prev = lnew; |
lnew->l_next = l; |
lnew->l_next = l; |
l = lines = lnew; |
l = lines = lnew; |
extra_lines++; |
extra_lines++; |
|
this_line--; |
} |
} |
} else { |
} else { |
if (!warned++) |
if (!warned++) |
dowarn(cur_line); |
dowarn(cur_line); |
cur_line -= nmove; |
cur_line = this_line - adjust; |
} |
} |
} |
} |
} else { |
} else { |
/* may need to allocate here */ |
/* may need to allocate here */ |
for (; nmove > 0 && l->l_next; nmove--) |
while (cur_line + adjust > this_line) { |
|
if (l->l_next == NULL) { |
|
l->l_next = alloc_line(); |
|
l->l_next->l_prev = l; |
|
} |
l = l->l_next; |
l = l->l_next; |
for (; nmove > 0; nmove--) { |
this_line++; |
lnew = alloc_line(); |
|
lnew->l_prev = l; |
|
l->l_next = lnew; |
|
l = lnew; |
|
} |
} |
} |
} |
this_line = cur_line + adjust; |
if (this_line > nflushd_lines && |
nmove = this_line - nflushd_lines; |
this_line - nflushd_lines >= |
if (nmove >= max_bufd_lines + BUFFER_MARGIN) { |
max_bufd_lines + BUFFER_MARGIN) { |
nflushd_lines += nmove - max_bufd_lines; |
if (extra_lines) { |
flush_lines(nmove - max_bufd_lines); |
flush_lines(extra_lines); |
|
extra_lines = 0; |
|
} |
|
flush_lines(this_line - nflushd_lines - |
|
max_bufd_lines); |
|
nflushd_lines = this_line - max_bufd_lines; |
} |
} |
} |
} |
/* grow line's buffer? */ |
/* grow line's buffer? */ |
|
|
l->l_max_col = cur_col; |
l->l_max_col = cur_col; |
cur_col++; |
cur_col++; |
} |
} |
if (max_line == 0) |
if (extra_lines) |
exit(0); /* no lines, so just exit */ |
flush_lines(extra_lines); |
|
|
/* goto the last line that had a character on it */ |
/* goto the last line that had a character on it */ |
for (; l->l_next; l = l->l_next) |
for (; l->l_next; l = l->l_next) |
this_line++; |
this_line++; |
flush_lines(this_line - nflushd_lines + extra_lines + 1); |
flush_lines(this_line - nflushd_lines + 1); |
|
|
/* make sure we leave things in a sane state */ |
/* make sure we leave things in a sane state */ |
if (last_set != CS_NORMAL) |
if (last_set != CS_NORMAL) |
PUTC('\017'); |
PUTC('\017'); |
|
|
/* flush out the last few blank lines */ |
/* flush out the last few blank lines */ |
nblank_lines = max_line - this_line; |
if (max_line > this_line) |
|
nblank_lines = max_line - this_line; |
if (max_line & 1) |
if (max_line & 1) |
nblank_lines++; |
nblank_lines++; |
else if (!nblank_lines) |
|
/* missing a \n on the last line? */ |
|
nblank_lines = 2; |
|
flush_blanks(); |
flush_blanks(); |
exit(0); |
exit(0); |
} |
} |
|
|
flush_blanks(); |
flush_blanks(); |
flush_line(l); |
flush_line(l); |
} |
} |
nblank_lines++; |
if (l->l_line || l->l_next) |
|
nblank_lines++; |
if (l->l_line) |
if (l->l_line) |
(void)free((void *)l->l_line); |
(void)free((void *)l->l_line); |
free_line(l); |
free_line(l); |
|
|
PUTC('\b'); |
PUTC('\b'); |
} |
} |
} |
} |
|
} |
|
|
|
/* |
|
* Increment or decrement a line number, checking for overflow. |
|
* Stop one below INT_MAX such that the adjust variable is safe. |
|
*/ |
|
void |
|
addto_lineno(int *lno, int offset) |
|
{ |
|
if (offset > 0) { |
|
if (*lno >= INT_MAX - offset) |
|
errx(1, "too many lines"); |
|
} else { |
|
if (*lno < INT_MIN - offset) |
|
errx(1, "too many reverse line feeds"); |
|
} |
|
*lno += offset; |
} |
} |
|
|
#define NALLOC 64 |
#define NALLOC 64 |