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