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