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