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