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