diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-23 22:02:30 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-23 22:02:30 +0000 |
commit | 8f39b72aba3fbb360ea46c6124c9ac90e54372f6 (patch) | |
tree | d906a485b128ed12be69f75b096f9f3475b1dba3 | |
parent | 2dfd295726a0e71c5901214b78cc13a0775a4102 (diff) | |
download | busybox-w32-8f39b72aba3fbb360ea46c6124c9ac90e54372f6.tar.gz busybox-w32-8f39b72aba3fbb360ea46c6124c9ac90e54372f6.tar.bz2 busybox-w32-8f39b72aba3fbb360ea46c6124c9ac90e54372f6.zip |
less: more sane way of line numbering. Prepares for
wrap/unwrap and line numbers to be toggleable.
-rw-r--r-- | miscutils/less.c | 75 |
1 files changed, 53 insertions, 22 deletions
diff --git a/miscutils/less.c b/miscutils/less.c index cd47590ee..049814319 100644 --- a/miscutils/less.c +++ b/miscutils/less.c | |||
@@ -166,6 +166,14 @@ struct globals { | |||
166 | USE_FEATURE_LESS_REGEXP(wanted_match = -1;) \ | 166 | USE_FEATURE_LESS_REGEXP(wanted_match = -1;) \ |
167 | } while (0) | 167 | } while (0) |
168 | 168 | ||
169 | /* flines[] are lines read from stdin, each in malloc'ed buffer. | ||
170 | * Line numbers are stored as uint32_t prepended to each line. | ||
171 | * Pointer is adjusted so that flines[i] points directly past | ||
172 | * line number. Accesor: */ | ||
173 | #define MEMPTR(p) ((char*)(p) - 4) | ||
174 | #define LINENO(p) (*(uint32_t*)((p) - 4)) | ||
175 | |||
176 | |||
169 | /* Reset terminal input to normal */ | 177 | /* Reset terminal input to normal */ |
170 | static void set_tty_cooked(void) | 178 | static void set_tty_cooked(void) |
171 | { | 179 | { |
@@ -252,15 +260,13 @@ static void read_lines(void) | |||
252 | 260 | ||
253 | USE_FEATURE_LESS_REGEXP(again0:) | 261 | USE_FEATURE_LESS_REGEXP(again0:) |
254 | 262 | ||
255 | p = current_line = xmalloc(w); | 263 | p = current_line = ((char*)xmalloc(w + 4)) + 4; |
256 | max_fline += last_terminated; | 264 | max_fline += last_terminated; |
257 | if (!last_terminated) { | 265 | if (!last_terminated) { |
258 | const char *cp = flines[max_fline]; | 266 | const char *cp = flines[max_fline]; |
259 | if (option_mask32 & FLAG_N) | 267 | strcpy(p, cp); |
260 | cp += 8; | ||
261 | strcpy(current_line, cp); | ||
262 | p += strlen(current_line); | 268 | p += strlen(current_line); |
263 | free((char*)flines[max_fline]); | 269 | free(MEMPTR(flines[max_fline])); |
264 | /* linepos is still valid from previous read_lines() */ | 270 | /* linepos is still valid from previous read_lines() */ |
265 | } else { | 271 | } else { |
266 | linepos = 0; | 272 | linepos = 0; |
@@ -324,17 +330,12 @@ static void read_lines(void) | |||
324 | reached_eof: | 330 | reached_eof: |
325 | last_terminated = terminated; | 331 | last_terminated = terminated; |
326 | flines = xrealloc_vector(flines, 8, max_fline); | 332 | flines = xrealloc_vector(flines, 8, max_fline); |
327 | if (option_mask32 & FLAG_N) { | 333 | |
328 | /* Width of 7 preserves tab spacing in the text */ | 334 | flines[max_fline] = (char*)xrealloc(MEMPTR(current_line), strlen(current_line) + 1 + 4) + 4; |
329 | flines[max_fline] = xasprintf( | 335 | LINENO(flines[max_fline]) = max_lineno; |
330 | (max_lineno <= 9999999) ? "%7u %s" : "%07u %s", | 336 | if (terminated) |
331 | max_lineno % 10000000, current_line); | 337 | max_lineno++; |
332 | free(current_line); | 338 | |
333 | if (terminated) | ||
334 | max_lineno++; | ||
335 | } else { | ||
336 | flines[max_fline] = xrealloc(current_line, strlen(current_line) + 1); | ||
337 | } | ||
338 | if (max_fline >= MAXLINES) { | 339 | if (max_fline >= MAXLINES) { |
339 | eof_error = 0; /* Pretend we saw EOF */ | 340 | eof_error = 0; /* Pretend we saw EOF */ |
340 | break; | 341 | break; |
@@ -380,7 +381,7 @@ static void read_lines(void) | |||
380 | #endif | 381 | #endif |
381 | } | 382 | } |
382 | max_fline++; | 383 | max_fline++; |
383 | current_line = xmalloc(w); | 384 | current_line = ((char*)xmalloc(w + 4)) + 4; |
384 | p = current_line; | 385 | p = current_line; |
385 | linepos = 0; | 386 | linepos = 0; |
386 | } /* end of "read lines until we reach cur_fline" loop */ | 387 | } /* end of "read lines until we reach cur_fline" loop */ |
@@ -487,6 +488,30 @@ static const char ctrlconv[] ALIGN1 = | |||
487 | "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f" | 488 | "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f" |
488 | "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"; | 489 | "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"; |
489 | 490 | ||
491 | static void lineno_str(char *nbuf9, const char *line) | ||
492 | { | ||
493 | nbuf9[0] = '\0'; | ||
494 | if (option_mask32 & FLAG_N) { | ||
495 | const char *fmt; | ||
496 | unsigned n; | ||
497 | |||
498 | if (line == empty_line_marker) { | ||
499 | memset(nbuf9, ' ', 8); | ||
500 | nbuf9[8] = '\0'; | ||
501 | return; | ||
502 | } | ||
503 | /* Width of 7 preserves tab spacing in the text */ | ||
504 | fmt = "%7u "; | ||
505 | n = LINENO(line); | ||
506 | if (n > 9999999) { | ||
507 | n %= 10000000; | ||
508 | fmt = "%07u "; | ||
509 | } | ||
510 | sprintf(nbuf9, fmt, n); | ||
511 | } | ||
512 | } | ||
513 | |||
514 | |||
490 | #if ENABLE_FEATURE_LESS_REGEXP | 515 | #if ENABLE_FEATURE_LESS_REGEXP |
491 | static void print_found(const char *line) | 516 | static void print_found(const char *line) |
492 | { | 517 | { |
@@ -496,6 +521,7 @@ static void print_found(const char *line) | |||
496 | regmatch_t match_structs; | 521 | regmatch_t match_structs; |
497 | 522 | ||
498 | char buf[width]; | 523 | char buf[width]; |
524 | char nbuf9[9]; | ||
499 | const char *str = line; | 525 | const char *str = line; |
500 | char *p = buf; | 526 | char *p = buf; |
501 | size_t n; | 527 | size_t n; |
@@ -532,7 +558,8 @@ static void print_found(const char *line) | |||
532 | match_structs.rm_so, str, | 558 | match_structs.rm_so, str, |
533 | match_structs.rm_eo - match_structs.rm_so, | 559 | match_structs.rm_eo - match_structs.rm_so, |
534 | str + match_structs.rm_so); | 560 | str + match_structs.rm_so); |
535 | free(growline); growline = new; | 561 | free(growline); |
562 | growline = new; | ||
536 | str += match_structs.rm_eo; | 563 | str += match_structs.rm_eo; |
537 | line += match_structs.rm_eo; | 564 | line += match_structs.rm_eo; |
538 | eflags = REG_NOTBOL; | 565 | eflags = REG_NOTBOL; |
@@ -544,11 +571,12 @@ static void print_found(const char *line) | |||
544 | match_status = 1; | 571 | match_status = 1; |
545 | } | 572 | } |
546 | 573 | ||
574 | lineno_str(nbuf9, line); | ||
547 | if (!growline) { | 575 | if (!growline) { |
548 | printf(CLEAR_2_EOL"%s\n", str); | 576 | printf(CLEAR_2_EOL"%s%s\n", nbuf9, str); |
549 | return; | 577 | return; |
550 | } | 578 | } |
551 | printf(CLEAR_2_EOL"%s%s\n", growline, str); | 579 | printf(CLEAR_2_EOL"%s%s%s\n", nbuf9, growline, str); |
552 | free(growline); | 580 | free(growline); |
553 | } | 581 | } |
554 | #else | 582 | #else |
@@ -558,10 +586,13 @@ void print_found(const char *line); | |||
558 | static void print_ascii(const char *str) | 586 | static void print_ascii(const char *str) |
559 | { | 587 | { |
560 | char buf[width]; | 588 | char buf[width]; |
589 | char nbuf9[9]; | ||
561 | char *p; | 590 | char *p; |
562 | size_t n; | 591 | size_t n; |
563 | 592 | ||
564 | printf(CLEAR_2_EOL); | 593 | lineno_str(nbuf9, str); |
594 | printf(CLEAR_2_EOL"%s", nbuf9); | ||
595 | |||
565 | while (*str) { | 596 | while (*str) { |
566 | n = strcspn(str, controls); | 597 | n = strcspn(str, controls); |
567 | if (n) { | 598 | if (n) { |
@@ -670,7 +701,7 @@ static void reinitialize(void) | |||
670 | 701 | ||
671 | if (flines) { | 702 | if (flines) { |
672 | for (i = 0; i <= max_fline; i++) | 703 | for (i = 0; i <= max_fline; i++) |
673 | free((void*)(flines[i])); | 704 | free(MEMPTR(flines[i])); |
674 | free(flines); | 705 | free(flines); |
675 | flines = NULL; | 706 | flines = NULL; |
676 | } | 707 | } |