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 --- 37 unchanged lines hidden (view full) --- 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 |
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)); |
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 */ |
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) |
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)); |
88private int history_set_fun __P((History *, History *)); 89private int history_load __P((History *, const char *)); 90private int history_save __P((History *, const char *)); |
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 --- 17 unchanged lines hidden (view full) --- 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)); |
124private void history_def_clear __P((ptr_t)); |
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. --- 94 unchanged lines hidden (view full) --- 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); |
235 (void)strcpy(s, h->cursor->ev.str); /* XXX strcpy is safe */ 236 (void)strcat(s, str); /* XXX strcat is safe */ |
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 --- 75 unchanged lines hidden (view full) --- 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 |
328/* history_def_clear(): |
329 * Default history cleanup function 330 */ 331private void |
332history_def_clear(p) |
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; |
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; |
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) |
376 history_def_clear(h->h_ref); |
377} 378 379 380 381/* history_set_num(): 382 * Set history number of events 383 */ 384private int --- 7 unchanged lines hidden (view full) --- 392 return 0; 393} 394 395 396/* history_set_fun(): 397 * Set history functions 398 */ 399private int |
400history_set_fun(h, nh) 401 History *h, *nh; |
402{ |
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) { |
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; |
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) |
422 history_def_clear(h->h_ref); |
423 |
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; |
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 |
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{ --- 66 unchanged lines hidden (view full) --- 568#else 569history(va_alist) 570 va_dcl 571#endif 572{ 573 va_list va; 574 const HistEvent *ev = NULL; 575 const char *str; |
576 static HistEvent sev = { 0, "" }; |
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 *); --- 26 unchanged lines hidden (view full) --- 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 |
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: |
650 if (history_set_num(h, va_arg(va, int)) == 0) { 651 sev.num = -1; |
652 ev = &sev; |
653 } |
654 break; 655 656 case H_FUNC: 657 { |
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); |
668 |
669 if (history_set_fun(h, &hf) == 0) { 670 sev.num = -1; |
671 ev = &sev; |
672 } |
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} |