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