xref: /netbsd-src/distrib/utils/more/decode.c (revision d710132b4b8ce7f7cccaaf660cb16aa16b4077a0)
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