Annotation of src/usr.bin/less/optfunc.c, Revision 1.8
1.1 etheisen 1: /*
1.7 shadchin 2: * Copyright (C) 1984-2011 Mark Nudelman
1.1 etheisen 3: *
1.4 millert 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.
1.1 etheisen 6: *
1.4 millert 7: * For more information about less, or for information on how to
8: * contact the author, see the README file.
1.1 etheisen 9: */
10:
11:
12: /*
13: * Handling functions for command line options.
14: *
15: * Most options are handled by the generic code in option.c.
16: * But all string options, and a few non-string options, require
17: * special handling specific to the particular option.
18: * This special processing is done by the "handling functions" in this file.
19: *
20: * Each handling function is passed a "type" and, if it is a string
21: * option, the string which should be "assigned" to the option.
22: * The type may be one of:
23: * INIT The option is being initialized from the command line.
24: * TOGGLE The option is being changed from within the program.
25: * QUERY The setting of the option is merely being queried.
26: */
27:
28: #include "less.h"
29: #include "option.h"
30:
31: extern int nbufs;
1.4 millert 32: extern int bufspace;
1.1 etheisen 33: extern int pr_type;
34: extern int plusoption;
35: extern int swindow;
1.7 shadchin 36: extern int sc_width;
1.1 etheisen 37: extern int sc_height;
1.4 millert 38: extern int secure;
1.7 shadchin 39: extern int dohelp;
1.1 etheisen 40: extern int any_display;
1.4 millert 41: extern char openquote;
42: extern char closequote;
1.1 etheisen 43: extern char *prproto[];
44: extern char *eqproto;
1.4 millert 45: extern char *hproto;
46: extern char *wproto;
1.1 etheisen 47: extern IFILE curr_ifile;
1.4 millert 48: extern char version[];
1.7 shadchin 49: extern int jump_sline;
50: extern int jump_sline_fraction;
51: extern int shift_count;
52: extern int shift_count_fraction;
53: extern int less_is_more;
1.1 etheisen 54: #if LOGFILE
55: extern char *namelogfile;
56: extern int force_logfile;
57: extern int logfile;
58: #endif
59: #if TAGS
60: public char *tagoption = NULL;
61: extern char *tags;
62: #endif
1.4 millert 63: #if MSDOS_COMPILER
1.1 etheisen 64: extern int nm_fg_color, nm_bg_color;
65: extern int bo_fg_color, bo_bg_color;
66: extern int ul_fg_color, ul_bg_color;
67: extern int so_fg_color, so_bg_color;
68: extern int bl_fg_color, bl_bg_color;
69: #endif
1.8 ! millert 70: extern char *every_first_cmd;
1.1 etheisen 71:
72:
73: #if LOGFILE
74: /*
75: * Handler for -o option.
76: */
77: public void
78: opt_o(type, s)
79: int type;
80: char *s;
81: {
82: PARG parg;
83:
1.4 millert 84: if (secure)
85: {
86: error("log file support is not available", NULL_PARG);
87: return;
88: }
1.1 etheisen 89: switch (type)
90: {
91: case INIT:
92: namelogfile = s;
93: break;
94: case TOGGLE:
95: if (ch_getflags() & CH_CANSEEK)
96: {
97: error("Input is not a pipe", NULL_PARG);
98: return;
99: }
100: if (logfile >= 0)
101: {
102: error("Log file is already in use", NULL_PARG);
103: return;
104: }
105: s = skipsp(s);
1.4 millert 106: namelogfile = lglob(s);
1.1 etheisen 107: use_logfile(namelogfile);
108: sync_logfile();
109: break;
110: case QUERY:
111: if (logfile < 0)
112: error("No log file", NULL_PARG);
113: else
114: {
115: parg.p_string = namelogfile;
116: error("Log file \"%s\"", &parg);
117: }
118: break;
119: }
120: }
121:
122: /*
123: * Handler for -O option.
124: */
125: public void
126: opt__O(type, s)
127: int type;
128: char *s;
129: {
130: force_logfile = TRUE;
131: opt_o(type, s);
132: }
133: #endif
134:
135: /*
1.7 shadchin 136: * Handlers for -j option.
1.1 etheisen 137: */
138: public void
1.7 shadchin 139: opt_j(type, s)
1.1 etheisen 140: int type;
141: char *s;
142: {
1.7 shadchin 143: PARG parg;
144: char buf[16];
145: int len;
1.1 etheisen 146: int err;
1.7 shadchin 147:
148: switch (type)
149: {
150: case INIT:
151: case TOGGLE:
152: if (*s == '.')
153: {
154: s++;
155: jump_sline_fraction = getfraction(&s, "j", &err);
156: if (err)
157: error("Invalid line fraction", NULL_PARG);
158: else
159: calc_jump_sline();
160: } else
161: {
162: int sline = getnum(&s, "j", &err);
163: if (err)
164: error("Invalid line number", NULL_PARG);
165: else
166: {
167: jump_sline = sline;
168: jump_sline_fraction = -1;
169: }
170: }
171: break;
172: case QUERY:
173: if (jump_sline_fraction < 0)
174: {
175: parg.p_int = jump_sline;
176: error("Position target at screen line %d", &parg);
177: } else
178: {
179:
180: snprintf(buf, sizeof(buf), ".%06d", jump_sline_fraction);
181: len = strlen(buf);
182: while (len > 2 && buf[len-1] == '0')
183: len--;
184: buf[len] = '\0';
185: parg.p_string = buf;
186: error("Position target at screen position %s", &parg);
187: }
188: break;
189: }
190: }
191:
192: public void
193: calc_jump_sline()
194: {
195: if (jump_sline_fraction < 0)
196: return;
197: jump_sline = sc_height * jump_sline_fraction / NUM_FRAC_DENOM;
198: }
199:
200: /*
201: * Handlers for -# option.
202: */
203: public void
204: opt_shift(type, s)
205: int type;
206: char *s;
207: {
208: PARG parg;
209: char buf[16];
210: int len;
211: int err;
212:
1.1 etheisen 213: switch (type)
214: {
215: case INIT:
1.7 shadchin 216: case TOGGLE:
217: if (*s == '.')
218: {
219: s++;
220: shift_count_fraction = getfraction(&s, "#", &err);
221: if (err)
222: error("Invalid column fraction", NULL_PARG);
223: else
224: calc_shift_count();
225: } else
226: {
227: int hs = getnum(&s, "#", &err);
228: if (err)
229: error("Invalid column number", NULL_PARG);
230: else
231: {
232: shift_count = hs;
233: shift_count_fraction = -1;
234: }
235: }
236: break;
237: case QUERY:
238: if (shift_count_fraction < 0)
239: {
240: parg.p_int = shift_count;
241: error("Horizontal shift %d columns", &parg);
242: } else
1.1 etheisen 243: {
1.7 shadchin 244:
245: snprintf(buf, sizeof(buf), ".%06d", shift_count_fraction);
246: len = strlen(buf);
247: while (len > 2 && buf[len-1] == '0')
248: len--;
249: buf[len] = '\0';
250: parg.p_string = buf;
251: error("Horizontal shift %s of screen width", &parg);
1.1 etheisen 252: }
253: break;
254: }
255: }
1.7 shadchin 256: public void
257: calc_shift_count()
258: {
259: if (shift_count_fraction < 0)
260: return;
261: shift_count = sc_width * shift_count_fraction / NUM_FRAC_DENOM;
262: }
1.1 etheisen 263:
264: #if USERFILE
265: public void
266: opt_k(type, s)
267: int type;
268: char *s;
269: {
270: PARG parg;
271:
272: switch (type)
273: {
274: case INIT:
1.4 millert 275: if (lesskey(s, 0))
1.1 etheisen 276: {
277: parg.p_string = s;
278: error("Cannot use lesskey file \"%s\"", &parg);
279: }
280: break;
281: }
282: }
283: #endif
284:
285: #if TAGS
286: /*
287: * Handler for -t option.
288: */
289: public void
290: opt_t(type, s)
291: int type;
292: char *s;
293: {
294: IFILE save_ifile;
295: POSITION pos;
296:
297: switch (type)
298: {
299: case INIT:
300: tagoption = s;
301: /* Do the rest in main() */
302: break;
303: case TOGGLE:
1.4 millert 304: if (secure)
305: {
306: error("tags support is not available", NULL_PARG);
307: break;
308: }
1.1 etheisen 309: findtag(skipsp(s));
1.4 millert 310: save_ifile = save_curr_ifile();
1.7 shadchin 311: /*
312: * Try to open the file containing the tag
313: * and search for the tag in that file.
314: */
315: if (edit_tagfile() || (pos = tagsearch()) == NULL_POSITION)
1.1 etheisen 316: {
1.7 shadchin 317: /* Failed: reopen the old file. */
1.4 millert 318: reedit_ifile(save_ifile);
1.1 etheisen 319: break;
320: }
1.4 millert 321: unsave_ifile(save_ifile);
1.1 etheisen 322: jump_loc(pos, jump_sline);
323: break;
324: }
325: }
326:
327: /*
328: * Handler for -T option.
329: */
330: public void
331: opt__T(type, s)
332: int type;
333: char *s;
334: {
335: PARG parg;
336:
337: switch (type)
338: {
339: case INIT:
340: tags = s;
341: break;
342: case TOGGLE:
343: s = skipsp(s);
1.4 millert 344: tags = lglob(s);
1.1 etheisen 345: break;
346: case QUERY:
347: parg.p_string = tags;
348: error("Tags file \"%s\"", &parg);
349: break;
350: }
351: }
352: #endif
353:
354: /*
355: * Handler for -p option.
356: */
357: public void
358: opt_p(type, s)
359: int type;
1.4 millert 360: register char *s;
1.1 etheisen 361: {
362: switch (type)
363: {
364: case INIT:
365: /*
366: * Unget a search command for the specified string.
367: * {{ This won't work if the "/" command is
368: * changed or invalidated by a .lesskey file. }}
369: */
1.8 ! millert 370: if (less_is_more) {
! 371: /*
! 372: * In "more" mode, the -p argument is a command,
! 373: * not a search string, run for each file.
! 374: */
! 375: every_first_cmd = save(s);
! 376: } else {
! 377: plusoption = TRUE;
! 378: ungetsc(s);
1.7 shadchin 379: ungetsc("/");
1.8 ! millert 380: }
1.1 etheisen 381: break;
382: }
383: }
384:
385: /*
386: * Handler for -P option.
387: */
388: public void
389: opt__P(type, s)
390: int type;
1.4 millert 391: register char *s;
1.1 etheisen 392: {
1.4 millert 393: register char **proto;
1.1 etheisen 394: PARG parg;
395:
396: switch (type)
397: {
398: case INIT:
399: case TOGGLE:
400: /*
401: * Figure out which prototype string should be changed.
402: */
403: switch (*s)
404: {
1.4 millert 405: case 's': proto = &prproto[PR_SHORT]; s++; break;
1.1 etheisen 406: case 'm': proto = &prproto[PR_MEDIUM]; s++; break;
407: case 'M': proto = &prproto[PR_LONG]; s++; break;
408: case '=': proto = &eqproto; s++; break;
1.4 millert 409: case 'h': proto = &hproto; s++; break;
410: case 'w': proto = &wproto; s++; break;
1.1 etheisen 411: default: proto = &prproto[PR_SHORT]; break;
412: }
413: free(*proto);
414: *proto = save(s);
415: break;
416: case QUERY:
417: parg.p_string = prproto[pr_type];
418: error("%s", &parg);
419: break;
420: }
421: }
422:
423: /*
424: * Handler for the -b option.
425: */
426: /*ARGSUSED*/
427: public void
428: opt_b(type, s)
429: int type;
430: char *s;
431: {
432: switch (type)
433: {
1.4 millert 434: case INIT:
1.1 etheisen 435: case TOGGLE:
436: /*
1.4 millert 437: * Set the new number of buffers.
1.1 etheisen 438: */
1.4 millert 439: ch_setbufspace(bufspace);
1.1 etheisen 440: break;
1.4 millert 441: case QUERY:
1.1 etheisen 442: break;
443: }
444: }
445:
446: /*
447: * Handler for the -i option.
448: */
449: /*ARGSUSED*/
450: public void
451: opt_i(type, s)
452: int type;
453: char *s;
454: {
455: switch (type)
456: {
457: case TOGGLE:
458: chg_caseless();
459: break;
460: case QUERY:
461: case INIT:
462: break;
463: }
464: }
465:
466: /*
467: * Handler for the -V option.
468: */
469: /*ARGSUSED*/
470: public void
471: opt__V(type, s)
472: int type;
473: char *s;
474: {
475: switch (type)
476: {
477: case TOGGLE:
478: case QUERY:
1.4 millert 479: dispversion();
480: break;
1.1 etheisen 481: case INIT:
1.4 millert 482: /*
483: * Force output to stdout per GNU standard for --version output.
484: */
485: any_display = 1;
486: putstr("less ");
487: putstr(version);
1.7 shadchin 488: putstr("\nCopyright (C) 1984-2009 Mark Nudelman\n\n");
1.4 millert 489: putstr("less comes with NO WARRANTY, to the extent permitted by law.\n");
490: putstr("For information about the terms of redistribution,\n");
491: putstr("see the file named README in the less distribution.\n");
492: putstr("Homepage: http://www.greenwoodsoftware.com/less\n");
493: quit(QUIT_OK);
1.1 etheisen 494: break;
495: }
496: }
497:
1.4 millert 498: #if MSDOS_COMPILER
1.1 etheisen 499: /*
1.4 millert 500: * Parse an MSDOS color descriptor.
1.1 etheisen 501: */
502: static void
503: colordesc(s, fg_color, bg_color)
504: char *s;
505: int *fg_color;
506: int *bg_color;
507: {
508: int fg, bg;
509: int err;
510:
1.4 millert 511: fg = getnum(&s, "D", &err);
1.1 etheisen 512: if (err)
513: {
514: error("Missing fg color in -D", NULL_PARG);
515: return;
516: }
517: if (*s != '.')
1.7 shadchin 518: bg = nm_bg_color;
1.1 etheisen 519: else
520: {
521: s++;
1.4 millert 522: bg = getnum(&s, "D", &err);
1.1 etheisen 523: if (err)
524: {
1.7 shadchin 525: error("Missing bg color in -D", NULL_PARG);
1.1 etheisen 526: return;
527: }
528: }
1.4 millert 529: if (*s != '\0')
530: error("Extra characters at end of -D option", NULL_PARG);
1.1 etheisen 531: *fg_color = fg;
532: *bg_color = bg;
533: }
534:
535: /*
536: * Handler for the -D option.
537: */
538: /*ARGSUSED*/
539: public void
540: opt_D(type, s)
541: int type;
542: char *s;
543: {
544: switch (type)
545: {
546: case INIT:
547: case TOGGLE:
548: switch (*s++)
549: {
550: case 'n':
551: colordesc(s, &nm_fg_color, &nm_bg_color);
552: break;
553: case 'd':
554: colordesc(s, &bo_fg_color, &bo_bg_color);
555: break;
556: case 'u':
557: colordesc(s, &ul_fg_color, &ul_bg_color);
558: break;
559: case 'k':
560: colordesc(s, &bl_fg_color, &bl_bg_color);
561: break;
562: case 's':
563: colordesc(s, &so_fg_color, &so_bg_color);
564: break;
565: default:
566: error("-D must be followed by n, d, u, k or s", NULL_PARG);
567: break;
568: }
569: if (type == TOGGLE)
570: {
1.7 shadchin 571: at_enter(AT_STANDOUT);
572: at_exit();
1.1 etheisen 573: }
574: break;
575: case QUERY:
576: break;
577: }
578: }
579: #endif
580:
581: /*
1.4 millert 582: * Handler for the -x option.
583: */
584: public void
585: opt_x(type, s)
586: int type;
587: register char *s;
588: {
589: extern int tabstops[];
590: extern int ntabstops;
591: extern int tabdefault;
592: char msg[60+(4*TABSTOP_MAX)];
593: int i;
594: PARG p;
595:
596: switch (type)
597: {
598: case INIT:
599: case TOGGLE:
600: /* Start at 1 because tabstops[0] is always zero. */
601: for (i = 1; i < TABSTOP_MAX; )
602: {
603: int n = 0;
604: s = skipsp(s);
605: while (*s >= '0' && *s <= '9')
606: n = (10 * n) + (*s++ - '0');
607: if (n > tabstops[i-1])
608: tabstops[i++] = n;
609: s = skipsp(s);
610: if (*s++ != ',')
611: break;
612: }
613: if (i < 2)
614: return;
615: ntabstops = i;
616: tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2];
617: break;
618: case QUERY:
619: strlcpy(msg, "Tab stops ", sizeof(msg));
620: if (ntabstops > 2)
621: {
622: for (i = 1; i < ntabstops; i++)
623: {
624: if (i > 1)
625: strlcat(msg, ",", sizeof(msg));
626: snprintf(msg+strlen(msg),
627: sizeof(msg)-strlen(msg), "%d", tabstops[i]);
628: }
629: snprintf(msg+strlen(msg), sizeof(msg)-strlen(msg),
630: " and then ");
631: }
632: snprintf(msg+strlen(msg), sizeof(msg)-strlen(msg),
1.7 shadchin 633: "every %d spaces", tabdefault);
1.4 millert 634: p.p_string = msg;
635: error("%s", &p);
636: break;
637: }
638: }
639:
640:
641: /*
642: * Handler for the -" option.
643: */
644: public void
645: opt_quote(type, s)
646: int type;
647: register char *s;
648: {
649: char buf[3];
650: PARG parg;
651:
652: switch (type)
653: {
654: case INIT:
655: case TOGGLE:
656: if (s[0] == '\0')
657: {
658: openquote = closequote = '\0';
659: break;
660: }
661: if (s[1] != '\0' && s[2] != '\0')
662: {
663: error("-\" must be followed by 1 or 2 chars", NULL_PARG);
664: return;
665: }
666: openquote = s[0];
667: if (s[1] == '\0')
668: closequote = openquote;
669: else
670: closequote = s[1];
671: break;
672: case QUERY:
673: buf[0] = openquote;
674: buf[1] = closequote;
675: buf[2] = '\0';
676: parg.p_string = buf;
677: error("quotes %s", &parg);
678: break;
679: }
680: }
681:
682: /*
1.1 etheisen 683: * "-?" means display a help message.
684: * If from the command line, exit immediately.
685: */
686: /*ARGSUSED*/
687: public void
688: opt_query(type, s)
689: int type;
690: char *s;
691: {
692: switch (type)
693: {
694: case QUERY:
695: case TOGGLE:
696: error("Use \"h\" for help", NULL_PARG);
697: break;
698: case INIT:
1.7 shadchin 699: dohelp = 1;
1.1 etheisen 700: }
701: }
702:
703: /*
704: * Get the "screen window" size.
705: */
706: public int
707: get_swindow()
708: {
709: if (swindow > 0)
710: return (swindow);
711: return (sc_height + swindow);
712: }
713: