11297Salm/* glob.c: This file contains the global command routines for the ed line 21297Salm editor */ 31297Salm/*- 41297Salm * Copyright (c) 1993 Andrew Moore, Talke Studio. 51297Salm * All rights reserved. 61297Salm * 71297Salm * Redistribution and use in source and binary forms, with or without 81297Salm * modification, are permitted provided that the following conditions 91297Salm * are met: 101297Salm * 1. Redistributions of source code must retain the above copyright 111297Salm * notice, this list of conditions and the following disclaimer. 121297Salm * 2. Redistributions in binary form must reproduce the above copyright 131297Salm * notice, this list of conditions and the following disclaimer in the 141297Salm * documentation and/or other materials provided with the distribution. 151297Salm * 161297Salm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 171297Salm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 181297Salm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 191297Salm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 201297Salm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 211297Salm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 221297Salm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 231297Salm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 241297Salm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 251297Salm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261297Salm * SUCH DAMAGE. 271297Salm */ 281297Salm 2999109Sobrien#include <sys/cdefs.h> 3099109Sobrien__FBSDID("$FreeBSD$"); 311297Salm 3267183Sbrian#include <sys/types.h> 331297Salm#include <sys/ioctl.h> 341297Salm#include <sys/wait.h> 351297Salm 361297Salm#include "ed.h" 371297Salm 381297Salm 391297Salm/* build_active_list: add line matching a pattern to the global-active list */ 401297Salmint 4190109Simpbuild_active_list(int isgcmd) 421297Salm{ 431297Salm pattern_t *pat; 441297Salm line_t *lp; 451297Salm long n; 461297Salm char *s; 471297Salm char delimiter; 481297Salm 491297Salm if ((delimiter = *ibufp) == ' ' || delimiter == '\n') { 5081220Smike errmsg = "invalid pattern delimiter"; 511297Salm return ERR; 521297Salm } else if ((pat = get_compiled_pattern()) == NULL) 531297Salm return ERR; 541297Salm else if (*ibufp == delimiter) 551297Salm ibufp++; 561297Salm clear_active_list(); 571297Salm lp = get_addressed_line_node(first_addr); 581297Salm for (n = first_addr; n <= second_addr; n++, lp = lp->q_forw) { 591297Salm if ((s = get_sbuf_line(lp)) == NULL) 601297Salm return ERR; 611297Salm if (isbinary) 621297Salm NUL_TO_NEWLINE(s, lp->len); 631297Salm if (!regexec(pat, s, 0, NULL, 0) == isgcmd && 641297Salm set_active_node(lp) < 0) 651297Salm return ERR; 661297Salm } 671297Salm return 0; 681297Salm} 691297Salm 701297Salm 711297Salm/* exec_global: apply command list in the command buffer to the active 721297Salm lines in a range; return command status */ 731297Salmlong 7490109Simpexec_global(int interact, int gflag) 751297Salm{ 761297Salm static char *ocmd = NULL; 771297Salm static int ocmdsz = 0; 781297Salm 791297Salm line_t *lp = NULL; 801297Salm int status; 811297Salm int n; 821297Salm char *cmd = NULL; 831297Salm 841297Salm#ifdef BACKWARDS 851297Salm if (!interact) 861297Salm if (!strcmp(ibufp, "\n")) 871297Salm cmd = "p\n"; /* null cmd-list == `p' */ 881297Salm else if ((cmd = get_extended_line(&n, 0)) == NULL) 891297Salm return ERR; 901297Salm#else 911297Salm if (!interact && (cmd = get_extended_line(&n, 0)) == NULL) 921297Salm return ERR; 931297Salm#endif 941297Salm clear_undo_stack(); 951297Salm while ((lp = next_active_node()) != NULL) { 961297Salm if ((current_addr = get_line_node_addr(lp)) < 0) 971297Salm return ERR; 981297Salm if (interact) { 991297Salm /* print current_addr; get a command in global syntax */ 1001297Salm if (display_lines(current_addr, current_addr, gflag) < 0) 1011297Salm return ERR; 1021297Salm while ((n = get_tty_line()) > 0 && 1031297Salm ibuf[n - 1] != '\n') 1041297Salm clearerr(stdin); 1051297Salm if (n < 0) 1061297Salm return ERR; 1071297Salm else if (n == 0) { 10881220Smike errmsg = "unexpected end-of-file"; 1091297Salm return ERR; 1101297Salm } else if (n == 1 && !strcmp(ibuf, "\n")) 1111297Salm continue; 1121297Salm else if (n == 2 && !strcmp(ibuf, "&\n")) { 1131297Salm if (cmd == NULL) { 11481220Smike errmsg = "no previous command"; 1151297Salm return ERR; 1161297Salm } else cmd = ocmd; 1171297Salm } else if ((cmd = get_extended_line(&n, 0)) == NULL) 1181297Salm return ERR; 1191297Salm else { 1201297Salm REALLOC(ocmd, ocmdsz, n + 1, ERR); 1211297Salm memcpy(ocmd, cmd, n + 1); 1221297Salm cmd = ocmd; 1231297Salm } 1241297Salm 1251297Salm } 1261297Salm ibufp = cmd; 1271297Salm for (; *ibufp;) 1281297Salm if ((status = extract_addr_range()) < 0 || 1291297Salm (status = exec_command()) < 0 || 1307165Sjoerg (status > 0 && (status = display_lines( 1317165Sjoerg current_addr, current_addr, status)) < 0)) 1321297Salm return status; 1331297Salm } 1341297Salm return 0; 1351297Salm} 1361297Salm 1371297Salm 138241720Sedstatic line_t **active_list; /* list of lines active in a global command */ 139241720Sedstatic long active_last; /* index of last active line in active_list */ 140241720Sedstatic long active_size; /* size of active_list */ 141241720Sedstatic long active_ptr; /* active_list index (non-decreasing) */ 142241720Sedstatic long active_ndx; /* active_list index (modulo active_last) */ 1431297Salm 1441297Salm/* set_active_node: add a line node to the global-active list */ 1451297Salmint 14690109Simpset_active_node(line_t *lp) 1471297Salm{ 1481297Salm if (active_last + 1 > active_size) { 1491297Salm int ti = active_size; 1501297Salm line_t **ts; 1511297Salm SPL1(); 1521297Salm#if defined(sun) || defined(NO_REALLOC_NULL) 1531297Salm if (active_list != NULL) { 1541297Salm#endif 1558855Srgrimes if ((ts = (line_t **) realloc(active_list, 1561297Salm (ti += MINBUFSZ) * sizeof(line_t **))) == NULL) { 1571297Salm fprintf(stderr, "%s\n", strerror(errno)); 15881220Smike errmsg = "out of memory"; 1591297Salm SPL0(); 1601297Salm return ERR; 1611297Salm } 1621297Salm#if defined(sun) || defined(NO_REALLOC_NULL) 1631297Salm } else { 1648855Srgrimes if ((ts = (line_t **) malloc((ti += MINBUFSZ) * 1651297Salm sizeof(line_t **))) == NULL) { 1661297Salm fprintf(stderr, "%s\n", strerror(errno)); 16781220Smike errmsg = "out of memory"; 1681297Salm SPL0(); 1691297Salm return ERR; 1701297Salm } 1711297Salm } 1721297Salm#endif 1731297Salm active_size = ti; 1741297Salm active_list = ts; 1751297Salm SPL0(); 1761297Salm } 1771297Salm active_list[active_last++] = lp; 1781297Salm return 0; 1791297Salm} 1801297Salm 1811297Salm 1821297Salm/* unset_active_nodes: remove a range of lines from the global-active list */ 1831297Salmvoid 18490109Simpunset_active_nodes(line_t *np, line_t *mp) 1851297Salm{ 1861297Salm line_t *lp; 1871297Salm long i; 1881297Salm 1891297Salm for (lp = np; lp != mp; lp = lp->q_forw) 1901297Salm for (i = 0; i < active_last; i++) 1911297Salm if (active_list[active_ndx] == lp) { 1921297Salm active_list[active_ndx] = NULL; 1931297Salm active_ndx = INC_MOD(active_ndx, active_last - 1); 1941297Salm break; 1951297Salm } else active_ndx = INC_MOD(active_ndx, active_last - 1); 1961297Salm} 1971297Salm 1981297Salm 1991297Salm/* next_active_node: return the next global-active line node */ 2001297Salmline_t * 20190109Simpnext_active_node(void) 2021297Salm{ 2031297Salm while (active_ptr < active_last && active_list[active_ptr] == NULL) 2041297Salm active_ptr++; 2051297Salm return (active_ptr < active_last) ? active_list[active_ptr++] : NULL; 2061297Salm} 2071297Salm 2081297Salm 2091297Salm/* clear_active_list: clear the global-active list */ 2101297Salmvoid 21190109Simpclear_active_list(void) 2121297Salm{ 2131297Salm SPL1(); 2141297Salm active_size = active_last = active_ptr = active_ndx = 0; 2151297Salm free(active_list); 2161297Salm active_list = NULL; 2171297Salm SPL0(); 2181297Salm} 219