1 /* $NetBSD: less.h,v 1.5 2023/10/06 05:49:49 simonb Exp $ */ 2 3 /* 4 * Copyright (C) 1984-2023 Mark Nudelman 5 * 6 * You may distribute under the terms of either the GNU General Public 7 * License or the Less License, as specified in the README file. 8 * 9 * For more information, see the README file. 10 */ 11 12 #define NEWBOT 1 13 14 /* 15 * Standard include file for "less". 16 */ 17 18 /* 19 * Defines for MSDOS_COMPILER. 20 */ 21 #define MSOFTC 1 /* Microsoft C */ 22 #define BORLANDC 2 /* Borland C */ 23 #define WIN32C 3 /* Windows (Borland C or Microsoft C) */ 24 #define DJGPPC 4 /* DJGPP C */ 25 26 /* 27 * Include the file of compile-time options. 28 * The <> make cc search for it in -I., not srcdir. 29 */ 30 #include <defines.h> 31 32 #ifdef _SEQUENT_ 33 /* 34 * Kludge for Sequent Dynix systems that have sigsetmask, but 35 * it's not compatible with the way less calls it. 36 * {{ Do other systems need this? }} 37 */ 38 #undef HAVE_SIGSETMASK 39 #endif 40 41 /* 42 * Language details. 43 */ 44 #if HAVE_CONST 45 #define constant const 46 #else 47 #define constant 48 #endif 49 50 #define public /* PUBLIC FUNCTION */ 51 52 /* Library function declarations */ 53 54 #if HAVE_SYS_TYPES_H 55 #include <sys/types.h> 56 #endif 57 #if HAVE_STDIO_H 58 #include <stdio.h> 59 #endif 60 #if HAVE_FCNTL_H 61 #include <fcntl.h> 62 #endif 63 #if HAVE_UNISTD_H 64 #include <unistd.h> 65 #endif 66 #if HAVE_CTYPE_H 67 #include <ctype.h> 68 #endif 69 #if HAVE_WCTYPE_H 70 #include <wctype.h> 71 #endif 72 #if HAVE_LIMITS_H 73 #include <limits.h> 74 #endif 75 #if HAVE_STDINT_H 76 #include <stdint.h> 77 #endif 78 #if HAVE_STDLIB_H 79 #include <stdlib.h> 80 #endif 81 #if HAVE_STRING_H 82 #include <string.h> 83 #endif 84 85 #if HAVE_STDCKDINT_H 86 #include <stdckdint.h> 87 #else 88 /* 89 * These substitutes for C23 stdckdint macros do not set *R on overflow, 90 * and they assume A and B are nonnegative. That is good enough for us. 91 */ 92 #define ckd_add(r, a, b) help_ckd_add(r, a, b, sizeof *(r), signed_expr(*(r))) 93 #define ckd_mul(r, a, b) help_ckd_mul(r, a, b, sizeof *(r), signed_expr(*(r))) 94 /* True if the integer expression E, after promotion, is signed. */ 95 #define signed_expr(e) ((TRUE ? 0 : e) - 1 < 0) 96 #endif 97 98 #if defined UINTMAX_MAX 99 typedef uintmax_t uintmax; 100 #elif defined ULLONG_MAX 101 typedef unsigned long long uintmax; 102 #else 103 typedef unsigned long uintmax; 104 #endif 105 106 /* OS-specific includes */ 107 #ifdef _OSK 108 #include <modes.h> 109 #include <strings.h> 110 #endif 111 112 #ifdef __TANDEM 113 #include <floss.h> 114 #endif 115 116 #if MSDOS_COMPILER==WIN32C || OS2 117 #include <io.h> 118 #endif 119 120 #if MSDOS_COMPILER==DJGPPC 121 #include <io.h> 122 #include <sys/exceptn.h> 123 #include <conio.h> 124 #include <pc.h> 125 #endif 126 127 #if !HAVE_STDLIB_H 128 char *getenv(); 129 off_t lseek(); 130 void *calloc(); 131 void free(); 132 #endif 133 134 /* 135 * Simple lowercase test which can be used during option processing 136 * (before options are parsed which might tell us what charset to use). 137 */ 138 #define ASCII_IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z') 139 #define ASCII_IS_LOWER(c) ((c) >= 'a' && (c) <= 'z') 140 #define ASCII_TO_UPPER(c) ((c) - 'a' + 'A') 141 #define ASCII_TO_LOWER(c) ((c) - 'A' + 'a') 142 143 #undef IS_UPPER 144 #undef IS_LOWER 145 #undef TO_UPPER 146 #undef TO_LOWER 147 #undef IS_SPACE 148 #undef IS_DIGIT 149 150 #if HAVE_WCTYPE 151 #define IS_UPPER(c) iswupper(c) 152 #define IS_LOWER(c) iswlower(c) 153 #define TO_UPPER(c) towupper(c) 154 #define TO_LOWER(c) towlower(c) 155 #else 156 #if HAVE_UPPER_LOWER 157 #define IS_UPPER(c) isupper((unsigned char) (c)) 158 #define IS_LOWER(c) islower((unsigned char) (c)) 159 #define TO_UPPER(c) toupper((unsigned char) (c)) 160 #define TO_LOWER(c) tolower((unsigned char) (c)) 161 #else 162 #define IS_UPPER(c) ASCII_IS_UPPER(c) 163 #define IS_LOWER(c) ASCII_IS_LOWER(c) 164 #define TO_UPPER(c) ASCII_TO_UPPER(c) 165 #define TO_LOWER(c) ASCII_TO_LOWER(c) 166 #endif 167 #endif 168 169 #ifdef isspace 170 #define IS_SPACE(c) isspace((unsigned char)(c)) 171 #else 172 #define IS_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == '\f') 173 #endif 174 175 #ifdef isdigit 176 #define IS_DIGIT(c) isdigit((unsigned char)(c)) 177 #else 178 #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') 179 #endif 180 181 #define IS_CSI_START(c) (((LWCHAR)(c)) == ESC || (((LWCHAR)(c)) == CSI)) 182 183 #ifndef NULL 184 #define NULL 0 185 #endif 186 187 #ifndef TRUE 188 #define TRUE 1 189 #endif 190 #ifndef FALSE 191 #define FALSE 0 192 #endif 193 194 #define OPT_OFF 0 195 #define OPT_ON 1 196 #define OPT_ONPLUS 2 197 198 #if !HAVE_MEMCPY 199 #ifndef memcpy 200 #define memcpy(to,from,len) bcopy((from),(to),(len)) 201 #endif 202 #endif 203 204 #if HAVE_SNPRINTF 205 #define SNPRINTF1(str, size, fmt, v1) snprintf((str), (size), (fmt), (v1)) 206 #define SNPRINTF2(str, size, fmt, v1, v2) snprintf((str), (size), (fmt), (v1), (v2)) 207 #define SNPRINTF3(str, size, fmt, v1, v2, v3) snprintf((str), (size), (fmt), (v1), (v2), (v3)) 208 #define SNPRINTF4(str, size, fmt, v1, v2, v3, v4) snprintf((str), (size), (fmt), (v1), (v2), (v3), (v4)) 209 #else 210 /* Use unsafe sprintf if we don't have snprintf. */ 211 #define SNPRINTF1(str, size, fmt, v1) sprintf((str), (fmt), (v1)) 212 #define SNPRINTF2(str, size, fmt, v1, v2) sprintf((str), (fmt), (v1), (v2)) 213 #define SNPRINTF3(str, size, fmt, v1, v2, v3) sprintf((str), (fmt), (v1), (v2), (v3)) 214 #define SNPRINTF4(str, size, fmt, v1, v2, v3, v4) sprintf((str), (fmt), (v1), (v2), (v3), (v4)) 215 #endif 216 217 #define BAD_LSEEK ((off_t)-1) 218 219 #ifndef SEEK_SET 220 #define SEEK_SET 0 221 #endif 222 #ifndef SEEK_END 223 #define SEEK_END 2 224 #endif 225 226 #ifndef CHAR_BIT 227 #define CHAR_BIT 8 228 #endif 229 230 /* 231 * Upper bound on the string length of an integer converted to string. 232 * 302 / 1000 is ceil (log10 (2.0)). Subtract 1 for the sign bit; 233 * add 1 for integer division truncation; add 1 more for a minus sign. 234 */ 235 #define INT_STRLEN_BOUND(t) ((sizeof(t) * CHAR_BIT - 1) * 302 / 1000 + 1 + 1) 236 237 /* 238 * Special types and constants. 239 */ 240 typedef unsigned long LWCHAR; 241 typedef off_t POSITION; 242 typedef off_t LINENUM; 243 #define MIN_LINENUM_WIDTH 7 /* Default min printing width of a line number */ 244 #define MAX_LINENUM_WIDTH 16 /* Max width of a line number */ 245 #define MAX_STATUSCOL_WIDTH 4 /* Max width of the status column */ 246 #define MAX_UTF_CHAR_LEN 6 /* Max bytes in one UTF-8 char */ 247 #define MAX_PRCHAR_LEN 31 /* Max chars in prchar() result */ 248 249 #define NULL_POSITION ((POSITION)(-1)) 250 251 /* 252 * Flags for open() 253 */ 254 #if MSDOS_COMPILER || OS2 255 #define OPEN_READ (O_RDONLY|O_BINARY) 256 #else 257 #ifdef _OSK 258 #define OPEN_READ (S_IREAD) 259 #else 260 #ifdef O_RDONLY 261 #define OPEN_READ (O_RDONLY) 262 #else 263 #define OPEN_READ (0) 264 #endif 265 #endif 266 #endif 267 268 #if defined(O_WRONLY) && defined(O_APPEND) 269 #define OPEN_APPEND (O_APPEND|O_WRONLY) 270 #else 271 #ifdef _OSK 272 #define OPEN_APPEND (S_IWRITE) 273 #else 274 #define OPEN_APPEND (1) 275 #endif 276 #endif 277 278 /* 279 * Flags for creat() 280 */ 281 #if MSDOS_COMPILER 282 #define CREAT_RW (S_IREAD|S_IWRITE) 283 #else 284 #define CREAT_RW 0644 285 #endif 286 287 /* 288 * Set a file descriptor to binary mode. 289 */ 290 #if MSDOS_COMPILER==MSOFTC 291 #define SET_BINARY(f) _setmode(f, _O_BINARY); 292 #else 293 #if MSDOS_COMPILER || OS2 294 #define SET_BINARY(f) setmode(f, O_BINARY) 295 #else 296 #define SET_BINARY(f) 297 #endif 298 #endif 299 300 /* 301 * Does the shell treat "?" as a metacharacter? 302 */ 303 #if MSDOS_COMPILER || OS2 || _OSK 304 #define SHELL_META_QUEST 0 305 #else 306 #define SHELL_META_QUEST 1 307 #endif 308 309 #define SPACES_IN_FILENAMES 1 310 311 /* 312 * An IFILE represents an input file. 313 */ 314 #define IFILE void* 315 #define NULL_IFILE ((IFILE)NULL) 316 317 /* 318 * The structure used to represent a "screen position". 319 * This consists of a file position, and a screen line number. 320 * The meaning is that the line starting at the given file 321 * position is displayed on the ln-th line of the screen. 322 * (Screen lines before ln are empty.) 323 */ 324 struct scrpos 325 { 326 POSITION pos; 327 int ln; 328 }; 329 330 typedef union parg 331 { 332 char *p_string; 333 int p_int; 334 LINENUM p_linenum; 335 char p_char; 336 } PARG; 337 338 #define NULL_PARG ((PARG *)NULL) 339 340 struct textlist 341 { 342 char *string; 343 char *endstring; 344 }; 345 346 struct wchar_range 347 { 348 LWCHAR first, last; 349 }; 350 351 struct wchar_range_table 352 { 353 struct wchar_range *table; 354 int count; 355 }; 356 357 #if HAVE_POLL 358 typedef short POLL_EVENTS; 359 #endif 360 361 #define EOI (-1) 362 363 #define READ_ERR (-1) 364 #define READ_INTR (-2) 365 #define READ_AGAIN (-3) 366 367 /* 368 * A fraction is represented by a long n; the fraction is n/NUM_FRAC_DENOM. 369 * To avoid overflow problems, 0 <= n < NUM_FRAC_DENUM <= LONG_MAX/100. 370 */ 371 #define NUM_FRAC_DENOM 1000000 372 #define NUM_LOG_FRAC_DENOM 6 373 374 /* How quiet should we be? */ 375 #define NOT_QUIET 0 /* Ring bell at eof and for errors */ 376 #define LITTLE_QUIET 1 /* Ring bell only for errors */ 377 #define VERY_QUIET 2 /* Never ring bell */ 378 379 /* How should we prompt? */ 380 #define PR_SHORT 0 /* Prompt with colon */ 381 #define PR_MEDIUM 1 /* Prompt with message */ 382 #define PR_LONG 2 /* Prompt with longer message */ 383 384 /* How should we handle backspaces? */ 385 #define BS_SPECIAL 0 /* Do special things for underlining and bold */ 386 #define BS_NORMAL 1 /* \b treated as normal char; actually output */ 387 #define BS_CONTROL 2 /* \b treated as control char; prints as ^H */ 388 389 /* How should we search? */ 390 #define SRCH_FORW (1 << 0) /* Search forward from current position */ 391 #define SRCH_BACK (1 << 1) /* Search backward from current position */ 392 #define SRCH_NO_MOVE (1 << 2) /* Highlight, but don't move */ 393 #define SRCH_INCR (1 << 3) /* Incremental search */ 394 #define SRCH_FIND_ALL (1 << 4) /* Find and highlight all matches */ 395 #define SRCH_NO_MATCH (1 << 8) /* Search for non-matching lines */ 396 #define SRCH_PAST_EOF (1 << 9) /* Search past end-of-file, into next file */ 397 #define SRCH_FIRST_FILE (1 << 10) /* Search starting at the first file */ 398 #define SRCH_NO_REGEX (1 << 12) /* Don't use regular expressions */ 399 #define SRCH_FILTER (1 << 13) /* Search is for '&' (filter) command */ 400 #define SRCH_AFTER_TARGET (1 << 14) /* Start search after the target line */ 401 #define SRCH_WRAP (1 << 15) /* Wrap-around search (continue at BOF/EOF) */ 402 #define SRCH_SUBSEARCH(i) (1 << (16+(i))) /* Search for subpattern */ 403 /* {{ Depends on NUM_SEARCH_COLORS==5 }} */ 404 #define SRCH_SUBSEARCH_ALL (SRCH_SUBSEARCH(1)|SRCH_SUBSEARCH(2)|SRCH_SUBSEARCH(3)|SRCH_SUBSEARCH(4)|SRCH_SUBSEARCH(5)) 405 406 #define SRCH_REVERSE(t) (((t) & SRCH_FORW) ? \ 407 (((t) & ~SRCH_FORW) | SRCH_BACK) : \ 408 (((t) & ~SRCH_BACK) | SRCH_FORW)) 409 410 /* */ 411 #define NO_MCA 0 412 #define MCA_DONE 1 413 #define MCA_MORE 2 414 415 #define CC_OK 0 /* Char was accepted & processed */ 416 #define CC_QUIT 1 /* Char was a request to abort current cmd */ 417 #define CC_ERROR 2 /* Char could not be accepted due to error */ 418 #define CC_PASS 3 /* Char was rejected (internal) */ 419 420 #define CF_QUIT_ON_ERASE 0001 /* Abort cmd if its entirely erased */ 421 422 /* Special char bit-flags used to tell put_line() to do something special */ 423 #define AT_NORMAL (0) 424 #define AT_UNDERLINE (1 << 0) 425 #define AT_BOLD (1 << 1) 426 #define AT_BLINK (1 << 2) 427 #define AT_STANDOUT (1 << 3) 428 #define AT_ANSI (1 << 4) /* Content-supplied "ANSI" escape sequence */ 429 #define AT_BINARY (1 << 5) /* LESS*BINFMT representation */ 430 #define AT_HILITE (1 << 6) /* Internal highlights (e.g., for search) */ 431 432 #define AT_COLOR_SHIFT 8 433 #define AT_NUM_COLORS 16 434 #define AT_COLOR ((AT_NUM_COLORS-1) << AT_COLOR_SHIFT) 435 #define AT_COLOR_ATTN (1 << AT_COLOR_SHIFT) 436 #define AT_COLOR_BIN (2 << AT_COLOR_SHIFT) 437 #define AT_COLOR_CTRL (3 << AT_COLOR_SHIFT) 438 #define AT_COLOR_ERROR (4 << AT_COLOR_SHIFT) 439 #define AT_COLOR_LINENUM (5 << AT_COLOR_SHIFT) 440 #define AT_COLOR_MARK (6 << AT_COLOR_SHIFT) 441 #define AT_COLOR_PROMPT (7 << AT_COLOR_SHIFT) 442 #define AT_COLOR_RSCROLL (8 << AT_COLOR_SHIFT) 443 #define AT_COLOR_HEADER (9 << AT_COLOR_SHIFT) 444 #define AT_COLOR_SEARCH (10 << AT_COLOR_SHIFT) 445 #define AT_COLOR_SUBSEARCH(i) ((10+(i)) << AT_COLOR_SHIFT) 446 #define NUM_SEARCH_COLORS (AT_NUM_COLORS-10-1) 447 448 typedef enum { CT_NULL, CT_4BIT, CT_6BIT } COLOR_TYPE; 449 450 typedef enum { 451 CV_BLUE = 1, 452 CV_GREEN = 2, 453 CV_RED = 4, 454 CV_BRIGHT = 8, 455 CV_NOCHANGE = -2, 456 CV_ERROR = -1 457 } COLOR_VALUE; 458 459 /* ANSI states */ 460 #define ANSI_MID 1 461 #define ANSI_ERR 2 462 #define ANSI_END 3 463 464 #if '0' == 240 465 #define IS_EBCDIC_HOST 1 466 #endif 467 468 #if IS_EBCDIC_HOST 469 /* 470 * Long definition for EBCDIC. 471 * Since the argument is usually a constant, this macro normally compiles 472 * into a constant. 473 */ 474 #define CONTROL(c) ( \ 475 (c)=='[' ? '\047' : \ 476 (c)=='a' ? '\001' : \ 477 (c)=='b' ? '\002' : \ 478 (c)=='c' ? '\003' : \ 479 (c)=='d' ? '\067' : \ 480 (c)=='e' ? '\055' : \ 481 (c)=='f' ? '\056' : \ 482 (c)=='g' ? '\057' : \ 483 (c)=='h' ? '\026' : \ 484 (c)=='i' ? '\005' : \ 485 (c)=='j' ? '\025' : \ 486 (c)=='k' ? '\013' : \ 487 (c)=='l' ? '\014' : \ 488 (c)=='m' ? '\015' : \ 489 (c)=='n' ? '\016' : \ 490 (c)=='o' ? '\017' : \ 491 (c)=='p' ? '\020' : \ 492 (c)=='q' ? '\021' : \ 493 (c)=='r' ? '\022' : \ 494 (c)=='s' ? '\023' : \ 495 (c)=='t' ? '\074' : \ 496 (c)=='u' ? '\075' : \ 497 (c)=='v' ? '\062' : \ 498 (c)=='w' ? '\046' : \ 499 (c)=='x' ? '\030' : \ 500 (c)=='y' ? '\031' : \ 501 (c)=='z' ? '\077' : \ 502 (c)=='A' ? '\001' : \ 503 (c)=='B' ? '\002' : \ 504 (c)=='C' ? '\003' : \ 505 (c)=='D' ? '\067' : \ 506 (c)=='E' ? '\055' : \ 507 (c)=='F' ? '\056' : \ 508 (c)=='G' ? '\057' : \ 509 (c)=='H' ? '\026' : \ 510 (c)=='I' ? '\005' : \ 511 (c)=='J' ? '\025' : \ 512 (c)=='K' ? '\013' : \ 513 (c)=='L' ? '\014' : \ 514 (c)=='M' ? '\015' : \ 515 (c)=='N' ? '\016' : \ 516 (c)=='O' ? '\017' : \ 517 (c)=='P' ? '\020' : \ 518 (c)=='Q' ? '\021' : \ 519 (c)=='R' ? '\022' : \ 520 (c)=='S' ? '\023' : \ 521 (c)=='T' ? '\074' : \ 522 (c)=='U' ? '\075' : \ 523 (c)=='V' ? '\062' : \ 524 (c)=='W' ? '\046' : \ 525 (c)=='X' ? '\030' : \ 526 (c)=='Y' ? '\031' : \ 527 (c)=='Z' ? '\077' : \ 528 (c)=='|' ? '\031' : \ 529 (c)=='\\' ? '\034' : \ 530 (c)=='^' ? '\036' : \ 531 (c)&077) 532 #else 533 #define CONTROL(c) ((c)&037) 534 #endif /* IS_EBCDIC_HOST */ 535 536 #define ESC CONTROL('[') 537 #define ESCS "\33" 538 #define CSI ((unsigned char)'\233') 539 #define CHAR_END_COMMAND 0x40000000 540 541 #if _OSK_MWC32 542 #define LSIGNAL(sig,func) os9_signal(sig,func) 543 #else 544 #define LSIGNAL(sig,func) signal(sig,func) 545 #endif 546 547 #if HAVE_SIGPROCMASK 548 #if HAVE_SIGSET_T 549 #else 550 #undef HAVE_SIGPROCMASK 551 #endif 552 #endif 553 #if HAVE_SIGPROCMASK 554 #if HAVE_SIGEMPTYSET 555 #else 556 #undef sigemptyset 557 #define sigemptyset(mp) *(mp) = 0 558 #endif 559 #endif 560 561 #define S_INTERRUPT 01 562 #define S_STOP 02 563 #define S_WINCH 04 564 #define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP)) 565 566 #ifdef EXIT_SUCCESS 567 #define QUIT_OK EXIT_SUCCESS 568 #else 569 #define QUIT_OK 0 570 #endif 571 #ifdef EXIT_FAILURE 572 #define QUIT_ERROR EXIT_FAILURE 573 #define QUIT_INTERRUPT (EXIT_FAILURE+1) 574 #else 575 #define QUIT_ERROR 1 576 #define QUIT_INTERRUPT 2 577 #endif 578 #define QUIT_SAVED_STATUS (-1) 579 580 #define FOLLOW_DESC 0 581 #define FOLLOW_NAME 1 582 583 /* filestate flags */ 584 #define CH_CANSEEK 001 585 #define CH_KEEPOPEN 002 586 #define CH_POPENED 004 587 #define CH_HELPFILE 010 588 #define CH_NODATA 020 /* Special case for zero length files */ 589 590 #define ch_zero() ((POSITION)0) 591 592 #define FAKE_HELPFILE "@/\\less/\\help/\\file/\\@" 593 #define FAKE_EMPTYFILE "@/\\less/\\empty/\\file/\\@" 594 595 /* Flags for cvt_text */ 596 #define CVT_TO_LC 01 /* Convert upper-case to lower-case */ 597 #define CVT_BS 02 /* Do backspace processing */ 598 #define CVT_CRLF 04 /* Remove CR after LF */ 599 #define CVT_ANSI 010 /* Remove ANSI escape sequences */ 600 601 #if HAVE_TIME_T 602 #define time_type time_t 603 #else 604 #define time_type long 605 #endif 606 607 /* X11 mouse reporting definitions */ 608 #define X11MOUSE_BUTTON1 0 /* Left button press */ 609 #define X11MOUSE_BUTTON2 1 /* Middle button press */ 610 #define X11MOUSE_BUTTON3 2 /* Right button press */ 611 #define X11MOUSE_BUTTON_REL 3 /* Button release */ 612 #define X11MOUSE_WHEEL_UP 0x40 /* Wheel scroll up */ 613 #define X11MOUSE_WHEEL_DOWN 0x41 /* Wheel scroll down */ 614 #define X11MOUSE_OFFSET 0x20 /* Added to button & pos bytes to create a char */ 615 616 #if LESSTEST 617 #define LESS_DUMP_CHAR CONTROL(']') 618 #endif 619 620 struct mlist; 621 struct loption; 622 struct hilite_tree; 623 struct ansi_state; 624 #include "pattern.h" 625 #include "xbuf.h" 626 #include "funcs.h" 627 628 /* Functions not included in funcs.h */ 629 void postoa(POSITION, char*, int); 630 void linenumtoa(LINENUM, char*, int); 631 void inttoa(int, char*, int); 632 int lstrtoi(char*, char**, int); 633 POSITION lstrtopos(char*, char**, int); 634 unsigned long lstrtoul(char*, char**, int); 635 #if MSDOS_COMPILER==WIN32C 636 int pclose(FILE*); 637 #endif 638