glbl.c revision 1297
1231200Smm/* glob.c: This file contains the global command routines for the ed line 2231200Smm editor */ 3231200Smm/*- 4231200Smm * Copyright (c) 1993 Andrew Moore, Talke Studio. 5231200Smm * All rights reserved. 6231200Smm * 7231200Smm * Redistribution and use in source and binary forms, with or without 8231200Smm * modification, are permitted provided that the following conditions 9231200Smm * are met: 10231200Smm * 1. Redistributions of source code must retain the above copyright 11231200Smm * notice, this list of conditions and the following disclaimer. 12231200Smm * 2. Redistributions in binary form must reproduce the above copyright 13231200Smm * notice, this list of conditions and the following disclaimer in the 14231200Smm * documentation and/or other materials provided with the distribution. 15231200Smm * 16231200Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17231200Smm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18231200Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19231200Smm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20231200Smm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21231200Smm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22231200Smm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23231200Smm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24231200Smm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25231200Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26238856Smm * SUCH DAMAGE. 27231200Smm */ 28231200Smm 29231200Smm#ifndef lint 30231200Smmstatic char *rcsid = "@(#)glob.c,v 1.1 1994/02/01 00:34:40 alm Exp"; 31231200Smm#endif /* not lint */ 32231200Smm 33231200Smm#include <sys/ioctl.h> 34231200Smm#include <sys/wait.h> 35231200Smm 36231200Smm#include "ed.h" 37231200Smm 38231200Smm 39231200Smm/* build_active_list: add line matching a pattern to the global-active list */ 40231200Smmint 41231200Smmbuild_active_list(isgcmd) 42231200Smm int isgcmd; 43231200Smm{ 44231200Smm pattern_t *pat; 45231200Smm line_t *lp; 46231200Smm long n; 47231200Smm char *s; 48231200Smm char delimiter; 49231200Smm 50231200Smm if ((delimiter = *ibufp) == ' ' || delimiter == '\n') { 51231200Smm sprintf(errmsg, "invalid pattern delimiter"); 52231200Smm return ERR; 53231200Smm } else if ((pat = get_compiled_pattern()) == NULL) 54231200Smm return ERR; 55238856Smm else if (*ibufp == delimiter) 56238856Smm ibufp++; 57231200Smm clear_active_list(); 58231200Smm lp = get_addressed_line_node(first_addr); 59231200Smm for (n = first_addr; n <= second_addr; n++, lp = lp->q_forw) { 60231200Smm if ((s = get_sbuf_line(lp)) == NULL) 61231200Smm return ERR; 62231200Smm if (isbinary) 63231200Smm NUL_TO_NEWLINE(s, lp->len); 64231200Smm if (!regexec(pat, s, 0, NULL, 0) == isgcmd && 65231200Smm set_active_node(lp) < 0) 66231200Smm return ERR; 67231200Smm } 68231200Smm return 0; 69231200Smm} 70231200Smm 71231200Smm 72231200Smm/* exec_global: apply command list in the command buffer to the active 73231200Smm lines in a range; return command status */ 74231200Smmlong 75231200Smmexec_global(interact, gflag) 76231200Smm int interact; 77231200Smm int gflag; 78231200Smm{ 79231200Smm static char *ocmd = NULL; 80231200Smm static int ocmdsz = 0; 81231200Smm 82231200Smm line_t *lp = NULL; 83231200Smm int status; 84231200Smm int n; 85231200Smm char *cmd = NULL; 86231200Smm 87231200Smm#ifdef BACKWARDS 88231200Smm if (!interact) 89231200Smm if (!strcmp(ibufp, "\n")) 90231200Smm cmd = "p\n"; /* null cmd-list == `p' */ 91231200Smm else if ((cmd = get_extended_line(&n, 0)) == NULL) 92231200Smm return ERR; 93231200Smm#else 94231200Smm if (!interact && (cmd = get_extended_line(&n, 0)) == NULL) 95231200Smm return ERR; 96231200Smm#endif 97231200Smm clear_undo_stack(); 98231200Smm while ((lp = next_active_node()) != NULL) { 99231200Smm if ((current_addr = get_line_node_addr(lp)) < 0) 100231200Smm return ERR; 101231200Smm if (interact) { 102231200Smm /* print current_addr; get a command in global syntax */ 103231200Smm if (display_lines(current_addr, current_addr, gflag) < 0) 104231200Smm return ERR; 105231200Smm while ((n = get_tty_line()) > 0 && 106231200Smm ibuf[n - 1] != '\n') 107231200Smm clearerr(stdin); 108231200Smm if (n < 0) 109231200Smm return ERR; 110231200Smm else if (n == 0) { 111231200Smm sprintf(errmsg, "unexpected end-of-file"); 112231200Smm return ERR; 113231200Smm } else if (n == 1 && !strcmp(ibuf, "\n")) 114231200Smm continue; 115231200Smm else if (n == 2 && !strcmp(ibuf, "&\n")) { 116231200Smm if (cmd == NULL) { 117231200Smm sprintf(errmsg, "no previous command"); 118231200Smm return ERR; 119231200Smm } else cmd = ocmd; 120231200Smm } else if ((cmd = get_extended_line(&n, 0)) == NULL) 121231200Smm return ERR; 122231200Smm else { 123231200Smm REALLOC(ocmd, ocmdsz, n + 1, ERR); 124231200Smm memcpy(ocmd, cmd, n + 1); 125231200Smm cmd = ocmd; 126231200Smm } 127231200Smm 128231200Smm } 129231200Smm ibufp = cmd; 130231200Smm for (; *ibufp;) 131231200Smm if ((status = extract_addr_range()) < 0 || 132231200Smm (status = exec_command()) < 0 || 133231200Smm status > 0 && (status = display_lines( 134231200Smm current_addr, current_addr, status)) < 0) 135231200Smm return status; 136231200Smm } 137231200Smm return 0; 138231200Smm} 139231200Smm 140231200Smm 141231200Smmline_t **active_list; /* list of lines active in a global command */ 142231200Smmlong active_last; /* index of last active line in active_list */ 143231200Smmlong active_size; /* size of active_list */ 144231200Smmlong active_ptr; /* active_list index (non-decreasing) */ 145231200Smmlong active_ndx; /* active_list index (modulo active_last) */ 146231200Smm 147231200Smm/* set_active_node: add a line node to the global-active list */ 148231200Smmint 149231200Smmset_active_node(lp) 150231200Smm line_t *lp; 151231200Smm{ 152231200Smm if (active_last + 1 > active_size) { 153231200Smm int ti = active_size; 154231200Smm line_t **ts; 155231200Smm SPL1(); 156231200Smm#if defined(sun) || defined(NO_REALLOC_NULL) 157231200Smm if (active_list != NULL) { 158231200Smm#endif 159231200Smm if ((ts = (line_t **) realloc(active_list, 160231200Smm (ti += MINBUFSZ) * sizeof(line_t **))) == NULL) { 161231200Smm fprintf(stderr, "%s\n", strerror(errno)); 162231200Smm sprintf(errmsg, "out of memory"); 163231200Smm SPL0(); 164231200Smm return ERR; 165231200Smm } 166231200Smm#if defined(sun) || defined(NO_REALLOC_NULL) 167231200Smm } else { 168231200Smm if ((ts = (line_t **) malloc((ti += MINBUFSZ) * 169231200Smm sizeof(line_t **))) == NULL) { 170231200Smm fprintf(stderr, "%s\n", strerror(errno)); 171231200Smm sprintf(errmsg, "out of memory"); 172231200Smm SPL0(); 173231200Smm return ERR; 174231200Smm } 175231200Smm } 176231200Smm#endif 177231200Smm active_size = ti; 178231200Smm active_list = ts; 179231200Smm SPL0(); 180231200Smm } 181231200Smm active_list[active_last++] = lp; 182231200Smm return 0; 183231200Smm} 184231200Smm 185231200Smm 186231200Smm/* unset_active_nodes: remove a range of lines from the global-active list */ 187231200Smmvoid 188231200Smmunset_active_nodes(np, mp) 189231200Smm line_t *np, *mp; 190231200Smm{ 191231200Smm line_t *lp; 192231200Smm long i; 193231200Smm 194231200Smm for (lp = np; lp != mp; lp = lp->q_forw) 195231200Smm for (i = 0; i < active_last; i++) 196231200Smm if (active_list[active_ndx] == lp) { 197231200Smm active_list[active_ndx] = NULL; 198231200Smm active_ndx = INC_MOD(active_ndx, active_last - 1); 199231200Smm break; 200231200Smm } else active_ndx = INC_MOD(active_ndx, active_last - 1); 201231200Smm} 202231200Smm 203231200Smm 204231200Smm/* next_active_node: return the next global-active line node */ 205231200Smmline_t * 206231200Smmnext_active_node() 207231200Smm{ 208231200Smm while (active_ptr < active_last && active_list[active_ptr] == NULL) 209231200Smm active_ptr++; 210 return (active_ptr < active_last) ? active_list[active_ptr++] : NULL; 211} 212 213 214/* clear_active_list: clear the global-active list */ 215void 216clear_active_list() 217{ 218 SPL1(); 219 active_size = active_last = active_ptr = active_ndx = 0; 220 free(active_list); 221 active_list = NULL; 222 SPL0(); 223} 224