|
|
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: { 'd', BOOL|NO_TOGGLE, 0, &know_dumb,
65: { NULL, NULL, NULL}
66: },
67: { 'e', BOOL, 0, &quit_at_eof,
68: { "Don't quit at end-of-file",
69: "Quit at end-of-file",
70: NULL
71: }
72: },
73: { 'h', NUMBER, -1, &back_scroll,
74: { "Backwards scroll limit is %d lines",
75: NULL, NULL
76: }
77: },
78: { 'p', BOOL, 0, &top_scroll,
79: { "Repaint by scrolling from bottom of screen",
80: "Repaint by painting from top of screen",
81: NULL
82: }
83: },
84: { 'x', NUMBER, 8, &tabstop,
85: { "Tab stops every %d spaces",
86: NULL, NULL
87: }
88: },
89: { 's', BOOL, 0, &squeeze,
90: { "Don't squeeze multiple blank lines",
91: "Squeeze multiple blank lines",
92: NULL
93: }
94: },
95: { 't', BOOL, 1, &top_search,
96: { "Forward search starts from bottom of screen",
97: "Forward search starts from top of screen",
98: NULL
99: }
100: },
101: { 'w', BOOL, 1, &twiddle,
102: { "Display nothing for lines after end-of-file",
103: "Display ~ for lines after end-of-file",
104: NULL
105: }
106: },
107: { 'm', TRIPLE, 0, &pr_type,
108: { "Prompt with a colon",
109: "Prompt with a message",
110: "Prompt with a verbose message"
111: }
112: },
113: { 'q', TRIPLE, 0, &quiet,
114: { "Ring the bell for errors AND at eof/bof",
115: "Ring the bell for errors but not at eof/bof",
116: "Never ring the bell"
117: }
118: },
119: { 'u', TRIPLE, 0, &bs_mode,
120: { "Underlined text displayed in underline mode",
121: "All backspaces cause overstrike",
122: "Backspaces print as ^H"
123: }
124: },
125: { '\0' }
126: };
127:
128: public char all_options[64]; /* List of all valid options */
129:
130: /*
131: * Initialize each option to its default value.
132: */
133: public void
134: init_option()
135: {
136: register struct option *o;
137: register char *p;
138:
139: /*
140: * First do special cases, not in option table.
141: */
142: first_cmd = every_first_cmd = NULL;
143: f_nbufs = DEF_F_NBUFS; /* -bf */
144: p_nbufs = DEF_P_NBUFS; /* -bp */
145:
146: p = all_options;
147: *p++ = 'b';
148:
149: for (o = option; o->oletter != '\0'; o++)
150: {
151: /*
152: * Set each variable to its default.
153: * Also make a list of all options, in "all_options".
154: */
155: *(o->ovar) = o->odefault;
156: *p++ = o->oletter;
157: if (o->otype & TRIPLE)
158: *p++ = toupper(o->oletter);
159: }
160: *p = '\0';
161: }
162:
163: /*
164: * Toggle command line flags from within the program.
165: * Used by the "-" command.
166: */
167: public void
168: toggle_option(c)
169: int c;
170: {
171: register struct option *o;
172: char message[100];
173: char buf[5];
174:
175: /*
176: * First check for special cases not handled by the option table.
177: */
178: switch (c)
179: {
180: case 'b':
181: sprintf(message, "%d buffers", nbufs);
182: error(message);
183: return;
184: }
185:
186:
187: for (o = option; o->oletter != '\0'; o++)
188: {
189: if ((o->otype & BOOL) && (o->oletter == c) &&
190: (o->otype & NO_TOGGLE) == 0)
191: {
192: /*
193: * Boolean option:
194: * just toggle it.
195: */
196: *(o->ovar) = ! *(o->ovar);
197: error(o->odesc[*(o->ovar)]);
198: return;
199: } else if ((o->otype & TRIPLE) && (o->oletter == c) &&
200: (o->otype & NO_TOGGLE) == 0)
201: {
202: /*
203: * Triple-valued option with lower case letter:
204: * make it 1 unless already 1, then make it 0.
205: */
206: *(o->ovar) = (*(o->ovar) == 1) ? 0 : 1;
207: error(o->odesc[*(o->ovar)]);
208: return;
209: } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c) &&
210: (o->otype & NO_TOGGLE) == 0)
211: {
212: /*
213: * Triple-valued option with upper case letter:
214: * make it 2 unless already 2, then make it 0.
215: */
216: *(o->ovar) = (*(o->ovar) == 2) ? 0 : 2;
217: error(o->odesc[*(o->ovar)]);
218: return;
219: } else if ((o->otype & NUMBER) && (o->oletter == c) &&
220: (o->otype & NO_TOGGLE) == 0)
221: {
222: sprintf(message, o->odesc[0], *(o->ovar));
223: error(message);
224: return;
225: }
226: }
227:
228: if (control_char(c))
229: sprintf(buf, "^%c", carat_char(c));
230: else
231: sprintf(buf, "%c", c);
232: sprintf(message, "\"-%s\": no such flag. Use one of \"%s\"",
233: buf, all_options);
234: error(message);
235: }
236:
237: /*
238: * Scan an argument (either from command line or from LESS environment
239: * variable) and process it.
240: */
241: public void
242: scan_option(s)
243: char *s;
244: {
245: register struct option *o;
246: register int c;
247:
248: if (s == NULL)
249: return;
250:
251: next:
252: if (*s == '\0')
253: return;
254: switch (c = *s++)
255: {
256: case '-':
257: case ' ':
258: case '\t':
259: goto next;
260: case '+':
261: if (*s == '+')
262: every_first_cmd = ++s;
263: first_cmd = s;
264: return;
265: case 'b':
266: switch (*s)
267: {
268: case 'f':
269: s++;
270: f_nbufs = getnum(&s, 'b');
271: break;
272: case 'p':
273: s++;
274: p_nbufs = getnum(&s, 'b');
275: break;
276: default:
277: f_nbufs = p_nbufs = getnum(&s, 'b');
278: break;
279: }
280: goto next;
281: }
282:
283: for (o = option; o->oletter != '\0'; o++)
284: {
285: if ((o->otype & BOOL) && (o->oletter == c))
286: {
287: *(o->ovar) = ! o->odefault;
288: goto next;
289: } else if ((o->otype & TRIPLE) && (o->oletter == c))
290: {
291: *(o->ovar) = (o->odefault == 1) ? 0 : 1;
292: goto next;
293: } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c))
294: {
295: *(o->ovar) = (o->odefault == 2) ? 0 : 2;
296: goto next;
297: } else if ((o->otype & NUMBER) && (o->oletter == c))
298: {
299: *(o->ovar) = getnum(&s, c);
300: goto next;
301: }
302: }
303:
304: printf("\"-%c\": invalid flag\n", c);
305: exit(1);
306: }
307:
308: /*
309: * Translate a string into a number.
310: * Like atoi(), but takes a pointer to a char *, and updates
311: * the char * to point after the translated number.
312: */
313: static int
314: getnum(sp, c)
315: char **sp;
316: int c;
317: {
318: register char *s;
319: register int n;
320:
321: s = *sp;
322: if (*s < '0' || *s > '9')
323: {
324: printf("number is required after -%c\n", c);
325: exit(1);
326: }
327:
328: n = 0;
329: while (*s >= '0' && *s <= '9')
330: n = 10 * n + *s++ - '0';
331: *sp = s;
332: return (n);
333: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.