|
|
1.1 root 1: /*
2: * Process command line options.
3: * Each option is a single letter which controls a program variable.
4: * The options have defaults which may be changed via
5: * the command line option, or toggled via the "-" command.
6: */
7:
8: #include "less.h"
9:
10: #define toupper(c) ((c)-'a'+'A')
11:
12: /*
13: * Types of options.
14: */
15: #define BOOL 01 /* Boolean option: 0 or 1 */
16: #define TRIPLE 02 /* Triple-valued option: 0, 1 or 2 */
17: #define NUMBER 04 /* Numeric option */
18: #define NO_TOGGLE 0100 /* Option cannot be toggled with "-" cmd */
19:
20: /*
21: * Variables controlled by command line options.
22: */
23: public int p_nbufs, f_nbufs; /* Number of buffers. There are two values,
24: one used for input from a pipe and
25: the other for input from a file. */
26: public int clean_data; /* Can we assume the data is "clean"?
27: (That is, free of nulls, etc) */
28: public int quiet; /* Should we suppress the audible bell? */
29: public int top_search; /* Should forward searches start at the top
30: of the screen? (alternative is bottom) */
31: public int top_scroll; /* Repaint screen from top?
32: (alternative is scroll from bottom) */
33: public int pr_type; /* Type of prompt (short, medium, long) */
34: public int bs_mode; /* How to process backspaces */
35: public int know_dumb; /* Don't complain about dumb terminals */
36: public int quit_at_eof; /* Quit after hitting end of file twice */
37: public int squeeze; /* Squeeze multiple blank lines into one */
38: public int tabstop; /* Tab settings */
39: public int back_scroll; /* Repaint screen on backwards movement */
40: public int twiddle; /* Display "~" for lines after EOF */
41:
42: extern int nbufs;
43: extern char *first_cmd;
44: extern char *every_first_cmd;
45:
46: #define DEF_F_NBUFS 5 /* Default for f_nbufs */
47: #define DEF_P_NBUFS 12 /* Default for p_nbufs */
48:
49: static struct option
50: {
51: char oletter; /* The controlling letter (a-z) */
52: char otype; /* Type of the option */
53: int odefault; /* Default value */
54: int *ovar; /* Pointer to the associated variable */
55: char *odesc[3]; /* Description of each value */
56: } option[] =
57: {
58: { 'c', BOOL, 0, &clean_data,
59: { "Don't assume data is clean",
60: "Assume data is clean",
61: NULL
62: }
63: },
64: #ifndef NRTC
65: { 'd', BOOL|NO_TOGGLE, 0, &know_dumb,
66: { NULL, NULL, NULL}
67: },
68: #else NRTC
69: { 'd', BOOL|NO_TOGGLE, 1, &know_dumb,
70: { NULL, NULL, NULL}
71: },
72: #endif NRTC
73: { 'e', BOOL, 0, &quit_at_eof,
74: { "Don't quit at end-of-file",
75: "Quit at end-of-file",
76: NULL
77: }
78: },
79: { 'h', NUMBER, -1, &back_scroll,
80: { "Backwards scroll limit is %d lines",
81: NULL, NULL
82: }
83: },
84: { 'p', BOOL, 0, &top_scroll,
85: { "Repaint by scrolling from bottom of screen",
86: "Repaint by painting from top of screen",
87: NULL
88: }
89: },
90: { 'x', NUMBER, 8, &tabstop,
91: { "Tab stops every %d spaces",
92: NULL, NULL
93: }
94: },
95: { 's', BOOL, 0, &squeeze,
96: { "Don't squeeze multiple blank lines",
97: "Squeeze multiple blank lines",
98: NULL
99: }
100: },
101: { 't', BOOL, 1, &top_search,
102: { "Forward search starts from bottom of screen",
103: "Forward search starts from top of screen",
104: NULL
105: }
106: },
107: { 'w', BOOL, 1, &twiddle,
108: { "Display nothing for lines after end-of-file",
109: "Display ~ for lines after end-of-file",
110: NULL
111: }
112: },
113: { 'm', TRIPLE, 0, &pr_type,
114: { "Prompt with a colon",
115: "Prompt with a message",
116: "Prompt with a verbose message"
117: }
118: },
119: { 'q', TRIPLE, 0, &quiet,
120: { "Ring the bell for errors AND at eof/bof",
121: "Ring the bell for errors but not at eof/bof",
122: "Never ring the bell"
123: }
124: },
125: { 'u', TRIPLE, 0, &bs_mode,
126: { "Underlined text displayed in underline mode",
127: "All backspaces cause overstrike",
128: "Backspaces print as ^H"
129: }
130: },
131: { '\0' }
132: };
133:
134: public char all_options[64]; /* List of all valid options */
135:
136: /*
137: * Initialize each option to its default value.
138: */
139: public void
140: init_option()
141: {
142: register struct option *o;
143: register char *p;
144:
145: /*
146: * First do special cases, not in option table.
147: */
148: first_cmd = every_first_cmd = NULL;
149: f_nbufs = DEF_F_NBUFS; /* -bf */
150: p_nbufs = DEF_P_NBUFS; /* -bp */
151:
152: p = all_options;
153: *p++ = 'b';
154:
155: for (o = option; o->oletter != '\0'; o++)
156: {
157: /*
158: * Set each variable to its default.
159: * Also make a list of all options, in "all_options".
160: */
161: *(o->ovar) = o->odefault;
162: *p++ = o->oletter;
163: if (o->otype & TRIPLE)
164: *p++ = toupper(o->oletter);
165: }
166: *p = '\0';
167: }
168:
169: /*
170: * Toggle command line flags from within the program.
171: * Used by the "-" command.
172: */
173: public void
174: toggle_option(c)
175: int c;
176: {
177: register struct option *o;
178: char message[100];
179: char buf[5];
180:
181: /*
182: * First check for special cases not handled by the option table.
183: */
184: switch (c)
185: {
186: case 'b':
187: sprintf(message, "%d buffers", nbufs);
188: error(message);
189: return;
190: }
191:
192:
193: for (o = option; o->oletter != '\0'; o++)
194: {
195: if ((o->otype & BOOL) && (o->oletter == c) &&
196: (o->otype & NO_TOGGLE) == 0)
197: {
198: /*
199: * Boolean option:
200: * just toggle it.
201: */
202: *(o->ovar) = ! *(o->ovar);
203: error(o->odesc[*(o->ovar)]);
204: return;
205: } else if ((o->otype & TRIPLE) && (o->oletter == c) &&
206: (o->otype & NO_TOGGLE) == 0)
207: {
208: /*
209: * Triple-valued option with lower case letter:
210: * make it 1 unless already 1, then make it 0.
211: */
212: *(o->ovar) = (*(o->ovar) == 1) ? 0 : 1;
213: error(o->odesc[*(o->ovar)]);
214: return;
215: } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c) &&
216: (o->otype & NO_TOGGLE) == 0)
217: {
218: /*
219: * Triple-valued option with upper case letter:
220: * make it 2 unless already 2, then make it 0.
221: */
222: *(o->ovar) = (*(o->ovar) == 2) ? 0 : 2;
223: error(o->odesc[*(o->ovar)]);
224: return;
225: } else if ((o->otype & NUMBER) && (o->oletter == c) &&
226: (o->otype & NO_TOGGLE) == 0)
227: {
228: sprintf(message, o->odesc[0], *(o->ovar));
229: error(message);
230: return;
231: }
232: }
233:
234: if (control_char(c))
235: sprintf(buf, "^%c", carat_char(c));
236: else
237: sprintf(buf, "%c", c);
238: sprintf(message, "\"-%s\": no such flag. Use one of \"%s\"",
239: buf, all_options);
240: error(message);
241: }
242:
243: /*
244: * Scan an argument (either from command line or from LESS environment
245: * variable) and process it.
246: */
247: public void
248: scan_option(s)
249: char *s;
250: {
251: register struct option *o;
252: register int c;
253:
254: if (s == NULL)
255: return;
256:
257: next:
258: if (*s == '\0')
259: return;
260: switch (c = *s++)
261: {
262: case '-':
263: case ' ':
264: case '\t':
265: goto next;
266: case '+':
267: if (*s == '+')
268: every_first_cmd = ++s;
269: first_cmd = s;
270: return;
271: case 'b':
272: switch (*s)
273: {
274: case 'f':
275: s++;
276: f_nbufs = getnum(&s, 'b');
277: break;
278: case 'p':
279: s++;
280: p_nbufs = getnum(&s, 'b');
281: break;
282: default:
283: f_nbufs = p_nbufs = getnum(&s, 'b');
284: break;
285: }
286: goto next;
287: }
288:
289: for (o = option; o->oletter != '\0'; o++)
290: {
291: if ((o->otype & BOOL) && (o->oletter == c))
292: {
293: *(o->ovar) = ! o->odefault;
294: goto next;
295: } else if ((o->otype & TRIPLE) && (o->oletter == c))
296: {
297: *(o->ovar) = (o->odefault == 1) ? 0 : 1;
298: goto next;
299: } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c))
300: {
301: *(o->ovar) = (o->odefault == 2) ? 0 : 2;
302: goto next;
303: } else if ((o->otype & NUMBER) && (o->oletter == c))
304: {
305: *(o->ovar) = getnum(&s, c);
306: goto next;
307: }
308: }
309:
310: printf("\"-%c\": invalid flag\n", c);
311: exit(1);
312: }
313:
314: /*
315: * Translate a string into a number.
316: * Like atoi(), but takes a pointer to a char *, and updates
317: * the char * to point after the translated number.
318: */
319: static int
320: getnum(sp, c)
321: char **sp;
322: int c;
323: {
324: register char *s;
325: register int n;
326:
327: s = *sp;
328: if (*s < '0' || *s > '9')
329: {
330: printf("number is required after -%c\n", c);
331: exit(1);
332: }
333:
334: n = 0;
335: while (*s >= '0' && *s <= '9')
336: n = 10 * n + *s++ - '0';
337: *sp = s;
338: return (n);
339: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.