1/* $NetBSD: hist.c,v 1.22 2019/01/05 16:54:00 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.22 2019/01/05 16:54:00 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
85#ifdef EDIT
86void
87loadhist(struct Hist *hp) {
88    char *h = NULL;
89
90    if (hi == NULL || hp == NULL)
91	return;
92    loadhist(hp->Hnext);
93    if (sprlex(&h, &hp->Hlex) != -1) {
94	HistEvent ev;
95	history(hi, &ev, H_ENTER, h);
96    }
97}
98#endif
99
100struct Hist *
101enthist(int event, struct wordent *lp, int docopy)
102{
103    struct Hist *np;
104
105#ifdef EDIT
106    if (hi) {
107	char *h = NULL;
108	if (sprlex(&h, lp) != -1) {
109	    HistEvent ev;
110	    history(hi, &ev, H_ENTER, h);
111	}
112    }
113#endif
114    np = xmalloc(sizeof(*np));
115    np->Hnum = np->Href = event;
116    if (docopy) {
117	copylex(&np->Hlex, lp);
118    }
119    else {
120	np->Hlex.next = lp->next;
121	lp->next->prev = &np->Hlex;
122	np->Hlex.prev = lp->prev;
123	lp->prev->next = &np->Hlex;
124    }
125    np->Hnext = Histlist.Hnext;
126    Histlist.Hnext = np;
127    return (np);
128}
129
130static void
131hfree(struct Hist *hp)
132{
133    freelex(&hp->Hlex);
134    free(hp);
135}
136
137void
138/*ARGSUSED*/
139dohist(Char **v, struct command *t)
140{
141    sigset_t nsigset;
142    int hflg, n, rflg;
143
144    hflg = 0;
145    rflg = 0;
146
147    if (getn(value(STRhistory)) == 0)
148	return;
149    if (setintr) {
150	sigemptyset(&nsigset);
151	(void)sigaddset(&nsigset, SIGINT);
152	(void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL);
153    }
154    while (*++v && **v == '-') {
155	Char *vp = *v;
156
157	while (*++vp)
158	    switch (*vp) {
159	    case 'h':
160		hflg++;
161		break;
162	    case 'r':
163		rflg++;
164		break;
165	    case '-':		/* ignore multiple '-'s */
166		break;
167	    default:
168		stderror(ERR_HISTUS);
169		/* NOTREACHED */
170	    }
171    }
172    if (*v)
173	n = getn(*v);
174    else {
175	n = getn(value(STRhistory));
176    }
177    dohist1(Histlist.Hnext, &n, rflg, hflg);
178}
179
180static void
181dohist1(struct Hist *hp, int *np, int rflg, int hflg)
182{
183    int print;
184
185    print = (*np) > 0;
186
187    for (; hp != 0; hp = hp->Hnext) {
188	(*np)--;
189	hp->Href++;
190	if (rflg == 0) {
191	    dohist1(hp->Hnext, np, rflg, hflg);
192	    if (print)
193		phist(hp, hflg);
194	    return;
195	}
196	if (*np >= 0)
197	    phist(hp, hflg);
198    }
199}
200
201static void
202phist(struct Hist *hp, int hflg)
203{
204    if (hflg == 0)
205	(void)fprintf(cshout, "%6d\t", hp->Hnum);
206    prlex(cshout, &hp->Hlex);
207}
208