xref: /netbsd/bin/csh/hist.c (revision bf9ec67e)
1 /* $NetBSD: hist.c,v 1.13 2002/05/25 23:29:16 wiz Exp $ */
2 
3 /*-
4  * Copyright (c) 1980, 1991, 1993
5  *	The Regents of the University of California.  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  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)hist.c	8.1 (Berkeley) 5/31/93";
40 #else
41 __RCSID("$NetBSD: hist.c,v 1.13 2002/05/25 23:29:16 wiz Exp $");
42 #endif
43 #endif /* not lint */
44 
45 #include <sys/types.h>
46 
47 #include <stdarg.h>
48 #include <stdlib.h>
49 
50 #include "csh.h"
51 #include "extern.h"
52 
53 static void hfree(struct Hist *);
54 static void dohist1(struct Hist *, int *, int, int);
55 static void phist(struct Hist *, int);
56 
57 void
58 savehist(struct wordent *sp)
59 {
60     struct Hist *hp, *np;
61     Char *cp;
62     int histlen;
63 
64     histlen = 0;
65 
66     /* throw away null lines */
67     if (sp->next->word[0] == '\n')
68 	return;
69     cp = value(STRhistory);
70     if (*cp) {
71 	Char *p = cp;
72 
73 	while (*p) {
74 	    if (!Isdigit(*p)) {
75 		histlen = 0;
76 		break;
77 	    }
78 	    histlen = histlen * 10 + *p++ - '0';
79 	}
80     }
81     for (hp = &Histlist; (np = hp->Hnext) != NULL;)
82 	if (eventno - np->Href >= histlen || histlen == 0)
83 	    hp->Hnext = np->Hnext, hfree(np);
84 	else
85 	    hp = np;
86     (void) enthist(++eventno, sp, 1);
87 }
88 
89 struct Hist *
90 enthist(int event, struct wordent *lp, bool docopy)
91 {
92     struct Hist *np;
93 
94     np = (struct Hist *)xmalloc((size_t)sizeof(*np));
95     np->Hnum = np->Href = event;
96     if (docopy) {
97 	copylex(&np->Hlex, lp);
98     }
99     else {
100 	np->Hlex.next = lp->next;
101 	lp->next->prev = &np->Hlex;
102 	np->Hlex.prev = lp->prev;
103 	lp->prev->next = &np->Hlex;
104     }
105     np->Hnext = Histlist.Hnext;
106     Histlist.Hnext = np;
107     return (np);
108 }
109 
110 static void
111 hfree(struct Hist *hp)
112 {
113     freelex(&hp->Hlex);
114     xfree((ptr_t) hp);
115 }
116 
117 void
118 /*ARGSUSED*/
119 dohist(Char **v, struct command *t)
120 {
121     sigset_t sigset;
122     int hflg, n, rflg;
123 
124     hflg = 0;
125     rflg = 0;
126 
127     if (getn(value(STRhistory)) == 0)
128 	return;
129     if (setintr) {
130 	sigemptyset(&sigset);
131 	(void)sigaddset(&sigset, SIGINT);
132 	(void)sigprocmask(SIG_UNBLOCK, &sigset, NULL);
133     }
134     while (*++v && **v == '-') {
135 	Char *vp = *v;
136 
137 	while (*++vp)
138 	    switch (*vp) {
139 	    case 'h':
140 		hflg++;
141 		break;
142 	    case 'r':
143 		rflg++;
144 		break;
145 	    case '-':		/* ignore multiple '-'s */
146 		break;
147 	    default:
148 		stderror(ERR_HISTUS);
149 		/* NOTREACHED */
150 	    }
151     }
152     if (*v)
153 	n = getn(*v);
154     else {
155 	n = getn(value(STRhistory));
156     }
157     dohist1(Histlist.Hnext, &n, rflg, hflg);
158 }
159 
160 static void
161 dohist1(struct Hist *hp, int *np, int rflg, int hflg)
162 {
163     bool print;
164 
165     print = (*np) > 0;
166 
167     for (; hp != 0; hp = hp->Hnext) {
168 	(*np)--;
169 	hp->Href++;
170 	if (rflg == 0) {
171 	    dohist1(hp->Hnext, np, rflg, hflg);
172 	    if (print)
173 		phist(hp, hflg);
174 	    return;
175 	}
176 	if (*np >= 0)
177 	    phist(hp, hflg);
178     }
179 }
180 
181 static void
182 phist(struct Hist *hp, int hflg)
183 {
184     if (hflg == 0)
185 	(void)fprintf(cshout, "%6d\t", hp->Hnum);
186     prlex(cshout, &hp->Hlex);
187 }
188