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