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}
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}