home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume6 / less.patch / option.c < prev    next >
C/C++ Source or Header  |  1986-11-30  |  8KB  |  351 lines

  1. /*
  2.  * Process command line options.
  3.  * Each option is a single letter which controls a program variable.
  4.  * The options have defaults which may be changed via
  5.  * the command line option, or toggled via the "-" command.
  6.  */
  7.  
  8. #include "less.h"
  9.  
  10. #define    toupper(c)    ((c)-'a'+'A')
  11.  
  12. /*
  13.  * Types of options.
  14.  */
  15. #define    BOOL        01    /* Boolean option: 0 or 1 */
  16. #define    TRIPLE        02    /* Triple-valued option: 0, 1 or 2 */
  17. #define    NUMBER        04    /* Numeric option */
  18. #define    NO_TOGGLE    0100    /* Option cannot be toggled with "-" cmd */
  19.  
  20. /*
  21.  * Variables controlled by command line options.
  22.  */
  23. public int p_nbufs, f_nbufs;    /* Number of buffers.  There are two values,
  24.                    one used for input from a pipe and 
  25.                    the other for input from a file. */
  26. public int clean_data;        /* Can we assume the data is "clean"? 
  27.                    (That is, free of nulls, etc) */
  28. public int quiet;        /* Should we suppress the audible bell? */
  29. public int top_search;        /* Should forward searches start at the top 
  30.                    of the screen? (alternative is bottom) */
  31. public int top_scroll;        /* Repaint screen from top?
  32.                    (alternative is scroll from bottom) */
  33. public int pr_type;        /* Type of prompt (short, medium, long) */
  34. public int bs_mode;        /* How to process backspaces */
  35. public int know_dumb;        /* Don't complain about dumb terminals */
  36. public int quit_at_eof;        /* Quit after hitting end of file twice */
  37. public int squeeze;        /* Squeeze multiple blank lines into one */
  38. public int tabstop;        /* Tab settings */
  39. public int back_scroll;        /* Repaint screen on backwards movement */
  40. public int twiddle;        /* Display "~" for lines after EOF */
  41.  
  42. extern int nbufs;
  43. extern int sc_window;
  44. extern char *first_cmd;
  45. extern char *every_first_cmd;
  46.  
  47. #define    DEF_F_NBUFS    5    /* Default for f_nbufs */
  48. #define    DEF_P_NBUFS    12    /* Default for p_nbufs */
  49.  
  50. static struct option
  51. {
  52.     char oletter;        /* The controlling letter (a-z) */
  53.     char otype;        /* Type of the option */
  54.     int odefault;        /* Default value */
  55.     int *ovar;        /* Pointer to the associated variable */
  56.     char *odesc[3];        /* Description of each value */
  57. } option[] =
  58. {
  59.     { 'c', BOOL, 0, &clean_data,
  60.         { "Don't assume data is clean",
  61.           "Assume data is clean",
  62.           NULL
  63.         }
  64.     },
  65.     { 'd', BOOL|NO_TOGGLE, 0, &know_dumb,
  66.         { NULL, NULL, NULL}
  67.     },
  68.     { 'e', BOOL, 0, &quit_at_eof,
  69.         { "Don't quit at end-of-file",
  70.           "Quit at end-of-file",
  71.           NULL
  72.         }
  73.     },
  74.     { 'h', NUMBER, -1, &back_scroll,
  75.         { "Backwards scroll limit is %d lines",
  76.           NULL, NULL
  77.         }
  78.     },
  79.     { 'p', BOOL, 0, &top_scroll,
  80.         { "Repaint by scrolling from bottom of screen",
  81.           "Repaint by painting from top of screen",
  82.           NULL
  83.         }
  84.     },
  85.     { 'x', NUMBER, 8, &tabstop,
  86.         { "Tab stops every %d spaces", 
  87.           NULL, NULL 
  88.         }
  89.     },
  90.     { 's', BOOL, 0, &squeeze,
  91.         { "Don't squeeze multiple blank lines",
  92.           "Squeeze multiple blank lines",
  93.           NULL
  94.         }
  95.     },
  96.     { 't', BOOL, 1, &top_search,
  97.         { "Forward search starts from bottom of screen",
  98.           "Forward search starts from top of screen",
  99.           NULL
  100.         }
  101.     },
  102.     { 'w', BOOL, 1, &twiddle,
  103.         { "Display nothing for lines after end-of-file",
  104.           "Display ~ for lines after end-of-file",
  105.           NULL
  106.         }
  107.     },
  108.     { 'm', TRIPLE, 0, &pr_type,
  109.         { "Prompt with a colon",
  110.           "Prompt with a message",
  111.           "Prompt with a verbose message"
  112.         }
  113.     },
  114.     { 'q', TRIPLE, 0, &quiet,
  115.         { "Ring the bell for errors AND at eof/bof",
  116.           "Ring the bell for errors but not at eof/bof",
  117.           "Never ring the bell"
  118.         }
  119.     },
  120.     { 'u', TRIPLE, 0, &bs_mode,
  121.         { "Underlined text displayed in underline mode",
  122.           "All backspaces cause overstrike",
  123.           "Backspaces print as ^H"
  124.         }
  125.     },
  126.     { 'z', NUMBER, 24, &sc_window,
  127.         { "Scroll window size is %d lines",
  128.           NULL, NULL
  129.         }
  130.     },
  131.     { '\0' }
  132. };
  133.  
  134. public char all_options[64];    /* List of all valid options */
  135.  
  136. /*
  137.  * Initialize each option to its default value.
  138.  */
  139.     public void
  140. init_option()
  141. {
  142.     register struct option *o;
  143.     register char *p;
  144.  
  145.     /*
  146.      * First do special cases, not in option table.
  147.      */
  148.     first_cmd = every_first_cmd = NULL;
  149.     f_nbufs = DEF_F_NBUFS;        /* -bf */
  150.     p_nbufs = DEF_P_NBUFS;        /* -bp */
  151.  
  152.     p = all_options;
  153.     *p++ = 'b';
  154.  
  155.     for (o = option;  o->oletter != '\0';  o++)
  156.     {
  157.         /*
  158.          * Set each variable to its default.
  159.          * Also make a list of all options, in "all_options".
  160.          */
  161.         *(o->ovar) = o->odefault;
  162.         *p++ = o->oletter;
  163.         if (o->otype & TRIPLE)
  164.             *p++ = toupper(o->oletter);
  165.     }
  166.     *p = '\0';
  167. }
  168.  
  169. /*
  170.  * Toggle command line flags from within the program.
  171.  * Used by the "-" command.
  172.  */
  173.     public void
  174. toggle_option(c)
  175.     int c;
  176. {
  177.     register struct option *o;
  178.     char message[100];
  179.     char buf[5];
  180.  
  181.     /*
  182.      * First check for special cases not handled by the option table.
  183.      */
  184.     switch (c)
  185.     {
  186.     case 'b':
  187.         sprintf(message, "%d buffers", nbufs);
  188.         error(message);
  189.         return;
  190.     }
  191.  
  192.  
  193.     for (o = option;  o->oletter != '\0';  o++)
  194.     {
  195.         if ((o->otype & BOOL) && (o->oletter == c) &&
  196.             (o->otype & NO_TOGGLE) == 0)
  197.         {
  198.             /*
  199.              * Boolean option: 
  200.              * just toggle it.
  201.              */
  202.             *(o->ovar) = ! *(o->ovar);
  203.             error(o->odesc[*(o->ovar)]);
  204.             return;
  205.         } else if ((o->otype & TRIPLE) && (o->oletter == c) &&
  206.             (o->otype & NO_TOGGLE) == 0)
  207.         {
  208.             /*
  209.              * Triple-valued option with lower case letter:
  210.              * make it 1 unless already 1, then make it 0.
  211.              */
  212.             *(o->ovar) = (*(o->ovar) == 1) ? 0 : 1;
  213.             error(o->odesc[*(o->ovar)]);
  214.             return;
  215.         } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c) &&
  216.             (o->otype & NO_TOGGLE) == 0)
  217.         {
  218.             /*
  219.              * Triple-valued option with upper case letter:
  220.              * make it 2 unless already 2, then make it 0.
  221.              */
  222.             *(o->ovar) = (*(o->ovar) == 2) ? 0 : 2;
  223.             error(o->odesc[*(o->ovar)]);
  224.             return;
  225.         } else if ((o->otype & NUMBER) && (o->oletter == c) &&
  226.             (o->otype & NO_TOGGLE) == 0)
  227.         {
  228.             sprintf(message, o->odesc[0], *(o->ovar));
  229.             error(message);
  230.             return;
  231.         }
  232.     }
  233.  
  234.     if (control_char(c))
  235.         sprintf(buf, "^%c", carat_char(c));
  236.     else
  237.         sprintf(buf, "%c", c);
  238.     sprintf(message, "\"-%s\": no such flag.  Use one of \"%s\"", 
  239.         buf, all_options);
  240.     error(message);
  241. }
  242.  
  243. /*
  244.  * Scan an argument (either from command line or from LESS environment 
  245.  * variable) and process it.
  246.  */
  247.     public void
  248. scan_option(s)
  249.     char *s;
  250. {
  251.     register struct option *o;
  252.     register int c;
  253.  
  254.     if (s == NULL)
  255.         return;
  256.  
  257.     next:
  258.     if (*s == '\0')
  259.         return;
  260.     switch (c = *s++)
  261.     {
  262.     case '-':
  263.     case ' ':
  264.     case '\t':
  265.         goto next;
  266.     case '+':
  267.         if (*s == '+')
  268.             every_first_cmd = ++s;
  269.         first_cmd = s;
  270.         return;
  271.     case 'b':
  272.         switch (*s)
  273.         {
  274.         case 'f':
  275.             s++;
  276.             f_nbufs = getnum(&s, 'b');
  277.             break;
  278.         case 'p':
  279.             s++;
  280.             p_nbufs = getnum(&s, 'b');
  281.             break;
  282.         default:
  283.             f_nbufs = p_nbufs = getnum(&s, 'b');
  284.             break;
  285.         }
  286.         goto next;
  287.     case '0':  case '1':  case '2':  case '3':  case '4':
  288.     case '5':  case '6':  case '7':  case '8':  case '9':
  289.         {
  290.             /*
  291.              * Handle special "more" compatibility form "-number"
  292.              * to set the scrolling window size.
  293.              */
  294.             s--;
  295.             sc_window = getnum(&s, '-');
  296.             goto next;
  297.         }
  298.     }
  299.  
  300.     for (o = option;  o->oletter != '\0';  o++)
  301.     {
  302.         if ((o->otype & BOOL) && (o->oletter == c))
  303.         {
  304.             *(o->ovar) = ! o->odefault;
  305.             goto next;
  306.         } else if ((o->otype & TRIPLE) && (o->oletter == c))
  307.         {
  308.             *(o->ovar) = (o->odefault == 1) ? 0 : 1;
  309.             goto next;
  310.         } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c))
  311.         {
  312.             *(o->ovar) = (o->odefault == 2) ? 0 : 2;
  313.             goto next;
  314.         } else if ((o->otype & NUMBER) && (o->oletter == c))
  315.         {
  316.             *(o->ovar) = getnum(&s, c);
  317.             goto next;
  318.         }
  319.     }
  320.  
  321.     printf("\"-%c\": invalid flag\n", c);
  322.     exit(1);
  323. }
  324.  
  325. /*
  326.  * Translate a string into a number.
  327.  * Like atoi(), but takes a pointer to a char *, and updates
  328.  * the char * to point after the translated number.
  329.  */
  330.     static int
  331. getnum(sp, c)
  332.     char **sp;
  333.     int c;
  334. {
  335.     register char *s;
  336.     register int n;
  337.  
  338.     s = *sp;
  339.     if (*s < '0' || *s > '9')
  340.     {
  341.         printf("number is required after -%c\n", c);
  342.         exit(1);
  343.     }
  344.  
  345.     n = 0;
  346.     while (*s >= '0' && *s <= '9')
  347.         n = 10 * n + *s++ - '0';
  348.     *sp = s;
  349.     return (n);
  350. }
  351.