1 /* @(#)hashcmd.c 1.9 19/11/19 Copyright 1986-2019 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)hashcmd.c 1.9 19/11/19 Copyright 1986-2019 J. Schilling";
6 #endif
7 /*
8 * Commands dealing with #<letter> commands
9 *
10 * Copyright (c) 1986-2019 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #ifdef DO_HASHCMDS
27
28 #include "defs.h"
29 #include "hashtab.h"
30 #include "abbrev.h"
31
32 #undef tolower
33 #define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c) + ('a'-'A') : (c))
34
35 extern abidx_t deftab; /* Variable is defined in abbrev.c */
36
37 LOCAL int delim;
38
39 EXPORT void hashcmd __PR((void));
40 LOCAL void abballusage __PR((void));
41 LOCAL void abbusage __PR((int cmdc));
42 LOCAL int nextch __PR((void));
43 LOCAL int skipwhite __PR((void));
44 LOCAL void eatline __PR((void));
45 LOCAL char *pstring __PR((int spc));
46 LOCAL char *nameok __PR((char *n));
47 LOCAL void herror __PR((char *s));
48
49 /*
50 * Parse and execute a hashmark command
51 */
52 EXPORT void
hashcmd()53 hashcmd()
54 {
55 int cmdc;
56 char *name;
57 char *val;
58 int bflg = 0;
59 int histflg = 0;
60 abidx_t tab = deftab;
61
62 cmdc = nextch(); /* First skip '#' */
63 skipwhite();
64 if (!isatty(standin->fdes) && (space(cmdc) || eolchar(delim)))
65 cmdc = ' '; /* # in script: ign. */
66 else
67 cmdc = tolower(delim);
68 if (cmdc != ' ' && eolchar(delim)) {
69 prversion();
70 return;
71 } else if (cmdc == 'b') {
72 bflg = AB_BEGIN;
73 }
74
75 if (cmdc == '!') {
76 nextch();
77 } else if (cmdc != ' ') {
78 nextch();
79 while (!(space(delim) || eolchar(delim))) {
80 delim = tolower(delim);
81 switch (delim) {
82
83 case 'g':
84 tab = GLOBAL_AB;
85 break;
86 case 'l':
87 tab = LOCAL_AB;
88 break;
89 case 'b':
90 if (cmdc == 'p') {
91 bflg = AB_BEGIN;
92 break;
93 }
94 goto err;
95 case 'a':
96 if (cmdc == 'p') {
97 bflg = 0;
98 break;
99 }
100 goto err;
101 case 'h':
102 if (cmdc == 'l') {
103 histflg = AB_HISTORY;
104 break;
105 }
106 default:
107 err:
108 herror("Bad modifier");
109 abbusage(cmdc);
110 eatline();
111 return;
112 }
113 nextch();
114 }
115 }
116 skipwhite();
117 if (cmdc != ' ')
118 name = pstring(TRUE); /* Get next word */
119 else
120 name = NULL;
121 if (name != NULL && eq(name, "-help")) {
122 free(name);
123 abbusage(cmdc);
124 eatline();
125 return;
126 }
127 switch (cmdc) {
128
129 case 'a':
130 case 'b':
131 case 'p':
132 if (nameok(name)) {
133 skipwhite();
134 val = pstring(FALSE);
135 if (val == NULL)
136 val = (char *)make(UC nullstr);
137 if (cmdc == 'p')
138 ab_push(tab, C make(UC name), val, bflg);
139 else
140 ab_insert(tab, C make(UC name), val, bflg);
141 } else {
142 abbusage(cmdc);
143 }
144 break;
145 case 'd':
146 if (nameok(name)) {
147 do {
148 if (name == NULL)
149 break;
150 ab_delete(tab, name, AB_NOFLAG);
151 free(name);
152 skipwhite();
153 } while ((name = pstring(TRUE)) != NULL);
154 } else {
155 abbusage(cmdc);
156 }
157 break;
158 case 'l':
159 if (name == NULL) {
160 ab_dump(tab, STDOUT_FILENO, histflg);
161 } else {
162 do {
163 ab_list(tab, name, STDOUT_FILENO, histflg);
164 free(name);
165 skipwhite();
166 } while ((name = pstring(TRUE)) != NULL);
167 }
168 flushb();
169 break;
170 case 's':
171 deftab = tab;
172 prs_buff(_gettext("Default: "));
173 prs_buff(UC(deftab == GLOBAL_AB?globalname:localname));
174 prc_buff(NL);
175 flushb();
176 break;
177 case '?':
178 case 'h':
179 abballusage();
180 break;
181 case '!': /* This shell always ignores #! */
182 case ' ':
183 break; /* Kommentar */
184 /*
185 * We do not implement all commands from the original concept
186 * in the UNOS command interpreter. The original did support
187 * the following additional commands:
188 *
189 * #! Manage other interpreters in scripts at user level.
190 * #e re-execute the parsed tree from the last command.
191 * #q quit the shell.
192 * #v switch on/off command verbosity similar to "set -x".
193 * #x manage the environemt variables.
194 *
195 * So keep in mind that the command characters from the list
196 * above should not be used for future extensions.
197 */
198 default:
199 herror("Unknown command");
200 abballusage();
201 break;
202 }
203 if (name)
204 free(name);
205 eatline();
206 }
207
208 LOCAL void
abballusage()209 abballusage()
210 {
211 register int i;
212 int save_fd = setb(STDERR_FILENO);
213
214 for (i = 0; abbtab[i].a_c != '\0'; i++) {
215 prs_buff(UC abbtab[i].a_msg);
216 prc_buff(NL);
217 }
218 flushb();
219 (void) setb(save_fd);
220 }
221
222 LOCAL void
abbusage(cmdc)223 abbusage(cmdc)
224 register int cmdc;
225 {
226 register int i;
227
228 for (i = 0; abbtab[i].a_c != '\0'; i++) {
229 if (abbtab[i].a_c == cmdc) {
230 int save_fd = setb(STDERR_FILENO);
231
232 prs_buff(_gettext("Usage: "));
233 prs_buff(_gettext(abbtab[i].a_msg));
234 prc_buff(NL);
235 flushb();
236 (void) setb(save_fd);
237 break;
238 }
239 }
240 if (abbtab[i].a_c == '\0') {
241 int save_fd = setb(STDERR_FILENO);
242
243 prs_buff(_gettext("Unknown command."));
244 prc_buff(NL);
245 flushb();
246 (void) setb(save_fd);
247 abballusage();
248 }
249 }
250
251 LOCAL int
nextch()252 nextch()
253 {
254 return (delim = readwc());
255 }
256
257 LOCAL int
skipwhite()258 skipwhite()
259 {
260 while (delim && space(delim))
261 nextch();
262 return (delim);
263 }
264
265 LOCAL void
eatline()266 eatline()
267 {
268 while (!eolchar(delim))
269 nextch();
270 }
271
272 LOCAL char *
pstring(spc)273 pstring(spc)
274 int spc;
275 {
276 char buf[1024];
277 char *p = buf;
278
279 if (eolchar(delim))
280 return (NULL);
281
282 while (!eolchar(delim)) {
283 if (spc && space(delim))
284 break;
285 if (p >= &buf[sizeof (buf) - MULTI_BYTE_MAX - 1]) {
286 herror("Argument too long");
287 eatline();
288 return (NULL);
289 }
290 p = (char *)movstr(readw(delim), UC p);
291 nextch();
292 }
293 *p = '\0';
294 return ((char *)make(UC buf));
295 }
296
297 LOCAL char *
nameok(n)298 nameok(n)
299 char *n;
300 {
301 if (n == NULL)
302 herror("Missing alias name");
303 return (n);
304 }
305
306 LOCAL void
herror(s)307 herror(s)
308 char *s;
309 {
310 int save_fd = setb(STDERR_FILENO);
311
312 prs_buff(_gettext(s));
313 prc_buff('.');
314 prc_buff(NL);
315 flushb();
316 (void) setb(save_fd);
317 }
318 #endif /* DO_HASHCMDS */
319