Annotation of OpenXM_contrib2/fep/fep_hist.c, Revision 1.3
1.1 noro 1: /* Copyright (c) 1987, 1988 by Software Research Associates, Inc. */
2:
3: #ifndef lint
4: static char rcsid[]=
5: "$Header: fep_hist.c,v 4.3 88/11/25 20:45:25 utashiro Exp $ (SRA)";
6: #endif /* lint */
7:
8: #include <stdio.h>
9: #include <stdlib.h>
10: #include <unistd.h>
11: #include <ctype.h>
12: #include "fep_defs.h"
13: #include "fep_glob.h"
14: #include "fep_funcs.h"
15:
1.3 ! noro 16: #if defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__APPLE_CC__)
1.2 noro 17: #include <regex.h>
18: regex_t Re_pat;
19: #define re_comp(p) (regcomp(&Re_pat,(p), REG_EXTENDED|REG_NOSUB))
20: #define re_exec(p) (!regexec(&Re_pat, (p), 0 , NULL, 0))
21: #else
22: char *re_comp();
1.1 noro 23: #endif
24:
25: char **HistoryTable;
26: int TopOfHist;
27: int TailOfHist;
28: int CurrentHist;
29: int HistorySize;
30:
31: int uniqline = 1;
32:
33: char *getOldestHistory();
34: char *getYoungestHistory();
35:
36: char *argv[MAXARGS];
37: int argc;
38:
39: init_hist(size)
40: int size;
41: {
42: char *itoa();
43:
44: TopOfHist = 0;
45: TailOfHist = 0;
46: CurrentHist = 0;
47: HistorySize = size;
48:
49: /*
50: * "set_var" will call "changeHistorySize" function for initilize
51: * history table.
52: */
53: set_var ("history", itoa (HistorySize));
54: }
55:
56: char *
57: itoa (i)
58: int i;
59: {
60: static char buf[64];
61:
62: sprintf (buf, "%d", i);
63: return (buf);
64: }
65:
66: addHistory(string)
67: char *string;
68: {
69: char *allocAndCopyThere();
70: char *prev;
71: int slen;
72:
73: if (HistorySize <= 0)
74: return;
75:
76: CurrentHist = TailOfHist;
77: prev = getYoungestHistory ();
78: if (look_var ("ignore-same-line") && prev && !strcmp (string, prev))
79: return;
80: if ((slen = lookd_var ("ignore-short-line"))>0 && strlen (string) <= slen)
81: return;
82:
83: if (TailOfHist-HistorySize >= TopOfHist) {
84: if (HistoryTable[TopOfHist % HistorySize])
85: free(HistoryTable[TopOfHist % HistorySize]);
86: TopOfHist++;
87: }
88: HistoryTable[(TailOfHist++)%HistorySize] = allocAndCopyThere(string);
89: CurrentHist = TailOfHist;
90: }
91:
92: void
93: resetCurrentHistory()
94: {
95: CurrentHist = TailOfHist;
96: }
97:
98: char *
99: getHistory(num)
100: int num;
101: {
102: if (HistorySize <= 0)
103: return (0);
104:
105: if (num < TopOfHist || TailOfHist <= num) {
106: return ((char *)0);
107: }
108: else {
109: return (HistoryTable[num % HistorySize]);
110: }
111: }
112:
113: char *
114: getCurrentHistory()
115: {
116: return (getHistory (CurrentHist));
117: }
118:
119: char *
120: getPreviousHistory()
121: {
122: if (HistorySize <= 0)
123: return (0);
124:
125: if (TailOfHist == 0) {
126: return((char *)0);
127: }
128: if (CurrentHist == TopOfHist)
129: CurrentHist = TailOfHist - 1;
130: else
131: CurrentHist--;
132: return (getCurrentHistory ());
133: }
134:
135: char *
136: getNextHistory()
137: {
138:
139: if (HistorySize <= 0)
140: return (0);
141:
142: if (CurrentHist == TailOfHist || CurrentHist == TailOfHist-1)
143: CurrentHist = TopOfHist;
144: else
145: CurrentHist++;
146: return (getCurrentHistory ());
147: }
148:
149: getOldestHistNum()
150: {
151:
152: return (TopOfHist);
153: }
154:
155: getYoungestHistNum()
156: {
157:
158: return (TailOfHist-1);
159: }
160:
161: char *
162: getOldestHistory()
163: {
164: register char *cp;
165:
166: if (TailOfHist == 0)
167: return("");
168:
169: cp = HistoryTable[TopOfHist];
170: return (cp ? cp : "");
171: }
172:
173: char *
174: getYoungestHistory()
175: {
176: register char *cp;
177:
178: if (TailOfHist == 0)
179: return("");
180:
181: cp = getHistory (getYoungestHistNum());
182: return (cp ? cp : "");
183: }
184:
185: getCurrentHistNum()
186: {
187: return (CurrentHist);
188: }
189:
190: char *
191: allocAndCopyThere(string)
192: char *string;
193: {
194: register char *cp;
195:
196: cp = (char *)malloc(strlen(string)+1);
197:
198: if (cp == (char *)0)
199: return ((char *)0);
200:
201: strcpy(cp, string);
202: return(cp);
203: }
204:
205: char *
206: historyExtract(string)
207: char *string;
208: {
209: char *search_reverse_history();
210:
211: if (HistorySize <= 0)
212: return (0);
213:
214: switch (*++string) {
215: case '0':
216: case '1':
217: case '2':
218: case '3':
219: case '4':
220: case '5':
221: case '6':
222: case '7':
223: case '8':
224: case '9':
225: {
226: register int histNum;
227:
228: histNum = (atoi (string)) - 1;
229: if (TopOfHist <= histNum && histNum < TailOfHist) {
230: CurrentHist = histNum;
231: return (HistoryTable[histNum % HistorySize]);
232: }
233: else {
234: return ((char *) 0);
235: }
236: }
237: break;
238:
239: case '-':
240: {
241: register int histNum;
242:
243: if (! isdigit(*++string))
244: return ((char *) 0);
245:
246: histNum = TailOfHist - (atoi (string));
247: if (TopOfHist <= histNum && histNum < TailOfHist) {
248: CurrentHist = histNum;
249: return (HistoryTable[histNum % HistorySize]);
250: }
251: else {
252: return ((char *) 0);
253: }
254: }
255: break;
256:
257: case '!':
258: if (TailOfHist != 0) {
259: CurrentHist = TailOfHist - 1;
260: return (HistoryTable[(TailOfHist - 1) % HistorySize]);
261: }
262: break;
263:
264: case '?':
265: return (search_reverse_history (++string));
266:
267: default:
268: {
269: char buf[64];
270:
271: strcpy (buf, "^");
272: strncat (buf, string, 64);
273: return (search_reverse_history (buf));
274: }
275: }
276: return ((char *) 0);
277: }
278:
279: char *
280: search_reverse_history (string)
281: char *string;
282: {
283: register int i;
284:
285: if (string != NULL) {
286: set_var ("search-string", string);
287: if (re_comp(string) != (char *)0)
288: return ((char *) 0);
289: i = TailOfHist - 1;
290: }
291: else
292: i = CurrentHist - 1;
293:
294: for (; i >= TopOfHist; i--) {
295: if (re_exec(HistoryTable[i % HistorySize]) == 1) {
296: CurrentHist = i;
297: return(HistoryTable[i % HistorySize]);
298: }
299: }
300: return ((char *) 0);
301: }
302:
303: char *
304: search_forward_history (string)
305: char *string;
306: {
307: register int i;
308:
309: if (string != NULL) {
310: if (re_comp(string) != (char *)0)
311: return ((char *) 0);
312: i = TopOfHist;
313: }
314: else
315: i = CurrentHist + 1;
316:
317: for (; i <= TailOfHist; i++) {
318: if (re_exec(HistoryTable[i % HistorySize]) == 1) {
319: CurrentHist = i;
320: return(HistoryTable[i % HistorySize]);
321: }
322: }
323: return ((char *) 0);
324: }
325:
326: /*
327: * Change history table size.
328: */
329: changeHistorySize(newsize)
330: int newsize;
331: {
332: char **newHistTable;
333: register int newTop, i;
334:
335: if (newsize > 0)
336: newHistTable = (char **)calloc(sizeof(char *), newsize);
337:
338:
339: if (newHistTable == 0)
340: return (0);
341:
342: newTop = (TailOfHist - newsize < TopOfHist)
343: ? TopOfHist : TailOfHist - newsize;
344:
345: /*
346: * This function can be called for initializing history table
347: */
348: if (HistoryTable) {
349: for (i = TailOfHist-1; i >= TopOfHist && i >= newTop; i--) {
350: newHistTable[i%newsize] = HistoryTable[i%HistorySize];
351: }
352:
353: for (i = TopOfHist; i < newTop; i++) {
354: if (HistoryTable[i%HistorySize]) {
355: free(HistoryTable[i%HistorySize]);
356: }
357: }
358: free(HistoryTable);
359: }
360:
361: if (newsize <= 0)
362: HistoryTable = (char **) 0;
363:
364: TopOfHist = newTop;
365: HistorySize = newsize;
366: HistoryTable = newHistTable;
367:
368: if (look_var ("debug")) {
369: printf ("history: top=%d, tail=%d, size=%d\n",
370: TopOfHist, TailOfHist, HistorySize);
371: }
372:
373: return (1);
374:
375: }
376:
377: /*
378: * Built-in function "fep-history"
379: */
380: fep_history (comline)
381: char *comline;
382: {
383: int num;
384:
385: argc = mkargv (comline, argv, MAXARGS);
386:
387: if (argc == 2)
388: num = atoi (argv[1]);
389: else
390: num = 0;
391:
392: hist_showHistory (num);
393: }
394:
395: hist_showHistory (num)
396: int num;
397: {
398: register int from, to, i;
399: char *cp;
400:
401: if (num <= 0)
402: num = HistorySize;
403:
404: from = getOldestHistNum ();
405: to = getYoungestHistNum ();
406:
407: from = max (from, to - num + 1);
408:
409: if (CurrentHist < from) {
410: from = max (getOldestHistNum(), CurrentHist - num/2);
411: to = min (getYoungestHistNum(), from + num - 1);
412: }
413:
414: for (i = from; i <= to; i++) {
415: if (cp = getHistory(i)) {
416: printf("%c%4d ", (i == CurrentHist) ? '>' : ' ', i+1);
417: ctlprint(cp);
418: }
419: }
420: }
421:
422: char *
423: mk_home_relative (cp)
424: char *cp;
425: {
426: static char buf[256];
427:
428: /*
429: * If variable "history-file" is not absolute path name,
430: * change it to relative path name from home directory.
431: */
432: if (*cp != '/' && !(*cp == '.' && *(cp+1) == '/')) {
433: strcpy (buf, getenv ("HOME"));
434: strcat (buf, "/");
435: strcat (buf, cp);
436: }
437: else
438: strcpy (buf, cp);
439:
440: return (buf);
441: }
442:
443: fep_save_history (comline)
444: char *comline;
445: {
446: char *file;
447: char **argp;
448: FILE *fp;
449: int num = 0;
450:
451: argc = mkargv (comline, argv, MAXARGS);
452:
453: argp = argv;
454: ++argp;
455:
456: if (isdigit (**argp))
457: num = atoi (*argp++);
458:
459: if (*argp == NULL) {
460: char *cp;
461:
462: if ((cp = look_var ("history-file")) == NULL) {
463: clear_edit_line ();
464: printf (
465: "%s: Argument or \"history-file\" variables is required\n",
466: argv[0]
467: );
468: recover_edit_line (1);
469: return;
470: }
471: file = mk_home_relative (cp);
472: }
473: else
474: file = *argp;
475:
476: save_history (file, num);
477: }
478:
479: #define MAXSAVEHIST 512
480:
481: save_history (file, num)
482: char *file;
483: int num;
484: {
485: int old, new;
486: FILE *fp, *fopen();
487: char *cp;
488:
489: old = getOldestHistNum ();
490: new = getYoungestHistNum ();
491:
492: if (num <= 0)
493: num = MAXSAVEHIST;
494:
495: if (new - num + 1 > old)
496: old = new - num + 1;
497:
498: if (look_var ("debug")) {
499: printf ("save history from %d to %d\n", old, new);
500: }
501:
502: if ((fp = fopen (file, "w")) == NULL) {
503: clear_edit_line ();
504: perror (file);
505: recover_edit_line (1);
506: return;
507: }
508:
509: while (old <= new) {
510: cp = getHistory (old++);
511: fprintf (fp, "%s\n", cp);
512: }
513:
514: fclose (fp);
515: return;
516: }
517:
518: fep_read_history (comline)
519: char *comline;
520: {
521: char *file;
522: char **argp;
523: FILE *fp;
524:
525: argc = mkargv (comline, argv, MAXARGS);
526:
527: argp = argv;
528: ++argp;
529:
530: if (*argp == NULL) {
531: char *cp;
532:
533: if ((cp = look_var ("history-file")) == NULL) {
534: clear_edit_line ();
535: printf (
536: "%s: Argument or \"history-file\" variables is required\n",
537: argv[0]
538: );
539: recover_edit_line (1);
540: return;
541: }
542: file = mk_home_relative (cp);
543: }
544: else
545: file = *argp;
546:
547: read_history (file);
548: }
549:
550: read_history (file)
551: char *file;
552: {
553: FILE *fp;
554: char line [MAXCMDLEN];
555: register int i;
556:
557: if ((fp = fopen (file, "r")) == NULL) {
558: clear_edit_line ();
559: perror (file);
560: recover_edit_line (1);
561: return;
562: }
563:
564: while (fgets (line, MAXCMDLEN, fp)) {
565: i = strlen (line) - 1;
566: if (line [i] == '\n')
567: line [i] = '\0';
568: addHistory (line);
569: }
570: return;
571: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>