source: trunk/minix/commands/elle/ellec.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 31.9 KB
Line 
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.
5 */
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.
9 * Otherwise:
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
20 */
21
22#if 0
23The ASCII profile file associates command chars with functions.
24It is simply a series of lisp-like expressions of the form
25 (keybind <char spec> <fun spec>)
26
27 e.g. (keybind "C-Y" "Yank Pop")
28
29Command char specification:
30 Allowed prefixes:
31 <ch> The char itself
32 C- Controlify (zap bits 140)
33 ^<ch> Ditto
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.
37
38Function name specification:
39 Function names are specified by quoted strings containing the entire
40 long-form ASCII function name. Matching is done case-independently.
41
42#endif /*COMMENT*/
43
44
45
46#include "eesite.h" /* Site specific stuff if any */
47#include <stdio.h>
48#include <ctype.h>
49#include <unistd.h>
50#include "eeprof.h" /* Profile structure definition */
51
52
53#define EFUNMAX 400 /* Maximum # (+1) of functions that can be defined */
54#define KBTSIZ (128*2) /* Initial size of key binding tables */
55
56
57/* EFUN Function definition table.
58** Functions that were copied from the pre-defined table will
59** have a value of NULL in ef_mod.
60*/
61struct fun {
62 int ef_idx; /* Function index (same as index of entry) */
63 char *ef_name; /* Function name */
64 char *ef_adr; /* C routine name in ELLE */
65 char *ef_mod; /* Source module that C routine lives in */
66};
67struct fun efuntab[EFUNMAX];
68int efxmax = 0; /* Largest function idx used */
69
70int format_ver = PROF_VER; /* Current version # of binary profile fmt */
71
72/* Keybind mapping tables. There are four separate tables:
73** Simple character. Always 128 single-byte items, indexed by the simple
74** command char. Each item is the corresponding function index.
75** Meta char. Variable number of 2-byte items; first is a command char
76** and second is its function index.
77** Extended char. Same format as Meta char.
78** Menu item (SUN only). Variable number of single-byte items, each
79** a function index.
80**
81*/
82char *chrptr; /* Pointer to simple-char table */
83int chrsiz = 128; /* Current size of table */
84int chrcnt = 0; /* # bytes actually used */
85
86char *mtaptr; /* Pointer to meta-char table */
87int mtasiz = KBTSIZ; /* Current size (twice the # of items) */
88int mtacnt = 0; /* # bytes actually used */
89
90char *extptr; /* Pointer to ext-char table */
91int extsiz = KBTSIZ; /* Current size (twice the # of items) */
92int extcnt = 0; /* # bytes actually used */
93
94char *mnuptr; /* Pointer to menu-item table (SUN only) */
95int mnusiz = KBTSIZ; /* Current size */
96int mnucnt = 0; /* # bytes actually used */
97
98
99#define CB_EXT 0400 /* "X-" prefix on command char */
100#define CB_META 0200 /* "M-" prefix on command char */
101
102
103/* Set up the pre-defined data areas. This includes the
104** predefined function table plus the default profile (keyboard mappings).
105** Note this only contains entries for ef_name and ef_adr.
106*/
107
108struct fun pdfuntab[] = { /* Pre-Defined Function table */
109#define EFUN(rtn,rtnstr,name) 0, name, rtnstr, 0,
110#define EFUNHOLE 0, 0, 0, 0,
111#include "eefdef.h"
112};
113int npdfuns = sizeof(pdfuntab)/sizeof(struct fun); /* # of entries */
114
115#include "defprf.c" /* Insert default profile mapping */
116 /* This defines charmap, metamap, and extmap. */
117
118
119/* Stuff for feeble-minded list processor */
120#define NIL ((struct lnode *)0)
121#define LTRUE (&ltruenode)
122
123#define LT_VAL 0
124#define LT_STR 1
125#define LT_LIST 2
126#define LT_ATOM 3 /* Should use this later instead of LT_STR */
127
128struct lnode {
129 struct lnode *lnxt;
130 int ltyp;
131 union {
132 int lvi;
133 char *lvs;
134 struct lnode *lvl;
135 } lval;
136};
137
138struct lnode ltruenode; /* Constant TRUE */
139
140_PROTOTYPE(int main , (int argc , char **argv ));
141_PROTOTYPE(int doargs , (int argc , char **argv ));
142_PROTOTYPE(char **findkey , (char *cp , char ***aretp , char **tabp , int tabsiz , int elsize ));
143_PROTOTYPE(int nstrcmp , (char *s1 , char *s2 ));
144_PROTOTYPE(int ustrcmp , (char *s1 , char *s2 ));
145_PROTOTYPE(int strueq , (char *s1 , char *s2 ));
146_PROTOTYPE(int do_opcod , (void));
147_PROTOTYPE(int do_opasc , (void));
148_PROTOTYPE(int outkbind , (int c , int fx ));
149_PROTOTYPE(int do_obprof , (void));
150_PROTOTYPE(int mupcase , (int ch ));
151_PROTOTYPE(int upcase , (int ch ));
152_PROTOTYPE(char *qstr , (char *str ));
153_PROTOTYPE(char *charep , (int c ));
154_PROTOTYPE(int do_ocnf , (char *str ));
155_PROTOTYPE(int do_ofcod , (void));
156_PROTOTYPE(int do_ofasc , (void));
157_PROTOTYPE(int do_ofxcod , (void));
158_PROTOTYPE(int compile_stdin , (void));
159_PROTOTYPE(int lrch , (void));
160_PROTOTYPE(struct lnode *lread , (void));
161_PROTOTYPE(int wspfls , (void));
162_PROTOTYPE(struct lnode *lrstr , (int flg ));
163_PROTOTYPE(int islword , (int c ));
164_PROTOTYPE(struct lnode *eval , (struct lnode *lp ));
165_PROTOTYPE(struct lnode *undefall , (struct lnode *lp ));
166_PROTOTYPE(struct lnode *efun , (struct lnode *lp ));
167_PROTOTYPE(struct lnode *keybind , (struct lnode *lp ));
168_PROTOTYPE(struct lnode *keyallun , (void));
169_PROTOTYPE(struct lnode *menuitem , (struct lnode *lp ));
170_PROTOTYPE(int repchar , (char *str ));
171_PROTOTYPE(struct lnode *getln , (void));
172_PROTOTYPE(int numcvt , (char *str , int *anum ));
173_PROTOTYPE(int listcnt , (struct lnode *lp ));
174_PROTOTYPE(char *funname , (int i ));
175_PROTOTYPE(int findfun , (char *name ));
176_PROTOTYPE(int funcnt , (int *arr ));
177_PROTOTYPE(int scpy , (char *from , char *to , int cnt ));
178_PROTOTYPE(char *stripsp , (char *cp ));
179
180int warn();
181int lerr();
182int fatal();
183
184
185
186/* ELLEC argument stuff */
187char *argfile;
188char *outfile;
189int swfilter; /* If no args */
190int swprof; /* -P */
191int swelle; /* -E */
192
193int uproflg; /* Do compilation of user's profile */
194int swpcnf; /* Output defprf.c (C initialization of profile) */
195int swfcnf; /* Output eefdef.h */
196int swfxcnf; /* Output eefidx.h */
197int swcmcnf; /* Output config makefile (makecf.fun) */
198char *swcscnf; /* Output config specially (for V6) */
199int swallc; /* Do all of config stuff */
200int swfdmp; /* Output deffun.e */
201int nfiles; /* # file specs seen */
202
203main(argc,argv)
204int argc;
205char **argv;
206{ register int i;
207 register char *cp;
208 char temp[300];
209
210 /* Initialize LTRUE
211 ** (cannot portably initialize a union at compile time)
212 */
213 ltruenode.ltyp = LT_VAL; /* Set type (other fields zero) */
214
215 /* Process switches */
216 if(argc <= 1) swfilter++; /* If no args, assume filter */
217 else doargs(argc,argv);
218
219 /* Initialize function definitions and key bindings from predefs */
220 chrptr = malloc(chrsiz);
221 mtaptr = malloc(mtasiz);
222 extptr = malloc(extsiz);
223 mnuptr = malloc(mnusiz);
224 if (!chrptr || !mtaptr || !extptr || !mnuptr)
225 fatal("cannot init, no memory");
226
227 scpy(charmap, chrptr, (chrcnt = sizeof(charmap)));
228 scpy(metamap, mtaptr, (mtacnt = sizeof(metamap)));
229 scpy( extmap, extptr, (extcnt = sizeof(extmap)));
230 if(def_prof.menuvec)
231 scpy(def_prof.menuvec, mnuptr, (mnucnt = def_prof.menuvcnt));
232
233 for(i = 0; i < npdfuns; ++i) /* Initialize function defs */
234 if(pdfuntab[i].ef_name)
235 { efuntab[i].ef_idx = i;
236 efuntab[i].ef_name = pdfuntab[i].ef_name;
237 efuntab[i].ef_adr = stripsp(pdfuntab[i].ef_adr);
238 if(efxmax < i) efxmax = i;
239 }
240
241
242 /* Routines expect input from stdin and output their results
243 * to stdout.
244 */
245 if(argfile)
246 if(freopen(argfile,"r",stdin) == NULL)
247 fatal("cannot open input file \"%s\"",argfile);
248 if(outfile)
249 if(freopen(outfile,"w",stdout) == NULL)
250 fatal("cannot open output file \"%s\"",outfile);
251
252
253 /* Check for general compilation */
254 if(swfilter)
255 { /* Not really implemented yet */
256 fatal("bad usage, see doc");
257 }
258
259 /* Do profile hacking of some kind */
260 if(swprof || swelle)
261 { if (compile_stdin()) /* Compile input profile */
262 { if(swprof)
263 do_opasc(); /* Output ASCII profile (.e) */
264 else if(swelle)
265 do_opcod(); /* Output bin profile (.b1) */
266 }
267 exit(0);
268 }
269
270 /* Check for variousness */
271 if(swpcnf)
272 { if(compile_stdin()) /* Compile input */
273 do_opcod(); /* Output the C initialization code */
274 exit(0);
275 }
276 if(swfxcnf)
277 { if(compile_stdin()) /* Compile input */
278 do_ofxcod(); /* Output the eefidx.h code */
279 exit(0);
280 }
281 if(swfcnf)
282 { if(compile_stdin()) /* Compile input */
283 do_ofcod(); /* Output the eefdef.h code */
284 exit(0);
285 }
286 if(swcmcnf || swcscnf)
287 { if(compile_stdin()) /* Compile input */
288 do_ocnf(swcscnf); /* Output the makecf.fun code */
289 exit(0);
290 }
291 if(swfdmp)
292 { if(compile_stdin()) /* Compile input */
293 do_ofasc(); /* Output the deffun.e code */
294 exit(0);
295 }
296
297
298 /* Hack user's profile */
299 if(!uproflg) exit(0);
300 if(!argfile)
301 {
302 temp[0] = 0;
303#if !V6
304 if (cp = getenv("HOME"))
305 strcat(temp, cp);
306#if !TOPS20
307 strcat(temp,"/");
308#endif /*-TOPS20*/
309#endif /*-V6*/
310 strcat(temp, EVPROFTEXTFILE);
311 if(freopen(temp,"r",stdin) == NULL)
312 fatal("cannot open profile \"%s\"",temp);
313 }
314 if(!outfile)
315 {
316 temp[0] = 0;
317#if !V6
318 if (cp = getenv("HOME"))
319 strcat(temp, cp);
320#if !TOPS20
321 strcat(temp,"/");
322#endif /*-TOPS20*/
323#endif /*-V6*/
324 strcat(temp, EVPROFBINFILE);
325 if(freopen(temp,"wb",stdout) == NULL /* Try binary 1st */
326 && freopen(temp,"w",stdout) == NULL)
327 fatal("cannot open output profile \"%s\"",temp);
328
329 }
330 /* Hack user's profile */
331 if(compile_stdin()) /* Compile input profile */
332 do_obprof(); /* Output the binary */
333
334}
335
336
337#define SW_FLG 0
338#define SW_VAR 1
339#define SW_STR 2
340struct swarg {
341 char *sw_name;
342 long sw_type;
343 int *sw_avar;
344 char **sw_astr;
345} swtab[] = {
346 "P", SW_FLG, &swprof, 0, /* Old stuff */
347 "E", SW_FLG, &swelle, 0,
348 "Profile", SW_FLG, &uproflg, 0,
349 "Pconf", SW_FLG, &swpcnf, 0,
350 "Fconf", SW_FLG, &swfcnf, 0,
351 "FXconf", SW_FLG, &swfxcnf, 0,
352 "CMconf", SW_FLG, &swcmcnf, 0,
353 "CSconf", SW_STR, 0, &swcscnf,
354 "Allconf", SW_FLG, &swallc, 0,
355 "Pdump", SW_FLG, &swprof, 0,
356 "Fdump", SW_FLG, &swfdmp, 0
357};
358
359doargs(argc,argv)
360int argc;
361char **argv;
362{ register int cnt, c;
363 register char **av;
364 register int i;
365 register struct swarg *swp;
366 struct swarg *swp2;
367 int swerrs = 0;
368
369 av = argv;
370 cnt = argc;
371 nfiles = 0;
372
373 while(--cnt > 0)
374 { ++av;
375 if(*av[0] != '-') /* If not switch, */
376 { /* assume it's an input filename */
377 nfiles++;
378 continue;
379 }
380 av[0]++;
381
382 /* Try to look up switch in table */
383 swp = (struct swarg *)findkey(av[0], &swp2, swtab,
384 (sizeof(swtab))/(sizeof(struct swarg)),
385 (sizeof(struct swarg))/(sizeof(char *)));
386 if(swp2)
387 { fprintf(stderr,"ellec: ambiguous switch: -%s = %s or %s\n",
388 av[0], swp->sw_name, swp2->sw_name);
389 goto swdone;
390 }
391 if(swp) switch(swp->sw_type)
392 { case SW_FLG:
393 *(swp->sw_avar) = 1;
394 goto swdone;
395 case SW_VAR:
396 *(swp->sw_avar) = 1;
397 if(cnt <= 1) goto swdone;
398 if(isdigit(*av[1]))
399 { *(swp->sw_avar) = atoi(av[1]);
400 --cnt;
401 goto swargdone;
402 }
403 goto swdone;
404
405 case SW_STR:
406 if(cnt <= 1) goto swdone;
407 *(swp->sw_astr) = av[1];
408 goto swargdone;
409
410 default:
411 fprintf(stderr,"ellec: bad switch type: %s\n",
412 av[0]);
413 swerrs++;
414 }
415
416 stop: fprintf(stderr,"ellec: bad switch: %s\n",*av);
417 swerrs++;
418 goto swdone;
419 swargdone:
420 av[0] = 0;
421 av++;
422 swdone: av[0] = 0;
423 }
424 if(swerrs) exit(1); /* Stop if any problems */
425}
426
427char **
428findkey(cp, aretp, tabp, tabsiz, elsize)
429register char *cp;
430char ***aretp;
431register char **tabp;
432int tabsiz, elsize;
433{ register char **mp1, **mp2;
434 register int i, res;
435
436 *aretp = mp1 = mp2 = 0;
437 for(i = 0; i < tabsiz; ++i, tabp += elsize)
438 { if(res = ustrcmp(cp,*tabp))
439 { if(res > 0) return(tabp);
440 if(!mp1) mp1 = tabp;
441 else mp2 = tabp;
442 }
443 }
444 if(mp2)
445 *aretp = mp2; /* Ambiguous */
446 return(mp1);
447}
448
449/* NSTRCMP - New string compare.
450 * Returns:
451 * 2 if str2 > str1 (mismatch)
452 * 1 if str2 counted out (str1 > str2)
453 * 0 if full match
454 * -1 if str1 counted out (str1 < str2)
455 * -2 if str1 < str2 (mismatch)
456 */
457
458nstrcmp(s1,s2)
459register char *s1, *s2;
460{ register int c, d;
461
462 while(c = *s1++)
463 { if(c != *s2)
464 { if((d = upcase(c) - upcase(*s2)) != 0)
465 return(*s2==0 ? 1 : (d > 0 ? 2 : -2));
466 }
467 ++s2;
468 }
469 return(*s2 ? -1 : 0);
470}
471
472/* USTRCMP - uppercase string compare.
473 * Returns 0 if mismatch,
474 * 1 if full match,
475 * -1 if str1 runs out first (partial match)
476 */
477ustrcmp(s1,s2)
478register char *s1, *s2;
479{ register int c;
480
481 if ( ! s1 || ! s2 ) return ( 0 ); /* Check for null ptr */
482 while(c = *s1++)
483 { if(c != *s2)
484 { if(((c ^ *s2) != 040)
485 || (upcase(c) != upcase(*s2)))
486 return(0);
487 }
488 s2++;
489 }
490 return(c == *s2 ? 1 : -1);
491}
492
493strueq(s1,s2)
494char *s1;
495char *s2;
496{ return (ustrcmp(s1, s2) > 0 ? 1 : 0);
497}
498
499
500/* Output C initialization code for default profile (defprf.c) */
501
502do_opcod()
503{ register int i, c, f;
504
505 printf("\
506/* This file defines the initial data for ELLE's default user profile.\n\
507** It is automatically generated by ELLEC, and should not be edited.\n\
508*/\n\
509char charmap[] = {\n");
510 for(i=0; i < chrcnt; i++)
511 { printf("\t%2d,",(f = chrptr[i]&0377));
512 printf("\t/* (%3o) %3s",i,charep(i));
513 printf(" %s",funname(f));
514 printf(" */\n");
515 }
516
517 printf("};\n char metamap[] = {\n");
518 for(i = 0; i < mtacnt; i += 2)
519 { printf("\t0%-3o,%3d,",(c = mtaptr[i]&0377),(f = mtaptr[i+1]&0377));
520 printf("\t/* %4s",charep(c|CB_META));
521 printf(" %s",funname(f));
522 printf(" */\n");
523 }
524
525 printf("};\n char extmap[] = {\n");
526 for(i = 0; i < extcnt; i += 2)
527 { printf("\t0%-3o,%3d,",(c = extptr[i]&0377),(f = extptr[i+1]&0377));
528 printf("\t/* %4s",charep(c|CB_EXT));
529 printf(" %s",funname(f));
530 printf(" */\n");
531 }
532 printf("};\n");
533 printf("struct profile def_prof = {\n");
534 printf(" %d, /* Ver */\n", format_ver);
535 printf(" sizeof(charmap), charmap,\n");
536 printf(" sizeof(metamap)/2, metamap,\n");
537 printf(" sizeof(extmap)/2, extmap, \n");
538 printf(" 0, 0\n");
539 printf("};\n");
540
541}
542
543
544/* Output ASCII version of default profile */
545
546int oerrs;
547
548do_opasc()
549{ register int i, c, f;
550
551 oerrs = 0;
552 printf("; ELLE default ASCII profile\n\n");
553 printf("(keyallunbind) ; To flush all existing bindings\n\n");
554 for(i=0; i < chrcnt; i++)
555 outkbind(i, chrptr[i]&0377);
556
557 printf("\n; Meta chars\n\n");
558 for(i = 0; i < mtacnt; i += 2)
559 outkbind(CB_META | (mtaptr[i]&0377), mtaptr[i+1]&0377);
560
561 printf("\n ; Extended commands\n\n");
562 for(i = 0; i < extcnt; i += 2)
563 outkbind(CB_EXT | (extptr[i]&0377), extptr[i+1]&0377);
564
565 printf("\n");
566 if(oerrs)
567 fatal("%d errors encountered, check output file.", oerrs);
568}
569
570outkbind(c, fx)
571{
572 if(fx == 0) /* Allow key to be mapped to nothing. */
573 return;
574 if(fx <= 0 || fx > efxmax)
575 printf(";INTERNAL ERROR: Bad function index %d for key %s\n",
576 fx, charep(c));
577 else if(efuntab[fx].ef_name == NULL)
578 printf(";INTERNAL ERROR: No name for function %d while mapping key %s\n",
579 fx, charep(c));
580 else {
581 printf("(keybind %s \"%s\")\n",
582 qstr(charep(c)),efuntab[fx].ef_name);
583 return;
584 }
585 oerrs++;
586}
587
588
589/* Output binary user profile */
590
591do_obprof()
592{ register unsigned int rp; /* Relative "pointer" */
593 struct stored_profile st_prof;
594
595 rp = sizeof(st_prof); /* Initialize */
596
597 /* Fixed by Kochin Chang, July 1995 */
598 /* format version should be the first field in compiled profile */
599 prof_pack(st_prof.version, format_ver);
600
601 prof_pack(st_prof.chrvec, rp);
602 prof_pack(st_prof.chrvcnt, chrcnt);
603 rp += chrcnt;
604
605 prof_pack(st_prof.metavec, rp);
606 prof_pack(st_prof.metavcnt, mtacnt/2);
607 rp += mtacnt;
608
609 prof_pack(st_prof.extvec, rp);
610 prof_pack(st_prof.extvcnt, extcnt/2);
611 rp += extcnt;
612
613 prof_pack(st_prof.menuvec, rp);
614 prof_pack(st_prof.menuvcnt, mnucnt);
615 rp += mnucnt;
616
617 fwrite((char *)&st_prof,sizeof(st_prof),1,stdout);
618 fwrite(chrptr,sizeof(char),chrcnt,stdout);
619 if(mtacnt) fwrite(mtaptr, sizeof(*mtaptr), mtacnt, stdout);
620 if(extcnt) fwrite(extptr, sizeof(*extptr), extcnt, stdout);
621 if(mnucnt) fwrite(mnuptr,sizeof(*mnuptr),mnucnt,stdout);
622}
623
624/* Return upper-case version of character */
625mupcase(ch)
626register int ch;
627{ return((ch&(~0177)) | upcase(ch));
628}
629upcase (ch)
630{ register int c;
631 c = ch&0177;
632 return((('a' <= c) && (c <= 'z')) ? (c - ('a'-'A')) : c);
633}
634
635char *
636qstr(str)
637register char *str;
638{ register int c;
639 static char qstrbuf[100];
640 register char *cp;
641 cp = str;
642 while((c = *cp++) && islword(c));
643 if(c == 0) return(str); /* No quoting needed */
644
645 cp = qstrbuf;
646 *cp++ = '"';
647 while(*cp++ = c = *str++)
648 if(c == '"') *cp++ = c; /* Double the quotes */
649 cp[-1] = '"';
650 *cp = 0;
651 return(qstrbuf);
652}
653
654char *
655charep(c)
656register int c;
657{ static char chrbuf[10];
658 register char *cp;
659 cp = chrbuf;
660 if(c&CB_EXT)
661 { *cp++ = 'X';
662 *cp++ = '-';
663 c &= ~CB_EXT;
664 }
665 if(c&CB_META)
666 { *cp++ = 'M';
667 *cp++ = '-';
668 c &= ~CB_META;
669 }
670 if(c <= 037)
671 { *cp++ = '^';
672 c += 0100;
673 }
674 if(c == 0177)
675 { *cp++ = 'D';
676 *cp++ = 'E';
677 *cp++ = 'L';
678 }
679 else *cp++ = c;
680 *cp = 0;
681 return(chrbuf);
682}
683
684
685/* Output config Makefile (makecf.fun)
686 * If argument is 0 (NULL), does Makefile type output.
687 * Otherwise uses string for special-purpose output.
688 */
689do_ocnf(str)
690char *str;
691{ register struct fun *fnp;
692 register int i, mi;
693 register char *cp;
694 int fmtab[EFUNMAX];
695 int nfmods;
696 char *modtab[EFUNMAX];
697 char *unknown = "unknown-module";
698
699 if(str == NULL) /* If not V6 version */
700 { printf("# Function module definition file, generated by ELLEC\n");
701 printf("FUN_OFILES = ");
702 }
703
704 nfmods = 0;
705
706 funcnt(fmtab); /* Count function occs */
707
708 for(i = 1; i <= efxmax; ++i)
709 { if(fmtab[i] == 0) continue;
710 fnp = &efuntab[i];
711
712 if(fnp->ef_name == 0)
713 fatal("internal error - no name for function %d", i);
714
715 /* Got a function, store its module name if not a dup */
716 if ((cp = fnp->ef_mod) == NULL) /* Substitute if undef */
717 cp = unknown;
718 for(mi=0; mi < nfmods; ++mi)
719 if(ustrcmp(cp, modtab[mi]) > 0)
720 break;
721 if(mi < nfmods) continue;
722 modtab[nfmods++] = cp;
723 }
724
725 /* Now have table of all modules used. Crunch them into output. */
726 for(mi=0; mi < nfmods; ++mi)
727 if (modtab[mi] != unknown)
728 { if(str != NULL) /* V6 version? */
729 printf("%s %s\n", str, modtab[mi]);
730 else printf("\\\n\t%s.o", modtab[mi]);
731 }
732 printf("\n");
733}
734
735
736/* Output eefdef.h */
737
738do_ofcod()
739{ register struct fun *fnp;
740 register int i;
741 char temp[40];
742 int fmtab[EFUNMAX];
743
744 printf("/* .H Function Definition file, generated by ELLEC */\n");
745 printf("/* 0 */ EFUNHOLE /* Always undefined */\n");
746
747 funcnt(fmtab); /* Count function occs */
748
749 for(i = 1; i <= efxmax ; ++i)
750 {
751 fnp = &efuntab[i];
752 printf("/* %3d */ ", i);
753 if(fmtab[i] == 0 || fnp->ef_name == 0)
754 printf("EFUNHOLE\n");
755 else
756 { sprintf(temp, "\"%s\"", fnp->ef_adr);
757 printf("EFUN( %-12s, %-14s, \"%s\")\n", fnp->ef_adr,
758 temp, fnp->ef_name);
759 }
760 }
761
762}
763
764
765/* Output ascii version of function def file
766*/
767do_ofasc()
768{ register struct fun *fnp;
769 register int i;
770 register char *fa, *fm;
771
772 printf("; Master Function Definition file\n");
773
774 for(i = 1; i <= efxmax ; ++i)
775 {
776 fnp = &efuntab[i];
777 if(fnp->ef_idx == 0) /* No definition for this index? */
778 continue;
779 if(fnp->ef_name == 0)
780 { warn("internal error - no name for function %d", i);
781 continue;
782 }
783
784 if ((fa = fnp->ef_adr) == NULL)
785 fa = "unknown-addr";
786 if ((fm = fnp->ef_mod) == NULL)
787 fm = "unknown-module";
788 printf("(efun %d \"%s\" %s %s)\n",
789 fnp->ef_idx, fnp->ef_name, fa, fm);
790 }
791}
792
793
794/* Output eefidx.h */
795
796do_ofxcod()
797{ register struct fun *fnp;
798 register int i;
799 register char *cp, *cp2;
800 int fmtab[EFUNMAX];
801 char tmpstr[100];
802
803 printf("\
804/* .H Function Index Definition file, generated by ELLEC */\n");
805 printf("\
806/* FN_ defines Function Numbers (indices) for all known functions */\n");
807 printf("\
808/* FX_ defines Function eXistence in this ELLE configuration */\n");
809
810 funcnt(fmtab); /* Count function occs */
811
812 for(i = 1; i <= efxmax ; ++i)
813 {
814 fnp = &efuntab[i];
815 if(fnp->ef_idx == 0) /* No definition for this index? */
816 continue;
817 if(fnp->ef_adr == 0 || fnp->ef_name == 0)
818 { warn("internal error - no addr/name for function %d", i);
819 continue;
820 }
821
822 cp2 = fnp->ef_adr;
823 cp = tmpstr;
824 while(*cp++ = upcase(*cp2++));
825 cp = tmpstr;
826 if((*cp++ != 'F') || (*cp++ != '_'))
827 cp = tmpstr;
828
829 /* Always define FN_ as index */
830 printf("#define FN_%-14s %3d /* %s */\n",
831 cp, i, fnp->ef_name);
832 /* Define FX_ as 0 if unused, else same as FN_ */
833 printf("#define FX_%-14s %3d\n", cp,
834 (fmtab[i] == 0) ? 0 : i); /* 0 if unused */
835 }
836
837}
838
839
840/* Compile input! */
841
842compile_stdin()
843{ register struct lnode *lp;
844
845 while((lp = lread()) != NIL)
846 eval(lp);
847
848 return(1);
849}
850
851
852#define MAXLINE 300
853int llstch = -1;
854int leofflg;
855#define unlrch(c) llstch = c
856
857int lineno = 0;
858char linebuf[MAXLINE];
859char *linecp = linebuf;
860
861lrch()
862{ register int c;
863 if((c = llstch) >= 0)
864 { if(c == 0 && leofflg)
865 return(EOF);
866 llstch = -1;
867 return(c);
868 }
869 if((c = getc(stdin)) == EOF)
870 { leofflg = 1;
871 llstch = 0;
872 *linecp = 0;
873 linecp = linebuf;
874 return(c);
875 }
876 if(c == '\n')
877 { lineno++;
878 linecp = linebuf;
879 }
880 else *linecp++ = c;
881 return(c);
882}
883
884struct lnode *
885lread()
886{ register int c;
887 register struct lnode *lp, *lp2;
888 struct lnode *head;
889
890 wspfls();
891 if((c = lrch())== EOF)
892 return(NIL);
893 if(c == ')') /* End of a list? */
894 return(NIL);
895 if(c == '(') /* Start of a list? */
896 { head = lp = getln();
897 lp->ltyp = LT_LIST;
898 if((head->lval.lvl = lp = lread()) == NIL)
899 return(head); /* Return empty list */
900 while(lp2 = lread())
901 { lp->lnxt = lp2;
902 lp = lp2;
903 }
904 return(head);
905 }
906
907 /* Atom of some kind */
908 if(c=='"')
909 { return(lrstr(1));
910 }
911 unlrch(c);
912 return(lrstr(0));
913}
914
915wspfls()
916{ register int c;
917 for(;;)
918 { c = lrch();
919 if(isspace(c)) continue;
920 if(c == ';')
921 while((c = lrch()) != '\n')
922 if(c == EOF) return;
923 break;
924 }
925 if(c != EOF) unlrch(c);
926}
927
928#define LSMAX 300 /* Max # chars in atom string */
929struct lnode *
930lrstr(flg)
931{ char cbuf[LSMAX];
932 register char *cp;
933 register int c, i;
934 struct lnode *lp;
935
936 cp = cbuf;
937 i = 0;
938
939 while((c = lrch()) != EOF)
940 if (flg) switch(c)
941 { case '"':
942 if((c = lrch()) == EOF)
943 return(NIL);
944 if(c != '"')
945 { unlrch(c);
946 goto out;
947 }
948 default:
949 ok:
950 if(++i > LSMAX)
951 break;
952 *cp++ = c;
953 continue;
954 }
955 else
956 { if(islword(c)) goto ok;
957 unlrch(c);
958 break;
959 }
960 out:
961 lp = getln();
962 lp->ltyp = LT_STR;
963 lp->lval.lvs = malloc(i+1);
964 *cp = 0;
965 strcpy(lp->lval.lvs, cbuf);
966 return(lp);
967}
968islword(c)
969{ return((040 < c && c < 0177
970 && c != '(' && c !=')' && c != ';'
971 && c != '"' && c != '\\') ? 1 : 0);
972}
973
974
975
976struct lnode *keybind(), *keyallun(), *menuitem(), *efun(),
977 *undefall();
978
979struct lfun {
980 char *lfname; /* Name of list function */
981 struct lnode * (*lfrtn)(); /* Function address */
982} lfntab[] = {
983 "keybind", keybind,
984 "efun", efun,
985 "menuitem", menuitem,
986 "keyallunbind", keyallun,
987/* "keyunbind", keyunbind, */ /* Not yet */
988 "undefall", undefall,
989/* "undef", undef, */ /* Not yet */
990 0, 0
991};
992
993struct lnode *
994eval(lp)
995register struct lnode *lp;
996{ register struct lnode *flp;
997 register struct lfun *lfent;
998
999 if(lp->ltyp != LT_LIST)
1000 return(lp);
1001 if((flp = lp->lval.lvl) == NIL)
1002 return(NIL);
1003 if(flp->ltyp != LT_STR)
1004 return(NIL);
1005
1006 /* Look up list function and invoke it */
1007 for(lfent = lfntab; lfent->lfname; lfent++)
1008 if(strueq(flp->lval.lvs, lfent->lfname))
1009 return((*(lfent->lfrtn))(flp->lnxt));
1010
1011 lerr("unknown op: (%s)", flp->lval.lvs);
1012 return(NIL);
1013}
1014
1015
1016
1017/* UNDEFALL - (undefall)
1018** Undefines all functions. Typically used to clear out
1019** predefined functions prior to compiling a set of new efuns.
1020*/
1021struct lnode *
1022undefall(lp)
1023register struct lnode *lp;
1024{
1025 register int i;
1026 efxmax = 0; /* Say nothing in function def table! */
1027 for(i = 0; i < EFUNMAX; ++i)
1028 { efuntab[i].ef_idx = 0;
1029 efuntab[i].ef_name = 0;
1030 efuntab[i].ef_adr = 0;
1031 efuntab[i].ef_mod = 0;
1032 }
1033 return(LTRUE);
1034}
1035
1036
1037/* EFUN - (efun <index> <functionname> <address> <module>)
1038** Checks out the args and if no problems, stores the function
1039** definition in efuntab.
1040*/
1041struct lnode *
1042efun(lp)
1043register struct lnode *lp;
1044{ struct lnode *nlp;
1045 register int c, i;
1046 register struct fun *fnp;
1047 char *fname, *faddr, *fmod;
1048 int fni, num;
1049
1050 if(listcnt(lp) < 4)
1051 { lerr("efun - not enough args");
1052 return(NIL);
1053 }
1054
1055 /* First thing should be function index */
1056 switch(lp->ltyp)
1057 { case LT_VAL:
1058 fni = lp->lval.lvi;
1059 break;
1060 case LT_STR:
1061 if(numcvt(lp->lval.lvs, &num))
1062 { fni = num;
1063 break;
1064 }
1065 default:
1066 lerr("efun - non-value function index");
1067 return(NIL);
1068 }
1069
1070 /* Next thing should be function name */
1071 lp = lp->lnxt;
1072 if(lp->ltyp != LT_STR) /* Function name not a string */
1073 { lerr("efun - non-string function name");
1074 return(NIL);
1075 }
1076 fname = lp->lval.lvs;
1077
1078 /* Next thing should be function addr */
1079 lp = lp->lnxt;
1080 if(lp->ltyp != LT_STR) /* Function addr not a string */
1081 { lerr("efun - non-string function addr");
1082 return(NIL);
1083 }
1084 faddr = lp->lval.lvs;
1085
1086 /* Next thing should be function module */
1087 lp = lp->lnxt;
1088 if(lp->ltyp != LT_STR) /* Function module not a string */
1089 { lerr("efun - non-string function module");
1090 return(NIL);
1091 }
1092 fmod = lp->lval.lvs;
1093
1094 /* Now see if already exists or anything */
1095 if(fni <= 0 || fni > EFUNMAX)
1096 { lerr("efun - bad function index %d", fni);
1097 return(NIL);
1098 }
1099 fnp = &efuntab[fni];
1100 if(fnp->ef_idx != 0)
1101 {
1102 if (fnp->ef_idx == fni
1103 && strueq(fnp->ef_name, fname)
1104 && strueq(fnp->ef_adr, faddr)
1105 && (fnp->ef_mod == NULL || strueq(fnp->ef_mod, fmod)))
1106 goto win; /* Benign redefinition */
1107
1108lerr("efun - redefining function (%d \"%s\" %s %s)",
1109 fnp->ef_idx, fnp->ef_name, fnp->ef_adr,
1110 (fnp->ef_mod ? fnp->ef_mod : "unknown-module"));
1111 }
1112 for(i = 0; i < EFUNMAX; ++i)
1113 { if(efuntab[i].ef_idx == 0) continue;
1114 if(ustrcmp(efuntab[i].ef_adr,faddr) > 0
1115 || ustrcmp(efuntab[i].ef_name, fname) > 0)
1116 { if(i == fni) continue;
1117 lerr("efun - name or address dup! \"%s\"", fname);
1118 return(NIL);
1119 }
1120 }
1121
1122 /* No problems, store the function def in efuntab! */
1123win: fnp->ef_idx = fni;
1124 fnp->ef_mod = fmod;
1125 fnp->ef_adr = faddr;
1126 fnp->ef_name = fname;
1127
1128 if(efxmax < fni) efxmax = fni;
1129 return(LTRUE);
1130}
1131
1132
1133
1134/* KEYBIND - (keybind <charspec> <functionname>) */
1135
1136struct lnode *
1137keybind(lp)
1138register struct lnode *lp;
1139{ struct lnode *nlp;
1140 register int c, i;
1141 int fni;
1142
1143 if(lp == NIL || (nlp = lp->lnxt)== NIL)
1144 return(NIL);
1145 switch(lp->ltyp)
1146 { case LT_VAL:
1147 c = lp->lval.lvi;
1148 break;
1149 case LT_LIST:
1150 return(NIL);
1151 case LT_STR:
1152 c = repchar(lp->lval.lvs);
1153 break;
1154 }
1155 if(c == -1)
1156 return(NIL); /* No such command char name */
1157
1158 lp = nlp;
1159 if(lp->ltyp != LT_STR) /* Function name not a string */
1160 { lerr("(keybind) non-string function name");
1161 return(NIL);
1162 }
1163 fni = findfun(lp->lval.lvs);
1164 if(fni == 0) /* No such function name */
1165 { lerr("(keybind) no such function - \"%s\"", lp->lval.lvs);
1166 return(NIL);
1167 }
1168 if(c & CB_EXT)
1169 { c &= ~CB_EXT;
1170
1171 /* Check for redefinition */
1172 for(i = 0; i < extcnt; i += 2)
1173 if(c == (extptr[i]&0377)) /* Already there? */
1174 { if((extptr[i+1]&0377) != fni) /* Yes, check fn */
1175 lerr("(keybind) redefining X-%s as %d=\"%s\"",
1176 charep(c), fni, lp->lval.lvs);
1177 break;
1178 }
1179 if(i >= extcnt) /* Didn't find? */
1180 { if(extcnt >= extsiz)
1181 { lerr("(keybind) too many X- commands");
1182 return(NIL); /* Too many EXT cmds */
1183 }
1184 i = extcnt; /* Increase size of table */
1185 extcnt += 2;
1186 }
1187 /* Now store new binding */
1188 extptr[i] = c;
1189 extptr[i+1] = fni;
1190 }
1191 else if(c&CB_META)
1192 { c &= ~CB_META;
1193
1194 /* Check for redefinition */
1195 for(i = 0; i < mtacnt; i += 2)
1196 if(c == (mtaptr[i]&0377)) /* Already there? */
1197 { if((mtaptr[i+1]&0377) != fni) /* Yes, check fn */
1198 lerr("(keybind) redefining M-%s as %d=\"%s\"",
1199 charep(c), fni, lp->lval.lvs);
1200 break;
1201 }
1202 if(i >= mtacnt) /* Didn't find? */
1203 { if(mtacnt >= mtasiz)
1204 { lerr("(keybind) too many M- commands");
1205 return(NIL); /* Too many META cmds */
1206 }
1207 i = mtacnt; /* Increase size of table */
1208 mtacnt += 2;
1209 }
1210 /* Now store new binding */
1211 mtaptr[i] = c;
1212 mtaptr[i+1] = fni;
1213 }
1214 else {
1215 i = c & 0177;
1216 if (chrptr[i] && (chrptr[i]&0377) != fni)
1217 lerr("(keybind) redefining %s as %d=\"%s\"",
1218 charep(c), fni, lp->lval.lvs);
1219 chrptr[i] = fni;
1220 }
1221 return(LTRUE);
1222}
1223
1224/* KEYALLUNBIND - (keyallunbind) */
1225struct lnode *
1226keyallun()
1227{ register int i;
1228 register char *cp;
1229
1230/* fprintf(stderr, "ellec: clearing all key definitions\n"); */
1231 for(i = 0, cp = chrptr; i < chrcnt; i++)
1232 *cp++ = 0;
1233 mtacnt = extcnt = mnucnt = 0;
1234 return(LTRUE);
1235}
1236
1237
1238/* MENUITEM - (menuitem <functionname>) */
1239
1240struct lnode *
1241menuitem(lp)
1242register struct lnode *lp;
1243{ register int i, fni;
1244
1245 if(lp == NIL)
1246 return(NIL);
1247 switch(lp->ltyp)
1248 { case LT_VAL:
1249 fni = lp->lval.lvi;
1250 break;
1251 case LT_LIST:
1252 return(NIL);
1253 case LT_STR:
1254 fni = findfun(lp->lval.lvs);
1255 break;
1256 }
1257 if(fni == 0) return(NIL); /* Bad val or no such function name */
1258 for(i = 0; i < mnusiz; i++)
1259 if(fni == (mnuptr[i]&0377) || mnuptr[i] == 0)
1260 { mnuptr[i] = fni;
1261 mnucnt++;
1262 return(LTRUE);
1263 }
1264 return(NIL); /* Too many menu items */
1265}
1266
1267
1268repchar(str)
1269register char *str;
1270{ register int c;
1271 register int i, l;
1272
1273 if (str == 0) return (-1);
1274 i = 0;
1275 l = strlen(str);
1276 c = (*str++)&0377;
1277 if(l == 0) return(-1);
1278 if(l == 1) return(c); /* One-char representation */
1279 if(c == '^')
1280 if(l == 2) return((~0140) & mupcase(*str));
1281 else return(-1);
1282 c = mupcase(c);
1283 if (*str == '-')
1284 { if(*++str == 0) return(-1);
1285 switch(c)
1286 { case 'X': return(CB_EXT | mupcase(repchar(str)));
1287 case 'M': return(CB_META | mupcase(repchar(str)));
1288 case 'C': return((~0140) & repchar(str));
1289 }
1290 }
1291 if(c == 'S' && upcase(*str) == 'P' && l == 2)
1292 return(' ');
1293 if(c == 'D' && upcase(*str++) == 'E' && upcase(*str++) == 'L'
1294 && *str == 0)
1295 return(0177);
1296 return(-1);
1297}
1298
1299struct lnode *
1300getln()
1301{ return((struct lnode *)calloc(1,sizeof(struct lnode)));
1302}
1303
1304numcvt(str, anum)
1305char *str;
1306int *anum;
1307{ register char *cp;
1308 register int i, c, sign;
1309 if((cp = str) == 0)
1310 return 0;
1311 i = sign = 0;
1312 if(*cp == '-')
1313 cp++, sign++;
1314 while(c = *cp++)
1315 if(!isdigit(c)) return(0);
1316 else i = 10*i + (c - '0');
1317 *anum = sign ? -i : i;
1318 return(1);
1319}
1320
1321
1322
1323listcnt(lp)
1324register struct lnode *lp;
1325{ register int i;
1326 i = 0;
1327 while(lp)
1328 ++i, lp = lp->lnxt;
1329 return(i);
1330}
1331
1332
1333/* FUNNAME - Given function index, return function name.
1334** Always wins; returns "unknown" for bad indices.
1335*/
1336char *
1337funname(i)
1338register int i;
1339{
1340 register char *cp = NULL;
1341 if(0 < i && i <= efxmax && (cp = efuntab[i].ef_name))
1342 return cp;
1343 return("unknown function");
1344}
1345
1346findfun(name)
1347register char *name;
1348{ register int i;
1349 if((i = efxmax) > 0)
1350 { do { if(strueq(name, efuntab[i].ef_name))
1351 return(i);
1352 } while(--i);
1353 return(0);
1354 }
1355 return(0);
1356}
1357
1358
1359/* FUNCNT - Scan all key bindings, counting each occurrence of every
1360** function index.
1361** This is used to determine which functions are actually used.
1362*/
1363funcnt(arr)
1364register int *arr; /* Pointer to array of EFUNMAX ints */
1365{
1366 register int i;
1367
1368 for(i = 0; i < EFUNMAX; ++i) /* Clear the array */
1369 arr[i] = 0;
1370
1371 for(i = 0; i < chrcnt; ++i) /* Scan bindings */
1372 arr[chrptr[i]&0377]++;
1373 for(i = 0; i < mtacnt; i += 2)
1374 arr[mtaptr[i+1]&0377]++;
1375 for(i = 0; i < extcnt; i += 2)
1376 arr[extptr[i+1]&0377]++;
1377}
1378
1379scpy(from,to,cnt)
1380register char *from,*to;
1381register int cnt;
1382{ if(cnt > 0)
1383 do { *to++ = *from++; }
1384 while(--cnt);
1385}
1386
1387/* STRIPSP - strip spaces from string. Returns ptr to start. */
1388char *
1389stripsp(cp)
1390register char *cp;
1391{
1392 register char *ep, *lastp;
1393 while(*cp == ' ') ++cp;
1394 if (*cp)
1395 { ep = cp + strlen(cp); /* Point to null ending the str */
1396 while (*--ep == ' ');
1397 *++ep = 0; /* Tie it off */
1398 }
1399 return cp;
1400}
1401
1402
1403warn(str,a,b,c,d,e,f,g,h,i)
1404char *str;
1405{
1406 fprintf(stderr, "ellec: ");
1407 fprintf(stderr, str, a,b,c,d,e,f,g,h,i);
1408 fprintf(stderr, "\n");
1409}
1410
1411lerr(str,a,b,c,d,e,f,g,h,i)
1412char *str;
1413{
1414 warn(str, a,b,c,d,e,f,g,h,i);
1415 *linecp = 0; /* Tie off current line buffer */
1416 fprintf(stderr, " Line %d: %s\n", lineno, linebuf);
1417}
1418
1419fatal(str,a,b,c,d,e,f,g,h,i)
1420char *str;
1421{
1422 warn(str, a,b,c,d,e,f,g,h,i);
1423 exit(1);
1424}
1425
Note: See TracBrowser for help on using the repository browser.