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

Defined functions

getnum defined in line 376; used 5 times
init_option defined in line 146; used 2 times
optstring defined in line 255; used 3 times
scan_option defined in line 274; used 3 times
toggle_option defined in line 180; used 2 times

Defined variables

all_options defined in line 141; used 2 times
back_scroll defined in line 42; used 5 times
bs_mode defined in line 37; used 3 times
clean_data defined in line 29; used 2 times
f_nbufs defined in line 26; used 4 times
know_dumb defined in line 38; used 2 times
option defined in line 64; used 3 times
p_nbufs defined in line 26; used 4 times
pr_type defined in line 36; used 2 times
public defined in line 180; never used
quiet defined in line 31; used 3 times
quit_at_eof defined in line 39; used 3 times
squeeze defined in line 40; used 3 times
tabstop defined in line 41; used 3 times
top_scroll defined in line 34; used 5 times
top_search defined in line 32; used 2 times
twiddle defined in line 43; used 2 times

Defined struct's

option defined in line 57; used 6 times

Defined macros

BOOL defined in line 17; used 9 times
DEF_F_NBUFS defined in line 54; used 1 times
DEF_P_NBUFS defined in line 55; used 1 times
END_OPTION_STRING defined in line 12; used 1 times
NO_TOGGLE defined in line 21; used 2 times
NUMBER defined in line 19; used 5 times
REPAINT defined in line 20; used 4 times
TRIPLE defined in line 18; used 8 times
toupper defined in line 10; used 3 times
Last modified: 1990-07-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3401
Valid CSS Valid XHTML 1.0 Strict