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