aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2015-08-04 09:46:24 +0100
committerRon Yorston <rmy@pobox.com>2015-08-04 09:46:24 +0100
commit64fde14d12cc5e6182f114ecaf4340ec1854c2f6 (patch)
tree4d2cabca7865dd74e2344834d89503c534fb502c /miscutils
parent7aabb625005c642d6a30d6d97b51bf183429152e (diff)
parent16aa7a73c40ba5dfaabaedb8a5533619cb8b6cb6 (diff)
downloadbusybox-w32-64fde14d12cc5e6182f114ecaf4340ec1854c2f6.tar.gz
busybox-w32-64fde14d12cc5e6182f114ecaf4340ec1854c2f6.tar.bz2
busybox-w32-64fde14d12cc5e6182f114ecaf4340ec1854c2f6.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/last_fancy.c4
-rw-r--r--miscutils/less.c324
2 files changed, 222 insertions, 106 deletions
diff --git a/miscutils/last_fancy.c b/miscutils/last_fancy.c
index 8194e31b5..e56e0ba85 100644
--- a/miscutils/last_fancy.c
+++ b/miscutils/last_fancy.c
@@ -233,7 +233,7 @@ int last_main(int argc UNUSED_PARAM, char **argv)
233 break; 233 break;
234 } 234 }
235 /* add_entry */ 235 /* add_entry */
236 llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut))); 236 llist_add_to(&zlist, xmemdup(&ut, sizeof(ut)));
237 break; 237 break;
238 case USER_PROCESS: { 238 case USER_PROCESS: {
239 int show; 239 int show;
@@ -275,7 +275,7 @@ int last_main(int argc UNUSED_PARAM, char **argv)
275 show_entry(&ut, state, boot_time); 275 show_entry(&ut, state, boot_time);
276 } 276 }
277 /* add_entry */ 277 /* add_entry */
278 llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut))); 278 llist_add_to(&zlist, xmemdup(&ut, sizeof(ut)));
279 break; 279 break;
280 } 280 }
281 } 281 }
diff --git a/miscutils/less.c b/miscutils/less.c
index d5a68d1e1..7a441bf7e 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -48,6 +48,14 @@
48//config: help 48//config: help
49//config: The -M/-m flag enables a more sophisticated status line. 49//config: The -M/-m flag enables a more sophisticated status line.
50//config: 50//config:
51//config:config FEATURE_LESS_TRUNCATE
52//config: bool "Enable -S"
53//config: default y
54//config: depends on LESS
55//config: help
56//config: The -S flag causes long lines to be truncated rather than
57//config: wrapped.
58//config:
51//config:config FEATURE_LESS_MARKS 59//config:config FEATURE_LESS_MARKS
52//config: bool "Enable marks" 60//config: bool "Enable marks"
53//config: default y 61//config: default y
@@ -98,7 +106,8 @@
98//config: Enables "-N" command. 106//config: Enables "-N" command.
99 107
100//usage:#define less_trivial_usage 108//usage:#define less_trivial_usage
101//usage: "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm") "Nh~] [FILE]..." 109//usage: "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm")
110//usage: "N" IF_FEATURE_LESS_TRUNCATE("S") "h~] [FILE]..."
102//usage:#define less_full_usage "\n\n" 111//usage:#define less_full_usage "\n\n"
103//usage: "View FILE (or stdin) one screenful at a time\n" 112//usage: "View FILE (or stdin) one screenful at a time\n"
104//usage: "\n -E Quit once the end of a file is reached" 113//usage: "\n -E Quit once the end of a file is reached"
@@ -110,6 +119,9 @@
110//usage: "\n and percentage through the file" 119//usage: "\n and percentage through the file"
111//usage: ) 120//usage: )
112//usage: "\n -N Prefix line number to each line" 121//usage: "\n -N Prefix line number to each line"
122//usage: IF_FEATURE_LESS_TRUNCATE(
123//usage: "\n -S Truncate long lines"
124//usage: )
113//usage: "\n -~ Suppress ~s displayed past EOF" 125//usage: "\n -~ Suppress ~s displayed past EOF"
114 126
115#include <sched.h> /* sched_yield() */ 127#include <sched.h> /* sched_yield() */
@@ -144,7 +156,7 @@ enum {
144 FLAG_N = 1 << 3, 156 FLAG_N = 1 << 3,
145 FLAG_TILDE = 1 << 4, 157 FLAG_TILDE = 1 << 4,
146 FLAG_I = 1 << 5, 158 FLAG_I = 1 << 5,
147 FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_DASHCMD, 159 FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_TRUNCATE,
148/* hijack command line options variable for internal state vars */ 160/* hijack command line options variable for internal state vars */
149 LESS_STATE_MATCH_BACKWARDS = 1 << 15, 161 LESS_STATE_MATCH_BACKWARDS = 1 << 15,
150}; 162};
@@ -176,6 +188,12 @@ struct globals {
176 unsigned current_file; 188 unsigned current_file;
177 char *filename; 189 char *filename;
178 char **files; 190 char **files;
191#if ENABLE_FEATURE_LESS_FLAGS
192 int num_lines; /* a flag if < 0, line count if >= 0 */
193# define REOPEN_AND_COUNT (-1)
194# define REOPEN_STDIN (-2)
195# define NOT_REGULAR_FILE (-3)
196#endif
179#if ENABLE_FEATURE_LESS_MARKS 197#if ENABLE_FEATURE_LESS_MARKS
180 unsigned num_marks; 198 unsigned num_marks;
181 unsigned mark_lines[15][2]; 199 unsigned mark_lines[15][2];
@@ -217,6 +235,7 @@ struct globals {
217#define current_file (G.current_file ) 235#define current_file (G.current_file )
218#define filename (G.filename ) 236#define filename (G.filename )
219#define files (G.files ) 237#define files (G.files )
238#define num_lines (G.num_lines )
220#define num_marks (G.num_marks ) 239#define num_marks (G.num_marks )
221#define mark_lines (G.mark_lines ) 240#define mark_lines (G.mark_lines )
222#if ENABLE_FEATURE_LESS_REGEXP 241#if ENABLE_FEATURE_LESS_REGEXP
@@ -319,8 +338,10 @@ static void re_wrap(void)
319 *d = *s; 338 *d = *s;
320 if (*d != '\0') { 339 if (*d != '\0') {
321 new_line_pos++; 340 new_line_pos++;
322 if (*d == '\t') /* tab */ 341 if (*d == '\t') { /* tab */
323 new_line_pos += 7; 342 new_line_pos += 7;
343 new_line_pos &= (~7);
344 }
324 s++; 345 s++;
325 d++; 346 d++;
326 if (new_line_pos >= w) { 347 if (new_line_pos >= w) {
@@ -382,6 +403,14 @@ static void fill_match_lines(unsigned pos);
382#define fill_match_lines(pos) ((void)0) 403#define fill_match_lines(pos) ((void)0)
383#endif 404#endif
384 405
406static int at_end(void)
407{
408 return (option_mask32 & FLAG_S)
409 ? !(cur_fline <= max_fline &&
410 max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
411 : !(max_fline > cur_fline + max_displayed_line);
412}
413
385/* Devilishly complex routine. 414/* Devilishly complex routine.
386 * 415 *
387 * Has to deal with EOF and EPIPE on input, 416 * Has to deal with EOF and EPIPE on input,
@@ -480,16 +509,6 @@ static void read_lines(void)
480 *--p = '\0'; 509 *--p = '\0';
481 continue; 510 continue;
482 } 511 }
483 {
484 size_t new_last_line_pos = last_line_pos + 1;
485 if (c == '\t') {
486 new_last_line_pos += 7;
487 new_last_line_pos &= (~7);
488 }
489 if ((int)new_last_line_pos >= w)
490 break;
491 last_line_pos = new_last_line_pos;
492 }
493 /* ok, we will eat this char */ 512 /* ok, we will eat this char */
494 readpos++; 513 readpos++;
495 if (c == '\n') { 514 if (c == '\n') {
@@ -501,6 +520,16 @@ static void read_lines(void)
501 if (c == '\0') c = '\n'; 520 if (c == '\0') c = '\n';
502 *p++ = c; 521 *p++ = c;
503 *p = '\0'; 522 *p = '\0';
523 {
524 size_t new_last_line_pos = last_line_pos + 1;
525 if (c == '\t') {
526 new_last_line_pos += 7;
527 new_last_line_pos &= (~7);
528 }
529 if ((int)new_last_line_pos >= w)
530 break;
531 last_line_pos = new_last_line_pos;
532 }
504 } /* end of "read chars until we have a line" loop */ 533 } /* end of "read chars until we have a line" loop */
505#if 0 534#if 0
506//BUG: also triggers on this: 535//BUG: also triggers on this:
@@ -528,11 +557,7 @@ static void read_lines(void)
528 eof_error = 0; /* Pretend we saw EOF */ 557 eof_error = 0; /* Pretend we saw EOF */
529 break; 558 break;
530 } 559 }
531 if (!(option_mask32 & FLAG_S) 560 if (!at_end()) {
532 ? (max_fline > cur_fline + max_displayed_line)
533 : (max_fline >= cur_fline
534 && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
535 ) {
536#if !ENABLE_FEATURE_LESS_REGEXP 561#if !ENABLE_FEATURE_LESS_REGEXP
537 break; 562 break;
538#else 563#else
@@ -560,6 +585,10 @@ static void read_lines(void)
560 print_statusline(bb_msg_read_error); 585 print_statusline(bb_msg_read_error);
561 } 586 }
562 } 587 }
588#if ENABLE_FEATURE_LESS_FLAGS
589 else if (eof_error == 0)
590 num_lines = max_lineno;
591#endif
563 592
564 fill_match_lines(old_max_fline); 593 fill_match_lines(old_max_fline);
565#if ENABLE_FEATURE_LESS_REGEXP 594#if ENABLE_FEATURE_LESS_REGEXP
@@ -570,18 +599,61 @@ static void read_lines(void)
570} 599}
571 600
572#if ENABLE_FEATURE_LESS_FLAGS 601#if ENABLE_FEATURE_LESS_FLAGS
573/* Interestingly, writing calc_percent as a function saves around 32 bytes 602static int safe_lineno(int fline)
574 * on my build. */
575static int calc_percent(void)
576{ 603{
577 unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1); 604 if (fline >= max_fline)
578 return p <= 100 ? p : 100; 605 fline = max_fline - 1;
606
607 /* also catches empty file (max_fline == 0) */
608 if (fline < 0)
609 return 0;
610
611 return LINENO(flines[fline]) + 1;
612}
613
614/* count number of lines in file */
615static void update_num_lines(void)
616{
617 int count, fd;
618 struct stat stbuf;
619 ssize_t len, i;
620 char buf[4096];
621
622 /* only do this for regular files */
623 if (num_lines == REOPEN_AND_COUNT || num_lines == REOPEN_STDIN) {
624 count = 0;
625 fd = open("/proc/self/fd/0", O_RDONLY);
626 if (fd < 0 && num_lines == REOPEN_AND_COUNT) {
627 /* "filename" is valid only if REOPEN_AND_COUNT */
628 fd = open(filename, O_RDONLY);
629 }
630 if (fd < 0) {
631 /* somebody stole my file! */
632 num_lines = NOT_REGULAR_FILE;
633 return;
634 }
635 if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) {
636 num_lines = NOT_REGULAR_FILE;
637 goto do_close;
638 }
639 while ((len = safe_read(fd, buf, sizeof(buf))) > 0) {
640 for (i = 0; i < len; ++i) {
641 if (buf[i] == '\n' && ++count == MAXLINES)
642 goto done;
643 }
644 }
645 done:
646 num_lines = count;
647 do_close:
648 close(fd);
649 }
579} 650}
580 651
581/* Print a status line if -M was specified */ 652/* Print a status line if -M was specified */
582static void m_status_print(void) 653static void m_status_print(void)
583{ 654{
584 int percentage; 655 int first, last;
656 unsigned percent;
585 657
586 if (less_gets_pos >= 0) /* don't touch statusline while input is done! */ 658 if (less_gets_pos >= 0) /* don't touch statusline while input is done! */
587 return; 659 return;
@@ -590,17 +662,26 @@ static void m_status_print(void)
590 printf(HIGHLIGHT"%s", filename); 662 printf(HIGHLIGHT"%s", filename);
591 if (num_files > 1) 663 if (num_files > 1)
592 printf(" (file %i of %i)", current_file, num_files); 664 printf(" (file %i of %i)", current_file, num_files);
593 printf(" lines %i-%i/%i ", 665
594 cur_fline + 1, cur_fline + max_displayed_line + 1, 666 first = safe_lineno(cur_fline);
595 max_fline + 1); 667 last = (option_mask32 & FLAG_S)
596 if (cur_fline >= (int)(max_fline - max_displayed_line)) { 668 ? MIN(first + max_displayed_line, max_lineno)
597 printf("(END)"NORMAL); 669 : safe_lineno(cur_fline + max_displayed_line);
670 printf(" lines %i-%i", first, last);
671
672 update_num_lines();
673 if (num_lines >= 0)
674 printf("/%i", num_lines);
675
676 if (at_end()) {
677 printf(" (END)");
598 if (num_files > 1 && current_file != num_files) 678 if (num_files > 1 && current_file != num_files)
599 printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]); 679 printf(" - next: %s", files[current_file]);
600 return; 680 } else if (num_lines > 0) {
681 percent = (100 * last + num_lines/2) / num_lines;
682 printf(" %i%%", percent <= 100 ? percent : 100);
601 } 683 }
602 percentage = calc_percent(); 684 printf(NORMAL);
603 printf("%i%%"NORMAL, percentage);
604} 685}
605#endif 686#endif
606 687
@@ -622,7 +703,7 @@ static void status_print(void)
622#endif 703#endif
623 704
624 clear_line(); 705 clear_line();
625 if (cur_fline && cur_fline < (int)(max_fline - max_displayed_line)) { 706 if (cur_fline && !at_end()) {
626 bb_putchar(':'); 707 bb_putchar(':');
627 return; 708 return;
628 } 709 }
@@ -637,23 +718,6 @@ static void status_print(void)
637 print_hilite(p); 718 print_hilite(p);
638} 719}
639 720
640static void cap_cur_fline(int nlines)
641{
642 int diff;
643 if (cur_fline < 0)
644 cur_fline = 0;
645 if (cur_fline + max_displayed_line > max_fline + TILDES) {
646 cur_fline -= nlines;
647 if (cur_fline < 0)
648 cur_fline = 0;
649 diff = max_fline - (cur_fline + max_displayed_line) + TILDES;
650 /* As the number of lines requested was too large, we just move
651 * to the end of the file */
652 if (diff > 0)
653 cur_fline += diff;
654 }
655}
656
657static const char controls[] ALIGN1 = 721static const char controls[] ALIGN1 =
658 /* NUL: never encountered; TAB: not converted */ 722 /* NUL: never encountered; TAB: not converted */
659 /**/"\x01\x02\x03\x04\x05\x06\x07\x08" "\x0a\x0b\x0c\x0d\x0e\x0f" 723 /**/"\x01\x02\x03\x04\x05\x06\x07\x08" "\x0a\x0b\x0c\x0d\x0e\x0f"
@@ -665,27 +729,21 @@ static const char ctrlconv[] ALIGN1 =
665 "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f" 729 "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f"
666 "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"; 730 "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f";
667 731
668static void lineno_str(char *nbuf9, const char *line) 732static void print_lineno(const char *line)
669{ 733{
670 nbuf9[0] = '\0'; 734 const char *fmt = " ";
671 if (option_mask32 & FLAG_N) { 735 unsigned n = n; /* for compiler */
672 const char *fmt; 736
673 unsigned n; 737 if (line != empty_line_marker) {
674
675 if (line == empty_line_marker) {
676 memset(nbuf9, ' ', 8);
677 nbuf9[8] = '\0';
678 return;
679 }
680 /* Width of 7 preserves tab spacing in the text */ 738 /* Width of 7 preserves tab spacing in the text */
681 fmt = "%7u "; 739 fmt = "%7u ";
682 n = LINENO(line) + 1; 740 n = LINENO(line) + 1;
683 if (n > 9999999) { 741 if (n > 9999999 && MAXLINES > 9999999) {
684 n %= 10000000; 742 n %= 10000000;
685 fmt = "%07u "; 743 fmt = "%07u ";
686 } 744 }
687 sprintf(nbuf9, fmt, n);
688 } 745 }
746 printf(fmt, n);
689} 747}
690 748
691 749
@@ -698,7 +756,6 @@ static void print_found(const char *line)
698 regmatch_t match_structs; 756 regmatch_t match_structs;
699 757
700 char buf[width]; 758 char buf[width];
701 char nbuf9[9];
702 const char *str = line; 759 const char *str = line;
703 char *p = buf; 760 char *p = buf;
704 size_t n; 761 size_t n;
@@ -748,12 +805,7 @@ static void print_found(const char *line)
748 match_status = 1; 805 match_status = 1;
749 } 806 }
750 807
751 lineno_str(nbuf9, line); 808 printf("%s%s\n", growline ? growline : "", str);
752 if (!growline) {
753 printf(CLEAR_2_EOL"%s%s\n", nbuf9, str);
754 return;
755 }
756 printf(CLEAR_2_EOL"%s%s%s\n", nbuf9, growline, str);
757 free(growline); 809 free(growline);
758} 810}
759#else 811#else
@@ -763,13 +815,9 @@ void print_found(const char *line);
763static void print_ascii(const char *str) 815static void print_ascii(const char *str)
764{ 816{
765 char buf[width]; 817 char buf[width];
766 char nbuf9[9];
767 char *p; 818 char *p;
768 size_t n; 819 size_t n;
769 820
770 lineno_str(nbuf9, str);
771 printf(CLEAR_2_EOL"%s", nbuf9);
772
773 while (*str) { 821 while (*str) {
774 n = strcspn(str, controls); 822 n = strcspn(str, controls);
775 if (n) { 823 if (n) {
@@ -803,6 +851,9 @@ static void buffer_print(void)
803 851
804 move_cursor(0, 0); 852 move_cursor(0, 0);
805 for (i = 0; i <= max_displayed_line; i++) { 853 for (i = 0; i <= max_displayed_line; i++) {
854 printf(CLEAR_2_EOL);
855 if (option_mask32 & FLAG_N)
856 print_lineno(buffer[i]);
806 if (pattern_valid) 857 if (pattern_valid)
807 print_found(buffer[i]); 858 print_found(buffer[i]);
808 else 859 else
@@ -820,7 +871,7 @@ static void buffer_print(void)
820static void buffer_fill_and_print(void) 871static void buffer_fill_and_print(void)
821{ 872{
822 unsigned i; 873 unsigned i;
823#if ENABLE_FEATURE_LESS_DASHCMD 874#if ENABLE_FEATURE_LESS_TRUNCATE
824 int fpos = cur_fline; 875 int fpos = cur_fline;
825 876
826 if (option_mask32 & FLAG_S) { 877 if (option_mask32 & FLAG_S) {
@@ -852,45 +903,112 @@ static void buffer_fill_and_print(void)
852 buffer_print(); 903 buffer_print();
853} 904}
854 905
906/* move cur_fline to a given line number, reading lines if necessary */
907static void goto_lineno(int target)
908{
909 if (target <= 0 ) {
910 cur_fline = 0;
911 }
912 else if (target > LINENO(flines[cur_fline])) {
913 retry:
914 while (LINENO(flines[cur_fline]) != target && cur_fline < max_fline)
915 ++cur_fline;
916 /* target not reached but more input is available */
917 if (LINENO(flines[cur_fline]) != target && eof_error > 0) {
918 read_lines();
919 goto retry;
920 }
921 }
922 else {
923 /* search backwards through already-read lines */
924 while (LINENO(flines[cur_fline]) != target && cur_fline > 0)
925 --cur_fline;
926 }
927}
928
929static void cap_cur_fline(void)
930{
931 if ((option_mask32 & FLAG_S)) {
932 if (cur_fline > max_fline)
933 cur_fline = max_fline;
934 if (LINENO(flines[cur_fline]) + max_displayed_line > max_lineno + TILDES) {
935 goto_lineno(max_lineno - max_displayed_line + TILDES);
936 read_lines();
937 }
938 }
939 else {
940 if (cur_fline + max_displayed_line > max_fline + TILDES)
941 cur_fline = max_fline - max_displayed_line + TILDES;
942 if (cur_fline < 0)
943 cur_fline = 0;
944 }
945}
946
855/* Move the buffer up and down in the file in order to scroll */ 947/* Move the buffer up and down in the file in order to scroll */
856static void buffer_down(int nlines) 948static void buffer_down(int nlines)
857{ 949{
858 cur_fline += nlines; 950 if ((option_mask32 & FLAG_S))
951 goto_lineno(LINENO(flines[cur_fline]) + nlines);
952 else
953 cur_fline += nlines;
859 read_lines(); 954 read_lines();
860 cap_cur_fline(nlines); 955 cap_cur_fline();
861 buffer_fill_and_print(); 956 buffer_fill_and_print();
862} 957}
863 958
864static void buffer_up(int nlines) 959static void buffer_up(int nlines)
865{ 960{
866 cur_fline -= nlines; 961 if ((option_mask32 & FLAG_S)) {
867 if (cur_fline < 0) cur_fline = 0; 962 goto_lineno(LINENO(flines[cur_fline]) - nlines);
963 }
964 else {
965 cur_fline -= nlines;
966 if (cur_fline < 0)
967 cur_fline = 0;
968 }
868 read_lines(); 969 read_lines();
869 buffer_fill_and_print(); 970 buffer_fill_and_print();
870} 971}
871 972
872static void buffer_line(int linenum) 973/* display a given line where the argument can be either an index into
974 * the flines array or a line number */
975static void buffer_to_line(int linenum, int is_lineno)
873{ 976{
874 if (linenum < 0) 977 if (linenum <= 0)
875 linenum = 0; 978 cur_fline = 0;
876 cur_fline = linenum; 979 else if (is_lineno)
980 goto_lineno(linenum);
981 else
982 cur_fline = linenum;
877 read_lines(); 983 read_lines();
878 if (linenum + max_displayed_line > max_fline) 984 cap_cur_fline();
879 linenum = max_fline - max_displayed_line + TILDES;
880 if (linenum < 0)
881 linenum = 0;
882 cur_fline = linenum;
883 buffer_fill_and_print(); 985 buffer_fill_and_print();
884} 986}
885 987
988static void buffer_line(int linenum)
989{
990 buffer_to_line(linenum, FALSE);
991}
992
993static void buffer_lineno(int lineno)
994{
995 buffer_to_line(lineno, TRUE);
996}
997
886static void open_file_and_read_lines(void) 998static void open_file_and_read_lines(void)
887{ 999{
888 if (filename) { 1000 if (filename) {
889 xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO); 1001 xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO);
1002#if ENABLE_FEATURE_LESS_FLAGS
1003 num_lines = REOPEN_AND_COUNT;
1004#endif
890 } else { 1005 } else {
891 /* "less" with no arguments in argv[] */ 1006 /* "less" with no arguments in argv[] */
892 /* For status line only */ 1007 /* For status line only */
893 filename = xstrdup(bb_msg_standard_input); 1008 filename = xstrdup(bb_msg_standard_input);
1009#if ENABLE_FEATURE_LESS_FLAGS
1010 num_lines = REOPEN_STDIN;
1011#endif
894 } 1012 }
895 readpos = 0; 1013 readpos = 0;
896 readeof = 0; 1014 readeof = 0;
@@ -942,12 +1060,7 @@ static int64_t getch_nowait(void)
942 */ 1060 */
943 rd = 1; 1061 rd = 1;
944 /* Are we interested in stdin? */ 1062 /* Are we interested in stdin? */
945//TODO: reuse code for determining this 1063 if (at_end()) {
946 if (!(option_mask32 & FLAG_S)
947 ? !(max_fline > cur_fline + max_displayed_line)
948 : !(max_fline >= cur_fline
949 && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
950 ) {
951 if (eof_error > 0) /* did NOT reach eof yet */ 1064 if (eof_error > 0) /* did NOT reach eof yet */
952 rd = 0; /* yes, we are interested in stdin */ 1065 rd = 0; /* yes, we are interested in stdin */
953 } 1066 }
@@ -1258,7 +1371,7 @@ static void number_process(int first_digit)
1258 i = 1; 1371 i = 1;
1259 while (i < sizeof(num_input)-1) { 1372 while (i < sizeof(num_input)-1) {
1260 keypress = less_getch(i + 1); 1373 keypress = less_getch(i + 1);
1261 if ((unsigned)keypress > 255 || !isdigit(num_input[i])) 1374 if ((unsigned)keypress > 255 || !isdigit(keypress))
1262 break; 1375 break;
1263 num_input[i] = keypress; 1376 num_input[i] = keypress;
1264 bb_putchar(keypress); 1377 bb_putchar(keypress);
@@ -1282,15 +1395,16 @@ static void number_process(int first_digit)
1282 buffer_up(num); 1395 buffer_up(num);
1283 break; 1396 break;
1284 case 'g': case '<': case 'G': case '>': 1397 case 'g': case '<': case 'G': case '>':
1285 cur_fline = num + max_displayed_line; 1398 buffer_lineno(num - 1);
1286 read_lines();
1287 buffer_line(num - 1);
1288 break; 1399 break;
1289 case 'p': case '%': 1400 case 'p': case '%':
1290 num = num * (max_fline / 100); /* + max_fline / 2; */ 1401#if ENABLE_FEATURE_LESS_FLAGS
1291 cur_fline = num + max_displayed_line; 1402 update_num_lines();
1292 read_lines(); 1403 num = num * (num_lines > 0 ? num_lines : max_lineno) / 100;
1293 buffer_line(num); 1404#else
1405 num = num * max_lineno / 100;
1406#endif
1407 buffer_lineno(num);
1294 break; 1408 break;
1295#if ENABLE_FEATURE_LESS_REGEXP 1409#if ENABLE_FEATURE_LESS_REGEXP
1296 case 'n': 1410 case 'n':
@@ -1330,10 +1444,12 @@ static void flag_change(void)
1330 case '~': 1444 case '~':
1331 option_mask32 ^= FLAG_TILDE; 1445 option_mask32 ^= FLAG_TILDE;
1332 break; 1446 break;
1447#if ENABLE_FEATURE_LESS_TRUNCATE
1333 case 'S': 1448 case 'S':
1334 option_mask32 ^= FLAG_S; 1449 option_mask32 ^= FLAG_S;
1335 buffer_fill_and_print(); 1450 buffer_fill_and_print();
1336 break; 1451 break;
1452#endif
1337#if ENABLE_FEATURE_LESS_LINENUMS 1453#if ENABLE_FEATURE_LESS_LINENUMS
1338 case 'N': 1454 case 'N':
1339 option_mask32 ^= FLAG_N; 1455 option_mask32 ^= FLAG_N;
@@ -1638,7 +1754,7 @@ int less_main(int argc, char **argv)
1638 * -s: condense many empty lines to one 1754 * -s: condense many empty lines to one
1639 * (used by some setups for manpage display) 1755 * (used by some setups for manpage display)
1640 */ 1756 */
1641 getopt32(argv, "EMmN~I" IF_FEATURE_LESS_DASHCMD("S") /*ignored:*/"s"); 1757 getopt32(argv, "EMmN~I" IF_FEATURE_LESS_TRUNCATE("S") /*ignored:*/"s");
1642 argc -= optind; 1758 argc -= optind;
1643 argv += optind; 1759 argv += optind;
1644 num_files = argc; 1760 num_files = argc;