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