[BACK]Return to option.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / less

Annotation of src/usr.bin/less/option.c, Revision 1.1

1.1     ! etheisen    1: /*
        !             2:  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice in the documentation and/or other materials provided with
        !            12:  *    the distribution.
        !            13:  *
        !            14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
        !            15:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            16:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            17:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
        !            18:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            19:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
        !            20:  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
        !            21:  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
        !            22:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
        !            23:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
        !            24:  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            25:  */
        !            26:
        !            27:
        !            28: /*
        !            29:  * Process command line options.
        !            30:  *
        !            31:  * Each option is a single letter which controls a program variable.
        !            32:  * The options have defaults which may be changed via
        !            33:  * the command line option, toggled via the "-" command,
        !            34:  * or queried via the "_" command.
        !            35:  */
        !            36:
        !            37: #include "less.h"
        !            38: #include "option.h"
        !            39:
        !            40: static struct option *pendopt;
        !            41: public int plusoption = FALSE;
        !            42:
        !            43: static char *propt();
        !            44: static char *optstring();
        !            45: static int flip_triple();
        !            46:
        !            47: extern int screen_trashed;
        !            48: extern char *every_first_cmd;
        !            49:
        !            50: /*
        !            51:  * Scan an argument (either from the command line or from the
        !            52:  * LESS environment variable) and process it.
        !            53:  */
        !            54:        public void
        !            55: scan_option(s)
        !            56:        char *s;
        !            57: {
        !            58:        register struct option *o;
        !            59:        register int c;
        !            60:        char *str;
        !            61:        int set_default;
        !            62:        PARG parg;
        !            63:
        !            64:        if (s == NULL)
        !            65:                return;
        !            66:
        !            67:        /*
        !            68:         * If we have a pending string-valued option, handle it now.
        !            69:         * This happens if the previous option was, for example, "-P"
        !            70:         * without a following string.  In that case, the current
        !            71:         * option is simply the string for the previous option.
        !            72:         */
        !            73:        if (pendopt != NULL)
        !            74:        {
        !            75:                (*pendopt->ofunc)(INIT, s);
        !            76:                pendopt = NULL;
        !            77:                return;
        !            78:        }
        !            79:
        !            80:        set_default = FALSE;
        !            81:
        !            82:        while (*s != '\0')
        !            83:        {
        !            84:                /*
        !            85:                 * Check some special cases first.
        !            86:                 */
        !            87:                switch (c = *s++)
        !            88:                {
        !            89:                case ' ':
        !            90:                case '\t':
        !            91:                case END_OPTION_STRING:
        !            92:                        continue;
        !            93:                case '-':
        !            94:                        /*
        !            95:                         * "-+" means set these options back to their defaults.
        !            96:                         * (They may have been set otherwise by previous
        !            97:                         * options.)
        !            98:                         */
        !            99:                        if (set_default = (*s == '+'))
        !           100:                                s++;
        !           101:                        continue;
        !           102:                case '+':
        !           103:                        /*
        !           104:                         * An option prefixed by a "+" is ungotten, so
        !           105:                         * that it is interpreted as less commands
        !           106:                         * processed at the start of the first input file.
        !           107:                         * "++" means process the commands at the start of
        !           108:                         * EVERY input file.
        !           109:                         */
        !           110:                        plusoption = TRUE;
        !           111:                        if (*s == '+')
        !           112:                                every_first_cmd = save(++s);
        !           113:                        else
        !           114:                                ungetsc(s);
        !           115:                        s = optstring(s, c);
        !           116:                        continue;
        !           117:                case '0':  case '1':  case '2':  case '3':  case '4':
        !           118:                case '5':  case '6':  case '7':  case '8':  case '9':
        !           119:                        /*
        !           120:                         * Special "more" compatibility form "-<number>"
        !           121:                         * instead of -z<number> to set the scrolling
        !           122:                         * window size.
        !           123:                         */
        !           124:                        s--;
        !           125:                        c = 'z';
        !           126:                        break;
        !           127:                }
        !           128:
        !           129:                /*
        !           130:                 * Not a special case.
        !           131:                 * Look up the option letter in the option table.
        !           132:                 */
        !           133:                o = findopt(c);
        !           134:                if (o == NULL)
        !           135:                {
        !           136:                        parg.p_string = propt(c);
        !           137: #if MSOFTC || OS2
        !           138:                        error("There is no %s flag (\"less -?\" for help)",
        !           139:                                &parg);
        !           140: #else
        !           141:                        error("There is no %s flag (\"less -\\?\" for help)",
        !           142:                                &parg);
        !           143: #endif
        !           144:                        quit(QUIT_ERROR);
        !           145:                }
        !           146:
        !           147:                switch (o->otype & OTYPE)
        !           148:                {
        !           149:                case BOOL:
        !           150:                        if (set_default)
        !           151:                                *(o->ovar) = o->odefault;
        !           152:                        else
        !           153:                                *(o->ovar) = ! o->odefault;
        !           154:                        break;
        !           155:                case TRIPLE:
        !           156:                        if (set_default)
        !           157:                                *(o->ovar) = o->odefault;
        !           158:                        else
        !           159:                                *(o->ovar) = flip_triple(o->odefault,
        !           160:                                                (o->oletter == c));
        !           161:                        break;
        !           162:                case STRING:
        !           163:                        if (*s == '\0')
        !           164:                        {
        !           165:                                /*
        !           166:                                 * Set pendopt and return.
        !           167:                                 * We will get the string next time
        !           168:                                 * scan_option is called.
        !           169:                                 */
        !           170:                                pendopt = o;
        !           171:                                return;
        !           172:                        }
        !           173:                        /*
        !           174:                         * Don't do anything here.
        !           175:                         * All processing of STRING options is done by
        !           176:                         * the handling function.
        !           177:                         */
        !           178:                        str = s;
        !           179:                        s = optstring(s, c);
        !           180:                        break;
        !           181:                case NUMBER:
        !           182:                        *(o->ovar) = getnum(&s, c, (int*)NULL);
        !           183:                        break;
        !           184:                }
        !           185:                /*
        !           186:                 * If the option has a handling function, call it.
        !           187:                 */
        !           188:                if (o->ofunc != NULL)
        !           189:                        (*o->ofunc)(INIT, str);
        !           190:        }
        !           191: }
        !           192:
        !           193: /*
        !           194:  * Toggle command line flags from within the program.
        !           195:  * Used by the "-" and "_" commands.
        !           196:  * how_toggle may be:
        !           197:  *     OPT_NO_TOGGLE   just report the current setting, without changing it.
        !           198:  *     OPT_TOGGLE      invert the current setting
        !           199:  *     OPT_UNSET       set to the default value
        !           200:  *     OPT_SET         set to the inverse of the default value
        !           201:  */
        !           202:        public void
        !           203: toggle_option(c, s, how_toggle)
        !           204:        int c;
        !           205:        char *s;
        !           206:        int how_toggle;
        !           207: {
        !           208:        register struct option *o;
        !           209:        register int num;
        !           210:        int err;
        !           211:        PARG parg;
        !           212:
        !           213:        /*
        !           214:         * Look up the option letter in the option table.
        !           215:         */
        !           216:        o = findopt(c);
        !           217:        if (o == NULL)
        !           218:        {
        !           219:                parg.p_string = propt(c);
        !           220:                error("There is no %s flag", &parg);
        !           221:                return;
        !           222:        }
        !           223:
        !           224:        if (how_toggle == OPT_TOGGLE && (o->otype & NO_TOGGLE))
        !           225:        {
        !           226:                parg.p_string = propt(c);
        !           227:                error("Cannot change the %s flag", &parg);
        !           228:                return;
        !           229:        }
        !           230:
        !           231:        if (how_toggle == OPT_NO_TOGGLE && (o->otype & NO_QUERY))
        !           232:        {
        !           233:                parg.p_string = propt(c);
        !           234:                error("Cannot query the %s flag", &parg);
        !           235:                return;
        !           236:        }
        !           237:
        !           238:        /*
        !           239:         * Check for something which appears to be a do_toggle
        !           240:         * (because the "-" command was used), but really is not.
        !           241:         * This could be a string option with no string, or
        !           242:         * a number option with no number.
        !           243:         */
        !           244:        switch (o->otype & OTYPE)
        !           245:        {
        !           246:        case STRING:
        !           247:        case NUMBER:
        !           248:                if (how_toggle == OPT_TOGGLE && *s == '\0')
        !           249:                        how_toggle = OPT_NO_TOGGLE;
        !           250:                break;
        !           251:        }
        !           252:
        !           253: #if HILITE_SEARCH
        !           254:        if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
        !           255:                repaint_hilite(0);
        !           256: #endif
        !           257:
        !           258:        /*
        !           259:         * Now actually toggle (change) the variable.
        !           260:         */
        !           261:        if (how_toggle != OPT_NO_TOGGLE)
        !           262:        {
        !           263:                switch (o->otype & OTYPE)
        !           264:                {
        !           265:                case BOOL:
        !           266:                        /*
        !           267:                         * Boolean.
        !           268:                         */
        !           269:                        switch (how_toggle)
        !           270:                        {
        !           271:                        case OPT_TOGGLE:
        !           272:                                *(o->ovar) = ! *(o->ovar);
        !           273:                                break;
        !           274:                        case OPT_UNSET:
        !           275:                                *(o->ovar) = o->odefault;
        !           276:                                break;
        !           277:                        case OPT_SET:
        !           278:                                *(o->ovar) = ! o->odefault;
        !           279:                                break;
        !           280:                        }
        !           281:                        break;
        !           282:                case TRIPLE:
        !           283:                        /*
        !           284:                         * Triple:
        !           285:                         *      If user gave the lower case letter, then switch
        !           286:                         *      to 1 unless already 1, in which case make it 0.
        !           287:                         *      If user gave the upper case letter, then switch
        !           288:                         *      to 2 unless already 2, in which case make it 0.
        !           289:                         */
        !           290:                        switch (how_toggle)
        !           291:                        {
        !           292:                        case OPT_TOGGLE:
        !           293:                                *(o->ovar) = flip_triple(*(o->ovar),
        !           294:                                                o->oletter == c);
        !           295:                                break;
        !           296:                        case OPT_UNSET:
        !           297:                                *(o->ovar) = o->odefault;
        !           298:                                break;
        !           299:                        case OPT_SET:
        !           300:                                *(o->ovar) = flip_triple(o->odefault,
        !           301:                                                o->oletter == c);
        !           302:                                break;
        !           303:                        }
        !           304:                        break;
        !           305:                case STRING:
        !           306:                        /*
        !           307:                         * String: don't do anything here.
        !           308:                         *      The handling function will do everything.
        !           309:                         */
        !           310:                        switch (how_toggle)
        !           311:                        {
        !           312:                        case OPT_SET:
        !           313:                        case OPT_UNSET:
        !           314:                                error("Can't use \"-+\" or \"--\" for a string flag",
        !           315:                                        NULL_PARG);
        !           316:                                return;
        !           317:                        }
        !           318:                        break;
        !           319:                case NUMBER:
        !           320:                        /*
        !           321:                         * Number: set the variable to the given number.
        !           322:                         */
        !           323:                        switch (how_toggle)
        !           324:                        {
        !           325:                        case OPT_TOGGLE:
        !           326:                                num = getnum(&s, '\0', &err);
        !           327:                                if (!err)
        !           328:                                        *(o->ovar) = num;
        !           329:                                break;
        !           330:                        case OPT_UNSET:
        !           331:                                *(o->ovar) = o->odefault;
        !           332:                                break;
        !           333:                        case OPT_SET:
        !           334:                                error("Can't use \"--\" for a numeric flag",
        !           335:                                        NULL_PARG);
        !           336:                                return;
        !           337:                        }
        !           338:                        break;
        !           339:                }
        !           340:        }
        !           341:
        !           342:        /*
        !           343:         * Call the handling function for any special action
        !           344:         * specific to this option.
        !           345:         */
        !           346:        if (o->ofunc != NULL)
        !           347:                (*o->ofunc)((how_toggle==OPT_NO_TOGGLE) ? QUERY : TOGGLE, s);
        !           348:
        !           349: #if HILITE_SEARCH
        !           350:        if (how_toggle != OPT_NO_TOGGLE && (o->otype & HL_REPAINT))
        !           351:                chg_hilite();
        !           352: #endif
        !           353:
        !           354:        /*
        !           355:         * Print a message describing the new setting.
        !           356:         */
        !           357:        switch (o->otype & OTYPE)
        !           358:        {
        !           359:        case BOOL:
        !           360:        case TRIPLE:
        !           361:                /*
        !           362:                 * Print the odesc message.
        !           363:                 */
        !           364:                error(o->odesc[*(o->ovar)], NULL_PARG);
        !           365:                break;
        !           366:        case NUMBER:
        !           367:                /*
        !           368:                 * The message is in odesc[1] and has a %d for
        !           369:                 * the value of the variable.
        !           370:                 */
        !           371:                parg.p_int = *(o->ovar);
        !           372:                error(o->odesc[1], &parg);
        !           373:                break;
        !           374:        case STRING:
        !           375:                /*
        !           376:                 * Message was already printed by the handling function.
        !           377:                 */
        !           378:                break;
        !           379:        }
        !           380:
        !           381:        if (how_toggle != OPT_NO_TOGGLE && (o->otype & REPAINT))
        !           382:                screen_trashed = TRUE;
        !           383: }
        !           384:
        !           385: /*
        !           386:  * "Toggle" a triple-valued option.
        !           387:  */
        !           388:        static int
        !           389: flip_triple(val, lc)
        !           390:        int val;
        !           391:        int lc;
        !           392: {
        !           393:        if (lc)
        !           394:                return ((val == OPT_ON) ? OPT_OFF : OPT_ON);
        !           395:        else
        !           396:                return ((val == OPT_ONPLUS) ? OPT_OFF : OPT_ONPLUS);
        !           397: }
        !           398:
        !           399: /*
        !           400:  * Return a string suitable for printing as the "name" of an option.
        !           401:  * For example, if the option letter is 'x', just return "-x".
        !           402:  */
        !           403:        static char *
        !           404: propt(c)
        !           405:        int c;
        !           406: {
        !           407:        static char buf[8];
        !           408:
        !           409:        sprintf(buf, "-%s", prchar(c));
        !           410:        return (buf);
        !           411: }
        !           412:
        !           413: /*
        !           414:  * Determine if an option is a single character option (BOOL or TRIPLE),
        !           415:  * or if it a multi-character option (NUMBER).
        !           416:  */
        !           417:        public int
        !           418: single_char_option(c)
        !           419:        int c;
        !           420: {
        !           421:        register struct option *o;
        !           422:
        !           423:        o = findopt(c);
        !           424:        if (o == NULL)
        !           425:                return (TRUE);
        !           426:        return ((o->otype & (BOOL|TRIPLE|NOVAR|NO_TOGGLE)) != 0);
        !           427: }
        !           428:
        !           429: /*
        !           430:  * Return the prompt to be used for a given option letter.
        !           431:  * Only string and number valued options have prompts.
        !           432:  */
        !           433:        public char *
        !           434: opt_prompt(c)
        !           435:        int c;
        !           436: {
        !           437:        register struct option *o;
        !           438:
        !           439:        o = findopt(c);
        !           440:        if (o == NULL || (o->otype & (STRING|NUMBER)) == 0)
        !           441:                return (NULL);
        !           442:        return (o->odesc[0]);
        !           443: }
        !           444:
        !           445: /*
        !           446:  * Return whether or not there is a string option pending;
        !           447:  * that is, if the previous option was a string-valued option letter
        !           448:  * (like -P) without a following string.
        !           449:  * In that case, the current option is taken to be the string for
        !           450:  * the previous option.
        !           451:  */
        !           452:        public int
        !           453: isoptpending()
        !           454: {
        !           455:        return (pendopt != NULL);
        !           456: }
        !           457:
        !           458: /*
        !           459:  * Print error message about missing string.
        !           460:  */
        !           461:        static void
        !           462: nostring(c)
        !           463:        int c;
        !           464: {
        !           465:        PARG parg;
        !           466:        parg.p_string = propt(c);
        !           467:        error("String is required after %s", &parg);
        !           468: }
        !           469:
        !           470: /*
        !           471:  * Print error message if a STRING type option is not followed by a string.
        !           472:  */
        !           473:        public void
        !           474: nopendopt()
        !           475: {
        !           476:        nostring(pendopt->oletter);
        !           477: }
        !           478:
        !           479: /*
        !           480:  * Scan to end of string or to an END_OPTION_STRING character.
        !           481:  * In the latter case, replace the char with a null char.
        !           482:  * Return a pointer to the remainder of the string, if any.
        !           483:  */
        !           484:        static char *
        !           485: optstring(s, c)
        !           486:        char *s;
        !           487:        int c;
        !           488: {
        !           489:        register char *p;
        !           490:
        !           491:        if (*s == '\0')
        !           492:        {
        !           493:                nostring(c);
        !           494:                quit(QUIT_ERROR);
        !           495:        }
        !           496:        for (p = s;  *p != '\0';  p++)
        !           497:                if (*p == END_OPTION_STRING)
        !           498:                {
        !           499:                        *p = '\0';
        !           500:                        return (p+1);
        !           501:                }
        !           502:        return (p);
        !           503: }
        !           504:
        !           505: /*
        !           506:  * Translate a string into a number.
        !           507:  * Like atoi(), but takes a pointer to a char *, and updates
        !           508:  * the char * to point after the translated number.
        !           509:  */
        !           510:        public int
        !           511: getnum(sp, c, errp)
        !           512:        char **sp;
        !           513:        int c;
        !           514:        int *errp;
        !           515: {
        !           516:        register char *s;
        !           517:        register int n;
        !           518:        register int neg;
        !           519:        PARG parg;
        !           520:
        !           521:        s = skipsp(*sp);
        !           522:        neg = FALSE;
        !           523:        if (*s == '-')
        !           524:        {
        !           525:                neg = TRUE;
        !           526:                s++;
        !           527:        }
        !           528:        if (*s < '0' || *s > '9')
        !           529:        {
        !           530:                if (errp != NULL)
        !           531:                {
        !           532:                        *errp = TRUE;
        !           533:                        return (-1);
        !           534:                }
        !           535:                parg.p_string = propt(c);
        !           536:                error("Number is required after %s", &parg);
        !           537:                quit(QUIT_ERROR);
        !           538:        }
        !           539:
        !           540:        n = 0;
        !           541:        while (*s >= '0' && *s <= '9')
        !           542:                n = 10 * n + *s++ - '0';
        !           543:        *sp = s;
        !           544:        if (errp != NULL)
        !           545:                *errp = FALSE;
        !           546:        if (neg)
        !           547:                n = -n;
        !           548:        return (n);
        !           549: }