1d165d4acSAndrew Moore /* glob.c: This file contains the global command routines for the ed line 2d165d4acSAndrew Moore editor */ 3d165d4acSAndrew Moore /*- 4d165d4acSAndrew Moore * Copyright (c) 1993 Andrew Moore, Talke Studio. 5d165d4acSAndrew Moore * All rights reserved. 6d165d4acSAndrew Moore * 7d165d4acSAndrew Moore * Redistribution and use in source and binary forms, with or without 8d165d4acSAndrew Moore * modification, are permitted provided that the following conditions 9d165d4acSAndrew Moore * are met: 10d165d4acSAndrew Moore * 1. Redistributions of source code must retain the above copyright 11d165d4acSAndrew Moore * notice, this list of conditions and the following disclaimer. 12d165d4acSAndrew Moore * 2. Redistributions in binary form must reproduce the above copyright 13d165d4acSAndrew Moore * notice, this list of conditions and the following disclaimer in the 14d165d4acSAndrew Moore * documentation and/or other materials provided with the distribution. 15d165d4acSAndrew Moore * 16d165d4acSAndrew Moore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17d165d4acSAndrew Moore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18d165d4acSAndrew Moore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19d165d4acSAndrew Moore * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20d165d4acSAndrew Moore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21d165d4acSAndrew Moore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22d165d4acSAndrew Moore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23d165d4acSAndrew Moore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24d165d4acSAndrew Moore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25d165d4acSAndrew Moore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26d165d4acSAndrew Moore * SUCH DAMAGE. 27d165d4acSAndrew Moore */ 28d165d4acSAndrew Moore 295eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 305eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 31d165d4acSAndrew Moore 320d8188ceSBrian Somers #include <sys/types.h> 33d165d4acSAndrew Moore #include <sys/ioctl.h> 34d165d4acSAndrew Moore #include <sys/wait.h> 35d165d4acSAndrew Moore 36d165d4acSAndrew Moore #include "ed.h" 37d165d4acSAndrew Moore 38d165d4acSAndrew Moore 39d165d4acSAndrew Moore /* build_active_list: add line matching a pattern to the global-active list */ 40d165d4acSAndrew Moore int 417669d0fcSWarner Losh build_active_list(int isgcmd) 42d165d4acSAndrew Moore { 43d165d4acSAndrew Moore pattern_t *pat; 44d165d4acSAndrew Moore line_t *lp; 45d165d4acSAndrew Moore long n; 46d165d4acSAndrew Moore char *s; 47d165d4acSAndrew Moore char delimiter; 48d165d4acSAndrew Moore 49d165d4acSAndrew Moore if ((delimiter = *ibufp) == ' ' || delimiter == '\n') { 50a4616748SMike Barcroft errmsg = "invalid pattern delimiter"; 51d165d4acSAndrew Moore return ERR; 52d165d4acSAndrew Moore } else if ((pat = get_compiled_pattern()) == NULL) 53d165d4acSAndrew Moore return ERR; 54d165d4acSAndrew Moore else if (*ibufp == delimiter) 55d165d4acSAndrew Moore ibufp++; 56d165d4acSAndrew Moore clear_active_list(); 57d165d4acSAndrew Moore lp = get_addressed_line_node(first_addr); 58d165d4acSAndrew Moore for (n = first_addr; n <= second_addr; n++, lp = lp->q_forw) { 59d165d4acSAndrew Moore if ((s = get_sbuf_line(lp)) == NULL) 60d165d4acSAndrew Moore return ERR; 61d165d4acSAndrew Moore if (isbinary) 62d165d4acSAndrew Moore NUL_TO_NEWLINE(s, lp->len); 63*7d00295bSEitan Adler if (!(regexec(pat, s, 0, NULL, 0) == isgcmd) && 64d165d4acSAndrew Moore set_active_node(lp) < 0) 65d165d4acSAndrew Moore return ERR; 66d165d4acSAndrew Moore } 67d165d4acSAndrew Moore return 0; 68d165d4acSAndrew Moore } 69d165d4acSAndrew Moore 70d165d4acSAndrew Moore 71d165d4acSAndrew Moore /* exec_global: apply command list in the command buffer to the active 72d165d4acSAndrew Moore lines in a range; return command status */ 73d165d4acSAndrew Moore long 747669d0fcSWarner Losh exec_global(int interact, int gflag) 75d165d4acSAndrew Moore { 76d165d4acSAndrew Moore static char *ocmd = NULL; 77d165d4acSAndrew Moore static int ocmdsz = 0; 78d165d4acSAndrew Moore 79d165d4acSAndrew Moore line_t *lp = NULL; 80d165d4acSAndrew Moore int status; 81d165d4acSAndrew Moore int n; 82d165d4acSAndrew Moore char *cmd = NULL; 83d165d4acSAndrew Moore 84d165d4acSAndrew Moore #ifdef BACKWARDS 85d165d4acSAndrew Moore if (!interact) 86d165d4acSAndrew Moore if (!strcmp(ibufp, "\n")) 87d165d4acSAndrew Moore cmd = "p\n"; /* null cmd-list == `p' */ 88d165d4acSAndrew Moore else if ((cmd = get_extended_line(&n, 0)) == NULL) 89d165d4acSAndrew Moore return ERR; 90d165d4acSAndrew Moore #else 91d165d4acSAndrew Moore if (!interact && (cmd = get_extended_line(&n, 0)) == NULL) 92d165d4acSAndrew Moore return ERR; 93d165d4acSAndrew Moore #endif 94d165d4acSAndrew Moore clear_undo_stack(); 95d165d4acSAndrew Moore while ((lp = next_active_node()) != NULL) { 96d165d4acSAndrew Moore if ((current_addr = get_line_node_addr(lp)) < 0) 97d165d4acSAndrew Moore return ERR; 98d165d4acSAndrew Moore if (interact) { 99d165d4acSAndrew Moore /* print current_addr; get a command in global syntax */ 100d165d4acSAndrew Moore if (display_lines(current_addr, current_addr, gflag) < 0) 101d165d4acSAndrew Moore return ERR; 102d165d4acSAndrew Moore while ((n = get_tty_line()) > 0 && 103d165d4acSAndrew Moore ibuf[n - 1] != '\n') 104d165d4acSAndrew Moore clearerr(stdin); 105d165d4acSAndrew Moore if (n < 0) 106d165d4acSAndrew Moore return ERR; 107d165d4acSAndrew Moore else if (n == 0) { 108a4616748SMike Barcroft errmsg = "unexpected end-of-file"; 109d165d4acSAndrew Moore return ERR; 110d165d4acSAndrew Moore } else if (n == 1 && !strcmp(ibuf, "\n")) 111d165d4acSAndrew Moore continue; 112d165d4acSAndrew Moore else if (n == 2 && !strcmp(ibuf, "&\n")) { 113d165d4acSAndrew Moore if (cmd == NULL) { 114a4616748SMike Barcroft errmsg = "no previous command"; 115d165d4acSAndrew Moore return ERR; 116d165d4acSAndrew Moore } else cmd = ocmd; 117d165d4acSAndrew Moore } else if ((cmd = get_extended_line(&n, 0)) == NULL) 118d165d4acSAndrew Moore return ERR; 119d165d4acSAndrew Moore else { 120d165d4acSAndrew Moore REALLOC(ocmd, ocmdsz, n + 1, ERR); 121d165d4acSAndrew Moore memcpy(ocmd, cmd, n + 1); 122d165d4acSAndrew Moore cmd = ocmd; 123d165d4acSAndrew Moore } 124d165d4acSAndrew Moore 125d165d4acSAndrew Moore } 126d165d4acSAndrew Moore ibufp = cmd; 127d165d4acSAndrew Moore for (; *ibufp;) 128d165d4acSAndrew Moore if ((status = extract_addr_range()) < 0 || 129d165d4acSAndrew Moore (status = exec_command()) < 0 || 1300fd510b7SJoerg Wunsch (status > 0 && (status = display_lines( 1310fd510b7SJoerg Wunsch current_addr, current_addr, status)) < 0)) 132d165d4acSAndrew Moore return status; 133d165d4acSAndrew Moore } 134d165d4acSAndrew Moore return 0; 135d165d4acSAndrew Moore } 136d165d4acSAndrew Moore 137d165d4acSAndrew Moore 138ae824d80SEd Schouten static line_t **active_list; /* list of lines active in a global command */ 139ae824d80SEd Schouten static long active_last; /* index of last active line in active_list */ 140ae824d80SEd Schouten static long active_size; /* size of active_list */ 141ae824d80SEd Schouten static long active_ptr; /* active_list index (non-decreasing) */ 142ae824d80SEd Schouten static long active_ndx; /* active_list index (modulo active_last) */ 143d165d4acSAndrew Moore 144d165d4acSAndrew Moore /* set_active_node: add a line node to the global-active list */ 145d165d4acSAndrew Moore int 1467669d0fcSWarner Losh set_active_node(line_t *lp) 147d165d4acSAndrew Moore { 148d165d4acSAndrew Moore if (active_last + 1 > active_size) { 149d165d4acSAndrew Moore int ti = active_size; 150d165d4acSAndrew Moore line_t **ts; 151d165d4acSAndrew Moore SPL1(); 152d165d4acSAndrew Moore #if defined(sun) || defined(NO_REALLOC_NULL) 153d165d4acSAndrew Moore if (active_list != NULL) { 154d165d4acSAndrew Moore #endif 155d165d4acSAndrew Moore if ((ts = (line_t **) realloc(active_list, 156e6743d31SEitan Adler (ti += MINBUFSZ) * sizeof(line_t *))) == NULL) { 157d165d4acSAndrew Moore fprintf(stderr, "%s\n", strerror(errno)); 158a4616748SMike Barcroft errmsg = "out of memory"; 159d165d4acSAndrew Moore SPL0(); 160d165d4acSAndrew Moore return ERR; 161d165d4acSAndrew Moore } 162d165d4acSAndrew Moore #if defined(sun) || defined(NO_REALLOC_NULL) 163d165d4acSAndrew Moore } else { 164d165d4acSAndrew Moore if ((ts = (line_t **) malloc((ti += MINBUFSZ) * 165d165d4acSAndrew Moore sizeof(line_t **))) == NULL) { 166d165d4acSAndrew Moore fprintf(stderr, "%s\n", strerror(errno)); 167a4616748SMike Barcroft errmsg = "out of memory"; 168d165d4acSAndrew Moore SPL0(); 169d165d4acSAndrew Moore return ERR; 170d165d4acSAndrew Moore } 171d165d4acSAndrew Moore } 172d165d4acSAndrew Moore #endif 173d165d4acSAndrew Moore active_size = ti; 174d165d4acSAndrew Moore active_list = ts; 175d165d4acSAndrew Moore SPL0(); 176d165d4acSAndrew Moore } 177d165d4acSAndrew Moore active_list[active_last++] = lp; 178d165d4acSAndrew Moore return 0; 179d165d4acSAndrew Moore } 180d165d4acSAndrew Moore 181d165d4acSAndrew Moore 182d165d4acSAndrew Moore /* unset_active_nodes: remove a range of lines from the global-active list */ 183d165d4acSAndrew Moore void 1847669d0fcSWarner Losh unset_active_nodes(line_t *np, line_t *mp) 185d165d4acSAndrew Moore { 186d165d4acSAndrew Moore line_t *lp; 187d165d4acSAndrew Moore long i; 188d165d4acSAndrew Moore 189d165d4acSAndrew Moore for (lp = np; lp != mp; lp = lp->q_forw) 190d165d4acSAndrew Moore for (i = 0; i < active_last; i++) 191d165d4acSAndrew Moore if (active_list[active_ndx] == lp) { 192d165d4acSAndrew Moore active_list[active_ndx] = NULL; 193d165d4acSAndrew Moore active_ndx = INC_MOD(active_ndx, active_last - 1); 194d165d4acSAndrew Moore break; 195d165d4acSAndrew Moore } else active_ndx = INC_MOD(active_ndx, active_last - 1); 196d165d4acSAndrew Moore } 197d165d4acSAndrew Moore 198d165d4acSAndrew Moore 199d165d4acSAndrew Moore /* next_active_node: return the next global-active line node */ 200d165d4acSAndrew Moore line_t * 2017669d0fcSWarner Losh next_active_node(void) 202d165d4acSAndrew Moore { 203d165d4acSAndrew Moore while (active_ptr < active_last && active_list[active_ptr] == NULL) 204d165d4acSAndrew Moore active_ptr++; 205d165d4acSAndrew Moore return (active_ptr < active_last) ? active_list[active_ptr++] : NULL; 206d165d4acSAndrew Moore } 207d165d4acSAndrew Moore 208d165d4acSAndrew Moore 209d165d4acSAndrew Moore /* clear_active_list: clear the global-active list */ 210d165d4acSAndrew Moore void 2117669d0fcSWarner Losh clear_active_list(void) 212d165d4acSAndrew Moore { 213d165d4acSAndrew Moore SPL1(); 214d165d4acSAndrew Moore active_size = active_last = active_ptr = active_ndx = 0; 215d165d4acSAndrew Moore free(active_list); 216d165d4acSAndrew Moore active_list = NULL; 217d165d4acSAndrew Moore SPL0(); 218d165d4acSAndrew Moore } 219