1 /* ELLEC - Copyright 1983 by Ken Harrenstien, SRI International
2 * This software is quasi-public; it may be used freely with
3 * like software, but may NOT be sold or made part of licensed
4 * products without permission of the author.
6 /* ELLEC - ELLE Compiler
7 * Invoked with no arguments, acts as general ELLE compiler filter;
8 * reads ASCII profile input, and outputs a binary profile.
10 * -Profile Compiles user's profile.
11 * HOME/.ellepro.e -> HOME/.ellepro.bN (N = fmt version #)
12 * NOTE: on V6, "HOME/" is left out.
13 * -Pconf Outputs defprf.c for ELLE (accepts std in) (old -E)
14 * -Fconf Outputs eefdef.h for ELLE (accepts std in)
15 * -FXconf Outputs eefidx.h for ELLE (accepts std in)
16 * -CMconf Outputs config makefile for ELLE ( " )
17 * -CSconf arg Outputs config file using "arg" - for V6 config.v6 file.
18 * -Pdump Outputs defprf.e user profile (old -P)
19 * -Fdump Outputs deffun.e
23 The ASCII profile file associates command chars with functions
.
24 It is simply a series of lisp
-like expressions of the form
25 (keybind
<char spec
> <fun spec
>)
27 e
.g
. (keybind
"C-Y" "Yank Pop")
29 Command
char specification
:
32 C
- Controlify (zap bits
140)
34 M
- Meta (add bit
200) - case ignored
35 X
- Extended (add bit
) - case ignored
36 To quote a
char or char spec
, use quoted
-string syntax
.
38 Function name specification
:
39 Function names are specified by quoted strings containing the entire
40 long-form ASCII function name
. Matching is done
case-independently
.
45 #include "eesite.h" /* Site specific stuff if any */
49 #include "eeprof.h" /* Profile structure definition */
52 #define EFUNMAX 400 /* Maximum # (+1) of functions that can be defined */
53 #define KBTSIZ (128*2) /* Initial size of key binding tables */
56 /* EFUN Function definition table.
57 ** Functions that were copied from the pre-defined table will
58 ** have a value of NULL in ef_mod.
61 int ef_idx
; /* Function index (same as index of entry) */
62 char *ef_name
; /* Function name */
63 char *ef_adr
; /* C routine name in ELLE */
64 char *ef_mod
; /* Source module that C routine lives in */
66 struct fun efuntab
[EFUNMAX
];
67 int efxmax
= 0; /* Largest function idx used */
69 int format_ver
= PROF_VER
; /* Current version # of binary profile fmt */
71 /* Keybind mapping tables. There are four separate tables:
72 ** Simple character. Always 128 single-byte items, indexed by the simple
73 ** command char. Each item is the corresponding function index.
74 ** Meta char. Variable number of 2-byte items; first is a command char
75 ** and second is its function index.
76 ** Extended char. Same format as Meta char.
77 ** Menu item (SUN only). Variable number of single-byte items, each
81 char *chrptr
; /* Pointer to simple-char table */
82 int chrsiz
= 128; /* Current size of table */
83 int chrcnt
= 0; /* # bytes actually used */
85 char *mtaptr
; /* Pointer to meta-char table */
86 int mtasiz
= KBTSIZ
; /* Current size (twice the # of items) */
87 int mtacnt
= 0; /* # bytes actually used */
89 char *extptr
; /* Pointer to ext-char table */
90 int extsiz
= KBTSIZ
; /* Current size (twice the # of items) */
91 int extcnt
= 0; /* # bytes actually used */
93 char *mnuptr
; /* Pointer to menu-item table (SUN only) */
94 int mnusiz
= KBTSIZ
; /* Current size */
95 int mnucnt
= 0; /* # bytes actually used */
98 #define CB_EXT 0400 /* "X-" prefix on command char */
99 #define CB_META 0200 /* "M-" prefix on command char */
102 /* Set up the pre-defined data areas. This includes the
103 ** predefined function table plus the default profile (keyboard mappings).
104 ** Note this only contains entries for ef_name and ef_adr.
107 struct fun pdfuntab
[] = { /* Pre-Defined Function table */
108 #define EFUN(rtn,rtnstr,name) 0, name, rtnstr, 0,
109 #define EFUNHOLE 0, 0, 0, 0,
112 int npdfuns
= sizeof(pdfuntab
)/sizeof(struct fun
); /* # of entries */
114 #include "defprf.c" /* Insert default profile mapping */
115 /* This defines charmap, metamap, and extmap. */
117 /* Stuff for feeble-minded list processor */
118 #define NIL ((struct lnode *)0)
119 #define LTRUE (<ruenode)
124 #define LT_ATOM 3 /* Should use this later instead of LT_STR */
136 struct lnode ltruenode
; /* Constant TRUE */
138 _PROTOTYPE(int main
, (int argc
, char **argv
));
139 _PROTOTYPE(int doargs
, (int argc
, char **argv
));
140 _PROTOTYPE(char **findkey
, (char *cp
, char ***aretp
, char **tabp
, int tabsiz
, int elsize
));
141 _PROTOTYPE(int nstrcmp
, (char *s1
, char *s2
));
142 _PROTOTYPE(int ustrcmp
, (char *s1
, char *s2
));
143 _PROTOTYPE(int strueq
, (char *s1
, char *s2
));
144 _PROTOTYPE(int do_opcod
, (void));
145 _PROTOTYPE(int do_opasc
, (void));
146 _PROTOTYPE(int outkbind
, (int c
, int fx
));
147 _PROTOTYPE(int do_obprof
, (void));
148 _PROTOTYPE(int mupcase
, (int ch
));
149 _PROTOTYPE(int upcase
, (int ch
));
150 _PROTOTYPE(char *qstr
, (char *str
));
151 _PROTOTYPE(char *charep
, (int c
));
152 _PROTOTYPE(int do_ocnf
, (char *str
));
153 _PROTOTYPE(int do_ofcod
, (void));
154 _PROTOTYPE(int do_ofasc
, (void));
155 _PROTOTYPE(int do_ofxcod
, (void));
156 _PROTOTYPE(int compile_stdin
, (void));
157 _PROTOTYPE(int lrch
, (void));
158 _PROTOTYPE(struct lnode
*lread
, (void));
159 _PROTOTYPE(int wspfls
, (void));
160 _PROTOTYPE(struct lnode
*lrstr
, (int flg
));
161 _PROTOTYPE(int islword
, (int c
));
162 _PROTOTYPE(struct lnode
*eval
, (struct lnode
*lp
));
163 _PROTOTYPE(struct lnode
*undefall
, (struct lnode
*lp
));
164 _PROTOTYPE(struct lnode
*efun
, (struct lnode
*lp
));
165 _PROTOTYPE(struct lnode
*keybind
, (struct lnode
*lp
));
166 _PROTOTYPE(struct lnode
*keyallun
, (void));
167 _PROTOTYPE(struct lnode
*menuitem
, (struct lnode
*lp
));
168 _PROTOTYPE(int repchar
, (char *str
));
169 _PROTOTYPE(struct lnode
*getln
, (void));
170 _PROTOTYPE(int numcvt
, (char *str
, int *anum
));
171 _PROTOTYPE(int listcnt
, (struct lnode
*lp
));
172 _PROTOTYPE(char *funname
, (int i
));
173 _PROTOTYPE(int findfun
, (char *name
));
174 _PROTOTYPE(int funcnt
, (int *arr
));
175 _PROTOTYPE(int scpy
, (char *from
, char *to
, int cnt
));
176 _PROTOTYPE(char *stripsp
, (char *cp
));
183 /* ELLEC argument stuff */
186 int swfilter
; /* If no args */
190 int uproflg
; /* Do compilation of user's profile */
191 int swpcnf
; /* Output defprf.c (C initialization of profile) */
192 int swfcnf
; /* Output eefdef.h */
193 int swfxcnf
; /* Output eefidx.h */
194 int swcmcnf
; /* Output config makefile (makecf.fun) */
195 char *swcscnf
; /* Output config specially (for V6) */
196 int swallc
; /* Do all of config stuff */
197 int swfdmp
; /* Output deffun.e */
198 int nfiles
; /* # file specs seen */
208 ** (cannot portably initialize a union at compile time)
210 ltruenode
.ltyp
= LT_VAL
; /* Set type (other fields zero) */
212 /* Process switches */
213 if(argc
<= 1) swfilter
++; /* If no args, assume filter */
214 else doargs(argc
,argv
);
216 /* Initialize function definitions and key bindings from predefs */
217 chrptr
= malloc(chrsiz
);
218 mtaptr
= malloc(mtasiz
);
219 extptr
= malloc(extsiz
);
220 mnuptr
= malloc(mnusiz
);
221 if (!chrptr
|| !mtaptr
|| !extptr
|| !mnuptr
)
222 fatal("cannot init, no memory");
224 scpy(charmap
, chrptr
, (chrcnt
= sizeof(charmap
)));
225 scpy(metamap
, mtaptr
, (mtacnt
= sizeof(metamap
)));
226 scpy( extmap
, extptr
, (extcnt
= sizeof(extmap
)));
228 scpy(def_prof
.menuvec
, mnuptr
, (mnucnt
= def_prof
.menuvcnt
));
230 for(i
= 0; i
< npdfuns
; ++i
) /* Initialize function defs */
231 if(pdfuntab
[i
].ef_name
)
232 { efuntab
[i
].ef_idx
= i
;
233 efuntab
[i
].ef_name
= pdfuntab
[i
].ef_name
;
234 efuntab
[i
].ef_adr
= stripsp(pdfuntab
[i
].ef_adr
);
235 if(efxmax
< i
) efxmax
= i
;
239 /* Routines expect input from stdin and output their results
243 if(freopen(argfile
,"r",stdin
) == NULL
)
244 fatal("cannot open input file \"%s\"",argfile
);
246 if(freopen(outfile
,"w",stdout
) == NULL
)
247 fatal("cannot open output file \"%s\"",outfile
);
250 /* Check for general compilation */
252 { /* Not really implemented yet */
253 fatal("bad usage, see doc");
256 /* Do profile hacking of some kind */
258 { if (compile_stdin()) /* Compile input profile */
260 do_opasc(); /* Output ASCII profile (.e) */
262 do_opcod(); /* Output bin profile (.b1) */
267 /* Check for variousness */
269 { if(compile_stdin()) /* Compile input */
270 do_opcod(); /* Output the C initialization code */
274 { if(compile_stdin()) /* Compile input */
275 do_ofxcod(); /* Output the eefidx.h code */
279 { if(compile_stdin()) /* Compile input */
280 do_ofcod(); /* Output the eefdef.h code */
283 if(swcmcnf
|| swcscnf
)
284 { if(compile_stdin()) /* Compile input */
285 do_ocnf(swcscnf
); /* Output the makecf.fun code */
289 { if(compile_stdin()) /* Compile input */
290 do_ofasc(); /* Output the deffun.e code */
295 /* Hack user's profile */
296 if(!uproflg
) exit(0);
301 if (cp
= getenv("HOME"))
307 strcat(temp
, EVPROFTEXTFILE
);
308 if(freopen(temp
,"r",stdin
) == NULL
)
309 fatal("cannot open profile \"%s\"",temp
);
315 if (cp
= getenv("HOME"))
321 strcat(temp
, EVPROFBINFILE
);
322 if(freopen(temp
,"wb",stdout
) == NULL
/* Try binary 1st */
323 && freopen(temp
,"w",stdout
) == NULL
)
324 fatal("cannot open output profile \"%s\"",temp
);
327 /* Hack user's profile */
328 if(compile_stdin()) /* Compile input profile */
329 do_obprof(); /* Output the binary */
342 "P", SW_FLG
, &swprof
, 0, /* Old stuff */
343 "E", SW_FLG
, &swelle
, 0,
344 "Profile", SW_FLG
, &uproflg
, 0,
345 "Pconf", SW_FLG
, &swpcnf
, 0,
346 "Fconf", SW_FLG
, &swfcnf
, 0,
347 "FXconf", SW_FLG
, &swfxcnf
, 0,
348 "CMconf", SW_FLG
, &swcmcnf
, 0,
349 "CSconf", SW_STR
, 0, &swcscnf
,
350 "Allconf", SW_FLG
, &swallc
, 0,
351 "Pdump", SW_FLG
, &swprof
, 0,
352 "Fdump", SW_FLG
, &swfdmp
, 0
358 { register int cnt
, c
;
361 register struct swarg
*swp
;
371 if(*av
[0] != '-') /* If not switch, */
372 { /* assume it's an input filename */
378 /* Try to look up switch in table */
379 swp
= (struct swarg
*)findkey(av
[0], &swp2
, swtab
,
380 (sizeof(swtab
))/(sizeof(struct swarg
)),
381 (sizeof(struct swarg
))/(sizeof(char *)));
383 { fprintf(stderr
,"ellec: ambiguous switch: -%s = %s or %s\n",
384 av
[0], swp
->sw_name
, swp2
->sw_name
);
387 if(swp
) switch(swp
->sw_type
)
393 if(cnt
<= 1) goto swdone
;
395 { *(swp
->sw_avar
) = atoi(av
[1]);
402 if(cnt
<= 1) goto swdone
;
403 *(swp
->sw_astr
) = av
[1];
407 fprintf(stderr
,"ellec: bad switch type: %s\n",
412 stop
: fprintf(stderr
,"ellec: bad switch: %s\n",*av
);
420 if(swerrs
) exit(1); /* Stop if any problems */
424 findkey(cp
, aretp
, tabp
, tabsiz
, elsize
)
427 register char **tabp
;
429 { register char **mp1
, **mp2
;
432 *aretp
= mp1
= mp2
= 0;
433 for(i
= 0; i
< tabsiz
; ++i
, tabp
+= elsize
)
434 { if(res
= ustrcmp(cp
,*tabp
))
435 { if(res
> 0) return(tabp
);
441 *aretp
= mp2
; /* Ambiguous */
445 /* NSTRCMP - New string compare.
447 * 2 if str2 > str1 (mismatch)
448 * 1 if str2 counted out (str1 > str2)
450 * -1 if str1 counted out (str1 < str2)
451 * -2 if str1 < str2 (mismatch)
455 register char *s1
, *s2
;
460 { if((d
= upcase(c
) - upcase(*s2
)) != 0)
461 return(*s2
==0 ? 1 : (d
> 0 ? 2 : -2));
465 return(*s2
? -1 : 0);
468 /* USTRCMP - uppercase string compare.
469 * Returns 0 if mismatch,
471 * -1 if str1 runs out first (partial match)
474 register char *s1
, *s2
;
477 if ( ! s1
|| ! s2
) return ( 0 ); /* Check for null ptr */
480 { if(((c
^ *s2
) != 040)
481 || (upcase(c
) != upcase(*s2
)))
486 return(c
== *s2
? 1 : -1);
492 { return (ustrcmp(s1
, s2
) > 0 ? 1 : 0);
495 /* Output C initialization code for default profile (defprf.c) */
498 { register int i
, c
, f
;
501 /* This file defines the initial data for ELLE's default user profile.\n\
502 ** It is automatically generated by ELLEC, and should not be edited.\n\
504 char charmap[] = {\n");
505 for(i
=0; i
< chrcnt
; i
++)
506 { printf("\t%2d,",(f
= chrptr
[i
]&0377));
507 printf("\t/* (%3o) %3s",i
,charep(i
));
508 printf(" %s",funname(f
));
512 printf("};\n char metamap[] = {\n");
513 for(i
= 0; i
< mtacnt
; i
+= 2)
514 { printf("\t0%-3o,%3d,",(c
= mtaptr
[i
]&0377),(f
= mtaptr
[i
+1]&0377));
515 printf("\t/* %4s",charep(c
|CB_META
));
516 printf(" %s",funname(f
));
520 printf("};\n char extmap[] = {\n");
521 for(i
= 0; i
< extcnt
; i
+= 2)
522 { printf("\t0%-3o,%3d,",(c
= extptr
[i
]&0377),(f
= extptr
[i
+1]&0377));
523 printf("\t/* %4s",charep(c
|CB_EXT
));
524 printf(" %s",funname(f
));
528 printf("struct profile def_prof = {\n");
529 printf(" %d, /* Ver */\n", format_ver
);
530 printf(" sizeof(charmap), charmap,\n");
531 printf(" sizeof(metamap)/2, metamap,\n");
532 printf(" sizeof(extmap)/2, extmap, \n");
538 /* Output ASCII version of default profile */
543 { register int i
, c
, f
;
546 printf("; ELLE default ASCII profile\n\n");
547 printf("(keyallunbind) ; To flush all existing bindings\n\n");
548 for(i
=0; i
< chrcnt
; i
++)
549 outkbind(i
, chrptr
[i
]&0377);
551 printf("\n; Meta chars\n\n");
552 for(i
= 0; i
< mtacnt
; i
+= 2)
553 outkbind(CB_META
| (mtaptr
[i
]&0377), mtaptr
[i
+1]&0377);
555 printf("\n ; Extended commands\n\n");
556 for(i
= 0; i
< extcnt
; i
+= 2)
557 outkbind(CB_EXT
| (extptr
[i
]&0377), extptr
[i
+1]&0377);
561 fatal("%d errors encountered, check output file.", oerrs
);
566 if(fx
== 0) /* Allow key to be mapped to nothing. */
568 if(fx
<= 0 || fx
> efxmax
)
569 printf(";INTERNAL ERROR: Bad function index %d for key %s\n",
571 else if(efuntab
[fx
].ef_name
== NULL
)
572 printf(";INTERNAL ERROR: No name for function %d while mapping key %s\n",
575 printf("(keybind %s \"%s\")\n",
576 qstr(charep(c
)),efuntab
[fx
].ef_name
);
582 /* Output binary user profile */
585 { register unsigned int rp
; /* Relative "pointer" */
586 struct stored_profile st_prof
;
588 rp
= sizeof(st_prof
); /* Initialize */
590 /* Fixed by Kochin Chang, July 1995 */
591 /* format version should be the first field in compiled profile */
592 prof_pack(st_prof
.version
, format_ver
);
594 prof_pack(st_prof
.chrvec
, rp
);
595 prof_pack(st_prof
.chrvcnt
, chrcnt
);
598 prof_pack(st_prof
.metavec
, rp
);
599 prof_pack(st_prof
.metavcnt
, mtacnt
/2);
602 prof_pack(st_prof
.extvec
, rp
);
603 prof_pack(st_prof
.extvcnt
, extcnt
/2);
606 prof_pack(st_prof
.menuvec
, rp
);
607 prof_pack(st_prof
.menuvcnt
, mnucnt
);
610 fwrite((char *)&st_prof
,sizeof(st_prof
),1,stdout
);
611 fwrite(chrptr
,sizeof(char),chrcnt
,stdout
);
612 if(mtacnt
) fwrite(mtaptr
, sizeof(*mtaptr
), mtacnt
, stdout
);
613 if(extcnt
) fwrite(extptr
, sizeof(*extptr
), extcnt
, stdout
);
614 if(mnucnt
) fwrite(mnuptr
,sizeof(*mnuptr
),mnucnt
,stdout
);
617 /* Return upper-case version of character */
620 { return((ch
&(~0177)) | upcase(ch
));
625 return((('a' <= c
) && (c
<= 'z')) ? (c
- ('a'-'A')) : c
);
632 static char qstrbuf
[100];
635 while((c
= *cp
++) && islword(c
));
636 if(c
== 0) return(str
); /* No quoting needed */
640 while(*cp
++ = c
= *str
++)
641 if(c
== '"') *cp
++ = c
; /* Double the quotes */
650 { static char chrbuf
[10];
677 /* Output config Makefile (makecf.fun)
678 * If argument is 0 (NULL), does Makefile type output.
679 * Otherwise uses string for special-purpose output.
683 { register struct fun
*fnp
;
688 char *modtab
[EFUNMAX
];
689 char *unknown
= "unknown-module";
691 if(str
== NULL
) /* If not V6 version */
692 { printf("# Function module definition file, generated by ELLEC\n");
693 printf("FUN_OFILES = ");
698 funcnt(fmtab
); /* Count function occs */
700 for(i
= 1; i
<= efxmax
; ++i
)
701 { if(fmtab
[i
] == 0) continue;
704 if(fnp
->ef_name
== 0)
705 fatal("internal error - no name for function %d", i
);
707 /* Got a function, store its module name if not a dup */
708 if ((cp
= fnp
->ef_mod
) == NULL
) /* Substitute if undef */
710 for(mi
=0; mi
< nfmods
; ++mi
)
711 if(ustrcmp(cp
, modtab
[mi
]) > 0)
713 if(mi
< nfmods
) continue;
714 modtab
[nfmods
++] = cp
;
717 /* Now have table of all modules used. Crunch them into output. */
718 for(mi
=0; mi
< nfmods
; ++mi
)
719 if (modtab
[mi
] != unknown
)
720 { if(str
!= NULL
) /* V6 version? */
721 printf("%s %s\n", str
, modtab
[mi
]);
722 else printf("\\\n\t%s.o", modtab
[mi
]);
727 /* Output eefdef.h */
730 { register struct fun
*fnp
;
735 printf("/* .H Function Definition file, generated by ELLEC */\n");
736 printf("/* 0 */ EFUNHOLE /* Always undefined */\n");
738 funcnt(fmtab
); /* Count function occs */
740 for(i
= 1; i
<= efxmax
; ++i
)
743 printf("/* %3d */ ", i
);
744 if(fmtab
[i
] == 0 || fnp
->ef_name
== 0)
745 printf("EFUNHOLE\n");
747 { sprintf(temp
, "\"%s\"", fnp
->ef_adr
);
748 printf("EFUN( %-12s, %-14s, \"%s\")\n", fnp
->ef_adr
,
755 /* Output ascii version of function def file
758 { register struct fun
*fnp
;
760 register char *fa
, *fm
;
762 printf("; Master Function Definition file\n");
764 for(i
= 1; i
<= efxmax
; ++i
)
767 if(fnp
->ef_idx
== 0) /* No definition for this index? */
769 if(fnp
->ef_name
== 0)
770 { warn("internal error - no name for function %d", i
);
774 if ((fa
= fnp
->ef_adr
) == NULL
)
776 if ((fm
= fnp
->ef_mod
) == NULL
)
777 fm
= "unknown-module";
778 printf("(efun %d \"%s\" %s %s)\n",
779 fnp
->ef_idx
, fnp
->ef_name
, fa
, fm
);
783 /* Output eefidx.h */
786 { register struct fun
*fnp
;
788 register char *cp
, *cp2
;
793 /* .H Function Index Definition file, generated by ELLEC */\n");
795 /* FN_ defines Function Numbers (indices) for all known functions */\n");
797 /* FX_ defines Function eXistence in this ELLE configuration */\n");
799 funcnt(fmtab
); /* Count function occs */
801 for(i
= 1; i
<= efxmax
; ++i
)
804 if(fnp
->ef_idx
== 0) /* No definition for this index? */
806 if(fnp
->ef_adr
== 0 || fnp
->ef_name
== 0)
807 { warn("internal error - no addr/name for function %d", i
);
813 while(*cp
++ = upcase(*cp2
++));
815 if((*cp
++ != 'F') || (*cp
++ != '_'))
818 /* Always define FN_ as index */
819 printf("#define FN_%-14s %3d /* %s */\n",
820 cp
, i
, fnp
->ef_name
);
821 /* Define FX_ as 0 if unused, else same as FN_ */
822 printf("#define FX_%-14s %3d\n", cp
,
823 (fmtab
[i
] == 0) ? 0 : i
); /* 0 if unused */
831 { register struct lnode
*lp
;
833 while((lp
= lread()) != NIL
)
842 #define unlrch(c) llstch = c
845 char linebuf
[MAXLINE
];
846 char *linecp
= linebuf
;
850 if((c
= llstch
) >= 0)
851 { if(c
== 0 && leofflg
)
856 if((c
= getc(stdin
)) == EOF
)
874 register struct lnode
*lp
, *lp2
;
878 if((c
= lrch())== EOF
)
880 if(c
== ')') /* End of a list? */
882 if(c
== '(') /* Start of a list? */
883 { head
= lp
= getln();
885 if((head
->lval
.lvl
= lp
= lread()) == NIL
)
886 return(head
); /* Return empty list */
894 /* Atom of some kind */
906 if(isspace(c
)) continue;
908 while((c
= lrch()) != '\n')
912 if(c
!= EOF
) unlrch(c
);
915 #define LSMAX 300 /* Max # chars in atom string */
926 while((c
= lrch()) != EOF
)
929 if((c
= lrch()) == EOF
)
943 { if(islword(c
)) goto ok
;
950 lp
->lval
.lvs
= malloc(i
+1);
952 strcpy(lp
->lval
.lvs
, cbuf
);
956 { return((040 < c
&& c
< 0177
957 && c
!= '(' && c
!=')' && c
!= ';'
958 && c
!= '"' && c
!= '\\') ? 1 : 0);
962 struct lnode
*keybind(), *keyallun(), *menuitem(), *efun(),
966 char *lfname
; /* Name of list function */
967 struct lnode
* (*lfrtn
)(); /* Function address */
971 "menuitem", menuitem
,
972 "keyallunbind", keyallun
,
973 /* "keyunbind", keyunbind, */ /* Not yet */
974 "undefall", undefall
,
975 /* "undef", undef, */ /* Not yet */
981 register struct lnode
*lp
;
982 { register struct lnode
*flp
;
983 register struct lfun
*lfent
;
985 if(lp
->ltyp
!= LT_LIST
)
987 if((flp
= lp
->lval
.lvl
) == NIL
)
989 if(flp
->ltyp
!= LT_STR
)
992 /* Look up list function and invoke it */
993 for(lfent
= lfntab
; lfent
->lfname
; lfent
++)
994 if(strueq(flp
->lval
.lvs
, lfent
->lfname
))
995 return((*(lfent
->lfrtn
))(flp
->lnxt
));
997 lerr("unknown op: (%s)", flp
->lval
.lvs
);
1002 /* UNDEFALL - (undefall)
1003 ** Undefines all functions. Typically used to clear out
1004 ** predefined functions prior to compiling a set of new efuns.
1008 register struct lnode
*lp
;
1011 efxmax
= 0; /* Say nothing in function def table! */
1012 for(i
= 0; i
< EFUNMAX
; ++i
)
1013 { efuntab
[i
].ef_idx
= 0;
1014 efuntab
[i
].ef_name
= 0;
1015 efuntab
[i
].ef_adr
= 0;
1016 efuntab
[i
].ef_mod
= 0;
1021 /* EFUN - (efun <index> <functionname> <address> <module>)
1022 ** Checks out the args and if no problems, stores the function
1023 ** definition in efuntab.
1027 register struct lnode
*lp
;
1028 { struct lnode
*nlp
;
1030 register struct fun
*fnp
;
1031 char *fname
, *faddr
, *fmod
;
1035 { lerr("efun - not enough args");
1039 /* First thing should be function index */
1045 if(numcvt(lp
->lval
.lvs
, &num
))
1050 lerr("efun - non-value function index");
1054 /* Next thing should be function name */
1056 if(lp
->ltyp
!= LT_STR
) /* Function name not a string */
1057 { lerr("efun - non-string function name");
1060 fname
= lp
->lval
.lvs
;
1062 /* Next thing should be function addr */
1064 if(lp
->ltyp
!= LT_STR
) /* Function addr not a string */
1065 { lerr("efun - non-string function addr");
1068 faddr
= lp
->lval
.lvs
;
1070 /* Next thing should be function module */
1072 if(lp
->ltyp
!= LT_STR
) /* Function module not a string */
1073 { lerr("efun - non-string function module");
1076 fmod
= lp
->lval
.lvs
;
1078 /* Now see if already exists or anything */
1079 if(fni
<= 0 || fni
> EFUNMAX
)
1080 { lerr("efun - bad function index %d", fni
);
1083 fnp
= &efuntab
[fni
];
1084 if(fnp
->ef_idx
!= 0)
1086 if (fnp
->ef_idx
== fni
1087 && strueq(fnp
->ef_name
, fname
)
1088 && strueq(fnp
->ef_adr
, faddr
)
1089 && (fnp
->ef_mod
== NULL
|| strueq(fnp
->ef_mod
, fmod
)))
1090 goto win
; /* Benign redefinition */
1092 lerr("efun - redefining function (%d \"%s\" %s %s)",
1093 fnp
->ef_idx
, fnp
->ef_name
, fnp
->ef_adr
,
1094 (fnp
->ef_mod
? fnp
->ef_mod
: "unknown-module"));
1096 for(i
= 0; i
< EFUNMAX
; ++i
)
1097 { if(efuntab
[i
].ef_idx
== 0) continue;
1098 if(ustrcmp(efuntab
[i
].ef_adr
,faddr
) > 0
1099 || ustrcmp(efuntab
[i
].ef_name
, fname
) > 0)
1100 { if(i
== fni
) continue;
1101 lerr("efun - name or address dup! \"%s\"", fname
);
1106 /* No problems, store the function def in efuntab! */
1107 win
: fnp
->ef_idx
= fni
;
1109 fnp
->ef_adr
= faddr
;
1110 fnp
->ef_name
= fname
;
1112 if(efxmax
< fni
) efxmax
= fni
;
1117 /* KEYBIND - (keybind <charspec> <functionname>) */
1121 register struct lnode
*lp
;
1122 { struct lnode
*nlp
;
1126 if(lp
== NIL
|| (nlp
= lp
->lnxt
)== NIL
)
1135 c
= repchar(lp
->lval
.lvs
);
1139 return(NIL
); /* No such command char name */
1142 if(lp
->ltyp
!= LT_STR
) /* Function name not a string */
1143 { lerr("(keybind) non-string function name");
1146 fni
= findfun(lp
->lval
.lvs
);
1147 if(fni
== 0) /* No such function name */
1148 { lerr("(keybind) no such function - \"%s\"", lp
->lval
.lvs
);
1154 /* Check for redefinition */
1155 for(i
= 0; i
< extcnt
; i
+= 2)
1156 if(c
== (extptr
[i
]&0377)) /* Already there? */
1157 { if((extptr
[i
+1]&0377) != fni
) /* Yes, check fn */
1158 lerr("(keybind) redefining X-%s as %d=\"%s\"",
1159 charep(c
), fni
, lp
->lval
.lvs
);
1162 if(i
>= extcnt
) /* Didn't find? */
1163 { if(extcnt
>= extsiz
)
1164 { lerr("(keybind) too many X- commands");
1165 return(NIL
); /* Too many EXT cmds */
1167 i
= extcnt
; /* Increase size of table */
1170 /* Now store new binding */
1177 /* Check for redefinition */
1178 for(i
= 0; i
< mtacnt
; i
+= 2)
1179 if(c
== (mtaptr
[i
]&0377)) /* Already there? */
1180 { if((mtaptr
[i
+1]&0377) != fni
) /* Yes, check fn */
1181 lerr("(keybind) redefining M-%s as %d=\"%s\"",
1182 charep(c
), fni
, lp
->lval
.lvs
);
1185 if(i
>= mtacnt
) /* Didn't find? */
1186 { if(mtacnt
>= mtasiz
)
1187 { lerr("(keybind) too many M- commands");
1188 return(NIL
); /* Too many META cmds */
1190 i
= mtacnt
; /* Increase size of table */
1193 /* Now store new binding */
1199 if (chrptr
[i
] && (chrptr
[i
]&0377) != fni
)
1200 lerr("(keybind) redefining %s as %d=\"%s\"",
1201 charep(c
), fni
, lp
->lval
.lvs
);
1207 /* KEYALLUNBIND - (keyallunbind) */
1213 /* fprintf(stderr, "ellec: clearing all key definitions\n"); */
1214 for(i
= 0, cp
= chrptr
; i
< chrcnt
; i
++)
1216 mtacnt
= extcnt
= mnucnt
= 0;
1220 /* MENUITEM - (menuitem <functionname>) */
1224 register struct lnode
*lp
;
1225 { register int i
, fni
;
1236 fni
= findfun(lp
->lval
.lvs
);
1239 if(fni
== 0) return(NIL
); /* Bad val or no such function name */
1240 for(i
= 0; i
< mnusiz
; i
++)
1241 if(fni
== (mnuptr
[i
]&0377) || mnuptr
[i
] == 0)
1246 return(NIL
); /* Too many menu items */
1254 if (str
== 0) return (-1);
1258 if(l
== 0) return(-1);
1259 if(l
== 1) return(c
); /* One-char representation */
1261 if(l
== 2) return((~0140) & mupcase(*str
));
1265 { if(*++str
== 0) return(-1);
1267 { case 'X': return(CB_EXT
| mupcase(repchar(str
)));
1268 case 'M': return(CB_META
| mupcase(repchar(str
)));
1269 case 'C': return((~0140) & repchar(str
));
1272 if(c
== 'S' && upcase(*str
) == 'P' && l
== 2)
1274 if(c
== 'D' && upcase(*str
++) == 'E' && upcase(*str
++) == 'L'
1282 { return((struct lnode
*)calloc(1,sizeof(struct lnode
)));
1288 { register char *cp
;
1289 register int i
, c
, sign
;
1296 if(!isdigit(c
)) return(0);
1297 else i
= 10*i
+ (c
- '0');
1298 *anum
= sign
? -i
: i
;
1305 register struct lnode
*lp
;
1313 /* FUNNAME - Given function index, return function name.
1314 ** Always wins; returns "unknown" for bad indices.
1320 register char *cp
= NULL
;
1321 if(0 < i
&& i
<= efxmax
&& (cp
= efuntab
[i
].ef_name
))
1323 return("unknown function");
1327 register char *name
;
1329 if((i
= efxmax
) > 0)
1330 { do { if(strueq(name
, efuntab
[i
].ef_name
))
1339 /* FUNCNT - Scan all key bindings, counting each occurrence of every
1341 ** This is used to determine which functions are actually used.
1344 register int *arr
; /* Pointer to array of EFUNMAX ints */
1348 for(i
= 0; i
< EFUNMAX
; ++i
) /* Clear the array */
1351 for(i
= 0; i
< chrcnt
; ++i
) /* Scan bindings */
1352 arr
[chrptr
[i
]&0377]++;
1353 for(i
= 0; i
< mtacnt
; i
+= 2)
1354 arr
[mtaptr
[i
+1]&0377]++;
1355 for(i
= 0; i
< extcnt
; i
+= 2)
1356 arr
[extptr
[i
+1]&0377]++;
1360 register char *from
,*to
;
1363 do { *to
++ = *from
++; }
1367 /* STRIPSP - strip spaces from string. Returns ptr to start. */
1372 register char *ep
, *lastp
;
1373 while(*cp
== ' ') ++cp
;
1375 { ep
= cp
+ strlen(cp
); /* Point to null ending the str */
1376 while (*--ep
== ' ');
1377 *++ep
= 0; /* Tie it off */
1382 warn(str
,a
,b
,c
,d
,e
,f
,g
,h
,i
)
1385 fprintf(stderr
, "ellec: ");
1386 fprintf(stderr
, str
, a
,b
,c
,d
,e
,f
,g
,h
,i
);
1387 fprintf(stderr
, "\n");
1390 lerr(str
,a
,b
,c
,d
,e
,f
,g
,h
,i
)
1393 warn(str
, a
,b
,c
,d
,e
,f
,g
,h
,i
);
1394 *linecp
= 0; /* Tie off current line buffer */
1395 fprintf(stderr
, " Line %d: %s\n", lineno
, linebuf
);
1398 fatal(str
,a
,b
,c
,d
,e
,f
,g
,h
,i
)
1401 warn(str
, a
,b
,c
,d
,e
,f
,g
,h
,i
);