Annotation of src/usr.bin/more/decode.c, Revision 1.1
1.1 ! deraadt 1: /*
! 2: * Copyright (c) 1988 Mark Nudleman
! 3: * Copyright (c) 1988 Regents of the University of California.
! 4: * All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: * 3. All advertising materials mentioning features or use of this software
! 15: * must display the following acknowledgement:
! 16: * This product includes software developed by the University of
! 17: * California, Berkeley and its contributors.
! 18: * 4. Neither the name of the University nor the names of its contributors
! 19: * may be used to endorse or promote products derived from this software
! 20: * without specific prior written permission.
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 32: * SUCH DAMAGE.
! 33: */
! 34:
! 35: #ifndef lint
! 36: /* from: static char sccsid[] = "@(#)decode.c 5.9 (Berkeley) 3/1/91"; */
! 37: static char *rcsid = "$Id: decode.c,v 1.2 1993/11/09 05:08:30 cgd Exp $";
! 38: #endif /* not lint */
! 39:
! 40: /*
! 41: * Routines to decode user commands.
! 42: *
! 43: * This is all table driven.
! 44: * A command table is a sequence of command descriptors.
! 45: * Each command descriptor is a sequence of bytes with the following format:
! 46: * <c1><c2>...<cN><0><action>
! 47: * The characters c1,c2,...,cN are the command string; that is,
! 48: * the characters which the user must type.
! 49: * It is terminated by a null <0> byte.
! 50: * The byte after the null byte is the action code associated
! 51: * with the command string.
! 52: *
! 53: * The default commands are described by cmdtable.
! 54: */
! 55:
! 56: #include <sys/param.h>
! 57: #include <sys/file.h>
! 58: #include <stdio.h>
! 59: #include <less.h>
! 60:
! 61: /*
! 62: * Command table is ordered roughly according to expected
! 63: * frequency of use, so the common commands are near the beginning.
! 64: */
! 65: #define CONTROL(c) ((c)&037)
! 66:
! 67: static char cmdtable[] = {
! 68: '\r',0, A_F_LINE,
! 69: '\n',0, A_F_LINE,
! 70: 's',0, A_F_LINE,
! 71: 'j',0, A_F_LINE,
! 72: 'k',0, A_B_LINE,
! 73: 'd',0, A_F_SCROLL,
! 74: CONTROL('D'),0, A_F_SCROLL,
! 75: 'f',0, A_F_SCROLL,
! 76: 'u',0, A_B_SCROLL,
! 77: CONTROL('U'),0, A_B_SCROLL,
! 78: ' ',0, A_F_SCREEN,
! 79: 'z',0, A_F_SCREEN,
! 80: CONTROL('F'),0, A_F_SCREEN,
! 81: 'b',0, A_B_SCREEN,
! 82: CONTROL('B'),0, A_B_SCREEN,
! 83: 'R',0, A_FREPAINT,
! 84: 'r',0, A_REPAINT,
! 85: CONTROL('L'),0, A_REPAINT,
! 86: 'g',0, A_GOLINE,
! 87: 'p',0, A_PERCENT,
! 88: '%',0, A_PERCENT,
! 89: 'G',0, A_GOEND,
! 90: '0',0, A_DIGIT,
! 91: '1',0, A_DIGIT,
! 92: '2',0, A_DIGIT,
! 93: '3',0, A_DIGIT,
! 94: '4',0, A_DIGIT,
! 95: '5',0, A_DIGIT,
! 96: '6',0, A_DIGIT,
! 97: '7',0, A_DIGIT,
! 98: '8',0, A_DIGIT,
! 99: '9',0, A_DIGIT,
! 100:
! 101: '=',0, A_STAT,
! 102: CONTROL('G'),0, A_STAT,
! 103: ':','f',0, A_STAT,
! 104: '/',0, A_F_SEARCH,
! 105: '?',0, A_B_SEARCH,
! 106: '!',0, A_SHELL,
! 107: ':','!',0, A_SHELL,
! 108: 'n',0, A_AGAIN_SEARCH,
! 109: 'm',0, A_SETMARK,
! 110: '\'',0, A_GOMARK,
! 111: 'E',0, A_EXAMINE,
! 112: 'N',0, A_NEXT_FILE,
! 113: ':','n',0, A_NEXT_FILE,
! 114: 'P',0, A_PREV_FILE,
! 115: ':','p',0, A_PREV_FILE,
! 116: 'v',0, A_VISUAL,
! 117:
! 118: 'h',0, A_HELP,
! 119: 'q',0, A_QUIT,
! 120: 'Q',0, A_QUIT,
! 121: ':','q',0, A_QUIT,
! 122: ':','t',0, A_TAGFILE,
! 123: ':', 'a', 0, A_FILE_LIST,
! 124: 'Z','Z',0, A_QUIT,
! 125: };
! 126:
! 127: char *cmdendtable = cmdtable + sizeof(cmdtable);
! 128:
! 129: #define MAX_CMDLEN 16
! 130:
! 131: static char kbuf[MAX_CMDLEN+1];
! 132: static char *kp = kbuf;
! 133:
! 134: /*
! 135: * Indicate that we're not in a prefix command
! 136: * by resetting the command buffer pointer.
! 137: */
! 138: noprefix()
! 139: {
! 140: kp = kbuf;
! 141: }
! 142:
! 143: /*
! 144: * Decode a command character and return the associated action.
! 145: */
! 146: cmd_decode(c)
! 147: int c;
! 148: {
! 149: register int action = A_INVALID;
! 150:
! 151: /*
! 152: * Append the new command character to the command string in kbuf.
! 153: */
! 154: *kp++ = c;
! 155: *kp = '\0';
! 156:
! 157: action = cmd_search(cmdtable, cmdendtable);
! 158:
! 159: /* This is not a prefix character. */
! 160: if (action != A_PREFIX)
! 161: noprefix();
! 162: return(action);
! 163: }
! 164:
! 165: /*
! 166: * Search a command table for the current command string (in kbuf).
! 167: */
! 168: cmd_search(table, endtable)
! 169: char *table;
! 170: char *endtable;
! 171: {
! 172: register char *p, *q;
! 173:
! 174: for (p = table, q = kbuf; p < endtable; p++, q++) {
! 175: if (*p == *q) {
! 176: /*
! 177: * Current characters match.
! 178: * If we're at the end of the string, we've found it.
! 179: * Return the action code, which is the character
! 180: * after the null at the end of the string
! 181: * in the command table.
! 182: */
! 183: if (*p == '\0')
! 184: return(p[1]);
! 185: }
! 186: else if (*q == '\0') {
! 187: /*
! 188: * Hit the end of the user's command,
! 189: * but not the end of the string in the command table.
! 190: * The user's command is incomplete.
! 191: */
! 192: return(A_PREFIX);
! 193: } else {
! 194: /*
! 195: * Not a match.
! 196: * Skip ahead to the next command in the
! 197: * command table, and reset the pointer
! 198: * to the user's command.
! 199: */
! 200: while (*p++ != '\0');
! 201: q = kbuf-1;
! 202: }
! 203: }
! 204: /*
! 205: * No match found in the entire command table.
! 206: */
! 207: return(A_INVALID);
! 208: }