|
|
1.1 ! root 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 char *first_cmd; ! 44: extern char *every_first_cmd; ! 45: ! 46: #define DEF_F_NBUFS 5 /* Default for f_nbufs */ ! 47: #define DEF_P_NBUFS 12 /* Default for p_nbufs */ ! 48: ! 49: static struct option ! 50: { ! 51: char oletter; /* The controlling letter (a-z) */ ! 52: char otype; /* Type of the option */ ! 53: int odefault; /* Default value */ ! 54: int *ovar; /* Pointer to the associated variable */ ! 55: char *odesc[3]; /* Description of each value */ ! 56: } option[] = ! 57: { ! 58: { 'c', BOOL, 0, &clean_data, ! 59: { "Don't assume data is clean", ! 60: "Assume data is clean", ! 61: NULL ! 62: } ! 63: }, ! 64: #ifndef NRTC ! 65: { 'd', BOOL|NO_TOGGLE, 0, &know_dumb, ! 66: { NULL, NULL, NULL} ! 67: }, ! 68: #else NRTC ! 69: { 'd', BOOL|NO_TOGGLE, 1, &know_dumb, ! 70: { NULL, NULL, NULL} ! 71: }, ! 72: #endif NRTC ! 73: { 'e', BOOL, 0, &quit_at_eof, ! 74: { "Don't quit at end-of-file", ! 75: "Quit at end-of-file", ! 76: NULL ! 77: } ! 78: }, ! 79: { 'h', NUMBER, -1, &back_scroll, ! 80: { "Backwards scroll limit is %d lines", ! 81: NULL, NULL ! 82: } ! 83: }, ! 84: { 'p', BOOL, 0, &top_scroll, ! 85: { "Repaint by scrolling from bottom of screen", ! 86: "Repaint by painting from top of screen", ! 87: NULL ! 88: } ! 89: }, ! 90: { 'x', NUMBER, 8, &tabstop, ! 91: { "Tab stops every %d spaces", ! 92: NULL, NULL ! 93: } ! 94: }, ! 95: { 's', BOOL, 0, &squeeze, ! 96: { "Don't squeeze multiple blank lines", ! 97: "Squeeze multiple blank lines", ! 98: NULL ! 99: } ! 100: }, ! 101: { 't', BOOL, 1, &top_search, ! 102: { "Forward search starts from bottom of screen", ! 103: "Forward search starts from top of screen", ! 104: NULL ! 105: } ! 106: }, ! 107: { 'w', BOOL, 1, &twiddle, ! 108: { "Display nothing for lines after end-of-file", ! 109: "Display ~ for lines after end-of-file", ! 110: NULL ! 111: } ! 112: }, ! 113: { 'm', TRIPLE, 0, &pr_type, ! 114: { "Prompt with a colon", ! 115: "Prompt with a message", ! 116: "Prompt with a verbose message" ! 117: } ! 118: }, ! 119: { 'q', TRIPLE, 0, &quiet, ! 120: { "Ring the bell for errors AND at eof/bof", ! 121: "Ring the bell for errors but not at eof/bof", ! 122: "Never ring the bell" ! 123: } ! 124: }, ! 125: { 'u', TRIPLE, 0, &bs_mode, ! 126: { "Underlined text displayed in underline mode", ! 127: "All backspaces cause overstrike", ! 128: "Backspaces print as ^H" ! 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: } ! 288: ! 289: for (o = option; o->oletter != '\0'; o++) ! 290: { ! 291: if ((o->otype & BOOL) && (o->oletter == c)) ! 292: { ! 293: *(o->ovar) = ! o->odefault; ! 294: goto next; ! 295: } else if ((o->otype & TRIPLE) && (o->oletter == c)) ! 296: { ! 297: *(o->ovar) = (o->odefault == 1) ? 0 : 1; ! 298: goto next; ! 299: } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c)) ! 300: { ! 301: *(o->ovar) = (o->odefault == 2) ? 0 : 2; ! 302: goto next; ! 303: } else if ((o->otype & NUMBER) && (o->oletter == c)) ! 304: { ! 305: *(o->ovar) = getnum(&s, c); ! 306: goto next; ! 307: } ! 308: } ! 309: ! 310: printf("\"-%c\": invalid flag\n", c); ! 311: exit(1); ! 312: } ! 313: ! 314: /* ! 315: * Translate a string into a number. ! 316: * Like atoi(), but takes a pointer to a char *, and updates ! 317: * the char * to point after the translated number. ! 318: */ ! 319: static int ! 320: getnum(sp, c) ! 321: char **sp; ! 322: int c; ! 323: { ! 324: register char *s; ! 325: register int n; ! 326: ! 327: s = *sp; ! 328: if (*s < '0' || *s > '9') ! 329: { ! 330: printf("number is required after -%c\n", c); ! 331: exit(1); ! 332: } ! 333: ! 334: n = 0; ! 335: while (*s >= '0' && *s <= '9') ! 336: n = 10 * n + *s++ - '0'; ! 337: *sp = s; ! 338: return (n); ! 339: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.