glbl.c

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

Generated by GNU Enscript 1.6.6.