1/*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Christos Zoulas of Cornell University. 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. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#if !defined(lint) && !defined(SCCSID) 38static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; 39#endif /* not lint && not SCCSID */ 40 41/* 42 * hist.c: History access functions 43 */ 44#include "sys.h" 45 46#include <string.h> 47#include <stdlib.h> 48#if __STDC__ 49#include <stdarg.h> 50#else 51#include <varargs.h> 52#endif 53
| 1/*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Christos Zoulas of Cornell University. 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. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#if !defined(lint) && !defined(SCCSID) 38static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; 39#endif /* not lint && not SCCSID */ 40 41/* 42 * hist.c: History access functions 43 */ 44#include "sys.h" 45 46#include <string.h> 47#include <stdlib.h> 48#if __STDC__ 49#include <stdarg.h> 50#else 51#include <varargs.h> 52#endif 53
|
| 54static const char hist_cookie[] = "_HiStOrY_V1_\n"; 55
|
54#include "histedit.h" 55 56typedef const HistEvent * (*history_gfun_t) __P((ptr_t)); 57typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));
| 56#include "histedit.h" 57 58typedef const HistEvent * (*history_gfun_t) __P((ptr_t)); 59typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));
|
| 60typedef void (*history_vfun_t) __P((ptr_t));
|
58 59struct history { 60 ptr_t h_ref; /* Argument for history fcns */ 61 history_gfun_t h_first; /* Get the first element */ 62 history_gfun_t h_next; /* Get the next element */ 63 history_gfun_t h_last; /* Get the last element */ 64 history_gfun_t h_prev; /* Get the previous element */ 65 history_gfun_t h_curr; /* Get the current element */
| 61 62struct history { 63 ptr_t h_ref; /* Argument for history fcns */ 64 history_gfun_t h_first; /* Get the first element */ 65 history_gfun_t h_next; /* Get the next element */ 66 history_gfun_t h_last; /* Get the last element */ 67 history_gfun_t h_prev; /* Get the previous element */ 68 history_gfun_t h_curr; /* Get the current element */
|
| 69 history_vfun_t h_clear; /* Clear the history list */
|
66 history_efun_t h_enter; /* Add an element */ 67 history_efun_t h_add; /* Append to an element */ 68}; 69 70#define HNEXT(h) (*(h)->h_next)((h)->h_ref) 71#define HFIRST(h) (*(h)->h_first)((h)->h_ref) 72#define HPREV(h) (*(h)->h_prev)((h)->h_ref) 73#define HLAST(h) (*(h)->h_last)((h)->h_ref) 74#define HCURR(h) (*(h)->h_curr)((h)->h_ref)
| 70 history_efun_t h_enter; /* Add an element */ 71 history_efun_t h_add; /* Append to an element */ 72}; 73 74#define HNEXT(h) (*(h)->h_next)((h)->h_ref) 75#define HFIRST(h) (*(h)->h_first)((h)->h_ref) 76#define HPREV(h) (*(h)->h_prev)((h)->h_ref) 77#define HLAST(h) (*(h)->h_last)((h)->h_ref) 78#define HCURR(h) (*(h)->h_curr)((h)->h_ref)
|
| 79#define HCLEAR(h) (*(h)->h_clear)((h)->h_ref)
|
75#define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str) 76#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str) 77 78#define h_malloc(a) malloc(a) 79#define h_free(a) free(a) 80 81 82private int history_set_num __P((History *, int));
| 80#define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str) 81#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str) 82 83#define h_malloc(a) malloc(a) 84#define h_free(a) free(a) 85 86 87private int history_set_num __P((History *, int));
|
83private int history_set_fun __P((History *, history_gfun_t, 84 history_gfun_t, 85 history_gfun_t, 86 history_gfun_t, 87 history_gfun_t, 88 history_efun_t, 89 history_efun_t, ptr_t));
| 88private int history_set_fun __P((History *, History *)); 89private int history_load __P((History *, const char *)); 90private int history_save __P((History *, const char *));
|
90private const HistEvent *history_prev_event __P((History *, int)); 91private const HistEvent *history_next_event __P((History *, int)); 92private const HistEvent *history_next_string __P((History *, const char *)); 93private const HistEvent *history_prev_string __P((History *, const char *)); 94 95 96/***********************************************************************/ 97 98/* 99 * Builtin- history implementation 100 */ 101typedef struct hentry_t { 102 HistEvent ev; /* What we return */ 103 struct hentry_t *next; /* Next entry */ 104 struct hentry_t *prev; /* Previous entry */ 105} hentry_t; 106 107typedef struct history_t { 108 hentry_t list; /* Fake list header element */ 109 hentry_t *cursor; /* Current element in the list */ 110 int max; /* Maximum number of events */ 111 int cur; /* Current number of events */ 112 int eventno; /* Current event number */ 113} history_t; 114 115private const HistEvent *history_def_first __P((ptr_t)); 116private const HistEvent *history_def_last __P((ptr_t)); 117private const HistEvent *history_def_next __P((ptr_t)); 118private const HistEvent *history_def_prev __P((ptr_t)); 119private const HistEvent *history_def_curr __P((ptr_t)); 120private const HistEvent *history_def_enter __P((ptr_t, const char *)); 121private const HistEvent *history_def_add __P((ptr_t, const char *)); 122private void history_def_init __P((ptr_t *, int));
| 91private const HistEvent *history_prev_event __P((History *, int)); 92private const HistEvent *history_next_event __P((History *, int)); 93private const HistEvent *history_next_string __P((History *, const char *)); 94private const HistEvent *history_prev_string __P((History *, const char *)); 95 96 97/***********************************************************************/ 98 99/* 100 * Builtin- history implementation 101 */ 102typedef struct hentry_t { 103 HistEvent ev; /* What we return */ 104 struct hentry_t *next; /* Next entry */ 105 struct hentry_t *prev; /* Previous entry */ 106} hentry_t; 107 108typedef struct history_t { 109 hentry_t list; /* Fake list header element */ 110 hentry_t *cursor; /* Current element in the list */ 111 int max; /* Maximum number of events */ 112 int cur; /* Current number of events */ 113 int eventno; /* Current event number */ 114} history_t; 115 116private const HistEvent *history_def_first __P((ptr_t)); 117private const HistEvent *history_def_last __P((ptr_t)); 118private const HistEvent *history_def_next __P((ptr_t)); 119private const HistEvent *history_def_prev __P((ptr_t)); 120private const HistEvent *history_def_curr __P((ptr_t)); 121private const HistEvent *history_def_enter __P((ptr_t, const char *)); 122private const HistEvent *history_def_add __P((ptr_t, const char *)); 123private void history_def_init __P((ptr_t *, int));
|
123private void history_def_end __P((ptr_t));
| 124private void history_def_clear __P((ptr_t));
|
124private const HistEvent *history_def_insert __P((history_t *, const char *)); 125private void history_def_delete __P((history_t *, hentry_t *)); 126 127#define history_def_set(p, num) (void) (((history_t *) p)->max = (num)) 128 129 130/* history_def_first(): 131 * Default function to return the first event in the history. 132 */ 133private const HistEvent * 134history_def_first(p) 135 ptr_t p; 136{ 137 history_t *h = (history_t *) p; 138 h->cursor = h->list.next; 139 if (h->cursor != &h->list) 140 return &h->cursor->ev; 141 else 142 return NULL; 143} 144 145/* history_def_last(): 146 * Default function to return the last event in the history. 147 */ 148private const HistEvent * 149history_def_last(p) 150 ptr_t p; 151{ 152 history_t *h = (history_t *) p; 153 h->cursor = h->list.prev; 154 if (h->cursor != &h->list) 155 return &h->cursor->ev; 156 else 157 return NULL; 158} 159 160/* history_def_next(): 161 * Default function to return the next event in the history. 162 */ 163private const HistEvent * 164history_def_next(p) 165 ptr_t p; 166{ 167 history_t *h = (history_t *) p; 168 169 if (h->cursor != &h->list) 170 h->cursor = h->cursor->next; 171 else 172 return NULL; 173 174 if (h->cursor != &h->list) 175 return &h->cursor->ev; 176 else 177 return NULL; 178} 179 180 181/* history_def_prev(): 182 * Default function to return the previous event in the history. 183 */ 184private const HistEvent * 185history_def_prev(p) 186 ptr_t p; 187{ 188 history_t *h = (history_t *) p; 189 190 if (h->cursor != &h->list) 191 h->cursor = h->cursor->prev; 192 else 193 return NULL; 194 195 if (h->cursor != &h->list) 196 return &h->cursor->ev; 197 else 198 return NULL; 199} 200 201 202/* history_def_curr(): 203 * Default function to return the current event in the history. 204 */ 205private const HistEvent * 206history_def_curr(p) 207 ptr_t p; 208{ 209 history_t *h = (history_t *) p; 210 211 if (h->cursor != &h->list) 212 return &h->cursor->ev; 213 else 214 return NULL; 215} 216 217 218/* history_def_add(): 219 * Append string to element 220 */ 221private const HistEvent * 222history_def_add(p, str) 223 ptr_t p; 224 const char *str; 225{ 226 history_t *h = (history_t *) p; 227 size_t len; 228 char *s; 229 230 if (h->cursor == &h->list) 231 return (history_def_enter(p, str)); 232 len = strlen(h->cursor->ev.str) + strlen(str) + 1; 233 s = (char *) h_malloc(len);
| 125private const HistEvent *history_def_insert __P((history_t *, const char *)); 126private void history_def_delete __P((history_t *, hentry_t *)); 127 128#define history_def_set(p, num) (void) (((history_t *) p)->max = (num)) 129 130 131/* history_def_first(): 132 * Default function to return the first event in the history. 133 */ 134private const HistEvent * 135history_def_first(p) 136 ptr_t p; 137{ 138 history_t *h = (history_t *) p; 139 h->cursor = h->list.next; 140 if (h->cursor != &h->list) 141 return &h->cursor->ev; 142 else 143 return NULL; 144} 145 146/* history_def_last(): 147 * Default function to return the last event in the history. 148 */ 149private const HistEvent * 150history_def_last(p) 151 ptr_t p; 152{ 153 history_t *h = (history_t *) p; 154 h->cursor = h->list.prev; 155 if (h->cursor != &h->list) 156 return &h->cursor->ev; 157 else 158 return NULL; 159} 160 161/* history_def_next(): 162 * Default function to return the next event in the history. 163 */ 164private const HistEvent * 165history_def_next(p) 166 ptr_t p; 167{ 168 history_t *h = (history_t *) p; 169 170 if (h->cursor != &h->list) 171 h->cursor = h->cursor->next; 172 else 173 return NULL; 174 175 if (h->cursor != &h->list) 176 return &h->cursor->ev; 177 else 178 return NULL; 179} 180 181 182/* history_def_prev(): 183 * Default function to return the previous event in the history. 184 */ 185private const HistEvent * 186history_def_prev(p) 187 ptr_t p; 188{ 189 history_t *h = (history_t *) p; 190 191 if (h->cursor != &h->list) 192 h->cursor = h->cursor->prev; 193 else 194 return NULL; 195 196 if (h->cursor != &h->list) 197 return &h->cursor->ev; 198 else 199 return NULL; 200} 201 202 203/* history_def_curr(): 204 * Default function to return the current event in the history. 205 */ 206private const HistEvent * 207history_def_curr(p) 208 ptr_t p; 209{ 210 history_t *h = (history_t *) p; 211 212 if (h->cursor != &h->list) 213 return &h->cursor->ev; 214 else 215 return NULL; 216} 217 218 219/* history_def_add(): 220 * Append string to element 221 */ 222private const HistEvent * 223history_def_add(p, str) 224 ptr_t p; 225 const char *str; 226{ 227 history_t *h = (history_t *) p; 228 size_t len; 229 char *s; 230 231 if (h->cursor == &h->list) 232 return (history_def_enter(p, str)); 233 len = strlen(h->cursor->ev.str) + strlen(str) + 1; 234 s = (char *) h_malloc(len);
|
234 (void) strcpy(s, h->cursor->ev.str); 235 (void) strcat(s, str);
| 235 (void)strcpy(s, h->cursor->ev.str); /* XXX strcpy is safe */ 236 (void)strcat(s, str); /* XXX strcat is safe */
|
236 h_free((ptr_t) h->cursor->ev.str); 237 h->cursor->ev.str = s; 238 return &h->cursor->ev; 239} 240 241 242/* history_def_delete(): 243 * Delete element hp of the h list 244 */ 245private void 246history_def_delete(h, hp) 247 history_t *h; 248 hentry_t *hp; 249{ 250 if (hp == &h->list) 251 abort(); 252 hp->prev->next = hp->next; 253 hp->next->prev = hp->prev; 254 h_free((ptr_t) hp->ev.str); 255 h_free(hp); 256 h->cur--; 257} 258 259 260/* history_def_insert(): 261 * Insert element with string str in the h list 262 */ 263private const HistEvent * 264history_def_insert(h, str) 265 history_t *h; 266 const char *str; 267{ 268 h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); 269 h->cursor->ev.str = strdup(str); 270 h->cursor->next = h->list.next; 271 h->cursor->prev = &h->list; 272 h->list.next->prev = h->cursor; 273 h->list.next = h->cursor; 274 h->cur++; 275 276 return &h->cursor->ev; 277} 278 279 280/* history_def_enter(): 281 * Default function to enter an item in the history 282 */ 283private const HistEvent * 284history_def_enter(p, str) 285 ptr_t p; 286 const char *str; 287{ 288 history_t *h = (history_t *) p; 289 const HistEvent *ev; 290 291 292 ev = history_def_insert(h, str); 293 ((HistEvent*) ev)->num = ++h->eventno; 294 295 /* 296 * Always keep at least one entry. 297 * This way we don't have to check for the empty list. 298 */ 299 while (h->cur > h->max + 1) 300 history_def_delete(h, h->list.prev); 301 return ev; 302} 303 304 305/* history_def_init(): 306 * Default history initialization function 307 */ 308private void 309history_def_init(p, n) 310 ptr_t *p; 311 int n; 312{ 313 history_t *h = (history_t *) h_malloc(sizeof(history_t)); 314 if (n <= 0) 315 n = 0; 316 h->eventno = 0; 317 h->cur = 0; 318 h->max = n; 319 h->list.next = h->list.prev = &h->list; 320 h->list.ev.str = NULL; 321 h->list.ev.num = 0; 322 h->cursor = &h->list; 323 *p = (ptr_t) h; 324} 325 326
| 237 h_free((ptr_t) h->cursor->ev.str); 238 h->cursor->ev.str = s; 239 return &h->cursor->ev; 240} 241 242 243/* history_def_delete(): 244 * Delete element hp of the h list 245 */ 246private void 247history_def_delete(h, hp) 248 history_t *h; 249 hentry_t *hp; 250{ 251 if (hp == &h->list) 252 abort(); 253 hp->prev->next = hp->next; 254 hp->next->prev = hp->prev; 255 h_free((ptr_t) hp->ev.str); 256 h_free(hp); 257 h->cur--; 258} 259 260 261/* history_def_insert(): 262 * Insert element with string str in the h list 263 */ 264private const HistEvent * 265history_def_insert(h, str) 266 history_t *h; 267 const char *str; 268{ 269 h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); 270 h->cursor->ev.str = strdup(str); 271 h->cursor->next = h->list.next; 272 h->cursor->prev = &h->list; 273 h->list.next->prev = h->cursor; 274 h->list.next = h->cursor; 275 h->cur++; 276 277 return &h->cursor->ev; 278} 279 280 281/* history_def_enter(): 282 * Default function to enter an item in the history 283 */ 284private const HistEvent * 285history_def_enter(p, str) 286 ptr_t p; 287 const char *str; 288{ 289 history_t *h = (history_t *) p; 290 const HistEvent *ev; 291 292 293 ev = history_def_insert(h, str); 294 ((HistEvent*) ev)->num = ++h->eventno; 295 296 /* 297 * Always keep at least one entry. 298 * This way we don't have to check for the empty list. 299 */ 300 while (h->cur > h->max + 1) 301 history_def_delete(h, h->list.prev); 302 return ev; 303} 304 305 306/* history_def_init(): 307 * Default history initialization function 308 */ 309private void 310history_def_init(p, n) 311 ptr_t *p; 312 int n; 313{ 314 history_t *h = (history_t *) h_malloc(sizeof(history_t)); 315 if (n <= 0) 316 n = 0; 317 h->eventno = 0; 318 h->cur = 0; 319 h->max = n; 320 h->list.next = h->list.prev = &h->list; 321 h->list.ev.str = NULL; 322 h->list.ev.num = 0; 323 h->cursor = &h->list; 324 *p = (ptr_t) h; 325} 326 327
|
327/* history_def_end():
| 328/* history_def_clear():
|
328 * Default history cleanup function 329 */ 330private void
| 329 * Default history cleanup function 330 */ 331private void
|
331history_def_end(p)
| 332history_def_clear(p)
|
332 ptr_t p; 333{ 334 history_t *h = (history_t *) p; 335 336 while (h->list.prev != &h->list) 337 history_def_delete(h, h->list.prev);
| 333 ptr_t p; 334{ 335 history_t *h = (history_t *) p; 336 337 while (h->list.prev != &h->list) 338 history_def_delete(h, h->list.prev);
|
| 339 h->eventno = 0; 340 h->cur = 0;
|
338} 339 340/************************************************************************/ 341 342/* history_init(): 343 * Initialization function. 344 */ 345public History * 346history_init() 347{ 348 History *h = (History *) h_malloc(sizeof(History)); 349 350 history_def_init(&h->h_ref, 0); 351 352 h->h_next = history_def_next; 353 h->h_first = history_def_first; 354 h->h_last = history_def_last; 355 h->h_prev = history_def_prev; 356 h->h_curr = history_def_curr;
| 341} 342 343/************************************************************************/ 344 345/* history_init(): 346 * Initialization function. 347 */ 348public History * 349history_init() 350{ 351 History *h = (History *) h_malloc(sizeof(History)); 352 353 history_def_init(&h->h_ref, 0); 354 355 h->h_next = history_def_next; 356 h->h_first = history_def_first; 357 h->h_last = history_def_last; 358 h->h_prev = history_def_prev; 359 h->h_curr = history_def_curr;
|
| 360 h->h_clear = history_def_clear;
|
357 h->h_enter = history_def_enter; 358 h->h_add = history_def_add; 359 360 return h; 361} 362 363 364/* history_end(): 365 * clean up history; 366 */ 367public void 368history_end(h) 369 History *h; 370{ 371 if (h->h_next == history_def_next)
| 361 h->h_enter = history_def_enter; 362 h->h_add = history_def_add; 363 364 return h; 365} 366 367 368/* history_end(): 369 * clean up history; 370 */ 371public void 372history_end(h) 373 History *h; 374{ 375 if (h->h_next == history_def_next)
|
372 history_def_end(h->h_ref);
| 376 history_def_clear(h->h_ref);
|
373} 374 375 376 377/* history_set_num(): 378 * Set history number of events 379 */ 380private int 381history_set_num(h, num) 382 History *h; 383 int num; 384{ 385 if (h->h_next != history_def_next || num < 0) 386 return -1; 387 history_def_set(h->h_ref, num); 388 return 0; 389} 390 391 392/* history_set_fun(): 393 * Set history functions 394 */ 395private int
| 377} 378 379 380 381/* history_set_num(): 382 * Set history number of events 383 */ 384private int 385history_set_num(h, num) 386 History *h; 387 int num; 388{ 389 if (h->h_next != history_def_next || num < 0) 390 return -1; 391 history_def_set(h->h_ref, num); 392 return 0; 393} 394 395 396/* history_set_fun(): 397 * Set history functions 398 */ 399private int
|
396history_set_fun(h, first, next, last, prev, curr, enter, add, ptr) 397 History *h; 398 history_gfun_t first, next, last, prev, curr; 399 history_efun_t enter, add; 400 ptr_t ptr;
| 400history_set_fun(h, nh) 401 History *h, *nh;
|
401{
| 402{
|
402 if (first == NULL || next == NULL || 403 last == NULL || prev == NULL || curr == NULL || 404 enter == NULL || add == NULL || 405 ptr == NULL ) {
| 403 if (nh->h_first == NULL || nh->h_next == NULL || 404 nh->h_last == NULL || nh->h_prev == NULL || nh->h_curr == NULL || 405 nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL || 406 nh->h_ref == NULL) {
|
406 if (h->h_next != history_def_next) { 407 history_def_init(&h->h_ref, 0); 408 h->h_first = history_def_first; 409 h->h_next = history_def_next; 410 h->h_last = history_def_last; 411 h->h_prev = history_def_prev; 412 h->h_curr = history_def_curr;
| 407 if (h->h_next != history_def_next) { 408 history_def_init(&h->h_ref, 0); 409 h->h_first = history_def_first; 410 h->h_next = history_def_next; 411 h->h_last = history_def_last; 412 h->h_prev = history_def_prev; 413 h->h_curr = history_def_curr;
|
| 414 h->h_clear = history_def_clear;
|
413 h->h_enter = history_def_enter; 414 h->h_add = history_def_add; 415 } 416 return -1; 417 } 418 419 if (h->h_next == history_def_next)
| 415 h->h_enter = history_def_enter; 416 h->h_add = history_def_add; 417 } 418 return -1; 419 } 420 421 if (h->h_next == history_def_next)
|
420 history_def_end(h->h_ref);
| 422 history_def_clear(h->h_ref);
|
421
| 423
|
422 h->h_next = next; 423 h->h_first = first; 424 h->h_enter = enter; 425 h->h_add = add;
| 424 h->h_first = nh->h_first; 425 h->h_next = nh->h_next; 426 h->h_last = nh->h_last; 427 h->h_prev = nh->h_prev; 428 h->h_curr = nh->h_curr; 429 h->h_clear = nh->h_clear; 430 h->h_enter = nh->h_enter; 431 h->h_add = nh->h_add;
|
426 return 0; 427} 428 429
| 432 return 0; 433} 434 435
|
| 436/* history_load(): 437 * History load function 438 */ 439private int 440history_load(h, fname) 441 History *h; 442 const char *fname; 443{ 444 FILE *fp; 445 char *line; 446 size_t sz; 447 int i = -1; 448 449 if ((fp = fopen(fname, "r")) == NULL) 450 return i; 451 452 if ((line = fgetln(fp, &sz)) == NULL) 453 goto done; 454 455 if (strncmp(line, hist_cookie, sz) != 0) 456 goto done; 457 458 for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) { 459 char c = line[sz]; 460 line[sz] = '\0'; 461 HENTER(h, line); 462 line[sz] = c; 463 } 464 465done: 466 (void) fclose(fp); 467 return i; 468} 469 470 471/* history_save(): 472 * History save function 473 */ 474private int 475history_save(h, fname) 476 History *h; 477 const char *fname; 478{ 479 FILE *fp; 480 const HistEvent *ev; 481 int i = 0; 482 483 if ((fp = fopen(fname, "w")) == NULL) 484 return -1; 485 486 (void) fputs(hist_cookie, fp); 487 for (ev = HLAST(h); ev != NULL; ev = HPREV(h), i++) 488 (void) fprintf(fp, "%s", ev->str); 489 (void) fclose(fp); 490 return i; 491} 492 493
|
430/* history_prev_event(): 431 * Find the previous event, with number given 432 */ 433private const HistEvent * 434history_prev_event(h, num) 435 History *h; 436 int num; 437{ 438 const HistEvent *ev; 439 for (ev = HCURR(h); ev != NULL; ev = HPREV(h)) 440 if (ev->num == num) 441 return ev; 442 return NULL; 443} 444 445 446/* history_next_event(): 447 * Find the next event, with number given 448 */ 449private const HistEvent * 450history_next_event(h, num) 451 History *h; 452 int num; 453{ 454 const HistEvent *ev; 455 for (ev = HCURR(h); ev != NULL; ev = HNEXT(h)) 456 if (ev->num == num) 457 return ev; 458 return NULL; 459} 460 461 462/* history_prev_string(): 463 * Find the previous event beginning with string 464 */ 465private const HistEvent * 466history_prev_string(h, str) 467 History *h; 468 const char* str; 469{ 470 const HistEvent *ev; 471 size_t len = strlen(str); 472 473 for (ev = HCURR(h); ev != NULL; ev = HNEXT(h)) 474 if (strncmp(str, ev->str, len) == 0) 475 return ev; 476 return NULL; 477} 478 479 480/* history_next_string(): 481 * Find the next event beginning with string 482 */ 483private const HistEvent * 484history_next_string(h, str) 485 History *h; 486 const char* str; 487{ 488 const HistEvent *ev; 489 size_t len = strlen(str); 490 491 for (ev = HCURR(h); ev != NULL; ev = HPREV(h)) 492 if (strncmp(str, ev->str, len) == 0) 493 return ev; 494 return NULL; 495} 496 497 498/* history(): 499 * User interface to history functions. 500 */ 501const HistEvent * 502#if __STDC__ 503history(History *h, int fun, ...) 504#else 505history(va_alist) 506 va_dcl 507#endif 508{ 509 va_list va; 510 const HistEvent *ev = NULL; 511 const char *str;
| 494/* history_prev_event(): 495 * Find the previous event, with number given 496 */ 497private const HistEvent * 498history_prev_event(h, num) 499 History *h; 500 int num; 501{ 502 const HistEvent *ev; 503 for (ev = HCURR(h); ev != NULL; ev = HPREV(h)) 504 if (ev->num == num) 505 return ev; 506 return NULL; 507} 508 509 510/* history_next_event(): 511 * Find the next event, with number given 512 */ 513private const HistEvent * 514history_next_event(h, num) 515 History *h; 516 int num; 517{ 518 const HistEvent *ev; 519 for (ev = HCURR(h); ev != NULL; ev = HNEXT(h)) 520 if (ev->num == num) 521 return ev; 522 return NULL; 523} 524 525 526/* history_prev_string(): 527 * Find the previous event beginning with string 528 */ 529private const HistEvent * 530history_prev_string(h, str) 531 History *h; 532 const char* str; 533{ 534 const HistEvent *ev; 535 size_t len = strlen(str); 536 537 for (ev = HCURR(h); ev != NULL; ev = HNEXT(h)) 538 if (strncmp(str, ev->str, len) == 0) 539 return ev; 540 return NULL; 541} 542 543 544/* history_next_string(): 545 * Find the next event beginning with string 546 */ 547private const HistEvent * 548history_next_string(h, str) 549 History *h; 550 const char* str; 551{ 552 const HistEvent *ev; 553 size_t len = strlen(str); 554 555 for (ev = HCURR(h); ev != NULL; ev = HPREV(h)) 556 if (strncmp(str, ev->str, len) == 0) 557 return ev; 558 return NULL; 559} 560 561 562/* history(): 563 * User interface to history functions. 564 */ 565const HistEvent * 566#if __STDC__ 567history(History *h, int fun, ...) 568#else 569history(va_alist) 570 va_dcl 571#endif 572{ 573 va_list va; 574 const HistEvent *ev = NULL; 575 const char *str;
|
512 static const HistEvent sev = { 0, "" };
| 576 static HistEvent sev = { 0, "" };
|
513 514#if __STDC__ 515 va_start(va, fun); 516#else 517 History *h; 518 int fun; 519 va_start(va); 520 h = va_arg(va, History *); 521 fun = va_arg(va, int); 522#endif 523 524 switch (fun) { 525 case H_ADD: 526 str = va_arg(va, const char *); 527 ev = HADD(h, str); 528 break; 529 530 case H_ENTER: 531 str = va_arg(va, const char *); 532 ev = HENTER(h, str); 533 break; 534 535 case H_FIRST: 536 ev = HFIRST(h); 537 break; 538 539 case H_NEXT: 540 ev = HNEXT(h); 541 break; 542 543 case H_LAST: 544 ev = HLAST(h); 545 break; 546 547 case H_PREV: 548 ev = HPREV(h); 549 break; 550 551 case H_CURR: 552 ev = HCURR(h); 553 break; 554
| 577 578#if __STDC__ 579 va_start(va, fun); 580#else 581 History *h; 582 int fun; 583 va_start(va); 584 h = va_arg(va, History *); 585 fun = va_arg(va, int); 586#endif 587 588 switch (fun) { 589 case H_ADD: 590 str = va_arg(va, const char *); 591 ev = HADD(h, str); 592 break; 593 594 case H_ENTER: 595 str = va_arg(va, const char *); 596 ev = HENTER(h, str); 597 break; 598 599 case H_FIRST: 600 ev = HFIRST(h); 601 break; 602 603 case H_NEXT: 604 ev = HNEXT(h); 605 break; 606 607 case H_LAST: 608 ev = HLAST(h); 609 break; 610 611 case H_PREV: 612 ev = HPREV(h); 613 break; 614 615 case H_CURR: 616 ev = HCURR(h); 617 break; 618
|
| 619 case H_CLEAR: 620 HCLEAR(h); 621 break; 622 623 case H_LOAD: 624 sev.num = history_load(h, va_arg(va, const char *)); 625 ev = &sev; 626 break; 627 628 case H_SAVE: 629 sev.num = history_save(h, va_arg(va, const char *)); 630 ev = &sev; 631 break; 632
|
555 case H_PREV_EVENT: 556 ev = history_prev_event(h, va_arg(va, int)); 557 break; 558 559 case H_NEXT_EVENT: 560 ev = history_next_event(h, va_arg(va, int)); 561 break; 562 563 case H_PREV_STR: 564 ev = history_prev_string(h, va_arg(va, const char*)); 565 break; 566 567 case H_NEXT_STR: 568 ev = history_next_string(h, va_arg(va, const char*)); 569 break; 570 571 case H_EVENT:
| 633 case H_PREV_EVENT: 634 ev = history_prev_event(h, va_arg(va, int)); 635 break; 636 637 case H_NEXT_EVENT: 638 ev = history_next_event(h, va_arg(va, int)); 639 break; 640 641 case H_PREV_STR: 642 ev = history_prev_string(h, va_arg(va, const char*)); 643 break; 644 645 case H_NEXT_STR: 646 ev = history_next_string(h, va_arg(va, const char*)); 647 break; 648 649 case H_EVENT:
|
572 if (history_set_num(h, va_arg(va, int)) == 0)
| 650 if (history_set_num(h, va_arg(va, int)) == 0) { 651 sev.num = -1;
|
573 ev = &sev;
| 652 ev = &sev;
|
| 653 }
|
574 break; 575 576 case H_FUNC: 577 {
| 654 break; 655 656 case H_FUNC: 657 {
|
578 history_gfun_t first = va_arg(va, history_gfun_t); 579 history_gfun_t next = va_arg(va, history_gfun_t); 580 history_gfun_t last = va_arg(va, history_gfun_t); 581 history_gfun_t prev = va_arg(va, history_gfun_t); 582 history_gfun_t curr = va_arg(va, history_gfun_t); 583 history_efun_t enter = va_arg(va, history_efun_t); 584 history_efun_t add = va_arg(va, history_efun_t); 585 ptr_t ptr = va_arg(va, ptr_t);
| 658 History hf; 659 hf.h_ref = va_arg(va, ptr_t); 660 hf.h_first = va_arg(va, history_gfun_t); 661 hf.h_next = va_arg(va, history_gfun_t); 662 hf.h_last = va_arg(va, history_gfun_t); 663 hf.h_prev = va_arg(va, history_gfun_t); 664 hf.h_curr = va_arg(va, history_gfun_t); 665 hf.h_clear = va_arg(va, history_vfun_t); 666 hf.h_enter = va_arg(va, history_efun_t); 667 hf.h_add = va_arg(va, history_efun_t);
|
586
| 668
|
587 if (history_set_fun(h, first, next, last, prev, 588 curr, enter, add, ptr) == 0)
| 669 if (history_set_fun(h, &hf) == 0) { 670 sev.num = -1;
|
589 ev = &sev;
| 671 ev = &sev;
|
| 672 }
|
590 } 591 break; 592 593 case H_END: 594 history_end(h); 595 break; 596 597 default: 598 break; 599 } 600 va_end(va); 601 return ev; 602}
| 673 } 674 break; 675 676 case H_END: 677 history_end(h); 678 break; 679 680 default: 681 break; 682 } 683 va_end(va); 684 return ev; 685}
|