Bug Summary

File:src/usr.bin/vi/build/../ex/ex.c
Warning:line 2085, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ex.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/vi/build/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/vi/build -I /usr/src/usr.bin/vi/build/../include -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/vi/build/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/vi/build/../ex/ex.c
1/* $OpenBSD: ex.c,v 1.21 2016/03/19 00:21:28 mestre Exp $ */
2
3/*-
4 * Copyright (c) 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 * Copyright (c) 1992, 1993, 1994, 1995, 1996
7 * Keith Bostic. All rights reserved.
8 *
9 * See the LICENSE file for redistribution information.
10 */
11
12#include "config.h"
13
14#include <sys/types.h>
15#include <sys/queue.h>
16#include <sys/stat.h>
17#include <sys/time.h>
18
19#include <bitstring.h>
20#include <ctype.h>
21#include <errno(*__errno()).h>
22#include <fcntl.h>
23#include <limits.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28
29#include "../common/common.h"
30#include "../vi/vi.h"
31
32#if defined(DEBUG) && defined(COMLOG)
33static void ex_comlog(SCR *, EXCMD *);
34#endif
35static EXCMDLIST const *
36 ex_comm_search(char *, size_t);
37static int ex_discard(SCR *);
38static int ex_line(SCR *, EXCMD *, MARK *, int *, int *);
39static int ex_load(SCR *);
40static void ex_unknown(SCR *, char *, size_t);
41
42/*
43 * ex --
44 * Main ex loop.
45 *
46 * PUBLIC: int ex(SCR **);
47 */
48int
49ex(SCR **spp)
50{
51 GS *gp;
52 MSGS *mp;
53 SCR *sp;
54 TEXT *tp;
55 u_int32_t flags;
56
57 sp = *spp;
58 gp = sp->gp;
59
60 /* Start the ex screen. */
61 if (ex_init(sp))
62 return (1);
63
64 /* Flush any saved messages. */
65 while ((mp = LIST_FIRST(&gp->msgq)((&gp->msgq)->lh_first)) != NULL((void *)0)) {
66 gp->scr_msg(sp, mp->mtype, mp->buf, mp->len);
67 LIST_REMOVE(mp, q)do { if ((mp)->q.le_next != ((void *)0)) (mp)->q.le_next
->q.le_prev = (mp)->q.le_prev; *(mp)->q.le_prev = (mp
)->q.le_next; ; ; } while (0)
;
68 free(mp->buf);
69 free(mp);
70 }
71
72 /* If reading from a file, errors should have name and line info. */
73 if (F_ISSET(gp, G_SCRIPTED)(((gp)->flags) & ((0x0010)))) {
74 gp->excmd.if_lno = 1;
75 gp->excmd.if_name = "script";
76 }
77
78 /*
79 * !!!
80 * Initialize the text flags. The beautify edit option historically
81 * applied to ex command input read from a file. In addition, the
82 * first time a ^H was discarded from the input, there was a message,
83 * "^H discarded", that was displayed. We don't bother.
84 */
85 LF_INIT(TXT_BACKSLASH | TXT_CNTRLD | TXT_CR)(flags) = ((0x00000020 | 0x00000200 | 0x00000800));
86 for (;; ++gp->excmd.if_lno) {
87 /* Display status line and flush. */
88 if (F_ISSET(sp, SC_STATUS)(((sp)->flags) & ((0x02000000)))) {
89 if (!F_ISSET(sp, SC_EX_SILENT)(((sp)->flags) & ((0x00040000))))
90 msgq_status(sp, sp->lno, 0);
91 F_CLR(sp, SC_STATUS)(((sp)->flags) &= ~((0x02000000)));
92 }
93 (void)ex_fflush(sp);
94
95 /* Set the flags the user can reset. */
96 if (O_ISSET(sp, O_BEAUTIFY)((((&(((sp)))->opts[(((O_BEAUTIFY)))])->flags) &
((0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((O_BEAUTIFY
)))].o_cur.val].o_cur.val : (((sp)))->opts[(((O_BEAUTIFY))
)].o_cur.val)
)
97 LF_SET(TXT_BEAUTIFY)((flags) |= ((0x00000040)));
98 if (O_ISSET(sp, O_PROMPT)((((&(((sp)))->opts[(((O_PROMPT)))])->flags) & (
(0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((O_PROMPT
)))].o_cur.val].o_cur.val : (((sp)))->opts[(((O_PROMPT)))]
.o_cur.val)
)
99 LF_SET(TXT_PROMPT)((flags) |= ((0x00400000)));
100
101 /* Clear any current interrupts, and get a command. */
102 CLR_INTERRUPT(sp)((((sp)->gp)->flags) &= ~((0x0004)));
103 if (ex_txt(sp, &sp->tiq, ':', flags))
104 return (1);
105 if (INTERRUPTED(sp)(((((sp)->gp)->flags) & ((0x0004))) || (!v_event_get
((sp), ((void *)0), 0, 0x001) && ((((sp)->gp)->
flags) & ((0x0004)))))
) {
106 (void)ex_puts(sp, "\n");
107 (void)ex_fflush(sp);
108 continue;
109 }
110
111 /* Initialize the command structure. */
112 CLEAR_EX_PARSER(&gp->excmd)memset(&((&gp->excmd)->cp), 0, ((char *)&(&
gp->excmd)->flags - (char *)&((&gp->excmd)->
cp)) + sizeof((&gp->excmd)->flags))
;
113
114 /*
115 * If the user entered a single carriage return, send
116 * ex_cmd() a separator -- it discards single newlines.
117 */
118 tp = TAILQ_FIRST(&sp->tiq)((&sp->tiq)->tqh_first);
119 if (tp->len == 0) {
120 gp->excmd.cp = " "; /* __TK__ why not |? */
121 gp->excmd.clen = 1;
122 } else {
123 gp->excmd.cp = tp->lb;
124 gp->excmd.clen = tp->len;
125 }
126 F_INIT(&gp->excmd, E_NRSEP)((&gp->excmd)->flags) = ((0x00008000));
127
128 if (ex_cmd(sp) && F_ISSET(gp, G_SCRIPTED)(((gp)->flags) & ((0x0010))))
129 return (1);
130
131 if (INTERRUPTED(sp)(((((sp)->gp)->flags) & ((0x0004))) || (!v_event_get
((sp), ((void *)0), 0, 0x001) && ((((sp)->gp)->
flags) & ((0x0004)))))
) {
132 CLR_INTERRUPT(sp)((((sp)->gp)->flags) &= ~((0x0004)));
133 msgq(sp, M_ERR, "Interrupted");
134 }
135
136 /*
137 * If the last command caused a restart, or switched screens
138 * or into vi, return.
139 */
140 if (F_ISSET(gp, G_SRESTART)(((gp)->flags) & ((0x0080))) || F_ISSET(sp, SC_SSWITCH | SC_VI)(((sp)->flags) & ((0x00001000 | 0x00000002)))) {
141 *spp = sp;
142 break;
143 }
144
145 /* If the last command switched files, we don't care. */
146 F_CLR(sp, SC_FSWITCH)(((sp)->flags) &= ~((0x00000800)));
147
148 /*
149 * If we're exiting this screen, move to the next one. By
150 * definition, this means returning into vi, so return to the
151 * main editor loop. The ordering is careful, don't discard
152 * the contents of sp until the end.
153 */
154 if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)(((sp)->flags) & ((0x00000200 | 0x00000400)))) {
155 if (file_end(sp, NULL((void *)0), F_ISSET(sp, SC_EXIT_FORCE)(((sp)->flags) & ((0x00000400)))))
156 return (1);
157 *spp = screen_next(sp);
158 return (screen_end(sp));
159 }
160 }
161 return (0);
162}
163
164/*
165 * ex_cmd --
166 * The guts of the ex parser: parse and execute a string containing
167 * ex commands.
168 *
169 * !!!
170 * This code MODIFIES the string that gets passed in, to delete quoting
171 * characters, etc. The string cannot be readonly/text space, nor should
172 * you expect to use it again after ex_cmd() returns.
173 *
174 * !!!
175 * For the fun of it, if you want to see if a vi clone got the ex argument
176 * parsing right, try:
177 *
178 * echo 'foo|bar' > file1; echo 'foo/bar' > file2;
179 * vi
180 * :edit +1|s/|/PIPE/|w file1| e file2|1 | s/\//SLASH/|wq
181 *
182 * or: vi
183 * :set|file|append|set|file
184 *
185 * For extra credit, try them in a startup .exrc file.
186 *
187 * PUBLIC: int ex_cmd(SCR *);
188 */
189int
190ex_cmd(SCR *sp)
191{
192 enum nresult nret;
193 EX_PRIVATE *exp;
194 EXCMD *ecp;
195 GS *gp;
196 MARK cur;
197 recno_t lno;
198 size_t arg1_len, discard, len;
199 u_int32_t flags;
200 long ltmp;
201 int at_found, gv_found;
202 int ch, cnt, delim, isaddr, namelen;
203 int newscreen, notempty, tmp, vi_address;
204 char *arg1, *p, *s, *t;
205
206 gp = sp->gp;
207 exp = EXP(sp)((EX_PRIVATE *)((sp)->ex_private));
208
209 /*
210 * We always start running the command on the top of the stack.
211 * This means that *everything* must be resolved when we leave
212 * this function for any reason.
213 */
214loop: ecp = LIST_FIRST(&gp->ecq)((&gp->ecq)->lh_first);
215
216 /* If we're reading a command from a file, set up error information. */
217 if (ecp->if_name != NULL((void *)0)) {
1
Assuming field 'if_name' is equal to NULL
2
Taking false branch
218 gp->if_lno = ecp->if_lno;
219 gp->if_name = ecp->if_name;
220 }
221
222 /*
223 * If a move to the end of the file is scheduled for this command,
224 * do it now.
225 */
226 if (F_ISSET(ecp, E_MOVETOEND)(((ecp)->flags) & ((0x00400000)))) {
3
Assuming the condition is false
4
Taking false branch
227 if (db_last(sp, &sp->lno))
228 goto rfail;
229 sp->cno = 0;
230 F_CLR(ecp, E_MOVETOEND)(((ecp)->flags) &= ~((0x00400000)));
231 }
232
233 /* If we found a newline, increment the count now. */
234 if (F_ISSET(ecp, E_NEWLINE)(((ecp)->flags) & ((0x00800000)))) {
5
Assuming the condition is false
6
Taking false branch
235 ++gp->if_lno;
236 ++ecp->if_lno;
237 F_CLR(ecp, E_NEWLINE)(((ecp)->flags) &= ~((0x00800000)));
238 }
239
240 /* (Re)initialize the EXCMD structure, preserving some flags. */
241 CLEAR_EX_CMD(ecp){ u_int32_t L__f = ((((ecp))->flags) & ((0x0003f800)))
; memset(&((ecp)->buffer), 0, ((char *)&(ecp)->
flags - (char *)&((ecp)->buffer)) + sizeof((ecp)->flags
)); ((((ecp))->flags) |= ((L__f))); }
;
242
243 /* Initialize the argument structures. */
244 if (argv_init(sp, ecp))
7
Assuming the condition is false
8
Taking false branch
245 goto err;
246
247 /* Initialize +cmd, saved command information. */
248 arg1 = NULL((void *)0);
249 ecp->save_cmdlen = 0;
250
251 /* Skip <blank>s, empty lines. */
252 for (notempty = 0; ecp->clen > 0; ++ecp->cp, --ecp->clen)
9
Assuming field 'clen' is <= 0
10
Loop condition is false. Execution continues on line 268
253 if ((ch = *ecp->cp) == '\n') {
254 ++gp->if_lno;
255 ++ecp->if_lno;
256 } else if (isblank(ch))
257 notempty = 1;
258 else
259 break;
260
261 /*
262 * !!!
263 * Permit extra colons at the start of the line. Historically,
264 * ex/vi allowed a single extra one. It's simpler not to count.
265 * The stripping is done here because, historically, any command
266 * could have preceding colons, e.g. ":g/pattern/:p" worked.
267 */
268 if (ecp->clen
10.1
Field 'clen' is equal to 0
!= 0 && ch == ':') {
269 notempty = 1;
270 while (--ecp->clen > 0 && (ch = *++ecp->cp) == ':');
271 }
272
273 /*
274 * Command lines that start with a double-quote are comments.
275 *
276 * !!!
277 * Historically, there was no escape or delimiter for a comment, e.g.
278 * :"foo|set was a single comment and nothing was output. Since nvi
279 * permits users to escape <newline> characters into command lines, we
280 * have to check for that case.
281 */
282 if (ecp->clen
10.2
Field 'clen' is equal to 0
!= 0 && ch == '"') {
283 while (--ecp->clen > 0 && *++ecp->cp != '\n');
284 if (*ecp->cp == '\n') {
285 F_SET(ecp, E_NEWLINE)(((ecp)->flags) |= ((0x00800000)));
286 ++ecp->cp;
287 --ecp->clen;
288 }
289 goto loop;
290 }
291
292 /* Skip whitespace. */
293 for (; ecp->clen > 0; ++ecp->cp, --ecp->clen) {
11
Loop condition is false. Execution continues on line 314
294 ch = *ecp->cp;
295 if (!isblank(ch))
296 break;
297 }
298
299 /*
300 * The last point at which an empty line can mean do nothing.
301 *
302 * !!!
303 * Historically, in ex mode, lines containing only <blank> characters
304 * were the same as a single <carriage-return>, i.e. a default command.
305 * In vi mode, they were ignored. In .exrc files this was a serious
306 * annoyance, as vi kept trying to treat them as print commands. We
307 * ignore backward compatibility in this case, discarding lines that
308 * contain only <blank> characters from .exrc files.
309 *
310 * !!!
311 * This is where you end up when you're done a command, i.e. clen has
312 * gone to zero. Continue if there are more commands to run.
313 */
314 if (ecp->clen
11.1
Field 'clen' is equal to 0
== 0 &&
315 (!notempty
11.2
'notempty' is 0
|| F_ISSET(sp, SC_VI)(((sp)->flags) & ((0x00000002))) || F_ISSET(ecp, E_BLIGNORE)(((ecp)->flags) & ((0x00000800))))) {
316 if (ex_load(sp))
12
Calling 'ex_load'
317 goto rfail;
318 ecp = LIST_FIRST(&gp->ecq)((&gp->ecq)->lh_first);
319 if (ecp->clen == 0)
320 goto rsuccess;
321 goto loop;
322 }
323
324 /*
325 * Check to see if this is a command for which we may want to move
326 * the cursor back up to the previous line. (The command :1<CR>
327 * wants a <newline> separator, but the command :<CR> wants to erase
328 * the command line.) If the line is empty except for <blank>s,
329 * <carriage-return> or <eof>, we'll probably want to move up. I
330 * don't think there's any way to get <blank> characters *after* the
331 * command character, but this is the ex parser, and I've been wrong
332 * before.
333 */
334 if (F_ISSET(ecp, E_NRSEP)(((ecp)->flags) & ((0x00008000))) &&
335 ecp->clen != 0 && (ecp->clen != 1 || ecp->cp[0] != '\004'))
336 F_CLR(ecp, E_NRSEP)(((ecp)->flags) &= ~((0x00008000)));
337
338 /* Parse command addresses. */
339 if (ex_range(sp, ecp, &tmp))
340 goto rfail;
341 if (tmp)
342 goto err;
343
344 /*
345 * Skip <blank>s and any more colons (the command :3,5:print
346 * worked, historically).
347 */
348 for (; ecp->clen > 0; ++ecp->cp, --ecp->clen) {
349 ch = *ecp->cp;
350 if (!isblank(ch) && ch != ':')
351 break;
352 }
353
354 /*
355 * If no command, ex does the last specified of p, l, or #, and vi
356 * moves to the line. Otherwise, determine the length of the command
357 * name by looking for the first non-alphabetic character. (There
358 * are a few non-alphabetic characters in command names, but they're
359 * all single character commands.) This isn't a great test, because
360 * it means that, for the command ":e +cut.c file", we'll report that
361 * the command "cut" wasn't known. However, it makes ":e+35 file" work
362 * correctly.
363 *
364 * !!!
365 * Historically, lines with multiple adjacent (or <blank> separated)
366 * command separators were very strange. For example, the command
367 * |||<carriage-return>, when the cursor was on line 1, displayed
368 * lines 2, 3 and 5 of the file. In addition, the command " | "
369 * would only display the line after the next line, instead of the
370 * next two lines. No ideas why. It worked reasonably when executed
371 * from vi mode, and displayed lines 2, 3, and 4, so we do a default
372 * command for each separator.
373 */
374#define SINGLE_CHAR_COMMANDS"\004!#&*<=>@~" "\004!#&*<=>@~"
375 newscreen = 0;
376 if (ecp->clen != 0 && ecp->cp[0] != '|' && ecp->cp[0] != '\n') {
377 if (strchr(SINGLE_CHAR_COMMANDS"\004!#&*<=>@~", *ecp->cp)) {
378 p = ecp->cp;
379 ++ecp->cp;
380 --ecp->clen;
381 namelen = 1;
382 } else {
383 for (p = ecp->cp;
384 ecp->clen > 0; --ecp->clen, ++ecp->cp)
385 if (!isalpha(*ecp->cp))
386 break;
387 if ((namelen = ecp->cp - p) == 0) {
388 msgq(sp, M_ERR, "Unknown command name");
389 goto err;
390 }
391 }
392
393 /*
394 * !!!
395 * Historic vi permitted flags to immediately follow any
396 * subset of the 'delete' command, but then did not permit
397 * further arguments (flag, buffer, count). Make it work.
398 * Permit further arguments for the few shreds of dignity
399 * it offers.
400 *
401 * Adding commands that start with 'd', and match "delete"
402 * up to a l, p, +, - or # character can break this code.
403 *
404 * !!!
405 * Capital letters beginning the command names ex, edit,
406 * next, previous, tag and visual (in vi mode) indicate the
407 * command should happen in a new screen.
408 */
409 switch (p[0]) {
410 case 'd':
411 for (s = p,
412 t = cmds[C_DELETE].name; *s == *t; ++s, ++t);
413 if (s[0] == 'l' || s[0] == 'p' || s[0] == '+' ||
414 s[0] == '-' || s[0] == '^' || s[0] == '#') {
415 len = (ecp->cp - p) - (s - p);
416 ecp->cp -= len;
417 ecp->clen += len;
418 ecp->rcmd = cmds[C_DELETE];
419 ecp->rcmd.syntax = "1bca1";
420 ecp->cmd = &ecp->rcmd;
421 goto skip_srch;
422 }
423 break;
424 case 'E': case 'F': case 'N': case 'P': case 'T': case 'V':
425 newscreen = 1;
426 p[0] = tolower(p[0]);
427 break;
428 }
429
430 /*
431 * Search the table for the command.
432 *
433 * !!!
434 * Historic vi permitted the mark to immediately follow the
435 * 'k' in the 'k' command. Make it work.
436 *
437 * !!!
438 * Historic vi permitted any flag to follow the s command, e.g.
439 * "s/e/E/|s|sgc3p" was legal. Make the command "sgc" work.
440 * Since the following characters all have to be flags, i.e.
441 * alphabetics, we can let the s command routine return errors
442 * if it was some illegal command string. This code will break
443 * if an "sg" or similar command is ever added. The substitute
444 * code doesn't care if it's a "cgr" flag or a "#lp" flag that
445 * follows the 's', but we limit the choices here to "cgr" so
446 * that we get unknown command messages for wrong combinations.
447 */
448 if ((ecp->cmd = ex_comm_search(p, namelen)) == NULL((void *)0))
449 switch (p[0]) {
450 case 'k':
451 if (namelen == 2) {
452 ecp->cp -= namelen - 1;
453 ecp->clen += namelen - 1;
454 ecp->cmd = &cmds[C_K];
455 break;
456 }
457 goto unknown;
458 case 's':
459 for (s = p + 1, cnt = namelen; --cnt; ++s)
460 if (s[0] != 'c' &&
461 s[0] != 'g' && s[0] != 'r')
462 break;
463 if (cnt == 0) {
464 ecp->cp -= namelen - 1;
465 ecp->clen += namelen - 1;
466 ecp->rcmd = cmds[C_SUBSTITUTE];
467 ecp->rcmd.fn = ex_subagain;
468 ecp->cmd = &ecp->rcmd;
469 break;
470 }
471 /* FALLTHROUGH */
472 default:
473unknown: if (newscreen)
474 p[0] = toupper(p[0]);
475 ex_unknown(sp, p, namelen);
476 goto err;
477 }
478
479 /*
480 * The visual command has a different syntax when called
481 * from ex than when called from a vi colon command. FMH.
482 * Make the change now, before we test for the newscreen
483 * semantic, so that we're testing the right one.
484 */
485skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI)(((sp)->flags) & ((0x00000002))))
486 ecp->cmd = &cmds[C_VISUAL_VI];
487
488 /*
489 * !!!
490 * Historic vi permitted a capital 'P' at the beginning of
491 * any command that started with 'p'. Probably wanted the
492 * P[rint] command for backward compatibility, and the code
493 * just made Preserve and Put work by accident. Nvi uses
494 * Previous to mean previous-in-a-new-screen, so be careful.
495 */
496 if (newscreen && !F_ISSET(ecp->cmd, E_NEWSCREEN)(((ecp->cmd)->flags) & ((0x00000100))) &&
497 (ecp->cmd == &cmds[C_PRINT] ||
498 ecp->cmd == &cmds[C_PRESERVE]))
499 newscreen = 0;
500
501 /* Test for a newscreen associated with this command. */
502 if (newscreen && !F_ISSET(ecp->cmd, E_NEWSCREEN)(((ecp->cmd)->flags) & ((0x00000100))))
503 goto unknown;
504
505 /* Secure means no shell access. */
506 if (F_ISSET(ecp->cmd, E_SECURE)(((ecp->cmd)->flags) & ((0x00000200))) && O_ISSET(sp, O_SECURE)((((&(((sp)))->opts[(((O_SECURE)))])->flags) & (
(0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((O_SECURE
)))].o_cur.val].o_cur.val : (((sp)))->opts[(((O_SECURE)))]
.o_cur.val)
) {
507 ex_emsg(sp, ecp->cmd->name, EXM_SECURE);
508 goto err;
509 }
510
511 /*
512 * Multiple < and > characters; another "feature". Note,
513 * The string passed to the underlying function may not be
514 * nul terminated in this case.
515 */
516 if ((ecp->cmd == &cmds[C_SHIFTL] && *p == '<') ||
517 (ecp->cmd == &cmds[C_SHIFTR] && *p == '>')) {
518 for (ch = *p;
519 ecp->clen > 0; --ecp->clen, ++ecp->cp)
520 if (*ecp->cp != ch)
521 break;
522 if (argv_exp0(sp, ecp, p, ecp->cp - p))
523 goto err;
524 }
525
526 /* Set the format style flags for the next command. */
527 if (ecp->cmd == &cmds[C_HASH])
528 exp->fdef = E_C_HASH0x00200;
529 else if (ecp->cmd == &cmds[C_LIST])
530 exp->fdef = E_C_LIST0x00400;
531 else if (ecp->cmd == &cmds[C_PRINT])
532 exp->fdef = E_C_PRINT0x01000;
533 F_CLR(ecp, E_USELASTCMD)(((ecp)->flags) &= ~((0x02000000)));
534 } else {
535 /* Print is the default command. */
536 ecp->cmd = &cmds[C_PRINT];
537
538 /* Set the saved format flags. */
539 F_SET(ecp, exp->fdef)(((ecp)->flags) |= ((exp->fdef)));
540
541 /*
542 * !!!
543 * If no address was specified, and it's not a global command,
544 * we up the address by one. (I have no idea why globals are
545 * exempted, but it's (ahem) historic practice.)
546 */
547 if (ecp->addrcnt == 0 && !F_ISSET(sp, SC_EX_GLOBAL)(((sp)->flags) & ((0x00020000)))) {
548 ecp->addrcnt = 1;
549 ecp->addr1.lno = sp->lno + 1;
550 ecp->addr1.cno = sp->cno;
551 }
552
553 F_SET(ecp, E_USELASTCMD)(((ecp)->flags) |= ((0x02000000)));
554 }
555
556 /*
557 * !!!
558 * Historically, the number option applied to both ex and vi. One
559 * strangeness was that ex didn't switch display formats until a
560 * command was entered, e.g. <CR>'s after the set didn't change to
561 * the new format, but :1p would.
562 */
563 if (O_ISSET(sp, O_NUMBER)((((&(((sp)))->opts[(((O_NUMBER)))])->flags) & (
(0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((O_NUMBER
)))].o_cur.val].o_cur.val : (((sp)))->opts[(((O_NUMBER)))]
.o_cur.val)
) {
564 F_SET(ecp, E_OPTNUM)(((ecp)->flags) |= ((0x00010000)));
565 FL_SET(ecp->iflags, E_C_HASH)((ecp->iflags) |= (0x00200));
566 } else
567 F_CLR(ecp, E_OPTNUM)(((ecp)->flags) &= ~((0x00010000)));
568
569 /* Check for ex mode legality. */
570 if (F_ISSET(sp, SC_EX)(((sp)->flags) & ((0x00000001))) && (F_ISSET(ecp->cmd, E_VIONLY)(((ecp->cmd)->flags) & ((0x00000400))) || newscreen)) {
571 msgq(sp, M_ERR,
572 "%s: command not available in ex mode", ecp->cmd->name);
573 goto err;
574 }
575
576 /* Add standard command flags. */
577 F_SET(ecp, ecp->cmd->flags)(((ecp)->flags) |= ((ecp->cmd->flags)));
578 if (!newscreen)
579 F_CLR(ecp, E_NEWSCREEN)(((ecp)->flags) &= ~((0x00000100)));
580
581 /*
582 * There are three normal termination cases for an ex command. They
583 * are the end of the string (ecp->clen), or unescaped (by <literal
584 * next> characters) <newline> or '|' characters. As we're now past
585 * possible addresses, we can determine how long the command is, so we
586 * don't have to look for all the possible terminations. Naturally,
587 * there are some exciting special cases:
588 *
589 * 1: The bang, global, v and the filter versions of the read and
590 * write commands are delimited by <newline>s (they can contain
591 * shell pipes).
592 * 2: The ex, edit, next and visual in vi mode commands all take ex
593 * commands as their first arguments.
594 * 3: The s command takes an RE as its first argument, and wants it
595 * to be specially delimited.
596 *
597 * Historically, '|' characters in the first argument of the ex, edit,
598 * next, vi visual, and s commands didn't delimit the command. And,
599 * in the filter cases for read and write, and the bang, global and v
600 * commands, they did not delimit the command at all.
601 *
602 * For example, the following commands were legal:
603 *
604 * :edit +25|s/abc/ABC/ file.c
605 * :s/|/PIPE/
606 * :read !spell % | columnate
607 * :global/pattern/p|l
608 *
609 * It's not quite as simple as it sounds, however. The command:
610 *
611 * :s/a/b/|s/c/d|set
612 *
613 * was also legal, i.e. the historic ex parser (using the word loosely,
614 * since "parser" implies some regularity of syntax) delimited the RE's
615 * based on its delimiter and not anything so irretrievably vulgar as a
616 * command syntax.
617 *
618 * Anyhow, the following code makes this all work. First, for the
619 * special cases we move past their special argument(s). Then, we
620 * do normal command processing on whatever is left. Barf-O-Rama.
621 */
622 discard = 0; /* Characters discarded from the command. */
623 arg1_len = 0;
624 ecp->save_cmd = ecp->cp;
625 if (ecp->cmd == &cmds[C_EDIT] || ecp->cmd == &cmds[C_EX] ||
626 ecp->cmd == &cmds[C_NEXT] || ecp->cmd == &cmds[C_VISUAL_VI]) {
627 /*
628 * Move to the next non-whitespace character. A '!'
629 * immediately following the command is eaten as a
630 * force flag.
631 */
632 if (ecp->clen > 0 && *ecp->cp == '!') {
633 ++ecp->cp;
634 --ecp->clen;
635 FL_SET(ecp->iflags, E_C_FORCE)((ecp->iflags) |= (0x00100));
636
637 /* Reset, don't reparse. */
638 ecp->save_cmd = ecp->cp;
639 }
640 for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
641 if (!isblank(*ecp->cp))
642 break;
643 /*
644 * QUOTING NOTE:
645 *
646 * The historic implementation ignored all escape characters
647 * so there was no way to put a space or newline into the +cmd
648 * field. We do a simplistic job of fixing it by moving to the
649 * first whitespace character that isn't escaped. The escaping
650 * characters are stripped as no longer useful.
651 */
652 if (ecp->clen > 0 && *ecp->cp == '+') {
653 ++ecp->cp;
654 --ecp->clen;
655 for (arg1 = p = ecp->cp;
656 ecp->clen > 0; --ecp->clen, ++ecp->cp) {
657 ch = *ecp->cp;
658 if (IS_ESCAPE(sp, ecp, ch)(((((ecp))->flags) & ((0x00020000))) ? (ch) == '\026' :
((unsigned char)((ch)) <= 254 ? ((sp))->gp->special_key
[(unsigned char)((ch))] : (unsigned char)((ch)) > ((sp))->
gp->max_special ? 0 : v_key_val(((sp)),((ch)))) == K_VLNEXT
)
&&
659 ecp->clen > 1) {
660 ++discard;
661 --ecp->clen;
662 ch = *++ecp->cp;
663 } else if (isblank(ch))
664 break;
665 *p++ = ch;
666 }
667 arg1_len = ecp->cp - arg1;
668
669 /* Reset, so the first argument isn't reparsed. */
670 ecp->save_cmd = ecp->cp;
671 }
672 } else if (ecp->cmd == &cmds[C_BANG] ||
673 ecp->cmd == &cmds[C_GLOBAL] || ecp->cmd == &cmds[C_V]) {
674 /*
675 * QUOTING NOTE:
676 *
677 * We use backslashes to escape <newline> characters, although
678 * this wasn't historic practice for the bang command. It was
679 * for the global and v commands, and it's common usage when
680 * doing text insert during the command. Escaping characters
681 * are stripped as no longer useful.
682 */
683 for (p = ecp->cp; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
684 ch = *ecp->cp;
685 if (ch == '\\' && ecp->clen > 1 && ecp->cp[1] == '\n') {
686 ++discard;
687 --ecp->clen;
688 ch = *++ecp->cp;
689
690 ++gp->if_lno;
691 ++ecp->if_lno;
692 } else if (ch == '\n')
693 break;
694 *p++ = ch;
695 }
696 } else if (ecp->cmd == &cmds[C_READ] || ecp->cmd == &cmds[C_WRITE]) {
697 /*
698 * For write commands, if the next character is a <blank>, and
699 * the next non-blank character is a '!', it's a filter command
700 * and we want to eat everything up to the <newline>. For read
701 * commands, if the next non-blank character is a '!', it's a
702 * filter command and we want to eat everything up to the next
703 * <newline>. Otherwise, we're done.
704 */
705 for (tmp = 0; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
706 ch = *ecp->cp;
707 if (isblank(ch))
708 tmp = 1;
709 else
710 break;
711 }
712 if (ecp->clen > 0 && ch == '!' &&
713 (ecp->cmd == &cmds[C_READ] || tmp))
714 for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
715 if (ecp->cp[0] == '\n')
716 break;
717 } else if (ecp->cmd == &cmds[C_SUBSTITUTE]) {
718 /*
719 * Move to the next non-whitespace character, we'll use it as
720 * the delimiter. If the character isn't an alphanumeric or
721 * a '|', it's the delimiter, so parse it. Otherwise, we're
722 * into something like ":s g", so use the special s command.
723 */
724 for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
725 if (!isblank(ecp->cp[0]))
726 break;
727
728 if (isalnum(ecp->cp[0]) || ecp->cp[0] == '|') {
729 ecp->rcmd = cmds[C_SUBSTITUTE];
730 ecp->rcmd.fn = ex_subagain;
731 ecp->cmd = &ecp->rcmd;
732 } else if (ecp->clen > 0) {
733 /*
734 * QUOTING NOTE:
735 *
736 * Backslashes quote delimiter characters for RE's.
737 * The backslashes are NOT removed since they'll be
738 * used by the RE code. Move to the third delimiter
739 * that's not escaped (or the end of the command).
740 */
741 delim = *ecp->cp;
742 ++ecp->cp;
743 --ecp->clen;
744 for (cnt = 2; ecp->clen > 0 &&
745 cnt != 0; --ecp->clen, ++ecp->cp)
746 if (ecp->cp[0] == '\\' &&
747 ecp->clen > 1) {
748 ++ecp->cp;
749 --ecp->clen;
750 } else if (ecp->cp[0] == delim)
751 --cnt;
752 }
753 }
754
755 /*
756 * Use normal quoting and termination rules to find the end of this
757 * command.
758 *
759 * QUOTING NOTE:
760 *
761 * Historically, vi permitted ^V's to escape <newline>'s in the .exrc
762 * file. It was almost certainly a bug, but that's what bug-for-bug
763 * compatibility means, Grasshopper. Also, ^V's escape the command
764 * delimiters. Literal next quote characters in front of the newlines,
765 * '|' characters or literal next characters are stripped as they're
766 * no longer useful.
767 */
768 vi_address = ecp->clen != 0 && ecp->cp[0] != '\n';
769 for (p = ecp->cp; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
770 ch = ecp->cp[0];
771 if (IS_ESCAPE(sp, ecp, ch)(((((ecp))->flags) & ((0x00020000))) ? (ch) == '\026' :
((unsigned char)((ch)) <= 254 ? ((sp))->gp->special_key
[(unsigned char)((ch))] : (unsigned char)((ch)) > ((sp))->
gp->max_special ? 0 : v_key_val(((sp)),((ch)))) == K_VLNEXT
)
&& ecp->clen > 1) {
772 tmp = ecp->cp[1];
773 if (tmp == '\n' || tmp == '|') {
774 if (tmp == '\n') {
775 ++gp->if_lno;
776 ++ecp->if_lno;
777 }
778 ++discard;
779 --ecp->clen;
780 ++ecp->cp;
781 ch = tmp;
782 }
783 } else if (ch == '\n' || ch == '|') {
784 if (ch == '\n')
785 F_SET(ecp, E_NEWLINE)(((ecp)->flags) |= ((0x00800000)));
786 --ecp->clen;
787 break;
788 }
789 *p++ = ch;
790 }
791
792 /*
793 * Save off the next command information, go back to the
794 * original start of the command.
795 */
796 p = ecp->cp + 1;
797 ecp->cp = ecp->save_cmd;
798 ecp->save_cmd = p;
799 ecp->save_cmdlen = ecp->clen;
800 ecp->clen = ((ecp->save_cmd - ecp->cp) - 1) - discard;
801
802 /*
803 * QUOTING NOTE:
804 *
805 * The "set tags" command historically used a backslash, not the
806 * user's literal next character, to escape whitespace. Handle
807 * it here instead of complicating the argv_exp3() code. Note,
808 * this isn't a particularly complex trap, and if backslashes were
809 * legal in set commands, this would have to be much more complicated.
810 */
811 if (ecp->cmd == &cmds[C_SET])
812 for (p = ecp->cp, len = ecp->clen; len > 0; --len, ++p)
813 if (*p == '\\')
814 *p = CH_LITERAL'\026';
815
816 /*
817 * Set the default addresses. It's an error to specify an address for
818 * a command that doesn't take them. If two addresses are specified
819 * for a command that only takes one, lose the first one. Two special
820 * cases here, some commands take 0 or 2 addresses. For most of them
821 * (the E_ADDR2_ALL flag), 0 defaults to the entire file. For one
822 * (the `!' command, the E_ADDR2_NONE flag), 0 defaults to no lines.
823 *
824 * Also, if the file is empty, some commands want to use an address of
825 * 0, i.e. the entire file is 0 to 0, and the default first address is
826 * 0. Otherwise, an entire file is 1 to N and the default line is 1.
827 * Note, we also add the E_ADDR_ZERO flag to the command flags, for the
828 * case where the 0 address is only valid if it's a default address.
829 *
830 * Also, set a flag if we set the default addresses. Some commands
831 * (ex: z) care if the user specified an address or if we just used
832 * the current cursor.
833 */
834 switch (F_ISSET(ecp, E_ADDR1 | E_ADDR2 | E_ADDR2_ALL | E_ADDR2_NONE)(((ecp)->flags) & ((0x00000001 | 0x00000002 | 0x00000004
| 0x00000008)))
) {
835 case E_ADDR10x00000001: /* One address: */
836 switch (ecp->addrcnt) {
837 case 0: /* Default cursor/empty file. */
838 ecp->addrcnt = 1;
839 F_SET(ecp, E_ADDR_DEF)(((ecp)->flags) |= ((0x00080000)));
840 if (F_ISSET(ecp, E_ADDR_ZERODEF)(((ecp)->flags) & ((0x00000020)))) {
841 if (db_last(sp, &lno))
842 goto err;
843 if (lno == 0) {
844 ecp->addr1.lno = 0;
845 F_SET(ecp, E_ADDR_ZERO)(((ecp)->flags) |= ((0x00000010)));
846 } else
847 ecp->addr1.lno = sp->lno;
848 } else
849 ecp->addr1.lno = sp->lno;
850 ecp->addr1.cno = sp->cno;
851 break;
852 case 1:
853 break;
854 case 2: /* Lose the first address. */
855 ecp->addrcnt = 1;
856 ecp->addr1 = ecp->addr2;
857 }
858 break;
859 case E_ADDR2_NONE0x00000008: /* Zero/two addresses: */
860 if (ecp->addrcnt == 0) /* Default to nothing. */
861 break;
862 goto two_addr;
863 case E_ADDR2_ALL0x00000004: /* Zero/two addresses: */
864 if (ecp->addrcnt == 0) { /* Default entire/empty file. */
865 F_SET(ecp, E_ADDR_DEF)(((ecp)->flags) |= ((0x00080000)));
866 ecp->addrcnt = 2;
867 if (sp->ep == NULL((void *)0))
868 ecp->addr2.lno = 0;
869 else if (db_last(sp, &ecp->addr2.lno))
870 goto err;
871 if (F_ISSET(ecp, E_ADDR_ZERODEF)(((ecp)->flags) & ((0x00000020))) &&
872 ecp->addr2.lno == 0) {
873 ecp->addr1.lno = 0;
874 F_SET(ecp, E_ADDR_ZERO)(((ecp)->flags) |= ((0x00000010)));
875 } else
876 ecp->addr1.lno = 1;
877 ecp->addr1.cno = ecp->addr2.cno = 0;
878 F_SET(ecp, E_ADDR2_ALL)(((ecp)->flags) |= ((0x00000004)));
879 break;
880 }
881 /* FALLTHROUGH */
882 case E_ADDR20x00000002: /* Two addresses: */
883two_addr: switch (ecp->addrcnt) {
884 case 0: /* Default cursor/empty file. */
885 ecp->addrcnt = 2;
886 F_SET(ecp, E_ADDR_DEF)(((ecp)->flags) |= ((0x00080000)));
887 if (sp->lno == 1 &&
888 F_ISSET(ecp, E_ADDR_ZERODEF)(((ecp)->flags) & ((0x00000020)))) {
889 if (db_last(sp, &lno))
890 goto err;
891 if (lno == 0) {
892 ecp->addr1.lno = ecp->addr2.lno = 0;
893 F_SET(ecp, E_ADDR_ZERO)(((ecp)->flags) |= ((0x00000010)));
894 } else
895 ecp->addr1.lno =
896 ecp->addr2.lno = sp->lno;
897 } else
898 ecp->addr1.lno = ecp->addr2.lno = sp->lno;
899 ecp->addr1.cno = ecp->addr2.cno = sp->cno;
900 break;
901 case 1: /* Default to first address. */
902 ecp->addrcnt = 2;
903 ecp->addr2 = ecp->addr1;
904 break;
905 case 2:
906 break;
907 }
908 break;
909 default:
910 if (ecp->addrcnt) /* Error. */
911 goto usage;
912 }
913
914 /*
915 * !!!
916 * The ^D scroll command historically scrolled the value of the scroll
917 * option or to EOF. It was an error if the cursor was already at EOF.
918 * (Leading addresses were permitted, but were then ignored.)
919 */
920 if (ecp->cmd == &cmds[C_SCROLL]) {
921 ecp->addrcnt = 2;
922 ecp->addr1.lno = sp->lno + 1;
923 ecp->addr2.lno = sp->lno + O_VAL(sp, O_SCROLL)((((&((sp))->opts[((O_SCROLL))])->flags) & ((0x01
))) ? ((sp))->gp->opts[((sp))->opts[((O_SCROLL))].o_cur
.val].o_cur.val : ((sp))->opts[((O_SCROLL))].o_cur.val)
;
924 ecp->addr1.cno = ecp->addr2.cno = sp->cno;
925 if (db_last(sp, &lno))
926 goto err;
927 if (lno != 0 && lno > sp->lno && ecp->addr2.lno > lno)
928 ecp->addr2.lno = lno;
929 }
930
931 ecp->flagoff = 0;
932 for (p = ecp->cmd->syntax; *p != '\0'; ++p) {
933 /*
934 * The force flag is sensitive to leading whitespace, i.e.
935 * "next !" is different from "next!". Handle it before
936 * skipping leading <blank>s.
937 */
938 if (*p == '!') {
939 if (ecp->clen > 0 && *ecp->cp == '!') {
940 ++ecp->cp;
941 --ecp->clen;
942 FL_SET(ecp->iflags, E_C_FORCE)((ecp->iflags) |= (0x00100));
943 }
944 continue;
945 }
946
947 /* Skip leading <blank>s. */
948 for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
949 if (!isblank(*ecp->cp))
950 break;
951 if (ecp->clen == 0)
952 break;
953
954 switch (*p) {
955 case '1': /* +, -, #, l, p */
956 /*
957 * !!!
958 * Historically, some flags were ignored depending
959 * on where they occurred in the command line. For
960 * example, in the command, ":3+++p--#", historic vi
961 * acted on the '#' flag, but ignored the '-' flags.
962 * It's unambiguous what the flags mean, so we just
963 * handle them regardless of the stupidity of their
964 * location.
965 */
966 for (; ecp->clen; --ecp->clen, ++ecp->cp)
967 switch (*ecp->cp) {
968 case '+':
969 ++ecp->flagoff;
970 break;
971 case '-':
972 case '^':
973 --ecp->flagoff;
974 break;
975 case '#':
976 F_CLR(ecp, E_OPTNUM)(((ecp)->flags) &= ~((0x00010000)));
977 FL_SET(ecp->iflags, E_C_HASH)((ecp->iflags) |= (0x00200));
978 exp->fdef |= E_C_HASH0x00200;
979 break;
980 case 'l':
981 FL_SET(ecp->iflags, E_C_LIST)((ecp->iflags) |= (0x00400));
982 exp->fdef |= E_C_LIST0x00400;
983 break;
984 case 'p':
985 FL_SET(ecp->iflags, E_C_PRINT)((ecp->iflags) |= (0x01000));
986 exp->fdef |= E_C_PRINT0x01000;
987 break;
988 default:
989 goto end_case1;
990 }
991end_case1: break;
992 case '2': /* -, ., +, ^ */
993 case '3': /* -, ., +, ^, = */
994 for (; ecp->clen; --ecp->clen, ++ecp->cp)
995 switch (*ecp->cp) {
996 case '-':
997 FL_SET(ecp->iflags, E_C_DASH)((ecp->iflags) |= (0x00020));
998 break;
999 case '.':
1000 FL_SET(ecp->iflags, E_C_DOT)((ecp->iflags) |= (0x00040));
1001 break;
1002 case '+':
1003 FL_SET(ecp->iflags, E_C_PLUS)((ecp->iflags) |= (0x00800));
1004 break;
1005 case '^':
1006 FL_SET(ecp->iflags, E_C_CARAT)((ecp->iflags) |= (0x00002));
1007 break;
1008 case '=':
1009 if (*p == '3') {
1010 FL_SET(ecp->iflags, E_C_EQUAL)((ecp->iflags) |= (0x00080));
1011 break;
1012 }
1013 /* FALLTHROUGH */
1014 default:
1015 goto end_case23;
1016 }
1017end_case23: break;
1018 case 'b': /* buffer */
1019 /*
1020 * !!!
1021 * Historically, "d #" was a delete with a flag, not a
1022 * delete into the '#' buffer. If the current command
1023 * permits a flag, don't use one as a buffer. However,
1024 * the 'l' and 'p' flags were legal buffer names in the
1025 * historic ex, and were used as buffers, not flags.
1026 */
1027 if ((ecp->cp[0] == '+' || ecp->cp[0] == '-' ||
1028 ecp->cp[0] == '^' || ecp->cp[0] == '#') &&
1029 strchr(p, '1') != NULL((void *)0))
1030 break;
1031 /*
1032 * !!!
1033 * Digits can't be buffer names in ex commands, or the
1034 * command "d2" would be a delete into buffer '2', and
1035 * not a two-line deletion.
1036 */
1037 if (!isdigit(ecp->cp[0])) {
1038 ecp->buffer = *ecp->cp;
1039 ++ecp->cp;
1040 --ecp->clen;
1041 FL_SET(ecp->iflags, E_C_BUFFER)((ecp->iflags) |= (0x00001));
1042 }
1043 break;
1044 case 'c': /* count [01+a] */
1045 ++p;
1046 /* Validate any signed value. */
1047 if (!isdigit(*ecp->cp) && (*p != '+' ||
1048 (*ecp->cp != '+' && *ecp->cp != '-')))
1049 break;
1050 /* If a signed value, set appropriate flags. */
1051 if (*ecp->cp == '-')
1052 FL_SET(ecp->iflags, E_C_COUNT_NEG)((ecp->iflags) |= (0x00008));
1053 else if (*ecp->cp == '+')
1054 FL_SET(ecp->iflags, E_C_COUNT_POS)((ecp->iflags) |= (0x00010));
1055 if ((nret =
1056 nget_slong(&ltmp, ecp->cp, &t, 10)) != NUM_OK) {
1057 ex_badaddr(sp, NULL((void *)0), A_NOTSET, nret);
1058 goto err;
1059 }
1060 if (ltmp == 0 && *p != '0') {
1061 msgq(sp, M_ERR, "Count may not be zero");
1062 goto err;
1063 }
1064 ecp->clen -= (t - ecp->cp);
1065 ecp->cp = t;
1066
1067 /*
1068 * Counts as address offsets occur in commands taking
1069 * two addresses. Historic vi practice was to use
1070 * the count as an offset from the *second* address.
1071 *
1072 * Set a count flag; some underlying commands (see
1073 * join) do different things with counts than with
1074 * line addresses.
1075 */
1076 if (*p == 'a') {
1077 ecp->addr1 = ecp->addr2;
1078 ecp->addr2.lno = ecp->addr1.lno + ltmp - 1;
1079 } else
1080 ecp->count = ltmp;
1081 FL_SET(ecp->iflags, E_C_COUNT)((ecp->iflags) |= (0x00004));
1082 break;
1083 case 'f': /* file */
1084 if (argv_exp2(sp, ecp, ecp->cp, ecp->clen))
1085 goto err;
1086 goto arg_cnt_chk;
1087 case 'l': /* line */
1088 /*
1089 * Get a line specification.
1090 *
1091 * If the line was a search expression, we may have
1092 * changed state during the call, and we're now
1093 * searching the file. Push ourselves onto the state
1094 * stack.
1095 */
1096 if (ex_line(sp, ecp, &cur, &isaddr, &tmp))
1097 goto rfail;
1098 if (tmp)
1099 goto err;
1100
1101 /* Line specifications are always required. */
1102 if (!isaddr) {
1103 msgq_str(sp, M_ERR, ecp->cp,
1104 "%s: bad line specification");
1105 goto err;
1106 }
1107 /*
1108 * The target line should exist for these commands,
1109 * but 0 is legal for them as well.
1110 */
1111 if (cur.lno != 0 && !db_exist(sp, cur.lno)) {
1112 ex_badaddr(sp, NULL((void *)0), A_EOF, NUM_OK);
1113 goto err;
1114 }
1115 ecp->lineno = cur.lno;
1116 break;
1117 case 'S': /* string, file exp. */
1118 if (ecp->clen != 0) {
1119 if (argv_exp1(sp, ecp, ecp->cp,
1120 ecp->clen, ecp->cmd == &cmds[C_BANG]))
1121 goto err;
1122 goto addr_verify;
1123 }
1124 /* FALLTHROUGH */
1125 case 's': /* string */
1126 if (argv_exp0(sp, ecp, ecp->cp, ecp->clen))
1127 goto err;
1128 goto addr_verify;
1129 case 'W': /* word string */
1130 /*
1131 * QUOTING NOTE:
1132 *
1133 * Literal next characters escape the following
1134 * character. Quoting characters are stripped here
1135 * since they are no longer useful.
1136 *
1137 * First there was the word.
1138 */
1139 for (p = t = ecp->cp;
1140 ecp->clen > 0; --ecp->clen, ++ecp->cp) {
1141 ch = *ecp->cp;
1142 if (IS_ESCAPE(sp,(((((ecp))->flags) & ((0x00020000))) ? (ch) == '\026' :
((unsigned char)((ch)) <= 254 ? ((sp))->gp->special_key
[(unsigned char)((ch))] : (unsigned char)((ch)) > ((sp))->
gp->max_special ? 0 : v_key_val(((sp)),((ch)))) == K_VLNEXT
)
1143 ecp, ch)(((((ecp))->flags) & ((0x00020000))) ? (ch) == '\026' :
((unsigned char)((ch)) <= 254 ? ((sp))->gp->special_key
[(unsigned char)((ch))] : (unsigned char)((ch)) > ((sp))->
gp->max_special ? 0 : v_key_val(((sp)),((ch)))) == K_VLNEXT
)
&& ecp->clen > 1) {
1144 --ecp->clen;
1145 *p++ = *++ecp->cp;
1146 } else if (isblank(ch)) {
1147 ++ecp->cp;
1148 --ecp->clen;
1149 break;
1150 } else
1151 *p++ = ch;
1152 }
1153 if (argv_exp0(sp, ecp, t, p - t))
1154 goto err;
1155
1156 /* Delete intervening whitespace. */
1157 for (; ecp->clen > 0;
1158 --ecp->clen, ++ecp->cp) {
1159 ch = *ecp->cp;
1160 if (!isblank(ch))
1161 break;
1162 }
1163 if (ecp->clen == 0)
1164 goto usage;
1165
1166 /* Followed by the string. */
1167 for (p = t = ecp->cp; ecp->clen > 0;
1168 --ecp->clen, ++ecp->cp, ++p) {
1169 ch = *ecp->cp;
1170 if (IS_ESCAPE(sp,(((((ecp))->flags) & ((0x00020000))) ? (ch) == '\026' :
((unsigned char)((ch)) <= 254 ? ((sp))->gp->special_key
[(unsigned char)((ch))] : (unsigned char)((ch)) > ((sp))->
gp->max_special ? 0 : v_key_val(((sp)),((ch)))) == K_VLNEXT
)
1171 ecp, ch)(((((ecp))->flags) & ((0x00020000))) ? (ch) == '\026' :
((unsigned char)((ch)) <= 254 ? ((sp))->gp->special_key
[(unsigned char)((ch))] : (unsigned char)((ch)) > ((sp))->
gp->max_special ? 0 : v_key_val(((sp)),((ch)))) == K_VLNEXT
)
&& ecp->clen > 1) {
1172 --ecp->clen;
1173 *p = *++ecp->cp;
1174 } else
1175 *p = ch;
1176 }
1177 if (argv_exp0(sp, ecp, t, p - t))
1178 goto err;
1179 goto addr_verify;
1180 case 'w': /* word */
1181 if (argv_exp3(sp, ecp, ecp->cp, ecp->clen))
1182 goto err;
1183arg_cnt_chk: if (*++p != 'N') { /* N */
1184 /*
1185 * If a number is specified, must either be
1186 * 0 or that number, if optional, and that
1187 * number, if required.
1188 */
1189 tmp = *p - '0';
1190 if ((*++p != 'o' || exp->argsoff != 0) &&
1191 exp->argsoff != tmp)
1192 goto usage;
1193 }
1194 goto addr_verify;
1195 default:
1196 msgq(sp, M_ERR,
1197 "Internal syntax table error (%s: %s)",
1198 ecp->cmd->name, KEY_NAME(sp, *p)((unsigned char)(*p) <= 254 ? (sp)->gp->cname[(unsigned
char)(*p)].name : v_key_name((sp), (*p)))
);
1199 }
1200 }
1201
1202 /* Skip trailing whitespace. */
1203 for (; ecp->clen > 0; --ecp->clen) {
1204 ch = *ecp->cp++;
1205 if (!isblank(ch))
1206 break;
1207 }
1208
1209 /*
1210 * There shouldn't be anything left, and no more required fields,
1211 * i.e neither 'l' or 'r' in the syntax string.
1212 */
1213 if (ecp->clen != 0 || strpbrk(p, "lr")) {
1214usage: msgq(sp, M_ERR, "Usage: %s", ecp->cmd->usage);
1215 goto err;
1216 }
1217
1218 /*
1219 * Verify that the addresses are legal. Check the addresses here,
1220 * because this is a place where all ex addresses pass through.
1221 * (They don't all pass through ex_line(), for instance.) We're
1222 * assuming that any non-existent line doesn't exist because it's
1223 * past the end-of-file. That's a pretty good guess.
1224 *
1225 * If it's a "default vi command", an address of zero is okay.
1226 */
1227addr_verify:
1228 switch (ecp->addrcnt) {
1229 case 2:
1230 /*
1231 * Historic ex/vi permitted commands with counts to go past
1232 * EOF. So, for example, if the file only had 5 lines, the
1233 * ex command "1,6>" would fail, but the command ">300"
1234 * would succeed. Since we don't want to have to make all
1235 * of the underlying commands handle random line numbers,
1236 * fix it here.
1237 */
1238 if (ecp->addr2.lno == 0) {
1239 if (!F_ISSET(ecp, E_ADDR_ZERO)(((ecp)->flags) & ((0x00000010))) &&
1240 (F_ISSET(sp, SC_EX)(((sp)->flags) & ((0x00000001))) ||
1241 !F_ISSET(ecp, E_USELASTCMD)(((ecp)->flags) & ((0x02000000))))) {
1242 ex_badaddr(sp, ecp->cmd, A_ZERO, NUM_OK);
1243 goto err;
1244 }
1245 } else if (!db_exist(sp, ecp->addr2.lno)) {
1246 if (FL_ISSET(ecp->iflags, E_C_COUNT)((ecp->iflags) & (0x00004))) {
1247 if (db_last(sp, &lno))
1248 goto err;
1249 ecp->addr2.lno = lno;
1250 } else {
1251 ex_badaddr(sp, NULL((void *)0), A_EOF, NUM_OK);
1252 goto err;
1253 }
1254 }
1255 /* FALLTHROUGH */
1256 case 1:
1257 if (ecp->addr1.lno == 0) {
1258 if (!F_ISSET(ecp, E_ADDR_ZERO)(((ecp)->flags) & ((0x00000010))) &&
1259 (F_ISSET(sp, SC_EX)(((sp)->flags) & ((0x00000001))) ||
1260 !F_ISSET(ecp, E_USELASTCMD)(((ecp)->flags) & ((0x02000000))))) {
1261 ex_badaddr(sp, ecp->cmd, A_ZERO, NUM_OK);
1262 goto err;
1263 }
1264 } else if (!db_exist(sp, ecp->addr1.lno)) {
1265 ex_badaddr(sp, NULL((void *)0), A_EOF, NUM_OK);
1266 goto err;
1267 }
1268 break;
1269 }
1270
1271 /*
1272 * If doing a default command and there's nothing left on the line,
1273 * vi just moves to the line. For example, ":3" and ":'a,'b" just
1274 * move to line 3 and line 'b, respectively, but ":3|" prints line 3.
1275 *
1276 * !!!
1277 * In addition, IF THE LINE CHANGES, move to the first nonblank of
1278 * the line.
1279 *
1280 * !!!
1281 * This is done before the absolute mark gets set; historically,
1282 * "/a/,/b/" did NOT set vi's absolute mark, but "/a/,/b/d" did.
1283 */
1284 if ((F_ISSET(sp, SC_VI)(((sp)->flags) & ((0x00000002))) || F_ISSET(ecp, E_NOPRDEF)(((ecp)->flags) & ((0x00004000)))) &&
1285 F_ISSET(ecp, E_USELASTCMD)(((ecp)->flags) & ((0x02000000))) && vi_address == 0) {
1286 switch (ecp->addrcnt) {
1287 case 2:
1288 if (sp->lno !=
1289 (ecp->addr2.lno ? ecp->addr2.lno : 1)) {
1290 sp->lno =
1291 ecp->addr2.lno ? ecp->addr2.lno : 1;
1292 sp->cno = 0;
1293 (void)nonblank(sp, sp->lno, &sp->cno);
1294 }
1295 break;
1296 case 1:
1297 if (sp->lno !=
1298 (ecp->addr1.lno ? ecp->addr1.lno : 1)) {
1299 sp->lno =
1300 ecp->addr1.lno ? ecp->addr1.lno : 1;
1301 sp->cno = 0;
1302 (void)nonblank(sp, sp->lno, &sp->cno);
1303 }
1304 break;
1305 }
1306 ecp->cp = ecp->save_cmd;
1307 ecp->clen = ecp->save_cmdlen;
1308 goto loop;
1309 }
1310
1311 /*
1312 * Set the absolute mark -- we have to set it for vi here, in case
1313 * it's a compound command, e.g. ":5p|6" should set the absolute
1314 * mark for vi.
1315 */
1316 if (F_ISSET(ecp, E_ABSMARK)(((ecp)->flags) & ((0x00040000)))) {
1317 cur.lno = sp->lno;
1318 cur.cno = sp->cno;
1319 F_CLR(ecp, E_ABSMARK)(((ecp)->flags) &= ~((0x00040000)));
1320 if (mark_set(sp, ABSMARK1'\'', &cur, 1))
1321 goto err;
1322 }
1323
1324#if defined(DEBUG) && defined(COMLOG)
1325 ex_comlog(sp, ecp);
1326#endif
1327 /* Increment the command count if not called from vi. */
1328 if (F_ISSET(sp, SC_EX)(((sp)->flags) & ((0x00000001))))
1329 ++sp->ccnt;
1330
1331 /*
1332 * If file state available, and not doing a global command,
1333 * log the start of an action.
1334 */
1335 if (sp->ep != NULL((void *)0) && !F_ISSET(sp, SC_EX_GLOBAL)(((sp)->flags) & ((0x00020000))))
1336 (void)log_cursor(sp);
1337
1338 /*
1339 * !!!
1340 * There are two special commands for the purposes of this code: the
1341 * default command (<carriage-return>) or the scrolling commands (^D
1342 * and <EOF>) as the first non-<blank> characters in the line.
1343 *
1344 * If this is the first command in the command line, we received the
1345 * command from the ex command loop and we're talking to a tty, and
1346 * and there's nothing else on the command line, and it's one of the
1347 * special commands, we move back up to the previous line, and erase
1348 * the prompt character with the output. Since ex runs in canonical
1349 * mode, we don't have to do anything else, a <newline> has already
1350 * been echoed by the tty driver. It's OK if vi calls us -- we won't
1351 * be in ex mode so we'll do nothing.
1352 */
1353 if (F_ISSET(ecp, E_NRSEP)(((ecp)->flags) & ((0x00008000)))) {
1354 if (sp->ep != NULL((void *)0) &&
1355 F_ISSET(sp, SC_EX)(((sp)->flags) & ((0x00000001))) && !F_ISSET(gp, G_SCRIPTED)(((gp)->flags) & ((0x0010))) &&
1356 (F_ISSET(ecp, E_USELASTCMD)(((ecp)->flags) & ((0x02000000))) || ecp->cmd == &cmds[C_SCROLL]))
1357 gp->scr_ex_adjust(sp, EX_TERM_SCROLL);
1358 F_CLR(ecp, E_NRSEP)(((ecp)->flags) &= ~((0x00008000)));
1359 }
1360
1361 /*
1362 * Call the underlying function for the ex command.
1363 *
1364 * XXX
1365 * Interrupts behave like errors, for now.
1366 */
1367 if (ecp->cmd->fn(sp, ecp) || INTERRUPTED(sp)(((((sp)->gp)->flags) & ((0x0004))) || (!v_event_get
((sp), ((void *)0), 0, 0x001) && ((((sp)->gp)->
flags) & ((0x0004)))))
) {
1368 if (F_ISSET(gp, G_SCRIPTED)(((gp)->flags) & ((0x0010))))
1369 F_SET(sp, SC_EXIT_FORCE)(((sp)->flags) |= ((0x00000400)));
1370 goto err;
1371 }
1372
1373#ifdef DEBUG
1374 /* Make sure no function left global temporary space locked. */
1375 if (F_ISSET(gp, G_TMP_INUSE)(((gp)->flags) & ((0x0100)))) {
1376 F_CLR(gp, G_TMP_INUSE)(((gp)->flags) &= ~((0x0100)));
1377 msgq(sp, M_ERR, "%s: temporary buffer not released",
1378 ecp->cmd->name);
1379 }
1380#endif
1381 /*
1382 * Ex displayed the number of lines modified immediately after each
1383 * command, so the command "1,10d|1,10d" would display:
1384 *
1385 * 10 lines deleted
1386 * 10 lines deleted
1387 * <autoprint line>
1388 *
1389 * Executing ex commands from vi only reported the final modified
1390 * lines message -- that's wrong enough that we don't match it.
1391 */
1392 if (F_ISSET(sp, SC_EX)(((sp)->flags) & ((0x00000001))))
1393 mod_rpt(sp);
1394
1395 /*
1396 * Integrate any offset parsed by the underlying command, and make
1397 * sure the referenced line exists.
1398 *
1399 * XXX
1400 * May not match historic practice (which I've never been able to
1401 * completely figure out.) For example, the '=' command from vi
1402 * mode often got the offset wrong, and complained it was too large,
1403 * but didn't seem to have a problem with the cursor. If anyone
1404 * complains, ask them how it's supposed to work, they might know.
1405 */
1406 if (sp->ep != NULL((void *)0) && ecp->flagoff) {
1407 if (ecp->flagoff < 0) {
1408 if (sp->lno <= -ecp->flagoff) {
1409 msgq(sp, M_ERR,
1410 "Flag offset to before line 1");
1411 goto err;
1412 }
1413 } else {
1414 if (!NPFITS(MAX_REC_NUMBER, sp->lno, ecp->flagoff)(((unsigned long)(0xffffffff)) - (sp->lno) >= (ecp->
flagoff))
) {
1415 ex_badaddr(sp, NULL((void *)0), A_NOTSET, NUM_OVER);
1416 goto err;
1417 }
1418 if (!db_exist(sp, sp->lno + ecp->flagoff)) {
1419 msgq(sp, M_ERR,
1420 "Flag offset past end-of-file");
1421 goto err;
1422 }
1423 }
1424 sp->lno += ecp->flagoff;
1425 }
1426
1427 /*
1428 * If the command executed successfully, we may want to display a line
1429 * based on the autoprint option or an explicit print flag. (Make sure
1430 * that there's a line to display.) Also, the autoprint edit option is
1431 * turned off for the duration of global commands.
1432 */
1433 if (F_ISSET(sp, SC_EX)(((sp)->flags) & ((0x00000001))) && sp->ep != NULL((void *)0) && sp->lno != 0) {
1434 /*
1435 * The print commands have already handled the `print' flags.
1436 * If so, clear them.
1437 */
1438 if (FL_ISSET(ecp->iflags, E_CLRFLAG)((ecp->iflags) & (0x00000080)))
1439 FL_CLR(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT)((ecp->iflags) &= ~(0x00200 | 0x00400 | 0x01000));
1440
1441 /* If hash set only because of the number option, discard it. */
1442 if (F_ISSET(ecp, E_OPTNUM)(((ecp)->flags) & ((0x00010000))))
1443 FL_CLR(ecp->iflags, E_C_HASH)((ecp->iflags) &= ~(0x00200));
1444
1445 /*
1446 * If there was an explicit flag to display the new cursor line,
1447 * or autoprint is set and a change was made, display the line.
1448 * If any print flags were set use them, else default to print.
1449 */
1450 LF_INIT(FL_ISSET(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT))(flags) = ((((ecp->iflags) & (0x00200 | 0x00400 | 0x01000
))))
;
1451 if (!LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT | E_NOAUTO)((flags) & ((0x00200 | 0x00400 | 0x01000 | 0x00002000))) &&
1452 !F_ISSET(sp, SC_EX_GLOBAL)(((sp)->flags) & ((0x00020000))) &&
1453 O_ISSET(sp, O_AUTOPRINT)((((&(((sp)))->opts[(((O_AUTOPRINT)))])->flags) &
((0x01))) ? (((sp)))->gp->opts[(((sp)))->opts[(((O_AUTOPRINT
)))].o_cur.val].o_cur.val : (((sp)))->opts[(((O_AUTOPRINT)
))].o_cur.val)
&& F_ISSET(ecp, E_AUTOPRINT)(((ecp)->flags) & ((0x00000040))))
1454 LF_INIT(E_C_PRINT)(flags) = ((0x01000));
1455
1456 if (LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT)((flags) & ((0x00200 | 0x00400 | 0x01000)))) {
1457 cur.lno = sp->lno;
1458 cur.cno = 0;
1459 (void)ex_print(sp, ecp, &cur, &cur, flags);
1460 }
1461 }
1462
1463 /*
1464 * If the command had an associated "+cmd", it has to be executed
1465 * before we finish executing any more of this ex command. For
1466 * example, consider a .exrc file that contains the following lines:
1467 *
1468 * :set all
1469 * :edit +25 file.c|s/abc/ABC/|1
1470 * :3,5 print
1471 *
1472 * This can happen more than once -- the historic vi simply hung or
1473 * dropped core, of course. Prepend the + command back into the
1474 * current command and continue. We may have to add an additional
1475 * <literal next> character. We know that it will fit because we
1476 * discarded at least one space and the + character.
1477 */
1478 if (arg1_len != 0) {
1479 /*
1480 * If the last character of the + command was a <literal next>
1481 * character, it would be treated differently because of the
1482 * append. Quote it, if necessary.
1483 */
1484 if (IS_ESCAPE(sp, ecp, arg1[arg1_len - 1])(((((ecp))->flags) & ((0x00020000))) ? (arg1[arg1_len -
1]) == '\026' : ((unsigned char)((arg1[arg1_len - 1])) <=
254 ? ((sp))->gp->special_key[(unsigned char)((arg1[arg1_len
- 1]))] : (unsigned char)((arg1[arg1_len - 1])) > ((sp))->
gp->max_special ? 0 : v_key_val(((sp)),((arg1[arg1_len - 1
])))) == K_VLNEXT)
) {
1485 *--ecp->save_cmd = CH_LITERAL'\026';
1486 ++ecp->save_cmdlen;
1487 }
1488
1489 ecp->save_cmd -= arg1_len;
1490 ecp->save_cmdlen += arg1_len;
1491 memmove(ecp->save_cmd, arg1, arg1_len);
1492
1493 /*
1494 * Any commands executed from a +cmd are executed starting at
1495 * the first column of the last line of the file -- NOT the
1496 * first nonblank.) The main file startup code doesn't know
1497 * that a +cmd was set, however, so it may have put us at the
1498 * top of the file. (Note, this is safe because we must have
1499 * switched files to get here.)
1500 */
1501 F_SET(ecp, E_MOVETOEND)(((ecp)->flags) |= ((0x00400000)));
1502 }
1503
1504 /* Update the current command. */
1505 ecp->cp = ecp->save_cmd;
1506 ecp->clen = ecp->save_cmdlen;
1507
1508 /*
1509 * !!!
1510 * If we've changed screens or underlying files, any pending global or
1511 * v command, or @ buffer that has associated addresses, has to be
1512 * discarded. This is historic practice for globals, and necessary for
1513 * @ buffers that had associated addresses.
1514 *
1515 * Otherwise, if we've changed underlying files, it's not a problem,
1516 * we continue with the rest of the ex command(s), operating on the
1517 * new file. However, if we switch screens (either by exiting or by
1518 * an explicit command), we have no way of knowing where to put output
1519 * messages, and, since we don't control screens here, we could screw
1520 * up the upper layers, (e.g. we could exit/reenter a screen multiple
1521 * times). So, return and continue after we've got a new screen.
1522 */
1523 if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE | SC_FSWITCH | SC_SSWITCH)(((sp)->flags) & ((0x00000200 | 0x00000400 | 0x00000800
| 0x00001000)))
) {
1524 at_found = gv_found = 0;
1525 LIST_FOREACH(ecp, &sp->gp->ecq, q)for((ecp) = ((&sp->gp->ecq)->lh_first); (ecp)!= (
(void *)0); (ecp) = ((ecp)->q.le_next))
1526 switch (ecp->agv_flags) {
1527 case 0:
1528 case AGV_AT_NORANGE0x02:
1529 break;
1530 case AGV_AT0x01:
1531 if (!at_found) {
1532 at_found = 1;
1533 msgq(sp, M_ERR,
1534 "@ with range running when the file/screen changed");
1535 }
1536 break;
1537 case AGV_GLOBAL0x04:
1538 case AGV_V0x08:
1539 if (!gv_found) {
1540 gv_found = 1;
1541 msgq(sp, M_ERR,
1542 "Global/v command running when the file/screen changed");
1543 }
1544 break;
1545 default:
1546 abort();
1547 }
1548 if (at_found || gv_found)
1549 goto discard;
1550 if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE | SC_SSWITCH)(((sp)->flags) & ((0x00000200 | 0x00000400 | 0x00001000
)))
)
1551 goto rsuccess;
1552 }
1553
1554 goto loop;
1555 /* NOTREACHED */
1556
1557err: /*
1558 * On command failure, we discard keys and pending commands remaining,
1559 * as well as any keys that were mapped and waiting. The save_cmdlen
1560 * test is not necessarily correct. If we fail early enough we don't
1561 * know if the entire string was a single command or not. Guess, as
1562 * it's useful to know if commands other than the current one are being
1563 * discarded.
1564 */
1565 if (ecp->save_cmdlen == 0)
1566 for (; ecp->clen; --ecp->clen) {
1567 ch = *ecp->cp++;
1568 if (IS_ESCAPE(sp, ecp, ch)(((((ecp))->flags) & ((0x00020000))) ? (ch) == '\026' :
((unsigned char)((ch)) <= 254 ? ((sp))->gp->special_key
[(unsigned char)((ch))] : (unsigned char)((ch)) > ((sp))->
gp->max_special ? 0 : v_key_val(((sp)),((ch)))) == K_VLNEXT
)
&& ecp->clen > 1) {
1569 --ecp->clen;
1570 ++ecp->cp;
1571 } else if (ch == '\n' || ch == '|') {
1572 if (ecp->clen > 1)
1573 ecp->save_cmdlen = 1;
1574 break;
1575 }
1576 }
1577 if (ecp->save_cmdlen != 0 || LIST_FIRST(&gp->ecq)((&gp->ecq)->lh_first) != &gp->excmd) {
1578discard: msgq(sp, M_BERR,
1579 "Ex command failed: pending commands discarded");
1580 ex_discard(sp);
1581 }
1582 if (v_event_flush(sp, CH_MAPPED0x02))
1583 msgq(sp, M_BERR,
1584 "Ex command failed: mapped keys discarded");
1585
1586rfail: tmp = 1;
1587 if (0)
1588rsuccess: tmp = 0;
1589
1590 /* Turn off any file name error information. */
1591 gp->if_name = NULL((void *)0);
1592
1593 /* Turn off the global bit. */
1594 F_CLR(sp, SC_EX_GLOBAL)(((sp)->flags) &= ~((0x00020000)));
1595
1596 return (tmp);
1597}
1598
1599/*
1600 * ex_range --
1601 * Get a line range for ex commands, or perform a vi ex address search.
1602 *
1603 * PUBLIC: int ex_range(SCR *, EXCMD *, int *);
1604 */
1605int
1606ex_range(SCR *sp, EXCMD *ecp, int *errp)
1607{
1608 enum { ADDR_FOUND, ADDR_NEED, ADDR_NONE } addr;
1609 MARK m;
1610 int isaddr;
1611
1612 *errp = 0;
1613
1614 /*
1615 * Parse comma or semi-colon delimited line specs.
1616 *
1617 * Semi-colon delimiters update the current address to be the last
1618 * address. For example, the command
1619 *
1620 * :3;/pattern/ecp->cp
1621 *
1622 * will search for pattern from line 3. In addition, if ecp->cp
1623 * is not a valid command, the current line will be left at 3, not
1624 * at the original address.
1625 *
1626 * Extra addresses are discarded, starting with the first.
1627 *
1628 * !!!
1629 * If any addresses are missing, they default to the current line.
1630 * This was historically true for both leading and trailing comma
1631 * delimited addresses as well as for trailing semicolon delimited
1632 * addresses. For consistency, we make it true for leading semicolon
1633 * addresses as well.
1634 */
1635 for (addr = ADDR_NONE, ecp->addrcnt = 0; ecp->clen > 0;)
1636 switch (*ecp->cp) {
1637 case '%': /* Entire file. */
1638 /* Vi ex address searches didn't permit % signs. */
1639 if (F_ISSET(ecp, E_VISEARCH)(((ecp)->flags) & ((0x04000000))))
1640 goto ret;
1641
1642 /* It's an error if the file is empty. */
1643 if (sp->ep == NULL((void *)0)) {
1644 ex_badaddr(sp, NULL((void *)0), A_EMPTY, NUM_OK);
1645 *errp = 1;
1646 return (0);
1647 }
1648 /*
1649 * !!!
1650 * A percent character addresses all of the lines in
1651 * the file. Historically, it couldn't be followed by
1652 * any other address. We do it as a text substitution
1653 * for simplicity. POSIX 1003.2 is expected to follow
1654 * this practice.
1655 *
1656 * If it's an empty file, the first line is 0, not 1.
1657 */
1658 if (addr == ADDR_FOUND) {
1659 ex_badaddr(sp, NULL((void *)0), A_COMBO, NUM_OK);
1660 *errp = 1;
1661 return (0);
1662 }
1663 if (db_last(sp, &ecp->addr2.lno))
1664 return (1);
1665 ecp->addr1.lno = ecp->addr2.lno == 0 ? 0 : 1;
1666 ecp->addr1.cno = ecp->addr2.cno = 0;
1667 ecp->addrcnt = 2;
1668 addr = ADDR_FOUND;
1669 ++ecp->cp;
1670 --ecp->clen;
1671 break;
1672 case ',': /* Comma delimiter. */
1673 /* Vi ex address searches didn't permit commas. */
1674 if (F_ISSET(ecp, E_VISEARCH)(((ecp)->flags) & ((0x04000000))))
1675 goto ret;
1676 /* FALLTHROUGH */
1677 case ';': /* Semi-colon delimiter. */
1678 if (sp->ep == NULL((void *)0)) {
1679 ex_badaddr(sp, NULL((void *)0), A_EMPTY, NUM_OK);
1680 *errp = 1;
1681 return (0);
1682 }
1683 if (addr != ADDR_FOUND)
1684 switch (ecp->addrcnt) {
1685 case 0:
1686 ecp->addr1.lno = sp->lno;
1687 ecp->addr1.cno = sp->cno;
1688 ecp->addrcnt = 1;
1689 break;
1690 case 2:
1691 ecp->addr1 = ecp->addr2;
1692 /* FALLTHROUGH */
1693 case 1:
1694 ecp->addr2.lno = sp->lno;
1695 ecp->addr2.cno = sp->cno;
1696 ecp->addrcnt = 2;
1697 break;
1698 }
1699 if (*ecp->cp == ';')
1700 switch (ecp->addrcnt) {
1701 case 0:
1702 abort();
1703 /* NOTREACHED */
1704 case 1:
1705 sp->lno = ecp->addr1.lno;
1706 sp->cno = ecp->addr1.cno;
1707 break;
1708 case 2:
1709 sp->lno = ecp->addr2.lno;
1710 sp->cno = ecp->addr2.cno;
1711 break;
1712 }
1713 addr = ADDR_NEED;
1714 /* FALLTHROUGH */
1715 case ' ': /* Whitespace. */
1716 case '\t': /* Whitespace. */
1717 ++ecp->cp;
1718 --ecp->clen;
1719 break;
1720 default:
1721 /* Get a line specification. */
1722 if (ex_line(sp, ecp, &m, &isaddr, errp))
1723 return (1);
1724 if (*errp)
1725 return (0);
1726 if (!isaddr)
1727 goto ret;
1728 if (addr == ADDR_FOUND) {
1729 ex_badaddr(sp, NULL((void *)0), A_COMBO, NUM_OK);
1730 *errp = 1;
1731 return (0);
1732 }
1733 switch (ecp->addrcnt) {
1734 case 0:
1735 ecp->addr1 = m;
1736 ecp->addrcnt = 1;
1737 break;
1738 case 1:
1739 ecp->addr2 = m;
1740 ecp->addrcnt = 2;
1741 break;
1742 case 2:
1743 ecp->addr1 = ecp->addr2;
1744 ecp->addr2 = m;
1745 break;
1746 }
1747 addr = ADDR_FOUND;
1748 break;
1749 }
1750
1751 /*
1752 * !!!
1753 * Vi ex address searches are indifferent to order or trailing
1754 * semi-colons.
1755 */
1756ret: if (F_ISSET(ecp, E_VISEARCH)(((ecp)->flags) & ((0x04000000))))
1757 return (0);
1758
1759 if (addr == ADDR_NEED)
1760 switch (ecp->addrcnt) {
1761 case 0:
1762 ecp->addr1.lno = sp->lno;
1763 ecp->addr1.cno = sp->cno;
1764 ecp->addrcnt = 1;
1765 break;
1766 case 2:
1767 ecp->addr1 = ecp->addr2;
1768 /* FALLTHROUGH */
1769 case 1:
1770 ecp->addr2.lno = sp->lno;
1771 ecp->addr2.cno = sp->cno;
1772 ecp->addrcnt = 2;
1773 break;
1774 }
1775
1776 if (ecp->addrcnt == 2 && ecp->addr2.lno < ecp->addr1.lno) {
1777 msgq(sp, M_ERR,
1778 "The second address is smaller than the first");
1779 *errp = 1;
1780 }
1781 return (0);
1782}
1783
1784/*
1785 * ex_line --
1786 * Get a single line address specifier.
1787 *
1788 * The way the "previous context" mark worked was that any "non-relative"
1789 * motion set it. While ex/vi wasn't totally consistent about this, ANY
1790 * numeric address, search pattern, '$', or mark reference in an address
1791 * was considered non-relative, and set the value. Which should explain
1792 * why we're hacking marks down here. The problem was that the mark was
1793 * only set if the command was called, i.e. we have to set a flag and test
1794 * it later.
1795 *
1796 * XXX
1797 * This is probably still not exactly historic practice, although I think
1798 * it's fairly close.
1799 */
1800static int
1801ex_line(SCR *sp, EXCMD *ecp, MARK *mp, int *isaddrp, int *errp)
1802{
1803 enum nresult nret;
1804 long total, val;
1805 int isneg;
1806 int (*sf)(SCR *, MARK *, MARK *, char *, size_t, char **, u_int);
1807 char *endp;
1808
1809 *isaddrp = *errp = 0;
1810 F_CLR(ecp, E_DELTA)(((ecp)->flags) &= ~((0x00100000)));
1811
1812 /* No addresses permitted until a file has been read in. */
1813 if (sp->ep == NULL((void *)0) && strchr("$0123456789'\\/?.+-^", *ecp->cp)) {
1814 ex_badaddr(sp, NULL((void *)0), A_EMPTY, NUM_OK);
1815 *errp = 1;
1816 return (0);
1817 }
1818
1819 switch (*ecp->cp) {
1820 case '$': /* Last line in the file. */
1821 *isaddrp = 1;
1822 F_SET(ecp, E_ABSMARK)(((ecp)->flags) |= ((0x00040000)));
1823
1824 mp->cno = 0;
1825 if (db_last(sp, &mp->lno))
1826 return (1);
1827 ++ecp->cp;
1828 --ecp->clen;
1829 break; /* Absolute line number. */
1830 case '0': case '1': case '2': case '3': case '4':
1831 case '5': case '6': case '7': case '8': case '9':
1832 *isaddrp = 1;
1833 F_SET(ecp, E_ABSMARK)(((ecp)->flags) |= ((0x00040000)));
1834
1835 if ((nret = nget_slong(&val, ecp->cp, &endp, 10)) != NUM_OK) {
1836 ex_badaddr(sp, NULL((void *)0), A_NOTSET, nret);
1837 *errp = 1;
1838 return (0);
1839 }
1840 if (!NPFITS(MAX_REC_NUMBER, 0, val)(((unsigned long)(0xffffffff)) - (0) >= (val))) {
1841 ex_badaddr(sp, NULL((void *)0), A_NOTSET, NUM_OVER);
1842 *errp = 1;
1843 return (0);
1844 }
1845 mp->lno = val;
1846 mp->cno = 0;
1847 ecp->clen -= (endp - ecp->cp);
1848 ecp->cp = endp;
1849 break;
1850 case '\'': /* Use a mark. */
1851 *isaddrp = 1;
1852 F_SET(ecp, E_ABSMARK)(((ecp)->flags) |= ((0x00040000)));
1853
1854 if (ecp->clen == 1) {
1855 msgq(sp, M_ERR, "No mark name supplied");
1856 *errp = 1;
1857 return (0);
1858 }
1859 if (mark_get(sp, ecp->cp[1], mp, M_ERR)) {
1860 *errp = 1;
1861 return (0);
1862 }
1863 ecp->cp += 2;
1864 ecp->clen -= 2;
1865 break;
1866 case '\\': /* Search: forward/backward. */
1867 /*
1868 * !!!
1869 * I can't find any difference between // and \/ or between
1870 * ?? and \?. Mark Horton doesn't remember there being any
1871 * difference. C'est la vie.
1872 */
1873 if (ecp->clen < 2 ||
1874 (ecp->cp[1] != '/' && ecp->cp[1] != '?')) {
1875 msgq(sp, M_ERR, "\\ not followed by / or ?");
1876 *errp = 1;
1877 return (0);
1878 }
1879 ++ecp->cp;
1880 --ecp->clen;
1881 sf = ecp->cp[0] == '/' ? f_search : b_search;
1882 goto search;
1883 case '/': /* Search forward. */
1884 sf = f_search;
1885 goto search;
1886 case '?': /* Search backward. */
1887 sf = b_search;
1888
1889search: mp->lno = sp->lno;
1890 mp->cno = sp->cno;
1891 if (sf(sp, mp, mp, ecp->cp, ecp->clen, &endp,
1892 SEARCH_MSG0x0010 | SEARCH_PARSE0x0020 | SEARCH_SET0x0040 |
1893 (F_ISSET(ecp, E_SEARCH_WMSG)(((ecp)->flags) & ((0x01000000))) ? SEARCH_WMSG0x0100 : 0))) {
1894 *errp = 1;
1895 return (0);
1896 }
1897
1898 /* Fix up the command pointers. */
1899 ecp->clen -= (endp - ecp->cp);
1900 ecp->cp = endp;
1901
1902 *isaddrp = 1;
1903 F_SET(ecp, E_ABSMARK)(((ecp)->flags) |= ((0x00040000)));
1904 break;
1905 case '.': /* Current position. */
1906 *isaddrp = 1;
1907 mp->cno = sp->cno;
1908
1909 /* If an empty file, then '.' is 0, not 1. */
1910 if (sp->lno == 1) {
1911 if (db_last(sp, &mp->lno))
1912 return (1);
1913 if (mp->lno != 0)
1914 mp->lno = 1;
1915 } else
1916 mp->lno = sp->lno;
1917
1918 /*
1919 * !!!
1920 * Historically, .<number> was the same as .+<number>, i.e.
1921 * the '+' could be omitted. (This feature is found in ed
1922 * as well.)
1923 */
1924 if (ecp->clen > 1 && isdigit(ecp->cp[1]))
1925 *ecp->cp = '+';
1926 else {
1927 ++ecp->cp;
1928 --ecp->clen;
1929 }
1930 break;
1931 }
1932
1933 /* Skip trailing <blank>s. */
1934 for (; ecp->clen > 0 &&
1935 isblank(ecp->cp[0]); ++ecp->cp, --ecp->clen);
1936
1937 /*
1938 * Evaluate any offset. If no address yet found, the offset
1939 * is relative to ".".
1940 */
1941 total = 0;
1942 if (ecp->clen != 0 && (isdigit(ecp->cp[0]) ||
1943 ecp->cp[0] == '+' || ecp->cp[0] == '-' ||
1944 ecp->cp[0] == '^')) {
1945 if (!*isaddrp) {
1946 *isaddrp = 1;
1947 mp->lno = sp->lno;
1948 mp->cno = sp->cno;
1949 }
1950 /*
1951 * Evaluate an offset, defined as:
1952 *
1953 * [+-^<blank>]*[<blank>]*[0-9]*
1954 *
1955 * The rough translation is any number of signs, optionally
1956 * followed by numbers, or a number by itself, all <blank>
1957 * separated.
1958 *
1959 * !!!
1960 * All address offsets were additive, e.g. "2 2 3p" was the
1961 * same as "7p", or, "/ZZZ/ 2" was the same as "/ZZZ/+2".
1962 * Note, however, "2 /ZZZ/" was an error. It was also legal
1963 * to insert signs without numbers, so "3 - 2" was legal, and
1964 * equal to 4.
1965 *
1966 * !!!
1967 * Offsets were historically permitted for any line address,
1968 * e.g. the command "1,2 copy 2 2 2 2" copied lines 1,2 after
1969 * line 8.
1970 *
1971 * !!!
1972 * Offsets were historically permitted for search commands,
1973 * and handled as addresses: "/pattern/2 2 2" was legal, and
1974 * referenced the 6th line after pattern.
1975 */
1976 F_SET(ecp, E_DELTA)(((ecp)->flags) |= ((0x00100000)));
1977 for (;;) {
1978 for (; ecp->clen > 0 && isblank(ecp->cp[0]);
1979 ++ecp->cp, --ecp->clen);
1980 if (ecp->clen == 0 || (!isdigit(ecp->cp[0]) &&
1981 ecp->cp[0] != '+' && ecp->cp[0] != '-' &&
1982 ecp->cp[0] != '^'))
1983 break;
1984 if (!isdigit(ecp->cp[0]) &&
1985 !isdigit(ecp->cp[1])) {
1986 total += ecp->cp[0] == '+' ? 1 : -1;
1987 --ecp->clen;
1988 ++ecp->cp;
1989 } else {
1990 if (ecp->cp[0] == '-' ||
1991 ecp->cp[0] == '^') {
1992 ++ecp->cp;
1993 --ecp->clen;
1994 isneg = 1;
1995 } else
1996 isneg = 0;
1997
1998 /* Get a signed long, add it to the total. */
1999 if ((nret = nget_slong(&val,
2000 ecp->cp, &endp, 10)) != NUM_OK ||
2001 (nret = NADD_SLONG(total, val)((total) < 0 ? ((val) < 0 && (((long)((-9223372036854775807L
-1L))) - ((total)) <= ((val)))) ? NUM_UNDER : NUM_OK : (total
) > 0 ? (val) > 0 && (((unsigned long)(9223372036854775807L
)) - ((total)) >= ((val))) ? NUM_OK : NUM_OVER : NUM_OK)
) != NUM_OK) {
2002 ex_badaddr(sp, NULL((void *)0), A_NOTSET, nret);
2003 *errp = 1;
2004 return (0);
2005 }
2006 total += isneg ? -val : val;
2007 ecp->clen -= (endp - ecp->cp);
2008 ecp->cp = endp;
2009 }
2010 }
2011 }
2012
2013 /*
2014 * Any value less than 0 is an error. Make sure that the new value
2015 * will fit into a recno_t.
2016 */
2017 if (*isaddrp && total != 0) {
2018 if (total < 0) {
2019 if (-total > mp->lno) {
2020 msgq(sp, M_ERR,
2021 "Reference to a line number less than 0");
2022 *errp = 1;
2023 return (0);
2024 }
2025 } else
2026 if (!NPFITS(MAX_REC_NUMBER, mp->lno, total)(((unsigned long)(0xffffffff)) - (mp->lno) >= (total))) {
2027 ex_badaddr(sp, NULL((void *)0), A_NOTSET, NUM_OVER);
2028 *errp = 1;
2029 return (0);
2030 }
2031 mp->lno += total;
2032 }
2033 return (0);
2034}
2035
2036
2037/*
2038 * ex_load --
2039 * Load up the next command, which may be an @ buffer or global command.
2040 */
2041static int
2042ex_load(SCR *sp)
2043{
2044 GS *gp;
2045 EXCMD *ecp;
2046 RANGE *rp;
2047
2048 F_CLR(sp, SC_EX_GLOBAL)(((sp)->flags) &= ~((0x00020000)));
2049
2050 /*
2051 * Lose any exhausted commands. We know that the first command
2052 * can't be an AGV command, which makes things a bit easier.
2053 */
2054 for (gp = sp->gp;;) {
13
Loop condition is true. Entering loop body
2055 /*
2056 * If we're back to the original structure, leave it around,
2057 * but discard any allocated source name, we've returned to
2058 * the beginning of the command stack.
2059 */
2060 if ((ecp = LIST_FIRST(&gp->ecq)((&gp->ecq)->lh_first)) == &gp->excmd) {
14
Assuming the condition is false
15
Taking false branch
2061 if (F_ISSET(ecp, E_NAMEDISCARD)(((ecp)->flags) & ((0x00001000)))) {
2062 free(ecp->if_name);
2063 ecp->if_name = NULL((void *)0);
2064 }
2065 return (0);
2066 }
2067
2068 /*
2069 * ecp->clen will be 0 for the first discarded command, but
2070 * may not be 0 for subsequent ones, e.g. if the original
2071 * command was ":g/xx/@a|s/b/c/", then when we discard the
2072 * command pushed on the stack by the @a, we have to resume
2073 * the global command which included the substitute command.
2074 */
2075 if (ecp->clen != 0)
16
Assuming field 'clen' is equal to 0
17
Taking false branch
2076 return (0);
2077
2078 /*
2079 * If it's an @, global or v command, we may need to continue
2080 * the command on a different line.
2081 */
2082 if (FL_ISSET(ecp->agv_flags, AGV_ALL)((ecp->agv_flags) & ((0x01 | 0x02 | 0x04 | 0x08)))) {
18
Assuming the condition is true
19
Taking true branch
2083 /* Discard any exhausted ranges. */
2084 while ((rp = TAILQ_FIRST(&ecp->rq)((&ecp->rq)->tqh_first))) {
20
Loop condition is true. Entering loop body
27
Loop condition is true. Entering loop body
2085 if (rp->start > rp->stop) {
21
Assuming field 'start' is > field 'stop'
22
Taking true branch
28
Use of memory after it is freed
2086 TAILQ_REMOVE(&ecp->rq, rp, q)do { if (((rp)->q.tqe_next) != ((void *)0)) (rp)->q.tqe_next
->q.tqe_prev = (rp)->q.tqe_prev; else (&ecp->rq)
->tqh_last = (rp)->q.tqe_prev; *(rp)->q.tqe_prev = (
rp)->q.tqe_next; ; ; } while (0)
;
23
Assuming field 'tqe_next' is equal to null
24
Taking false branch
25
Loop condition is false. Exiting loop
2087 free(rp);
26
Memory is released
2088 } else
2089 break;
2090 }
2091
2092 /* If there's another range, continue with it. */
2093 if (rp)
2094 break;
2095
2096 /* If it's a global/v command, fix up the last line. */
2097 if (FL_ISSET(ecp->agv_flags,((ecp->agv_flags) & (0x04 | 0x08))
2098 AGV_GLOBAL | AGV_V)((ecp->agv_flags) & (0x04 | 0x08)) && ecp->range_lno != OOBLNO0) {
2099 if (db_exist(sp, ecp->range_lno))
2100 sp->lno = ecp->range_lno;
2101 else {
2102 if (db_last(sp, &sp->lno))
2103 return (1);
2104 if (sp->lno == 0)
2105 sp->lno = 1;
2106 }
2107 }
2108 free(ecp->o_cp);
2109 }
2110
2111 /* Discard the EXCMD. */
2112 LIST_REMOVE(ecp, q)do { if ((ecp)->q.le_next != ((void *)0)) (ecp)->q.le_next
->q.le_prev = (ecp)->q.le_prev; *(ecp)->q.le_prev = (
ecp)->q.le_next; ; ; } while (0)
;
2113 free(ecp);
2114 }
2115
2116 /*
2117 * We only get here if it's an active @, global or v command. Set
2118 * the current line number, and get a new copy of the command for
2119 * the parser. Note, the original pointer almost certainly moved,
2120 * so we have play games.
2121 */
2122 ecp->cp = ecp->o_cp;
2123 memcpy(ecp->cp, ecp->cp + ecp->o_clen, ecp->o_clen);
2124 ecp->clen = ecp->o_clen;
2125 ecp->range_lno = sp->lno = rp->start++;
2126
2127 if (FL_ISSET(ecp->agv_flags, AGV_GLOBAL | AGV_V)((ecp->agv_flags) & (0x04 | 0x08)))
2128 F_SET(sp, SC_EX_GLOBAL)(((sp)->flags) |= ((0x00020000)));
2129 return (0);
2130}
2131
2132/*
2133 * ex_discard --
2134 * Discard any pending ex commands.
2135 */
2136static int
2137ex_discard(SCR *sp)
2138{
2139 GS *gp;
2140 EXCMD *ecp;
2141 RANGE *rp;
2142
2143 /*
2144 * We know the first command can't be an AGV command, so we don't
2145 * process it specially. We do, however, nail the command itself.
2146 */
2147 for (gp = sp->gp; (ecp = LIST_FIRST(&gp->ecq)((&gp->ecq)->lh_first)) != &gp->excmd;) {
2148 if (FL_ISSET(ecp->agv_flags, AGV_ALL)((ecp->agv_flags) & ((0x01 | 0x02 | 0x04 | 0x08)))) {
2149 while ((rp = TAILQ_FIRST(&ecp->rq)((&ecp->rq)->tqh_first))) {
2150 TAILQ_REMOVE(&ecp->rq, rp, q)do { if (((rp)->q.tqe_next) != ((void *)0)) (rp)->q.tqe_next
->q.tqe_prev = (rp)->q.tqe_prev; else (&ecp->rq)
->tqh_last = (rp)->q.tqe_prev; *(rp)->q.tqe_prev = (
rp)->q.tqe_next; ; ; } while (0)
;
2151 free(rp);
2152 }
2153 free(ecp->o_cp);
2154 }
2155 LIST_REMOVE(ecp, q)do { if ((ecp)->q.le_next != ((void *)0)) (ecp)->q.le_next
->q.le_prev = (ecp)->q.le_prev; *(ecp)->q.le_prev = (
ecp)->q.le_next; ; ; } while (0)
;
2156 free(ecp);
2157 }
2158 LIST_FIRST(&gp->ecq)((&gp->ecq)->lh_first)->clen = 0;
2159 return (0);
2160}
2161
2162/*
2163 * ex_unknown --
2164 * Display an unknown command name.
2165 */
2166static void
2167ex_unknown(SCR *sp, char *cmd, size_t len)
2168{
2169 size_t blen;
2170 char *bp;
2171
2172 GET_SPACE_GOTO(sp, bp, blen, len + 1){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp
; if (L__gp == ((void *)0) || (((L__gp)->flags) & ((0x0100
)))) { (bp) = ((void *)0); (blen) = 0; { void *L__bincp; if (
((len + 1)) > ((blen))) { if ((L__bincp = binc(((sp)), ((bp
)), &((blen)), ((len + 1)))) == ((void *)0)) goto alloc_err
; ((bp)) = L__bincp; } }; } else { { void *L__bincp; if (((len
+ 1)) > (L__gp->tmp_blen)) { if ((L__bincp = binc(((sp
)), (L__gp->tmp_bp), &(L__gp->tmp_blen), ((len + 1)
))) == ((void *)0)) goto alloc_err; (L__gp->tmp_bp) = L__bincp
; } }; (bp) = L__gp->tmp_bp; (blen) = L__gp->tmp_blen; (
((L__gp)->flags) |= ((0x0100))); } }
;
2173 bp[len] = '\0';
2174 memcpy(bp, cmd, len);
2175 msgq_str(sp, M_ERR, bp, "The %s command is unknown");
2176 FREE_SPACE(sp, bp, blen){ GS *L__gp = (sp) == ((void *)0) ? ((void *)0) : (sp)->gp
; if (L__gp != ((void *)0) && (bp) == L__gp->tmp_bp
) (((L__gp)->flags) &= ~((0x0100))); else free(bp); }
;
2177
2178alloc_err:
2179 return;
2180}
2181
2182/*
2183 * ex_is_abbrev -
2184 * The vi text input routine needs to know if ex thinks this is an
2185 * [un]abbreviate command, so it can turn off abbreviations. See
2186 * the usual ranting in the vi/v_txt_ev.c:txt_abbrev() routine.
2187 *
2188 * PUBLIC: int ex_is_abbrev(char *, size_t);
2189 */
2190int
2191ex_is_abbrev(char *name, size_t len)
2192{
2193 EXCMDLIST const *cp;
2194
2195 return ((cp = ex_comm_search(name, len)) != NULL((void *)0) &&
2196 (cp == &cmds[C_ABBR] || cp == &cmds[C_UNABBREVIATE]));
2197}
2198
2199/*
2200 * ex_is_unmap -
2201 * The vi text input routine needs to know if ex thinks this is an
2202 * unmap command, so it can turn off input mapping. See the usual
2203 * ranting in the vi/v_txt_ev.c:txt_unmap() routine.
2204 *
2205 * PUBLIC: int ex_is_unmap(char *, size_t);
2206 */
2207int
2208ex_is_unmap(char *name, size_t len)
2209{
2210 EXCMDLIST const *cp;
2211
2212 /*
2213 * The command the vi input routines are really interested in
2214 * is "unmap!", not just unmap.
2215 */
2216 if (name[len - 1] != '!')
2217 return (0);
2218 --len;
2219 return ((cp = ex_comm_search(name, len)) != NULL((void *)0) &&
2220 cp == &cmds[C_UNMAP]);
2221}
2222
2223/*
2224 * ex_comm_search --
2225 * Search for a command name.
2226 */
2227static EXCMDLIST const *
2228ex_comm_search(char *name, size_t len)
2229{
2230 EXCMDLIST const *cp;
2231
2232 for (cp = cmds; cp->name != NULL((void *)0); ++cp) {
2233 if (cp->name[0] > name[0])
2234 return (NULL((void *)0));
2235 if (cp->name[0] != name[0])
2236 continue;
2237 if (!memcmp(name, cp->name, len))
2238 return (cp);
2239 }
2240 return (NULL((void *)0));
2241}
2242
2243/*
2244 * ex_badaddr --
2245 * Display a bad address message.
2246 *
2247 * PUBLIC: void ex_badaddr
2248 * PUBLIC:(SCR *, EXCMDLIST const *, enum badaddr, enum nresult);
2249 */
2250void
2251ex_badaddr(SCR *sp, EXCMDLIST const *cp, enum badaddr ba, enum nresult nret)
2252{
2253 recno_t lno;
2254
2255 switch (nret) {
2256 case NUM_OK:
2257 break;
2258 case NUM_ERR:
2259 msgq(sp, M_SYSERR, NULL((void *)0));
2260 return;
2261 case NUM_OVER:
2262 msgq(sp, M_ERR, "Address value overflow");
2263 return;
2264 case NUM_UNDER:
2265 msgq(sp, M_ERR, "Address value underflow");
2266 return;
2267 }
2268
2269 /*
2270 * When encountering an address error, tell the user if there's no
2271 * underlying file, that's the real problem.
2272 */
2273 if (sp->ep == NULL((void *)0)) {
2274 ex_emsg(sp, cp != NULL((void *)0) ? cp->name : NULL((void *)0), EXM_NOFILEYET);
2275 return;
2276 }
2277
2278 switch (ba) {
2279 case A_COMBO:
2280 msgq(sp, M_ERR, "Illegal address combination");
2281 break;
2282 case A_EOF:
2283 if (db_last(sp, &lno))
2284 return;
2285 if (lno != 0) {
2286 msgq(sp, M_ERR,
2287 "Illegal address: only %lu lines in the file",
2288 lno);
2289 break;
2290 }
2291 /* FALLTHROUGH */
2292 case A_EMPTY:
2293 msgq(sp, M_ERR, "Illegal address: the file is empty");
2294 break;
2295 case A_NOTSET:
2296 abort();
2297 /* NOTREACHED */
2298 case A_ZERO:
2299 msgq(sp, M_ERR,
2300 "The %s command doesn't permit an address of 0",
2301 cp->name);
2302 break;
2303 }
2304 return;
2305}
2306
2307#if defined(DEBUG) && defined(COMLOG)
2308/*
2309 * ex_comlog --
2310 * Log ex commands.
2311 */
2312static void
2313ex_comlog(SCR *sp, EXCMD *ecp)
2314{
2315 TRACE(sp, "ecmd: %s", ecp->cmd->name);
2316 if (ecp->addrcnt > 0) {
2317 TRACE(sp, " a1 %d", ecp->addr1.lno);
2318 if (ecp->addrcnt > 1)
2319 TRACE(sp, " a2: %d", ecp->addr2.lno);
2320 }
2321 if (ecp->lineno)
2322 TRACE(sp, " line %d", ecp->lineno);
2323 if (ecp->flags)
2324 TRACE(sp, " flags 0x%x", ecp->flags);
2325 if (F_ISSET(&exc, E_BUFFER)(((&exc)->flags) & ((E_BUFFER))))
2326 TRACE(sp, " buffer %c", ecp->buffer);
2327 if (ecp->argc)
2328 for (cnt = 0; cnt < ecp->argc; ++cnt)
2329 TRACE(sp, " arg %d: {%s}", cnt, ecp->argv[cnt]->bp);
2330 TRACE(sp, "\n");
2331}
2332#endif