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