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