File: | src/bin/ed/main.c |
Warning: | line 1088, column 3 Null pointer passed as 1st argument to memory copy function |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: main.c,v 1.68 2022/11/18 14:52:03 millert Exp $ */ | |||
2 | /* $NetBSD: main.c,v 1.3 1995/03/21 09:04:44 cgd Exp $ */ | |||
3 | ||||
4 | /* main.c: This file contains the main control and user-interface routines | |||
5 | for the ed line editor. */ | |||
6 | /*- | |||
7 | * Copyright (c) 1993 Andrew Moore, Talke Studio. | |||
8 | * All rights reserved. | |||
9 | * | |||
10 | * Redistribution and use in source and binary forms, with or without | |||
11 | * modification, are permitted provided that the following conditions | |||
12 | * are met: | |||
13 | * 1. Redistributions of source code must retain the above copyright | |||
14 | * notice, this list of conditions and the following disclaimer. | |||
15 | * 2. Redistributions in binary form must reproduce the above copyright | |||
16 | * notice, this list of conditions and the following disclaimer in the | |||
17 | * documentation and/or other materials provided with the distribution. | |||
18 | * | |||
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
29 | * SUCH DAMAGE. | |||
30 | */ | |||
31 | ||||
32 | /* | |||
33 | * CREDITS | |||
34 | * | |||
35 | * This program is based on the editor algorithm described in | |||
36 | * Brian W. Kernighan and P. J. Plauger's book "Software Tools | |||
37 | * in Pascal," Addison-Wesley, 1981. | |||
38 | * | |||
39 | * The buffering algorithm is attributed to Rodney Ruddock of | |||
40 | * the University of Guelph, Guelph, Ontario. | |||
41 | * | |||
42 | */ | |||
43 | ||||
44 | #include <sys/ioctl.h> | |||
45 | #include <sys/stat.h> | |||
46 | #include <sys/wait.h> | |||
47 | ||||
48 | #include <ctype.h> | |||
49 | #include <err.h> | |||
50 | #include <errno(*__errno()).h> | |||
51 | #include <limits.h> | |||
52 | #include <pwd.h> | |||
53 | #include <regex.h> | |||
54 | #include <setjmp.h> | |||
55 | #include <signal.h> | |||
56 | #include <stdio.h> | |||
57 | #include <stdlib.h> | |||
58 | #include <string.h> | |||
59 | #include <unistd.h> | |||
60 | ||||
61 | #include "ed.h" | |||
62 | ||||
63 | void signal_hup(int); | |||
64 | void signal_int(int); | |||
65 | void handle_winch(int); | |||
66 | ||||
67 | static int next_addr(void); | |||
68 | static int check_addr_range(int, int); | |||
69 | static int get_matching_node_addr(regex_t *, int); | |||
70 | static char *get_filename(int); | |||
71 | static int get_shell_command(void); | |||
72 | static int append_lines(int); | |||
73 | static int join_lines(int, int); | |||
74 | static int move_lines(int); | |||
75 | static int copy_lines(int); | |||
76 | static int mark_line_node(line_t *, int); | |||
77 | static int get_marked_node_addr(int); | |||
78 | static line_t *dup_line_node(line_t *); | |||
79 | ||||
80 | sigjmp_buf env; | |||
81 | ||||
82 | /* static buffers */ | |||
83 | static char errmsg[PATH_MAX1024 + 40]; /* error message buffer */ | |||
84 | static char *shcmd; /* shell command buffer */ | |||
85 | static int shcmdsz; /* shell command buffer size */ | |||
86 | static int shcmdi; /* shell command buffer index */ | |||
87 | static char old_filename[PATH_MAX1024]; /* default filename */ | |||
88 | ||||
89 | /* global buffers */ | |||
90 | char *ibuf; /* ed command-line buffer */ | |||
91 | int ibufsz; /* ed command-line buffer size */ | |||
92 | char *ibufp; /* pointer to ed command-line buffer */ | |||
93 | ||||
94 | /* global flags */ | |||
95 | int garrulous = 0; /* if set, print all error messages */ | |||
96 | int isbinary; /* if set, buffer contains ASCII NULs */ | |||
97 | int isglobal; /* if set, doing a global command */ | |||
98 | int modified; /* if set, buffer modified since last write */ | |||
99 | int scripted = 0; /* if set, suppress diagnostics */ | |||
100 | int interactive = 0; /* if set, we are in interactive mode */ | |||
101 | ||||
102 | volatile sig_atomic_t mutex = 0; /* if set, signals set flags */ | |||
103 | volatile sig_atomic_t sighup = 0; /* if set, sighup received while mutex set */ | |||
104 | volatile sig_atomic_t sigint = 0; /* if set, sigint received while mutex set */ | |||
105 | ||||
106 | /* if set, signal handlers are enabled */ | |||
107 | volatile sig_atomic_t sigactive = 0; | |||
108 | ||||
109 | int current_addr; /* current address in editor buffer */ | |||
110 | int addr_last; /* last address in editor buffer */ | |||
111 | int lineno; /* script line number */ | |||
112 | static char *prompt; /* command-line prompt */ | |||
113 | static char *dps = "*"; /* default command-line prompt */ | |||
114 | ||||
115 | static const char usage[] = "usage: %s [-] [-s] [-p string] [file]\n"; | |||
116 | ||||
117 | static char *home; /* home directory */ | |||
118 | ||||
119 | void | |||
120 | seterrmsg(char *s) | |||
121 | { | |||
122 | strlcpy(errmsg, s, sizeof(errmsg)); | |||
123 | } | |||
124 | ||||
125 | /* ed: line editor */ | |||
126 | int | |||
127 | main(volatile int argc, char ** volatile argv) | |||
128 | { | |||
129 | int c, n; | |||
130 | int status = 0; | |||
131 | ||||
132 | if (pledge("stdio rpath wpath cpath proc exec tty", NULL((void *)0)) == -1) | |||
133 | err(1, "pledge"); | |||
134 | ||||
135 | home = getenv("HOME"); | |||
136 | ||||
137 | top: | |||
138 | while ((c = getopt(argc, argv, "p:sx")) != -1) | |||
139 | switch (c) { | |||
140 | case 'p': /* set prompt */ | |||
141 | dps = prompt = optarg; | |||
142 | break; | |||
143 | case 's': /* run script */ | |||
144 | scripted = 1; | |||
145 | break; | |||
146 | case 'x': /* use crypt */ | |||
147 | fprintf(stderr(&__sF[2]), "crypt unavailable\n?\n"); | |||
148 | break; | |||
149 | default: | |||
150 | fprintf(stderr(&__sF[2]), usage, argv[0]); | |||
151 | exit(1); | |||
152 | } | |||
153 | argv += optind; | |||
154 | argc -= optind; | |||
155 | if (argc && **argv == '-') { | |||
156 | scripted = 1; | |||
157 | if (argc > 1) { | |||
158 | optind = 1; | |||
159 | goto top; | |||
160 | } | |||
161 | argv++; | |||
162 | argc--; | |||
163 | } | |||
164 | ||||
165 | if (!(interactive = isatty(0))) { | |||
166 | struct stat sb; | |||
167 | ||||
168 | /* assert: pipes show up as fifo's when fstat'd */ | |||
169 | if (fstat(STDIN_FILENO0, &sb) || !S_ISFIFO(sb.st_mode)((sb.st_mode & 0170000) == 0010000)) { | |||
170 | if (lseek(STDIN_FILENO0, 0, SEEK_CUR1)) { | |||
171 | interactive = 1; | |||
172 | setvbuf(stdout(&__sF[1]), NULL((void *)0), _IOLBF1, 0); | |||
173 | } | |||
174 | } | |||
175 | } | |||
176 | ||||
177 | /* assert: reliable signals! */ | |||
178 | if (isatty(STDIN_FILENO0)) { | |||
179 | handle_winch(SIGWINCH28); | |||
180 | signal(SIGWINCH28, handle_winch); | |||
181 | } | |||
182 | signal(SIGHUP1, signal_hup); | |||
183 | signal(SIGQUIT3, SIG_IGN(void (*)(int))1); | |||
184 | signal(SIGINT2, signal_int); | |||
185 | if (sigsetjmp(env, 1)) { | |||
186 | status = -1; | |||
187 | fputs("\n?\n", stdout(&__sF[1])); | |||
188 | seterrmsg("interrupt"); | |||
189 | } else { | |||
190 | init_buffers(); | |||
191 | sigactive = 1; /* enable signal handlers */ | |||
192 | if (argc && **argv) { | |||
193 | if (read_file(*argv, 0) < 0 && !interactive) | |||
194 | quit(2); | |||
195 | else if (**argv != '!') | |||
196 | strlcpy(old_filename, *argv, | |||
197 | sizeof old_filename); | |||
198 | } else if (argc) { | |||
199 | fputs("?\n", stdout(&__sF[1])); | |||
200 | if (**argv == '\0') | |||
201 | seterrmsg("invalid filename"); | |||
202 | if (!interactive) | |||
203 | quit(2); | |||
204 | } | |||
205 | } | |||
206 | for (;;) { | |||
207 | if (status < 0 && garrulous) | |||
208 | fprintf(stderr(&__sF[2]), "%s\n", errmsg); | |||
209 | if (prompt) { | |||
210 | fputs(prompt, stdout(&__sF[1])); | |||
211 | fflush(stdout(&__sF[1])); | |||
212 | } | |||
213 | if ((n = get_tty_line()) < 0) { | |||
214 | status = ERR(-2); | |||
215 | continue; | |||
216 | } else if (n == 0) { | |||
217 | if (modified && !scripted) { | |||
218 | fputs("?\n", stdout(&__sF[1])); | |||
219 | seterrmsg("warning: file modified"); | |||
220 | if (!interactive) { | |||
221 | if (garrulous) | |||
222 | fprintf(stderr(&__sF[2]), | |||
223 | "script, line %d: %s\n", | |||
224 | lineno, errmsg); | |||
225 | quit(2); | |||
226 | } | |||
227 | clearerr(stdin)(!__isthreaded ? ((void)(((&__sF[0]))->_flags &= ~ (0x0040|0x0020))) : (clearerr)((&__sF[0]))); | |||
228 | modified = 0; | |||
229 | status = EMOD(-3); | |||
230 | continue; | |||
231 | } else | |||
232 | quit(0); | |||
233 | } else if (ibuf[n - 1] != '\n') { | |||
234 | /* discard line */ | |||
235 | seterrmsg("unexpected end-of-file"); | |||
236 | clearerr(stdin)(!__isthreaded ? ((void)(((&__sF[0]))->_flags &= ~ (0x0040|0x0020))) : (clearerr)((&__sF[0]))); | |||
237 | status = ERR(-2); | |||
238 | continue; | |||
239 | } | |||
240 | isglobal = 0; | |||
241 | if ((status = extract_addr_range()) >= 0 && | |||
242 | (status = exec_command()) >= 0) | |||
243 | if (!status || (status && | |||
244 | (status = display_lines(current_addr, current_addr, | |||
245 | status)) >= 0)) | |||
246 | continue; | |||
247 | switch (status) { | |||
248 | case EOF(-1): | |||
249 | quit(0); | |||
250 | break; | |||
251 | case EMOD(-3): | |||
252 | modified = 0; | |||
253 | fputs("?\n", stdout(&__sF[1])); /* give warning */ | |||
254 | seterrmsg("warning: file modified"); | |||
255 | if (!interactive) { | |||
256 | if (garrulous) | |||
257 | fprintf(stderr(&__sF[2]), | |||
258 | "script, line %d: %s\n", | |||
259 | lineno, errmsg); | |||
260 | quit(2); | |||
261 | } | |||
262 | break; | |||
263 | case FATAL(-4): | |||
264 | if (!interactive) { | |||
265 | if (garrulous) | |||
266 | fprintf(stderr(&__sF[2]), | |||
267 | "script, line %d: %s\n", | |||
268 | lineno, errmsg); | |||
269 | } else if (garrulous) | |||
270 | fprintf(stderr(&__sF[2]), "%s\n", errmsg); | |||
271 | quit(3); | |||
272 | break; | |||
273 | default: | |||
274 | fputs("?\n", stdout(&__sF[1])); | |||
275 | if (!interactive) { | |||
276 | if (garrulous) | |||
277 | fprintf(stderr(&__sF[2]), | |||
278 | "script, line %d: %s\n", | |||
279 | lineno, errmsg); | |||
280 | quit(2); | |||
281 | } | |||
282 | break; | |||
283 | } | |||
284 | } | |||
285 | /*NOTREACHED*/ | |||
286 | } | |||
287 | ||||
288 | int first_addr, second_addr, addr_cnt; | |||
289 | ||||
290 | /* extract_addr_range: get line addresses from the command buffer until an | |||
291 | illegal address is seen; return status */ | |||
292 | int | |||
293 | extract_addr_range(void) | |||
294 | { | |||
295 | int addr; | |||
296 | ||||
297 | addr_cnt = 0; | |||
298 | first_addr = second_addr = current_addr; | |||
299 | while ((addr = next_addr()) >= 0) { | |||
300 | addr_cnt++; | |||
301 | first_addr = second_addr; | |||
302 | second_addr = addr; | |||
303 | if (*ibufp != ',' && *ibufp != ';') | |||
304 | break; | |||
305 | else if (*ibufp++ == ';') | |||
306 | current_addr = addr; | |||
307 | } | |||
308 | if ((addr_cnt = min(addr_cnt, 2)((addr_cnt) < (2) ? (addr_cnt) : (2))) == 1 || second_addr != addr) | |||
309 | first_addr = second_addr; | |||
310 | return (addr == ERR(-2)) ? ERR(-2) : 0; | |||
311 | } | |||
312 | ||||
313 | ||||
314 | #define SKIP_BLANKS()do { while (isspace((unsigned char)*ibufp) && *ibufp != '\n') ibufp++; } while (0) \ | |||
315 | do { \ | |||
316 | while (isspace((unsigned char)*ibufp) && *ibufp != '\n') \ | |||
317 | ibufp++; \ | |||
318 | } while (0) | |||
319 | ||||
320 | #define MUST_BE_FIRST()do { if (!first) { seterrmsg("invalid address"); return (-2); } } while (0) \ | |||
321 | do { \ | |||
322 | if (!first) { \ | |||
323 | seterrmsg("invalid address"); \ | |||
324 | return ERR(-2); \ | |||
325 | } \ | |||
326 | } while (0) | |||
327 | ||||
328 | ||||
329 | /* next_addr: return the next line address in the command buffer */ | |||
330 | static int | |||
331 | next_addr(void) | |||
332 | { | |||
333 | char *hd; | |||
334 | int addr = current_addr; | |||
335 | int n; | |||
336 | int first = 1; | |||
337 | int c; | |||
338 | ||||
339 | SKIP_BLANKS()do { while (isspace((unsigned char)*ibufp) && *ibufp != '\n') ibufp++; } while (0); | |||
340 | for (hd = ibufp;; first = 0) | |||
341 | switch ((c = (unsigned char)*ibufp)) { | |||
342 | case '+': | |||
343 | case '\t': | |||
344 | case ' ': | |||
345 | case '-': | |||
346 | case '^': | |||
347 | ibufp++; | |||
348 | SKIP_BLANKS()do { while (isspace((unsigned char)*ibufp) && *ibufp != '\n') ibufp++; } while (0); | |||
349 | if (isdigit((unsigned char)*ibufp)) { | |||
350 | STRTOI(n, ibufp){ long l = strtol(ibufp, &ibufp, 10); if (l <= (-0x7fffffff -1) || l >= 0x7fffffff) { seterrmsg("number out of range") ; n = 0; return (-2); } else n = (int)l; }; | |||
351 | addr += (c == '-' || c == '^') ? -n : n; | |||
352 | } else if (!isspace(c)) | |||
353 | addr += (c == '-' || c == '^') ? -1 : 1; | |||
354 | break; | |||
355 | case '0': case '1': case '2': | |||
356 | case '3': case '4': case '5': | |||
357 | case '6': case '7': case '8': case '9': | |||
358 | MUST_BE_FIRST()do { if (!first) { seterrmsg("invalid address"); return (-2); } } while (0); | |||
359 | STRTOI(addr, ibufp){ long l = strtol(ibufp, &ibufp, 10); if (l <= (-0x7fffffff -1) || l >= 0x7fffffff) { seterrmsg("number out of range") ; addr = 0; return (-2); } else addr = (int)l; }; | |||
360 | break; | |||
361 | case '.': | |||
362 | case '$': | |||
363 | MUST_BE_FIRST()do { if (!first) { seterrmsg("invalid address"); return (-2); } } while (0); | |||
364 | ibufp++; | |||
365 | addr = (c == '.') ? current_addr : addr_last; | |||
366 | break; | |||
367 | case '/': | |||
368 | case '?': | |||
369 | MUST_BE_FIRST()do { if (!first) { seterrmsg("invalid address"); return (-2); } } while (0); | |||
370 | if ((addr = get_matching_node_addr( | |||
371 | get_compiled_pattern(), c == '/')) < 0) | |||
372 | return ERR(-2); | |||
373 | else if (c == *ibufp) | |||
374 | ibufp++; | |||
375 | break; | |||
376 | case '\'': | |||
377 | MUST_BE_FIRST()do { if (!first) { seterrmsg("invalid address"); return (-2); } } while (0); | |||
378 | ibufp++; | |||
379 | if ((addr = get_marked_node_addr((unsigned char)*ibufp++)) < 0) | |||
380 | return ERR(-2); | |||
381 | break; | |||
382 | case '%': | |||
383 | case ',': | |||
384 | case ';': | |||
385 | if (first) { | |||
386 | ibufp++; | |||
387 | addr_cnt++; | |||
388 | second_addr = (c == ';') ? current_addr : 1; | |||
389 | if ((addr = next_addr()) < 0) | |||
390 | addr = addr_last; | |||
391 | break; | |||
392 | } | |||
393 | /* FALLTHROUGH */ | |||
394 | default: | |||
395 | if (ibufp == hd) | |||
396 | return EOF(-1); | |||
397 | else if (addr < 0 || addr_last < addr) { | |||
398 | seterrmsg("invalid address"); | |||
399 | return ERR(-2); | |||
400 | } else | |||
401 | return addr; | |||
402 | } | |||
403 | /* NOTREACHED */ | |||
404 | } | |||
405 | ||||
406 | ||||
407 | /* GET_THIRD_ADDR: get a legal address from the command buffer */ | |||
408 | #define GET_THIRD_ADDR(addr)do { int ol1, ol2; ol1 = first_addr; ol2 = second_addr; if (extract_addr_range () < 0) return (-2); else if (addr_cnt == 0) { seterrmsg("destination expected" ); return (-2); } else if (second_addr < 0 || addr_last < second_addr) { seterrmsg("invalid address"); return (-2); } addr = second_addr; first_addr = ol1; second_addr = ol2; } while ( 0) \ | |||
409 | do { \ | |||
410 | int ol1, ol2; \ | |||
411 | \ | |||
412 | ol1 = first_addr; \ | |||
413 | ol2 = second_addr; \ | |||
414 | if (extract_addr_range() < 0) \ | |||
415 | return ERR(-2); \ | |||
416 | else if (addr_cnt == 0) { \ | |||
417 | seterrmsg("destination expected"); \ | |||
418 | return ERR(-2); \ | |||
419 | } else if (second_addr < 0 || addr_last < second_addr) { \ | |||
420 | seterrmsg("invalid address"); \ | |||
421 | return ERR(-2); \ | |||
422 | } \ | |||
423 | addr = second_addr; \ | |||
424 | first_addr = ol1; \ | |||
425 | second_addr = ol2; \ | |||
426 | } while (0) | |||
427 | ||||
428 | ||||
429 | /* GET_COMMAND_SUFFIX: verify the command suffix in the command buffer */ | |||
430 | #define GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0) \ | |||
431 | do { \ | |||
432 | int done = 0; \ | |||
433 | do { \ | |||
434 | switch (*ibufp) { \ | |||
435 | case 'p': \ | |||
436 | gflag |= GPR002; \ | |||
437 | ibufp++; \ | |||
438 | break; \ | |||
439 | case 'l': \ | |||
440 | gflag |= GLS004; \ | |||
441 | ibufp++; \ | |||
442 | break; \ | |||
443 | case 'n': \ | |||
444 | gflag |= GNP010; \ | |||
445 | ibufp++; \ | |||
446 | break; \ | |||
447 | default: \ | |||
448 | done++; \ | |||
449 | } \ | |||
450 | } while (!done); \ | |||
451 | if (*ibufp++ != '\n') { \ | |||
452 | seterrmsg("invalid command suffix"); \ | |||
453 | return ERR(-2); \ | |||
454 | } \ | |||
455 | } while (0) | |||
456 | ||||
457 | /* sflags */ | |||
458 | #define SGG001 001 /* complement previous global substitute suffix */ | |||
459 | #define SGP002 002 /* complement previous print suffix */ | |||
460 | #define SGR004 004 /* use last regex instead of last pat */ | |||
461 | #define SGF010 010 /* repeat last substitution */ | |||
462 | ||||
463 | int patlock = 0; /* if set, pattern not freed by get_compiled_pattern() */ | |||
464 | ||||
465 | volatile sig_atomic_t rows = 22; /* scroll length: ws_row - 2 */ | |||
466 | volatile sig_atomic_t cols = 72; /* wrap column */ | |||
467 | ||||
468 | /* exec_command: execute the next command in command buffer; return print | |||
469 | request, if any */ | |||
470 | int | |||
471 | exec_command(void) | |||
472 | { | |||
473 | extern int u_current_addr; | |||
474 | extern int u_addr_last; | |||
475 | ||||
476 | static regex_t *pat = NULL((void *)0); | |||
477 | static int sgflag = 0; | |||
478 | static int sgnum = 0; | |||
479 | ||||
480 | regex_t *tpat; | |||
481 | char *fnp; | |||
482 | int gflag = 0; | |||
483 | int sflags = 0; | |||
484 | int addr = 0; | |||
485 | int n = 0; | |||
486 | int c; | |||
487 | ||||
488 | SKIP_BLANKS()do { while (isspace((unsigned char)*ibufp) && *ibufp != '\n') ibufp++; } while (0); | |||
| ||||
489 | switch ((c = (unsigned char)*ibufp++)) { | |||
490 | case 'a': | |||
491 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
492 | if (!isglobal) clear_undo_stack(); | |||
493 | if (append_lines(second_addr) < 0) | |||
494 | return ERR(-2); | |||
495 | break; | |||
496 | case 'c': | |||
497 | if (check_addr_range(current_addr, current_addr) < 0) | |||
498 | return ERR(-2); | |||
499 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
500 | if (!isglobal) clear_undo_stack(); | |||
501 | if (delete_lines(first_addr, second_addr) < 0 || | |||
502 | append_lines(current_addr) < 0) | |||
503 | return ERR(-2); | |||
504 | break; | |||
505 | case 'd': | |||
506 | if (check_addr_range(current_addr, current_addr) < 0) | |||
507 | return ERR(-2); | |||
508 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
509 | if (!isglobal) clear_undo_stack(); | |||
510 | if (delete_lines(first_addr, second_addr) < 0) | |||
511 | return ERR(-2); | |||
512 | else if ((addr = INC_MOD(current_addr, addr_last)((current_addr) + 1 > (addr_last) ? 0 : (current_addr) + 1 )) != 0) | |||
513 | current_addr = addr; | |||
514 | break; | |||
515 | case 'e': | |||
516 | if (modified && !scripted) | |||
517 | return EMOD(-3); | |||
518 | /* FALLTHROUGH */ | |||
519 | case 'E': | |||
520 | if (addr_cnt > 0) { | |||
521 | seterrmsg("unexpected address"); | |||
522 | return ERR(-2); | |||
523 | } else if (!isspace((unsigned char)*ibufp)) { | |||
524 | seterrmsg("unexpected command suffix"); | |||
525 | return ERR(-2); | |||
526 | } else if ((fnp = get_filename(1)) == NULL((void *)0)) | |||
527 | return ERR(-2); | |||
528 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
529 | if (delete_lines(1, addr_last) < 0) | |||
530 | return ERR(-2); | |||
531 | clear_undo_stack(); | |||
532 | if (close_sbuf() < 0) | |||
533 | return ERR(-2); | |||
534 | else if (open_sbuf() < 0) | |||
535 | return FATAL(-4); | |||
536 | if (read_file(fnp, 0) < 0) | |||
537 | return ERR(-2); | |||
538 | clear_undo_stack(); | |||
539 | modified = 0; | |||
540 | u_current_addr = u_addr_last = -1; | |||
541 | break; | |||
542 | case 'f': | |||
543 | if (addr_cnt > 0) { | |||
544 | seterrmsg("unexpected address"); | |||
545 | return ERR(-2); | |||
546 | } else if (!isspace((unsigned char)*ibufp)) { | |||
547 | seterrmsg("unexpected command suffix"); | |||
548 | return ERR(-2); | |||
549 | } else if ((fnp = get_filename(1)) == NULL((void *)0)) | |||
550 | return ERR(-2); | |||
551 | else if (*fnp == '!') { | |||
552 | seterrmsg("invalid redirection"); | |||
553 | return ERR(-2); | |||
554 | } | |||
555 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
556 | puts(strip_escapes(fnp)); | |||
557 | break; | |||
558 | case 'g': | |||
559 | case 'v': | |||
560 | case 'G': | |||
561 | case 'V': | |||
562 | if (isglobal) { | |||
563 | seterrmsg("cannot nest global commands"); | |||
564 | return ERR(-2); | |||
565 | } else if (check_addr_range(1, addr_last) < 0) | |||
566 | return ERR(-2); | |||
567 | else if (build_active_list(c == 'g' || c == 'G') < 0) | |||
568 | return ERR(-2); | |||
569 | else if ((n = (c == 'G' || c == 'V'))) | |||
570 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
571 | isglobal++; | |||
572 | if (exec_global(n, gflag) < 0) | |||
573 | return ERR(-2); | |||
574 | break; | |||
575 | case 'h': | |||
576 | if (addr_cnt > 0) { | |||
577 | seterrmsg("unexpected address"); | |||
578 | return ERR(-2); | |||
579 | } | |||
580 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
581 | if (*errmsg) fprintf(stderr(&__sF[2]), "%s\n", errmsg); | |||
582 | break; | |||
583 | case 'H': | |||
584 | if (addr_cnt > 0) { | |||
585 | seterrmsg("unexpected address"); | |||
586 | return ERR(-2); | |||
587 | } | |||
588 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
589 | if ((garrulous = 1 - garrulous) && *errmsg) | |||
590 | fprintf(stderr(&__sF[2]), "%s\n", errmsg); | |||
591 | break; | |||
592 | case 'i': | |||
593 | if (second_addr == 0) { | |||
594 | second_addr = 1; | |||
595 | } | |||
596 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
597 | if (!isglobal) clear_undo_stack(); | |||
598 | if (append_lines(second_addr - 1) < 0) | |||
599 | return ERR(-2); | |||
600 | break; | |||
601 | case 'j': | |||
602 | if (check_addr_range(current_addr, current_addr + 1) < 0) | |||
603 | return ERR(-2); | |||
604 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
605 | if (!isglobal) clear_undo_stack(); | |||
606 | if (first_addr != second_addr && | |||
607 | join_lines(first_addr, second_addr) < 0) | |||
608 | return ERR(-2); | |||
609 | break; | |||
610 | case 'k': | |||
611 | c = (unsigned char)*ibufp++; | |||
612 | if (second_addr == 0) { | |||
613 | seterrmsg("invalid address"); | |||
614 | return ERR(-2); | |||
615 | } | |||
616 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
617 | if (mark_line_node(get_addressed_line_node(second_addr), c) < 0) | |||
618 | return ERR(-2); | |||
619 | break; | |||
620 | case 'l': | |||
621 | if (check_addr_range(current_addr, current_addr) < 0) | |||
622 | return ERR(-2); | |||
623 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
624 | if (display_lines(first_addr, second_addr, gflag | GLS004) < 0) | |||
625 | return ERR(-2); | |||
626 | gflag = 0; | |||
627 | break; | |||
628 | case 'm': | |||
629 | if (check_addr_range(current_addr, current_addr) < 0) | |||
630 | return ERR(-2); | |||
631 | GET_THIRD_ADDR(addr)do { int ol1, ol2; ol1 = first_addr; ol2 = second_addr; if (extract_addr_range () < 0) return (-2); else if (addr_cnt == 0) { seterrmsg("destination expected" ); return (-2); } else if (second_addr < 0 || addr_last < second_addr) { seterrmsg("invalid address"); return (-2); } addr = second_addr; first_addr = ol1; second_addr = ol2; } while ( 0); | |||
632 | if (first_addr <= addr && addr < second_addr) { | |||
633 | seterrmsg("invalid destination"); | |||
634 | return ERR(-2); | |||
635 | } | |||
636 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
637 | if (!isglobal) clear_undo_stack(); | |||
638 | if (move_lines(addr) < 0) | |||
639 | return ERR(-2); | |||
640 | break; | |||
641 | case 'n': | |||
642 | if (check_addr_range(current_addr, current_addr) < 0) | |||
643 | return ERR(-2); | |||
644 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
645 | if (display_lines(first_addr, second_addr, gflag | GNP010) < 0) | |||
646 | return ERR(-2); | |||
647 | gflag = 0; | |||
648 | break; | |||
649 | case 'p': | |||
650 | if (check_addr_range(current_addr, current_addr) < 0) | |||
651 | return ERR(-2); | |||
652 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
653 | if (display_lines(first_addr, second_addr, gflag | GPR002) < 0) | |||
654 | return ERR(-2); | |||
655 | gflag = 0; | |||
656 | break; | |||
657 | case 'P': | |||
658 | if (addr_cnt > 0) { | |||
659 | seterrmsg("unexpected address"); | |||
660 | return ERR(-2); | |||
661 | } | |||
662 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
663 | prompt = prompt ? NULL((void *)0) : optarg ? optarg : dps; | |||
664 | break; | |||
665 | case 'q': | |||
666 | case 'Q': | |||
667 | if (addr_cnt > 0) { | |||
668 | seterrmsg("unexpected address"); | |||
669 | return ERR(-2); | |||
670 | } | |||
671 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
672 | gflag = (modified && !scripted && c == 'q') ? EMOD(-3) : EOF(-1); | |||
673 | break; | |||
674 | case 'r': | |||
675 | if (!isspace((unsigned char)*ibufp)) { | |||
676 | seterrmsg("unexpected command suffix"); | |||
677 | return ERR(-2); | |||
678 | } else if (addr_cnt == 0) | |||
679 | second_addr = addr_last; | |||
680 | if ((fnp = get_filename(0)) == NULL((void *)0)) | |||
681 | return ERR(-2); | |||
682 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
683 | if (!isglobal) clear_undo_stack(); | |||
684 | if ((addr = read_file(fnp, second_addr)) < 0) | |||
685 | return ERR(-2); | |||
686 | else if (addr) | |||
687 | modified = 1; | |||
688 | break; | |||
689 | case 's': | |||
690 | do { | |||
691 | switch (*ibufp) { | |||
692 | case '\n': | |||
693 | sflags |=SGF010; | |||
694 | break; | |||
695 | case 'g': | |||
696 | sflags |= SGG001; | |||
697 | ibufp++; | |||
698 | break; | |||
699 | case 'p': | |||
700 | sflags |= SGP002; | |||
701 | ibufp++; | |||
702 | break; | |||
703 | case 'r': | |||
704 | sflags |= SGR004; | |||
705 | ibufp++; | |||
706 | break; | |||
707 | case '0': case '1': case '2': case '3': case '4': | |||
708 | case '5': case '6': case '7': case '8': case '9': | |||
709 | STRTOI(sgnum, ibufp){ long l = strtol(ibufp, &ibufp, 10); if (l <= (-0x7fffffff -1) || l >= 0x7fffffff) { seterrmsg("number out of range") ; sgnum = 0; return (-2); } else sgnum = (int)l; }; | |||
710 | sflags |= SGF010; | |||
711 | sgflag &= ~GSG020; /* override GSG */ | |||
712 | break; | |||
713 | default: | |||
714 | if (sflags) { | |||
715 | seterrmsg("invalid command suffix"); | |||
716 | return ERR(-2); | |||
717 | } | |||
718 | } | |||
719 | } while (sflags && *ibufp != '\n'); | |||
720 | if (sflags && !pat) { | |||
721 | seterrmsg("no previous substitution"); | |||
722 | return ERR(-2); | |||
723 | } else if (sflags & SGG001) | |||
724 | sgnum = 0; /* override numeric arg */ | |||
725 | if (*ibufp != '\n' && *(ibufp + 1) == '\n') { | |||
726 | seterrmsg("invalid pattern delimiter"); | |||
727 | return ERR(-2); | |||
728 | } | |||
729 | tpat = pat; | |||
730 | SPL1()mutex++; | |||
731 | if ((!sflags || (sflags & SGR004)) && | |||
732 | (tpat = get_compiled_pattern()) == NULL((void *)0)) { | |||
733 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
734 | return ERR(-2); | |||
735 | } else if (tpat != pat) { | |||
736 | if (pat) { | |||
737 | regfree(pat); | |||
738 | free(pat); | |||
739 | } | |||
740 | pat = tpat; | |||
741 | patlock = 1; /* reserve pattern */ | |||
742 | } | |||
743 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
744 | if (!sflags && extract_subst_tail(&sgflag, &sgnum) < 0) | |||
745 | return ERR(-2); | |||
746 | else if (isglobal) | |||
747 | sgflag |= GLB001; | |||
748 | else | |||
749 | sgflag &= ~GLB001; | |||
750 | if (sflags & SGG001) | |||
751 | sgflag ^= GSG020; | |||
752 | if (sflags & SGP002) { | |||
753 | sgflag ^= GPR002; | |||
754 | sgflag &= ~(GLS004 | GNP010); | |||
755 | } | |||
756 | do { | |||
757 | switch (*ibufp) { | |||
758 | case 'p': | |||
759 | sgflag |= GPR002; | |||
760 | ibufp++; | |||
761 | break; | |||
762 | case 'l': | |||
763 | sgflag |= GLS004; | |||
764 | ibufp++; | |||
765 | break; | |||
766 | case 'n': | |||
767 | sgflag |= GNP010; | |||
768 | ibufp++; | |||
769 | break; | |||
770 | default: | |||
771 | n++; | |||
772 | } | |||
773 | } while (!n); | |||
774 | if (check_addr_range(current_addr, current_addr) < 0) | |||
775 | return ERR(-2); | |||
776 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
777 | if (!isglobal) clear_undo_stack(); | |||
778 | if (search_and_replace(pat, sgflag, sgnum) < 0) | |||
779 | return ERR(-2); | |||
780 | break; | |||
781 | case 't': | |||
782 | if (check_addr_range(current_addr, current_addr) < 0) | |||
783 | return ERR(-2); | |||
784 | GET_THIRD_ADDR(addr)do { int ol1, ol2; ol1 = first_addr; ol2 = second_addr; if (extract_addr_range () < 0) return (-2); else if (addr_cnt == 0) { seterrmsg("destination expected" ); return (-2); } else if (second_addr < 0 || addr_last < second_addr) { seterrmsg("invalid address"); return (-2); } addr = second_addr; first_addr = ol1; second_addr = ol2; } while ( 0); | |||
785 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
786 | if (!isglobal) clear_undo_stack(); | |||
787 | if (copy_lines(addr) < 0) | |||
788 | return ERR(-2); | |||
789 | break; | |||
790 | case 'u': | |||
791 | if (addr_cnt > 0) { | |||
792 | seterrmsg("unexpected address"); | |||
793 | return ERR(-2); | |||
794 | } | |||
795 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
796 | if (pop_undo_stack() < 0) | |||
797 | return ERR(-2); | |||
798 | break; | |||
799 | case 'w': | |||
800 | case 'W': | |||
801 | if ((n = *ibufp) == 'q' || n == 'Q') { | |||
802 | gflag = EOF(-1); | |||
803 | ibufp++; | |||
804 | } | |||
805 | if (!isspace((unsigned char)*ibufp)) { | |||
806 | seterrmsg("unexpected command suffix"); | |||
807 | return ERR(-2); | |||
808 | } else if ((fnp = get_filename(0)) == NULL((void *)0)) | |||
809 | return ERR(-2); | |||
810 | if (addr_cnt == 0 && !addr_last) | |||
811 | first_addr = second_addr = 0; | |||
812 | else if (check_addr_range(1, addr_last) < 0) | |||
813 | return ERR(-2); | |||
814 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
815 | if ((addr = write_file(fnp, (c == 'W') ? "a" : "w", | |||
816 | first_addr, second_addr)) < 0) | |||
817 | return ERR(-2); | |||
818 | else if (addr == addr_last && *fnp != '!') | |||
819 | modified = 0; | |||
820 | else if (modified && !scripted && n == 'q') | |||
821 | gflag = EMOD(-3); | |||
822 | break; | |||
823 | case 'x': | |||
824 | if (addr_cnt > 0) { | |||
825 | seterrmsg("unexpected address"); | |||
826 | return ERR(-2); | |||
827 | } | |||
828 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
829 | seterrmsg("crypt unavailable"); | |||
830 | return ERR(-2); | |||
831 | case 'z': | |||
832 | first_addr = 1; | |||
833 | if (check_addr_range(first_addr, current_addr + 1) < 0) | |||
834 | return ERR(-2); | |||
835 | else if ('0' < *ibufp && *ibufp <= '9') | |||
836 | STRTOI(rows, ibufp){ long l = strtol(ibufp, &ibufp, 10); if (l <= (-0x7fffffff -1) || l >= 0x7fffffff) { seterrmsg("number out of range") ; rows = 0; return (-2); } else rows = (int)l; }; | |||
837 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
838 | if (display_lines(second_addr, min(addr_last,((addr_last) < (second_addr + rows) ? (addr_last) : (second_addr + rows)) | |||
839 | second_addr + rows)((addr_last) < (second_addr + rows) ? (addr_last) : (second_addr + rows)), gflag) < 0) | |||
840 | return ERR(-2); | |||
841 | gflag = 0; | |||
842 | break; | |||
843 | case '=': | |||
844 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
845 | printf("%d\n", addr_cnt ? second_addr : addr_last); | |||
846 | break; | |||
847 | case '!': | |||
848 | if (addr_cnt > 0) { | |||
849 | seterrmsg("unexpected address"); | |||
850 | return ERR(-2); | |||
851 | } else if ((sflags = get_shell_command()) < 0) | |||
852 | return ERR(-2); | |||
853 | GET_COMMAND_SUFFIX()do { int done = 0; do { switch (*ibufp) { case 'p': gflag |= 002 ; ibufp++; break; case 'l': gflag |= 004; ibufp++; break; case 'n': gflag |= 010; ibufp++; break; default: done++; } } while (!done); if (*ibufp++ != '\n') { seterrmsg("invalid command suffix" ); return (-2); } } while (0); | |||
854 | if (sflags) printf("%s\n", shcmd + 1); | |||
855 | fflush(NULL((void *)0)); /* flush any buffered I/O */ | |||
856 | system(shcmd + 1); | |||
857 | if (!scripted) printf("!\n"); | |||
858 | break; | |||
859 | case '\n': | |||
860 | first_addr = 1; | |||
861 | if (check_addr_range(first_addr, current_addr + 1) < 0 | |||
862 | || display_lines(second_addr, second_addr, 0) < 0) | |||
863 | return ERR(-2); | |||
864 | break; | |||
865 | default: | |||
866 | seterrmsg("unknown command"); | |||
867 | return ERR(-2); | |||
868 | } | |||
869 | return gflag; | |||
870 | } | |||
871 | ||||
872 | ||||
873 | /* check_addr_range: return status of address range check */ | |||
874 | static int | |||
875 | check_addr_range(int n, int m) | |||
876 | { | |||
877 | if (addr_cnt == 0) { | |||
878 | first_addr = n; | |||
879 | second_addr = m; | |||
880 | } | |||
881 | if (first_addr > second_addr || 1 > first_addr || | |||
882 | second_addr > addr_last) { | |||
883 | seterrmsg("invalid address"); | |||
884 | return ERR(-2); | |||
885 | } | |||
886 | return 0; | |||
887 | } | |||
888 | ||||
889 | ||||
890 | /* get_matching_node_addr: return the address of the next line matching a | |||
891 | pattern in a given direction. wrap around begin/end of editor buffer if | |||
892 | necessary */ | |||
893 | static int | |||
894 | get_matching_node_addr(regex_t *pat, int dir) | |||
895 | { | |||
896 | char *s; | |||
897 | int n = current_addr; | |||
898 | line_t *lp; | |||
899 | ||||
900 | if (!pat) return ERR(-2); | |||
901 | do { | |||
902 | if ((n = dir ? INC_MOD(n, addr_last)((n) + 1 > (addr_last) ? 0 : (n) + 1) : DEC_MOD(n, addr_last)((n) - 1 < 0 ? (addr_last) : (n) - 1))) { | |||
903 | lp = get_addressed_line_node(n); | |||
904 | if ((s = get_sbuf_line(lp)) == NULL((void *)0)) | |||
905 | return ERR(-2); | |||
906 | if (isbinary) | |||
907 | NUL_TO_NEWLINE(s, lp->len)translit_text(s, lp->len, '\0', '\n'); | |||
908 | if (!regexec(pat, s, 0, NULL((void *)0), 0)) | |||
909 | return n; | |||
910 | } | |||
911 | } while (n != current_addr); | |||
912 | seterrmsg("no match"); | |||
913 | return ERR(-2); | |||
914 | } | |||
915 | ||||
916 | ||||
917 | /* get_filename: return pointer to copy of filename in the command buffer */ | |||
918 | static char * | |||
919 | get_filename(int save) | |||
920 | { | |||
921 | static char filename[PATH_MAX1024]; | |||
922 | char *p; | |||
923 | int n; | |||
924 | ||||
925 | if (*ibufp != '\n') { | |||
926 | SKIP_BLANKS()do { while (isspace((unsigned char)*ibufp) && *ibufp != '\n') ibufp++; } while (0); | |||
927 | if (*ibufp == '\n') { | |||
928 | seterrmsg("invalid filename"); | |||
929 | return NULL((void *)0); | |||
930 | } else if ((ibufp = get_extended_line(&n, 1)) == NULL((void *)0)) | |||
931 | return NULL((void *)0); | |||
932 | else if (*ibufp == '!') { | |||
933 | ibufp++; | |||
934 | if ((n = get_shell_command()) < 0) | |||
935 | return NULL((void *)0); | |||
936 | if (n) printf("%s\n", shcmd + 1); | |||
937 | return shcmd; | |||
938 | } else if (n >= PATH_MAX1024 - 1) { | |||
939 | seterrmsg("filename too long"); | |||
940 | return NULL((void *)0); | |||
941 | } | |||
942 | } else { | |||
943 | if (*old_filename == '\0') { | |||
944 | seterrmsg("no current filename"); | |||
945 | return NULL((void *)0); | |||
946 | } | |||
947 | return old_filename; | |||
948 | } | |||
949 | ||||
950 | p = save ? old_filename : *old_filename ? filename : old_filename; | |||
951 | for (n = 0; *ibufp != '\n';) | |||
952 | p[n++] = *ibufp++; | |||
953 | p[n] = '\0'; | |||
954 | return p; | |||
955 | } | |||
956 | ||||
957 | ||||
958 | /* get_shell_command: read a shell command from stdin; return substitution | |||
959 | status */ | |||
960 | static int | |||
961 | get_shell_command(void) | |||
962 | { | |||
963 | static char *buf = NULL((void *)0); | |||
964 | static int n = 0; | |||
965 | ||||
966 | char *s; /* substitution char pointer */ | |||
967 | int i = 0; | |||
968 | int j = 0; | |||
969 | ||||
970 | if ((s = ibufp = get_extended_line(&j, 1)) == NULL((void *)0)) | |||
971 | return ERR(-2); | |||
972 | REALLOC(buf, n, j + 1, ERR)if ((j + 1) > (n)) { int ti = (n); char *ts; mutex++; if ( (ts = realloc((buf), ti += (((j + 1)) > (512) ? ((j + 1)) : (512)))) == ((void *)0)) { perror(((void *)0)); seterrmsg("out of memory" ); do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); return (-2); } (n) = ti; (buf ) = ts; do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint) handle_int(2); } } while (0); }; | |||
973 | buf[i++] = '!'; /* prefix command w/ bang */ | |||
974 | while (*ibufp != '\n') | |||
975 | switch (*ibufp) { | |||
976 | default: | |||
977 | REALLOC(buf, n, i + 2, ERR)if ((i + 2) > (n)) { int ti = (n); char *ts; mutex++; if ( (ts = realloc((buf), ti += (((i + 2)) > (512) ? ((i + 2)) : (512)))) == ((void *)0)) { perror(((void *)0)); seterrmsg("out of memory" ); do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); return (-2); } (n) = ti; (buf ) = ts; do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint) handle_int(2); } } while (0); }; | |||
978 | buf[i++] = *ibufp; | |||
979 | if (*ibufp++ == '\\') | |||
980 | buf[i++] = *ibufp++; | |||
981 | break; | |||
982 | case '!': | |||
983 | if (s != ibufp) { | |||
984 | REALLOC(buf, n, i + 1, ERR)if ((i + 1) > (n)) { int ti = (n); char *ts; mutex++; if ( (ts = realloc((buf), ti += (((i + 1)) > (512) ? ((i + 1)) : (512)))) == ((void *)0)) { perror(((void *)0)); seterrmsg("out of memory" ); do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); return (-2); } (n) = ti; (buf ) = ts; do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint) handle_int(2); } } while (0); }; | |||
985 | buf[i++] = *ibufp++; | |||
986 | } | |||
987 | else if (shcmd == NULL((void *)0)) | |||
988 | { | |||
989 | seterrmsg("no previous command"); | |||
990 | return ERR(-2); | |||
991 | } else { | |||
992 | REALLOC(buf, n, i + shcmdi, ERR)if ((i + shcmdi) > (n)) { int ti = (n); char *ts; mutex++; if ((ts = realloc((buf), ti += (((i + shcmdi)) > (512) ? ( (i + shcmdi)) : (512)))) == ((void *)0)) { perror(((void *)0) ); seterrmsg("out of memory"); do { if (--mutex == 0) { if (sighup ) handle_hup(1); if (sigint) handle_int(2); } } while (0); return (-2); } (n) = ti; (buf) = ts; do { if (--mutex == 0) { if (sighup ) handle_hup(1); if (sigint) handle_int(2); } } while (0); }; | |||
993 | for (s = shcmd + 1; s < shcmd + shcmdi;) | |||
994 | buf[i++] = *s++; | |||
995 | s = ibufp++; | |||
996 | } | |||
997 | break; | |||
998 | case '%': | |||
999 | if (*old_filename == '\0') { | |||
1000 | seterrmsg("no current filename"); | |||
1001 | return ERR(-2); | |||
1002 | } | |||
1003 | j = strlen(s = strip_escapes(old_filename)); | |||
1004 | REALLOC(buf, n, i + j, ERR)if ((i + j) > (n)) { int ti = (n); char *ts; mutex++; if ( (ts = realloc((buf), ti += (((i + j)) > (512) ? ((i + j)) : (512)))) == ((void *)0)) { perror(((void *)0)); seterrmsg("out of memory" ); do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); return (-2); } (n) = ti; (buf ) = ts; do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint) handle_int(2); } } while (0); }; | |||
1005 | while (j--) | |||
1006 | buf[i++] = *s++; | |||
1007 | s = ibufp++; | |||
1008 | break; | |||
1009 | } | |||
1010 | if (i == 1) { | |||
1011 | seterrmsg("no command"); | |||
1012 | return ERR(-2); | |||
1013 | } | |||
1014 | REALLOC(shcmd, shcmdsz, i + 1, ERR)if ((i + 1) > (shcmdsz)) { int ti = (shcmdsz); char *ts; mutex ++; if ((ts = realloc((shcmd), ti += (((i + 1)) > (512) ? ( (i + 1)) : (512)))) == ((void *)0)) { perror(((void *)0)); seterrmsg ("out of memory"); do { if (--mutex == 0) { if (sighup) handle_hup (1); if (sigint) handle_int(2); } } while (0); return (-2); } (shcmdsz) = ti; (shcmd) = ts; do { if (--mutex == 0) { if (sighup ) handle_hup(1); if (sigint) handle_int(2); } } while (0); }; | |||
1015 | memcpy(shcmd, buf, i); | |||
1016 | shcmd[shcmdi = i] = '\0'; | |||
1017 | return *s == '!' || *s == '%'; | |||
1018 | } | |||
1019 | ||||
1020 | ||||
1021 | /* append_lines: insert text from stdin to after line n; stop when either a | |||
1022 | single period is read or EOF; return status */ | |||
1023 | static int | |||
1024 | append_lines(int n) | |||
1025 | { | |||
1026 | int l; | |||
1027 | char *lp = ibuf; | |||
1028 | char *eot; | |||
1029 | undo_t *up = NULL((void *)0); | |||
1030 | ||||
1031 | for (current_addr = n;;) { | |||
1032 | if (!isglobal) { | |||
1033 | if ((l = get_tty_line()) < 0) | |||
1034 | return ERR(-2); | |||
1035 | else if (l == 0 || ibuf[l - 1] != '\n') { | |||
1036 | clearerr(stdin)(!__isthreaded ? ((void)(((&__sF[0]))->_flags &= ~ (0x0040|0x0020))) : (clearerr)((&__sF[0]))); | |||
1037 | return l ? EOF(-1) : 0; | |||
1038 | } | |||
1039 | lp = ibuf; | |||
1040 | } else if (*(lp = ibufp) == '\0') | |||
1041 | return 0; | |||
1042 | else { | |||
1043 | while (*ibufp++ != '\n') | |||
1044 | ; | |||
1045 | l = ibufp - lp; | |||
1046 | } | |||
1047 | if (l == 2 && lp[0] == '.' && lp[1] == '\n') { | |||
1048 | return 0; | |||
1049 | } | |||
1050 | eot = lp + l; | |||
1051 | SPL1()mutex++; | |||
1052 | do { | |||
1053 | if ((lp = put_sbuf_line(lp)) == NULL((void *)0)) { | |||
1054 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1055 | return ERR(-2); | |||
1056 | } else if (up) | |||
1057 | up->t = get_addressed_line_node(current_addr); | |||
1058 | else if ((up = push_undo_stack(UADD0, current_addr, | |||
1059 | current_addr)) == NULL((void *)0)) { | |||
1060 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1061 | return ERR(-2); | |||
1062 | } | |||
1063 | } while (lp != eot); | |||
1064 | modified = 1; | |||
1065 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1066 | } | |||
1067 | /* NOTREACHED */ | |||
1068 | } | |||
1069 | ||||
1070 | ||||
1071 | /* join_lines: replace a range of lines with the joined text of those lines */ | |||
1072 | static int | |||
1073 | join_lines(int from, int to) | |||
1074 | { | |||
1075 | static char *buf = NULL((void *)0); | |||
1076 | static int n; | |||
1077 | ||||
1078 | char *s; | |||
1079 | int size = 0; | |||
1080 | line_t *bp, *ep; | |||
1081 | ||||
1082 | ep = get_addressed_line_node(INC_MOD(to, addr_last)((to) + 1 > (addr_last) ? 0 : (to) + 1)); | |||
1083 | bp = get_addressed_line_node(from); | |||
1084 | for (; bp != ep; bp = bp->q_forw) { | |||
1085 | if ((s = get_sbuf_line(bp)) == NULL((void *)0)) | |||
1086 | return ERR(-2); | |||
1087 | REALLOC(buf, n, size + bp->len, ERR)if ((size + bp->len) > (n)) { int ti = (n); char *ts; mutex ++; if ((ts = realloc((buf), ti += (((size + bp->len)) > (512) ? ((size + bp->len)) : (512)))) == ((void *)0)) { perror (((void *)0)); seterrmsg("out of memory"); do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint) handle_int(2); } } while (0); return (-2); } (n) = ti; (buf) = ts; do { if (-- mutex == 0) { if (sighup) handle_hup(1); if (sigint) handle_int (2); } } while (0); }; | |||
1088 | memcpy(buf + size, s, bp->len); | |||
| ||||
1089 | size += bp->len; | |||
1090 | } | |||
1091 | REALLOC(buf, n, size + 2, ERR)if ((size + 2) > (n)) { int ti = (n); char *ts; mutex++; if ((ts = realloc((buf), ti += (((size + 2)) > (512) ? ((size + 2)) : (512)))) == ((void *)0)) { perror(((void *)0)); seterrmsg ("out of memory"); do { if (--mutex == 0) { if (sighup) handle_hup (1); if (sigint) handle_int(2); } } while (0); return (-2); } (n) = ti; (buf) = ts; do { if (--mutex == 0) { if (sighup) handle_hup (1); if (sigint) handle_int(2); } } while (0); }; | |||
1092 | memcpy(buf + size, "\n", 2); | |||
1093 | if (delete_lines(from, to) < 0) | |||
1094 | return ERR(-2); | |||
1095 | current_addr = from - 1; | |||
1096 | SPL1()mutex++; | |||
1097 | if (put_sbuf_line(buf) == NULL((void *)0) || | |||
1098 | push_undo_stack(UADD0, current_addr, current_addr) == NULL((void *)0)) { | |||
1099 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1100 | return ERR(-2); | |||
1101 | } | |||
1102 | modified = 1; | |||
1103 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1104 | return 0; | |||
1105 | } | |||
1106 | ||||
1107 | ||||
1108 | /* move_lines: move a range of lines */ | |||
1109 | static int | |||
1110 | move_lines(int addr) | |||
1111 | { | |||
1112 | line_t *b1, *a1, *b2, *a2; | |||
1113 | int n = INC_MOD(second_addr, addr_last)((second_addr) + 1 > (addr_last) ? 0 : (second_addr) + 1); | |||
1114 | int p = first_addr - 1; | |||
1115 | int done = (addr == first_addr - 1 || addr == second_addr); | |||
1116 | ||||
1117 | SPL1()mutex++; | |||
1118 | if (done) { | |||
1119 | a2 = get_addressed_line_node(n); | |||
1120 | b2 = get_addressed_line_node(p); | |||
1121 | current_addr = second_addr; | |||
1122 | } else if (push_undo_stack(UMOV2, p, n) == NULL((void *)0) || | |||
1123 | push_undo_stack(UMOV2, addr, INC_MOD(addr, addr_last)((addr) + 1 > (addr_last) ? 0 : (addr) + 1)) == NULL((void *)0)) { | |||
1124 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1125 | return ERR(-2); | |||
1126 | } else { | |||
1127 | a1 = get_addressed_line_node(n); | |||
1128 | if (addr < first_addr) { | |||
1129 | b1 = get_addressed_line_node(p); | |||
1130 | b2 = get_addressed_line_node(addr); | |||
1131 | /* this get_addressed_line_node last! */ | |||
1132 | } else { | |||
1133 | b2 = get_addressed_line_node(addr); | |||
1134 | b1 = get_addressed_line_node(p); | |||
1135 | /* this get_addressed_line_node last! */ | |||
1136 | } | |||
1137 | a2 = b2->q_forw; | |||
1138 | REQUE(b2, b1->q_forw)(b2)->q_forw = (b1->q_forw), (b1->q_forw)->q_back = (b2); | |||
1139 | REQUE(a1->q_back, a2)(a1->q_back)->q_forw = (a2), (a2)->q_back = (a1-> q_back); | |||
1140 | REQUE(b1, a1)(b1)->q_forw = (a1), (a1)->q_back = (b1); | |||
1141 | current_addr = addr + ((addr < first_addr) ? | |||
1142 | second_addr - first_addr + 1 : 0); | |||
1143 | } | |||
1144 | if (isglobal) | |||
1145 | unset_active_nodes(b2->q_forw, a2); | |||
1146 | modified = 1; | |||
1147 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1148 | return 0; | |||
1149 | } | |||
1150 | ||||
1151 | ||||
1152 | /* copy_lines: copy a range of lines; return status */ | |||
1153 | static int | |||
1154 | copy_lines(int addr) | |||
1155 | { | |||
1156 | line_t *lp, *np = get_addressed_line_node(first_addr); | |||
1157 | undo_t *up = NULL((void *)0); | |||
1158 | int n = second_addr - first_addr + 1; | |||
1159 | int m = 0; | |||
1160 | ||||
1161 | current_addr = addr; | |||
1162 | if (first_addr <= addr && addr < second_addr) { | |||
1163 | n = addr - first_addr + 1; | |||
1164 | m = second_addr - addr; | |||
1165 | } | |||
1166 | for (; n > 0; n=m, m=0, np = get_addressed_line_node(current_addr + 1)) | |||
1167 | for (; n-- > 0; np = np->q_forw) { | |||
1168 | SPL1()mutex++; | |||
1169 | if ((lp = dup_line_node(np)) == NULL((void *)0)) { | |||
1170 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1171 | return ERR(-2); | |||
1172 | } | |||
1173 | add_line_node(lp); | |||
1174 | if (up) | |||
1175 | up->t = lp; | |||
1176 | else if ((up = push_undo_stack(UADD0, current_addr, | |||
1177 | current_addr)) == NULL((void *)0)) { | |||
1178 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1179 | return ERR(-2); | |||
1180 | } | |||
1181 | modified = 1; | |||
1182 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1183 | } | |||
1184 | return 0; | |||
1185 | } | |||
1186 | ||||
1187 | ||||
1188 | /* delete_lines: delete a range of lines */ | |||
1189 | int | |||
1190 | delete_lines(int from, int to) | |||
1191 | { | |||
1192 | line_t *n, *p; | |||
1193 | ||||
1194 | SPL1()mutex++; | |||
1195 | if (push_undo_stack(UDEL1, from, to) == NULL((void *)0)) { | |||
1196 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1197 | return ERR(-2); | |||
1198 | } | |||
1199 | n = get_addressed_line_node(INC_MOD(to, addr_last)((to) + 1 > (addr_last) ? 0 : (to) + 1)); | |||
1200 | p = get_addressed_line_node(from - 1); | |||
1201 | /* this get_addressed_line_node last! */ | |||
1202 | if (isglobal) | |||
1203 | unset_active_nodes(p->q_forw, n); | |||
1204 | REQUE(p, n)(p)->q_forw = (n), (n)->q_back = (p); | |||
1205 | addr_last -= to - from + 1; | |||
1206 | current_addr = from - 1; | |||
1207 | modified = 1; | |||
1208 | SPL0()do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint ) handle_int(2); } } while (0); | |||
1209 | return 0; | |||
1210 | } | |||
1211 | ||||
1212 | ||||
1213 | /* display_lines: print a range of lines to stdout */ | |||
1214 | int | |||
1215 | display_lines(int from, int to, int gflag) | |||
1216 | { | |||
1217 | line_t *bp; | |||
1218 | line_t *ep; | |||
1219 | char *s; | |||
1220 | ||||
1221 | if (!from) { | |||
1222 | seterrmsg("invalid address"); | |||
1223 | return ERR(-2); | |||
1224 | } | |||
1225 | ep = get_addressed_line_node(INC_MOD(to, addr_last)((to) + 1 > (addr_last) ? 0 : (to) + 1)); | |||
1226 | bp = get_addressed_line_node(from); | |||
1227 | for (; bp != ep; bp = bp->q_forw) { | |||
1228 | if ((s = get_sbuf_line(bp)) == NULL((void *)0)) | |||
1229 | return ERR(-2); | |||
1230 | if (put_tty_line(s, bp->len, current_addr = from++, gflag) < 0) | |||
1231 | return ERR(-2); | |||
1232 | } | |||
1233 | return 0; | |||
1234 | } | |||
1235 | ||||
1236 | ||||
1237 | #define MAXMARK26 26 /* max number of marks */ | |||
1238 | ||||
1239 | static line_t *mark[MAXMARK26]; /* line markers */ | |||
1240 | static int markno; /* line marker count */ | |||
1241 | ||||
1242 | /* mark_line_node: set a line node mark */ | |||
1243 | static int | |||
1244 | mark_line_node(line_t *lp, int n) | |||
1245 | { | |||
1246 | if (!islower(n)) { | |||
1247 | seterrmsg("invalid mark character"); | |||
1248 | return ERR(-2); | |||
1249 | } else if (mark[n - 'a'] == NULL((void *)0)) | |||
1250 | markno++; | |||
1251 | mark[n - 'a'] = lp; | |||
1252 | return 0; | |||
1253 | } | |||
1254 | ||||
1255 | ||||
1256 | /* get_marked_node_addr: return address of a marked line */ | |||
1257 | static int | |||
1258 | get_marked_node_addr(int n) | |||
1259 | { | |||
1260 | if (!islower(n)) { | |||
1261 | seterrmsg("invalid mark character"); | |||
1262 | return ERR(-2); | |||
1263 | } | |||
1264 | return get_line_node_addr(mark[n - 'a']); | |||
1265 | } | |||
1266 | ||||
1267 | ||||
1268 | /* unmark_line_node: clear line node mark */ | |||
1269 | void | |||
1270 | unmark_line_node(line_t *lp) | |||
1271 | { | |||
1272 | int i; | |||
1273 | ||||
1274 | for (i = 0; markno && i < MAXMARK26; i++) | |||
1275 | if (mark[i] == lp) { | |||
1276 | mark[i] = NULL((void *)0); | |||
1277 | markno--; | |||
1278 | } | |||
1279 | } | |||
1280 | ||||
1281 | ||||
1282 | /* dup_line_node: return a pointer to a copy of a line node */ | |||
1283 | static line_t * | |||
1284 | dup_line_node(line_t *lp) | |||
1285 | { | |||
1286 | line_t *np; | |||
1287 | ||||
1288 | if ((np = malloc(sizeof(line_t))) == NULL((void *)0)) { | |||
1289 | perror(NULL((void *)0)); | |||
1290 | seterrmsg("out of memory"); | |||
1291 | return NULL((void *)0); | |||
1292 | } | |||
1293 | np->seek = lp->seek; | |||
1294 | np->len = lp->len; | |||
1295 | return np; | |||
1296 | } | |||
1297 | ||||
1298 | ||||
1299 | /* has_trailing_escape: return the parity of escapes preceding a character | |||
1300 | in a string */ | |||
1301 | int | |||
1302 | has_trailing_escape(char *s, char *t) | |||
1303 | { | |||
1304 | return (s == t || *(t - 1) != '\\') ? 0 : !has_trailing_escape(s, t - 1); | |||
1305 | } | |||
1306 | ||||
1307 | ||||
1308 | /* strip_escapes: return copy of escaped string of at most length PATH_MAX */ | |||
1309 | char * | |||
1310 | strip_escapes(char *s) | |||
1311 | { | |||
1312 | static char *file = NULL((void *)0); | |||
1313 | static int filesz = 0; | |||
1314 | ||||
1315 | int i = 0; | |||
1316 | ||||
1317 | REALLOC(file, filesz, PATH_MAX, NULL)if ((1024) > (filesz)) { int ti = (filesz); char *ts; mutex ++; if ((ts = realloc((file), ti += (((1024)) > (512) ? (( 1024)) : (512)))) == ((void *)0)) { perror(((void *)0)); seterrmsg ("out of memory"); do { if (--mutex == 0) { if (sighup) handle_hup (1); if (sigint) handle_int(2); } } while (0); return ((void * )0); } (filesz) = ti; (file) = ts; do { if (--mutex == 0) { if (sighup) handle_hup(1); if (sigint) handle_int(2); } } while (0); }; | |||
1318 | /* assert: no trailing escape */ | |||
1319 | while ((file[i++] = (*s == '\\') ? *++s : *s) != '\0' && | |||
1320 | i < PATH_MAX1024-1) | |||
1321 | s++; | |||
1322 | file[PATH_MAX1024-1] = '\0'; | |||
1323 | return file; | |||
1324 | } | |||
1325 | ||||
1326 | ||||
1327 | void | |||
1328 | signal_hup(int signo) | |||
1329 | { | |||
1330 | int save_errno = errno(*__errno()); | |||
1331 | ||||
1332 | if (mutex) | |||
1333 | sighup = 1; | |||
1334 | else | |||
1335 | handle_hup(signo); | |||
1336 | errno(*__errno()) = save_errno; | |||
1337 | } | |||
1338 | ||||
1339 | ||||
1340 | void | |||
1341 | signal_int(int signo) | |||
1342 | { | |||
1343 | int save_errno = errno(*__errno()); | |||
1344 | ||||
1345 | if (mutex) | |||
1346 | sigint = 1; | |||
1347 | else | |||
1348 | handle_int(signo); | |||
1349 | errno(*__errno()) = save_errno; | |||
1350 | } | |||
1351 | ||||
1352 | ||||
1353 | void | |||
1354 | handle_hup(int signo) | |||
1355 | { | |||
1356 | char hup[PATH_MAX1024]; | |||
1357 | ||||
1358 | if (!sigactive) | |||
1359 | quit(1); /* XXX signal race */ | |||
1360 | sighup = 0; | |||
1361 | /* XXX signal race */ | |||
1362 | if (addr_last && write_file("ed.hup", "w", 1, addr_last) < 0 && | |||
1363 | home != NULL((void *)0) && home[0] == '/') { | |||
1364 | if (strlcpy(hup, home, sizeof(hup)) < sizeof(hup) && | |||
1365 | strlcat(hup, "/ed.hup", sizeof(hup)) < sizeof(hup)) | |||
1366 | write_file(hup, "w", 1, addr_last); | |||
1367 | } | |||
1368 | _exit(2); | |||
1369 | } | |||
1370 | ||||
1371 | ||||
1372 | void | |||
1373 | handle_int(int signo) | |||
1374 | { | |||
1375 | if (!sigactive) | |||
1376 | _exit(1); | |||
1377 | sigint = 0; | |||
1378 | siglongjmp(env, -1); | |||
1379 | } | |||
1380 | ||||
1381 | ||||
1382 | void | |||
1383 | handle_winch(int signo) | |||
1384 | { | |||
1385 | int save_errno = errno(*__errno()); | |||
1386 | struct winsize ws; /* window size structure */ | |||
1387 | ||||
1388 | if (ioctl(STDIN_FILENO0, TIOCGWINSZ((unsigned long)0x40000000 | ((sizeof(struct winsize) & 0x1fff ) << 16) | ((('t')) << 8) | ((104))), &ws) == 0) { | |||
1389 | if (ws.ws_row > 2) | |||
1390 | rows = ws.ws_row - 2; | |||
1391 | if (ws.ws_col > 8) | |||
1392 | cols = ws.ws_col - 8; | |||
1393 | } | |||
1394 | errno(*__errno()) = save_errno; | |||
1395 | } |