Annotation of src/usr.bin/less/optfunc.c, Revision 1.10
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: */
1.10 ! nicm 9: /*
! 10: * Modified for use with illumos.
! 11: * Copyright 2014 Garrett D'Amore <garrett@damore.org>
! 12: */
1.1 etheisen 13:
14: /*
15: * Handling functions for command line options.
16: *
17: * Most options are handled by the generic code in option.c.
18: * But all string options, and a few non-string options, require
19: * special handling specific to the particular option.
20: * This special processing is done by the "handling functions" in this file.
21: *
22: * Each handling function is passed a "type" and, if it is a string
23: * option, the string which should be "assigned" to the option.
24: * The type may be one of:
25: * INIT The option is being initialized from the command line.
26: * TOGGLE The option is being changed from within the program.
27: * QUERY The setting of the option is merely being queried.
28: */
29:
30: #include "less.h"
31: #include "option.h"
32:
1.4 millert 33: extern int bufspace;
1.1 etheisen 34: extern int pr_type;
35: extern int plusoption;
36: extern int swindow;
1.7 shadchin 37: extern int sc_width;
1.1 etheisen 38: extern int sc_height;
1.4 millert 39: extern int secure;
1.7 shadchin 40: extern int dohelp;
1.1 etheisen 41: extern int any_display;
1.4 millert 42: extern char openquote;
43: extern char closequote;
1.1 etheisen 44: extern char *prproto[];
45: extern char *eqproto;
1.4 millert 46: extern char *hproto;
47: extern char *wproto;
1.1 etheisen 48: extern IFILE curr_ifile;
1.4 millert 49: extern char version[];
1.7 shadchin 50: extern int jump_sline;
51: extern int jump_sline_fraction;
52: extern int less_is_more;
1.1 etheisen 53: extern char *namelogfile;
54: extern int force_logfile;
55: extern int logfile;
1.10 ! nicm 56: char *tagoption = NULL;
1.1 etheisen 57: extern char *tags;
58:
1.10 ! nicm 59: int shift_count; /* Number of positions to shift horizontally */
! 60: static int shift_count_fraction = -1;
1.1 etheisen 61:
62: /*
63: * Handler for -o option.
64: */
1.10 ! nicm 65: void
! 66: opt_o(int type, char *s)
1.1 etheisen 67: {
68: PARG parg;
69:
1.10 ! nicm 70: if (secure) {
1.4 millert 71: error("log file support is not available", NULL_PARG);
72: return;
73: }
1.10 ! nicm 74: switch (type) {
1.1 etheisen 75: case INIT:
76: namelogfile = s;
77: break;
78: case TOGGLE:
1.10 ! nicm 79: if (ch_getflags() & CH_CANSEEK) {
1.1 etheisen 80: error("Input is not a pipe", NULL_PARG);
81: return;
82: }
1.10 ! nicm 83: if (logfile >= 0) {
1.1 etheisen 84: error("Log file is already in use", NULL_PARG);
85: return;
86: }
87: s = skipsp(s);
1.4 millert 88: namelogfile = lglob(s);
1.1 etheisen 89: use_logfile(namelogfile);
90: sync_logfile();
91: break;
92: case QUERY:
1.10 ! nicm 93: if (logfile < 0) {
1.1 etheisen 94: error("No log file", NULL_PARG);
1.10 ! nicm 95: } else {
1.1 etheisen 96: parg.p_string = namelogfile;
97: error("Log file \"%s\"", &parg);
98: }
99: break;
100: }
101: }
102:
103: /*
104: * Handler for -O option.
105: */
1.10 ! nicm 106: void
! 107: opt__O(int type, char *s)
1.1 etheisen 108: {
109: force_logfile = TRUE;
110: opt_o(type, s);
111: }
112:
113: /*
1.7 shadchin 114: * Handlers for -j option.
1.1 etheisen 115: */
1.10 ! nicm 116: void
! 117: opt_j(int type, char *s)
1.1 etheisen 118: {
1.7 shadchin 119: PARG parg;
120: char buf[16];
121: int len;
1.1 etheisen 122: int err;
1.7 shadchin 123:
1.10 ! nicm 124: switch (type) {
1.7 shadchin 125: case INIT:
126: case TOGGLE:
1.10 ! nicm 127: if (*s == '.') {
1.7 shadchin 128: s++;
129: jump_sline_fraction = getfraction(&s, "j", &err);
130: if (err)
131: error("Invalid line fraction", NULL_PARG);
132: else
133: calc_jump_sline();
1.10 ! nicm 134: } else {
1.7 shadchin 135: int sline = getnum(&s, "j", &err);
1.10 ! nicm 136: if (err) {
1.7 shadchin 137: error("Invalid line number", NULL_PARG);
1.10 ! nicm 138: } else {
1.7 shadchin 139: jump_sline = sline;
140: jump_sline_fraction = -1;
141: }
142: }
143: break;
144: case QUERY:
1.10 ! nicm 145: if (jump_sline_fraction < 0) {
1.7 shadchin 146: parg.p_int = jump_sline;
147: error("Position target at screen line %d", &parg);
1.10 ! nicm 148: } else {
! 149: (void) snprintf(buf, sizeof (buf), ".%06d",
! 150: jump_sline_fraction);
1.7 shadchin 151: len = strlen(buf);
152: while (len > 2 && buf[len-1] == '0')
153: len--;
154: buf[len] = '\0';
155: parg.p_string = buf;
156: error("Position target at screen position %s", &parg);
157: }
158: break;
159: }
160: }
161:
1.10 ! nicm 162: void
! 163: calc_jump_sline(void)
1.7 shadchin 164: {
165: if (jump_sline_fraction < 0)
166: return;
167: jump_sline = sc_height * jump_sline_fraction / NUM_FRAC_DENOM;
168: }
169:
170: /*
171: * Handlers for -# option.
172: */
1.10 ! nicm 173: void
! 174: opt_shift(int type, char *s)
1.7 shadchin 175: {
176: PARG parg;
177: char buf[16];
178: int len;
179: int err;
180:
1.10 ! nicm 181: switch (type) {
1.1 etheisen 182: case INIT:
1.7 shadchin 183: case TOGGLE:
1.10 ! nicm 184: if (*s == '.') {
1.7 shadchin 185: s++;
186: shift_count_fraction = getfraction(&s, "#", &err);
187: if (err)
188: error("Invalid column fraction", NULL_PARG);
189: else
190: calc_shift_count();
1.10 ! nicm 191: } else {
1.7 shadchin 192: int hs = getnum(&s, "#", &err);
1.10 ! nicm 193: if (err) {
1.7 shadchin 194: error("Invalid column number", NULL_PARG);
1.10 ! nicm 195: } else {
1.7 shadchin 196: shift_count = hs;
197: shift_count_fraction = -1;
198: }
199: }
200: break;
201: case QUERY:
1.10 ! nicm 202: if (shift_count_fraction < 0) {
1.7 shadchin 203: parg.p_int = shift_count;
204: error("Horizontal shift %d columns", &parg);
1.10 ! nicm 205: } else {
1.7 shadchin 206:
1.10 ! nicm 207: (void) snprintf(buf, sizeof (buf), ".%06d",
! 208: shift_count_fraction);
1.7 shadchin 209: len = strlen(buf);
210: while (len > 2 && buf[len-1] == '0')
211: len--;
212: buf[len] = '\0';
213: parg.p_string = buf;
214: error("Horizontal shift %s of screen width", &parg);
1.1 etheisen 215: }
216: break;
217: }
218: }
1.10 ! nicm 219:
! 220: void
! 221: calc_shift_count(void)
1.7 shadchin 222: {
223: if (shift_count_fraction < 0)
224: return;
225: shift_count = sc_width * shift_count_fraction / NUM_FRAC_DENOM;
226: }
1.1 etheisen 227:
1.10 ! nicm 228: void
! 229: opt_k(int type, char *s)
1.1 etheisen 230: {
231: PARG parg;
232:
1.10 ! nicm 233: switch (type) {
1.1 etheisen 234: case INIT:
1.10 ! nicm 235: if (lesskey(s, 0)) {
1.1 etheisen 236: parg.p_string = s;
237: error("Cannot use lesskey file \"%s\"", &parg);
238: }
239: break;
240: }
241: }
242:
243: /*
244: * Handler for -t option.
245: */
1.10 ! nicm 246: void
! 247: opt_t(int type, char *s)
1.1 etheisen 248: {
249: IFILE save_ifile;
1.10 ! nicm 250: off_t pos;
1.1 etheisen 251:
1.10 ! nicm 252: switch (type) {
1.1 etheisen 253: case INIT:
254: tagoption = s;
255: /* Do the rest in main() */
256: break;
257: case TOGGLE:
1.10 ! nicm 258: if (secure) {
1.4 millert 259: error("tags support is not available", NULL_PARG);
260: break;
261: }
1.1 etheisen 262: findtag(skipsp(s));
1.4 millert 263: save_ifile = save_curr_ifile();
1.7 shadchin 264: /*
265: * Try to open the file containing the tag
266: * and search for the tag in that file.
267: */
1.10 ! nicm 268: if (edit_tagfile() || (pos = tagsearch()) == -1) {
1.7 shadchin 269: /* Failed: reopen the old file. */
1.4 millert 270: reedit_ifile(save_ifile);
1.1 etheisen 271: break;
272: }
1.4 millert 273: unsave_ifile(save_ifile);
1.1 etheisen 274: jump_loc(pos, jump_sline);
275: break;
276: }
277: }
278:
279: /*
280: * Handler for -T option.
281: */
1.10 ! nicm 282: void
! 283: opt__T(int type, char *s)
1.1 etheisen 284: {
285: PARG parg;
286:
1.10 ! nicm 287: switch (type) {
1.1 etheisen 288: case INIT:
289: tags = s;
290: break;
291: case TOGGLE:
292: s = skipsp(s);
1.4 millert 293: tags = lglob(s);
1.1 etheisen 294: break;
295: case QUERY:
296: parg.p_string = tags;
297: error("Tags file \"%s\"", &parg);
298: break;
299: }
300: }
301:
302: /*
303: * Handler for -p option.
304: */
1.10 ! nicm 305: void
! 306: opt_p(int type, char *s)
1.1 etheisen 307: {
1.10 ! nicm 308: switch (type) {
1.1 etheisen 309: case INIT:
310: /*
311: * Unget a search command for the specified string.
312: * {{ This won't work if the "/" command is
313: * changed or invalidated by a .lesskey file. }}
314: */
1.10 ! nicm 315: plusoption = TRUE;
! 316: ungetsc(s);
! 317: /*
! 318: * In "more" mode, the -p argument is a command,
! 319: * not a search string, so we don't need a slash.
! 320: */
! 321: if (!less_is_more)
1.7 shadchin 322: ungetsc("/");
1.1 etheisen 323: break;
324: }
325: }
326:
327: /*
328: * Handler for -P option.
329: */
1.10 ! nicm 330: void
! 331: opt__P(int type, char *s)
1.1 etheisen 332: {
1.10 ! nicm 333: char **proto;
1.1 etheisen 334: PARG parg;
335:
1.10 ! nicm 336: switch (type) {
1.1 etheisen 337: case INIT:
338: case TOGGLE:
339: /*
340: * Figure out which prototype string should be changed.
341: */
1.10 ! nicm 342: switch (*s) {
1.4 millert 343: case 's': proto = &prproto[PR_SHORT]; s++; break;
1.1 etheisen 344: case 'm': proto = &prproto[PR_MEDIUM]; s++; break;
345: case 'M': proto = &prproto[PR_LONG]; s++; break;
346: case '=': proto = &eqproto; s++; break;
1.4 millert 347: case 'h': proto = &hproto; s++; break;
348: case 'w': proto = &wproto; s++; break;
1.1 etheisen 349: default: proto = &prproto[PR_SHORT]; break;
350: }
351: free(*proto);
352: *proto = save(s);
353: break;
354: case QUERY:
355: parg.p_string = prproto[pr_type];
356: error("%s", &parg);
357: break;
358: }
359: }
360:
361: /*
362: * Handler for the -b option.
363: */
1.10 ! nicm 364: /*ARGSUSED*/
! 365: void
! 366: opt_b(int type, char *s)
1.1 etheisen 367: {
1.10 ! nicm 368: switch (type) {
1.4 millert 369: case INIT:
1.1 etheisen 370: case TOGGLE:
371: /*
1.4 millert 372: * Set the new number of buffers.
1.1 etheisen 373: */
1.4 millert 374: ch_setbufspace(bufspace);
1.1 etheisen 375: break;
1.4 millert 376: case QUERY:
1.1 etheisen 377: break;
378: }
379: }
380:
381: /*
382: * Handler for the -i option.
383: */
1.10 ! nicm 384: /*ARGSUSED*/
! 385: void
! 386: opt_i(int type, char *s)
1.1 etheisen 387: {
1.10 ! nicm 388: switch (type) {
1.1 etheisen 389: case TOGGLE:
390: chg_caseless();
391: break;
392: case QUERY:
393: case INIT:
394: break;
395: }
396: }
397:
398: /*
399: * Handler for the -V option.
400: */
1.10 ! nicm 401: /*ARGSUSED*/
! 402: void
! 403: opt__V(int type, char *s)
1.1 etheisen 404: {
1.10 ! nicm 405: switch (type) {
1.1 etheisen 406: case TOGGLE:
407: case QUERY:
1.4 millert 408: dispversion();
409: break;
1.1 etheisen 410: case INIT:
1.4 millert 411: /*
412: * Force output to stdout per GNU standard for --version output.
413: */
414: any_display = 1;
415: putstr("less ");
416: putstr(version);
1.9 shadchin 417: putstr(" (");
418: putstr("POSIX ");
419: putstr("regular expressions)\n");
420: putstr("Copyright (C) 1984-2012 Mark Nudelman\n\n");
1.10 ! nicm 421: putstr("less comes with NO WARRANTY, ");
! 422: putstr("to the extent permitted by law.\n");
1.4 millert 423: putstr("For information about the terms of redistribution,\n");
424: putstr("see the file named README in the less distribution.\n");
425: putstr("Homepage: http://www.greenwoodsoftware.com/less\n");
1.10 ! nicm 426: putstr("\n");
! 427: putstr("Modified for use with illumos.\n");
! 428: putstr("Copyright 2014 Garrett D'Amore\n");
1.4 millert 429: quit(QUIT_OK);
1.1 etheisen 430: break;
431: }
432: }
433:
434: /*
1.4 millert 435: * Handler for the -x option.
436: */
1.10 ! nicm 437: void
! 438: opt_x(int type, char *s)
1.4 millert 439: {
440: extern int tabstops[];
441: extern int ntabstops;
442: extern int tabdefault;
443: char msg[60+(4*TABSTOP_MAX)];
444: int i;
445: PARG p;
446:
1.10 ! nicm 447: switch (type) {
1.4 millert 448: case INIT:
449: case TOGGLE:
450: /* Start at 1 because tabstops[0] is always zero. */
1.10 ! nicm 451: for (i = 1; i < TABSTOP_MAX; ) {
1.4 millert 452: int n = 0;
453: s = skipsp(s);
454: while (*s >= '0' && *s <= '9')
455: n = (10 * n) + (*s++ - '0');
456: if (n > tabstops[i-1])
457: tabstops[i++] = n;
458: s = skipsp(s);
459: if (*s++ != ',')
460: break;
461: }
462: if (i < 2)
463: return;
464: ntabstops = i;
465: tabdefault = tabstops[ntabstops-1] - tabstops[ntabstops-2];
466: break;
467: case QUERY:
1.10 ! nicm 468: (void) strlcpy(msg, "Tab stops ", sizeof(msg));
! 469: if (ntabstops > 2) {
! 470: for (i = 1; i < ntabstops; i++) {
1.4 millert 471: if (i > 1)
472: strlcat(msg, ",", sizeof(msg));
1.10 ! nicm 473: (void) snprintf(msg+strlen(msg),
1.4 millert 474: sizeof(msg)-strlen(msg), "%d", tabstops[i]);
475: }
1.10 ! nicm 476: (void) snprintf(msg+strlen(msg), sizeof(msg)-strlen(msg),
1.4 millert 477: " and then ");
478: }
1.10 ! nicm 479: (void) snprintf(msg+strlen(msg), sizeof(msg)-strlen(msg),
1.7 shadchin 480: "every %d spaces", tabdefault);
1.4 millert 481: p.p_string = msg;
482: error("%s", &p);
483: break;
484: }
485: }
486:
487:
488: /*
489: * Handler for the -" option.
490: */
1.10 ! nicm 491: void
! 492: opt_quote(int type, char *s)
1.4 millert 493: {
494: char buf[3];
495: PARG parg;
496:
1.10 ! nicm 497: switch (type) {
1.4 millert 498: case INIT:
499: case TOGGLE:
1.10 ! nicm 500: if (s[0] == '\0') {
1.4 millert 501: openquote = closequote = '\0';
502: break;
503: }
1.10 ! nicm 504: if (s[1] != '\0' && s[2] != '\0') {
! 505: error("-\" must be followed by 1 or 2 chars",
! 506: NULL_PARG);
1.4 millert 507: return;
508: }
509: openquote = s[0];
510: if (s[1] == '\0')
511: closequote = openquote;
512: else
513: closequote = s[1];
514: break;
515: case QUERY:
516: buf[0] = openquote;
517: buf[1] = closequote;
518: buf[2] = '\0';
519: parg.p_string = buf;
520: error("quotes %s", &parg);
521: break;
522: }
523: }
524:
525: /*
1.1 etheisen 526: * "-?" means display a help message.
527: * If from the command line, exit immediately.
528: */
1.10 ! nicm 529: /*ARGSUSED*/
! 530: void
! 531: opt_query(int type, char *s)
1.1 etheisen 532: {
1.10 ! nicm 533: switch (type) {
1.1 etheisen 534: case QUERY:
535: case TOGGLE:
536: error("Use \"h\" for help", NULL_PARG);
537: break;
538: case INIT:
1.7 shadchin 539: dohelp = 1;
1.1 etheisen 540: }
541: }
542:
543: /*
544: * Get the "screen window" size.
545: */
1.10 ! nicm 546: int
! 547: get_swindow(void)
1.1 etheisen 548: {
549: if (swindow > 0)
550: return (swindow);
551: return (sc_height + swindow);
552: }