1 /* This file is part of Mailfromd.
2 Copyright (C) 2006-2021 Sergey Poznyakoff
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 #include <stdlib.h>
21 #include "mailfromd.h"
22
23
24 #define BUCKETSIZE 16
25
26 struct symbucket {
27 struct symbucket *next;
28 size_t elsize;
29 size_t index;
30 char *buf;
31 };
32
33 struct _syment_align {
34 char c;
35 struct syment x;
36 };
37
38 #define __SYMENT_ALIGNMENT (offsetof(struct _syment_align, x))
39
40 #define __SYMENT_ALIGN(a, b) (((a) + (b) - 1) & ~((b) - 1))
41 #define SYMENT_SIZE(a) \
42 __SYMENT_ALIGN((a)->elsize,__SYMENT_ALIGNMENT)
43 #define __SYMENT(a,p,n) \
44 ((struct syment*) ((char*) (p) + SYMENT_SIZE(a) * (n)))
45 #define SYMENT(a,n) \
46 __SYMENT(a,(a)->buf,n)
47
48 static struct symbucket *symbucket;
49
50 /* Bucket handling */
51 static struct symbucket *
alloc_bucket(size_t elsize)52 alloc_bucket(size_t elsize)
53 {
54 size_t x;
55 size_t size;
56 struct symbucket *p;
57
58 x = __SYMENT_ALIGN(elsize,__SYMENT_ALIGNMENT);
59 size = ((sizeof(*p) + x - 1) / x) * x;
60 p = mu_alloc(size + x * BUCKETSIZE);
61 p->index = 0;
62 p->elsize = elsize;
63 p->buf = (char*)p + x;
64 p->next = symbucket;
65 return symbucket = p;
66 }
67
68 static struct symbucket *
find_bucket(size_t elsize)69 find_bucket(size_t elsize)
70 {
71 struct symbucket *sp;
72 for (sp = symbucket; sp; sp = sp->next)
73 if (sp->elsize == elsize && sp->index < BUCKETSIZE)
74 return sp;
75 return alloc_bucket(elsize);
76 }
77
78 static void *
alloc_entry(size_t size)79 alloc_entry(size_t size)
80 {
81 struct symbucket *bp = find_bucket(size);
82 size_t n = bp->index++;
83 struct syment *sym = SYMENT(bp, n);
84 memset(sym, 0, size);
85 sym->refcnt = 1;
86 return sym;
87 }
88
89 static void
free_entry(void * ptr)90 free_entry(void *ptr)
91 {
92 /* nothing */
93 }
94
95 static void
free_buckets()96 free_buckets()
97 {
98 struct symbucket *p = symbucket;
99 while (p) {
100 struct symbucket *next = p->next;
101 free(p);
102 p = next;
103 }
104 symbucket = NULL;
105 }
106
107
108 /* Import rules */
109 static int
make_transform_rule(struct import_rule * rule,const char * expr)110 make_transform_rule(struct import_rule *rule, const char *expr)
111 {
112 transform_t xform = transform_compile(expr, regex_flags);
113 if (!xform) {
114 parse_error(_("invalid transform string: %s"),
115 transform_error_string());
116 return 1;
117 }
118 rule->xform = xform;
119 rule->type = import_transform;
120 return 0;
121 }
122
123 static int
make_regex_rule(struct import_rule * rule)124 make_regex_rule(struct import_rule *rule)
125 {
126 char *start;
127 char *end;
128 int rc;
129 size_t len;
130 char *expr;
131 int neg = 0;
132
133 start = rule->literal->text;
134 if (start[0] == '!') {
135 neg = 1;
136 start++;
137 } else
138 neg = 0;
139 end = strchr(start + 1, start[0]);
140 start++;
141 if (!end)
142 return 1;
143 len = end - start;
144 expr = mu_alloc(len + 1);
145 memcpy(expr, start, len);
146 expr[len] = 0;
147 rc = regcomp(&rule->re, expr, regex_flags);
148 if (rc) {
149 char errbuf[512];
150 regerror(rc, &rule->re, errbuf, sizeof(errbuf));
151 parse_error(_("cannot compile regex (%s): %s"),
152 expr, errbuf);
153 free(expr);
154 return 1;
155 }
156 free(expr);
157 rule->neg = neg;
158 if (end[1] && make_transform_rule (rule, end + 1) == 0)
159 return 0;
160 rule->type = import_regex;
161 return 0;
162 }
163
164 struct import_rule *
import_rule_create(struct literal * lit)165 import_rule_create(struct literal *lit)
166 {
167 struct import_rule *rule = mu_alloc(sizeof(*rule));
168 rule->literal = lit;
169 rule->next = NULL;
170 if (mu_ispunct(lit->text[0]) && make_regex_rule(rule) == 0)
171 return rule;
172 rule->type = import_literal;
173 return rule;
174 }
175
176 void
import_rules_free(struct import_rule * rules)177 import_rules_free(struct import_rule *rules)
178 {
179 while (rules) {
180 struct import_rule *next = rules->next;
181 switch (rules->type) {
182 case import_literal:
183 break;
184 case import_transform:
185 transform_free(rules->xform);
186 /* fall through */
187 case import_regex:
188 regfree(&rules->re);
189 }
190 rules = next;
191 }
192 }
193
194 int
import_rules_eval(struct import_rule * rule,const char * name,char ** newname)195 import_rules_eval(struct import_rule *rule, const char *name,
196 char **newname)
197 {
198 int res;
199 regmatch_t *matches = NULL;
200 size_t matchsize = 0;
201 size_t matchcount;
202
203 if (!rule)
204 return 1;
205 res = 0;
206 *newname = NULL;
207 for (; res == 0 && rule; rule = rule->next) {
208 switch (rule->type) {
209 case import_literal:
210 res = strcmp(rule->literal->text, name) == 0;
211 break;
212
213 case import_regex:
214 case import_transform: /* FIXME */
215 matchcount = rule->re.re_nsub + 1;
216 if (matchsize < matchcount)
217 matches = mu_realloc(matches,
218 sizeof(matches[0]) * matchcount);
219 res = regexec(&rule->re, name, matchcount, matches, 0)
220 == 0;
221 if (rule->neg)
222 res = !res;
223 if (res && rule->type == import_transform) {
224 *newname = transform_string(rule->xform, name);
225 }
226 break;
227 }
228 }
229 free(matches);
230 return res;
231 }
232
233
234 struct symtab *stab_module;
235 struct symtab *stab_builtin;
236 struct symtab *stab_pragma;
237 struct symtab *stab_literal;
238 struct variable *builtin_variable_list;
239
240 struct symtab *
xsymtab_create(size_t elsize,int flags,void * (* alloc_fun)(size_t),void (* free_fun)(void *))241 xsymtab_create(size_t elsize, int flags,
242 void *(*alloc_fun)(size_t), void (*free_fun)(void *))
243 {
244 struct symtab *s = symtab_create(elsize, flags, alloc_fun, free_fun);
245 if (!s)
246 mu_alloc_die();
247 return s;
248 }
249
250 struct syment *
xsymtab_lookup(struct symtab * st,const char * name)251 xsymtab_lookup(struct symtab *st, const char *name)
252 {
253 struct syment *ep;
254 int rc = symtab_lookup_or_install(&ep, st, name, NULL);
255 switch (rc) {
256 case ENOMEM:
257 case E2BIG:
258 mu_error("%s", symtab_strerror(rc));
259 abort();
260 }
261 return rc == 0 ? ep : NULL;
262 }
263
264 struct builtin *
xsymtab_install_builtin(const char * name)265 xsymtab_install_builtin(const char *name)
266 {
267 struct syment *ep;
268 int install = 1;
269 int rc = symtab_lookup_or_install(&ep, stab_builtin, name, &install);
270 if (rc) {
271 parse_error(_("cannot install builtin function %s: %s"),
272 name, symtab_strerror(rc));
273 abort();
274 }
275 return (struct builtin*) ep;
276 }
277
278 void
import_builtin_variables(struct symtab * st)279 import_builtin_variables(struct symtab *st)
280 {
281 struct variable *var;
282
283 for (var = builtin_variable_list; var; var = var->next) {
284 int install;
285 struct syment *ent;
286
287 int rc = symtab_lookup_or_install_entry(&ent, st,
288 (struct syment *) var,
289 &install);
290 if (rc == 0 && !install) {
291 parse_error("INTERNAL ERROR at %s:%d: "
292 "cannot import builtin variable %s: %s",
293 __FILE__, __LINE__,
294 ((struct syment *) var)->name,
295 "variable already imported");
296 abort();
297 }
298 if (rc) {
299 parse_error("INTERNAL ERROR at %s:%d: "
300 "cannot import builtin variable %s: %s",
301 __FILE__, __LINE__,
302 ((struct syment *) var)->name,
303 symtab_strerror(rc));
304 abort();
305 }
306
307 }
308 }
309
310
311
312 struct symimport_closure {
313 struct module *module;
314 struct mu_locus_range locus;
315 struct import_rule *rules;
316 char *newname;
317 };
318
319 struct mf_symbol *
symbol_resolve_alias(struct mf_symbol * sp)320 symbol_resolve_alias(struct mf_symbol *sp)
321 {
322 if (sp) {
323 while (sp->alias)
324 sp = (struct mf_symbol *) sp->alias;
325 }
326 return sp;
327 }
328
329 int
import_selfun(const struct syment * ent,void * closure)330 import_selfun(const struct syment *ent, void *closure)
331 {
332 struct symimport_closure *sip = closure;
333 struct mf_symbol *sym = (struct mf_symbol*) ent;
334 return sym->module == sip->module
335 && (sym->module->flags == 0
336 || (sym->module->flags & SYM_PUBLIC)
337 || ((sym->module->flags & SYM_STATIC)
338 && (sym->flags & SYM_PUBLIC)))
339 && !(sym->flags & SYM_STATIC)
340 && import_rules_eval(sip->rules, ent->name, &sip->newname);
341 }
342
343 int
import_errfun(int rc,struct symtab * tab,const char * name,void * closure)344 import_errfun(int rc, struct symtab *tab, const char *name,
345 void *closure)
346 {
347 struct symimport_closure *sip = closure;
348 parse_error_locus(&sip->locus,
349 _("cannot import symbol `%s': %s"),
350 name, symtab_strerror(rc));
351 return rc;
352 }
353
354 int
import_confun(struct symtab * tab,struct syment * dstent,struct syment * srcent,void * closure)355 import_confun(struct symtab *tab,
356 struct syment *dstent, struct syment *srcent, void *closure)
357 {
358 struct symimport_closure *sip = closure;
359 struct mf_symbol *src = (struct mf_symbol*)srcent;
360 struct mf_symbol *dst = (struct mf_symbol*)dstent;
361
362 if (mu_locus_point_same_file (&src->locus.beg, &dst->locus.beg))
363 return 0;
364 parse_error_locus(&sip->locus,
365 _("symbol import conflict: %s"), srcent->name);
366 parse_error_locus(&src->locus, _("imported symbol location"));
367 parse_error_locus(&dst->locus, _("conflicting symbol location"));
368 return EBUSY;
369 }
370
371 int
import_cpyfun(struct syment ** pdst,struct syment * src,size_t symsize,void * closure)372 import_cpyfun(struct syment **pdst, struct syment *src, size_t symsize,
373 void *closure)
374 {
375 struct symimport_closure *sip = closure;
376 struct syment *dst;
377
378 if (sip->newname) {
379 struct mf_symbol *mdst = alloc_entry(sizeof(*mdst));
380 struct mf_symbol *s = symbol_resolve_alias((struct mf_symbol*)src);
381 mdst->name = mf_strdup(sip->newname);
382 mdst->refcnt = 1;
383 mdst->alias = (struct mf_symbol*)src;
384 mu_locus_range_copy(&mdst->locus, &s->locus);
385 dst = (struct syment*)mdst;
386 free(sip->newname);
387 sip->newname = NULL;
388 } else {
389 src->refcnt++;
390 dst = src;
391 }
392 *pdst = dst;
393 return 0;
394 }
395
396 int
module_import_symbols(struct module * dst,struct module * src,struct mu_locus_range const * loc)397 module_import_symbols(struct module *dst, struct module *src,
398 struct mu_locus_range const *loc)
399 {
400 int i;
401 struct symimport_closure clos;
402 clos.module = src;
403 clos.locus = *loc;
404 clos.rules = dst->import_rules;
405 clos.newname = NULL;
406 int res = 0;
407
408 for (i = 0; i < MODULE_NAMESPACE_COUNT; i++) {
409 if (symtab_import(dst->symtab[i], src->symtab[i],
410 import_selfun, import_errfun,
411 import_confun, import_cpyfun,
412 &clos)) {
413 res = 1;
414 break;
415 }
416 }
417 import_rules_free(dst->import_rules);
418 dst->import_rules = NULL;
419 return res;
420 }
421
422
423 struct module *top_module;
424 struct module_list *module_stack;
425 struct module_list *module_head, *module_tail;
426
427 static void
module_register(struct module * mod)428 module_register(struct module *mod)
429 {
430 struct module_list *p = alloc_entry(sizeof(*p));
431 p->module = mod;
432 p->next = NULL;
433 if (module_tail)
434 module_tail->next = p;
435 else
436 module_head = p;
437 module_tail = p;
438 }
439
440 int
module_symtab_enumerate(enum module_namespace ns,symtab_enumerator_t fun,void * data)441 module_symtab_enumerate(enum module_namespace ns, symtab_enumerator_t fun,
442 void *data)
443 {
444 struct module_list *p;
445
446 for (p = module_head; p; p = p->next) {
447 int rc = symtab_enumerate(p->module->symtab[ns], fun, data);
448 if (rc)
449 return rc;
450 }
451 return 0;
452 }
453
454 static void
module_init(struct module * mod,const char * name,const char * file)455 module_init(struct module *mod, const char *name, const char *file)
456 {
457 mod->name = mf_strdup(name);
458 mod->file = file ? mf_strdup(file) : NULL;
459 mod->dclname = NULL;
460 mod->flags = 0;
461 mod->symtab[namespace_function] =
462 xsymtab_create(sizeof(struct function), SYMTAB_COPY_KEY,
463 alloc_entry, free_entry);
464 mod->symtab[namespace_variable] =
465 xsymtab_create(sizeof(struct variable), SYMTAB_COPY_KEY,
466 alloc_entry, free_entry);
467 mod->symtab[namespace_constant] =
468 xsymtab_create(sizeof(struct constant), SYMTAB_COPY_KEY,
469 alloc_entry, free_entry);
470 mod->import_rules = NULL;
471 mod->submodule_head = mod->submodule_tail = NULL;
472 mod->incl_sources = NULL;
473
474 module_register(mod);
475 }
476
477 static struct module *
module_create(const char * name,const char * file)478 module_create(const char *name, const char *file)
479 {
480 struct module *mod = alloc_entry(sizeof(*mod));
481 module_init(mod, name, file);
482 return mod;
483 }
484
485 static void
module_free(struct module * mod)486 module_free(struct module *mod)
487 {
488 int i;
489 if (!mod)
490 return;
491 for (i = 0; i < MODULE_NAMESPACE_COUNT; i++)
492 symtab_destroy(&mod->symtab[i]);
493 mu_list_destroy(&mod->incl_sources);
494 }
495
496 static void
module_add_submodule(struct module * mod,struct module * submod)497 module_add_submodule(struct module *mod, struct module *submod)
498 {
499 struct module_list *p = alloc_entry(sizeof(*p));
500 p->module = submod;
501 p->next = NULL;
502 if (mod->submodule_tail)
503 mod->submodule_tail->next = p;
504 else
505 mod->submodule_head = p;
506 mod->submodule_tail = p;
507 }
508
509 static int
module_has_submodule(struct module * mod,struct module * submod)510 module_has_submodule(struct module *mod, struct module *submod)
511 {
512 struct module_list *p;
513 for (p = mod->submodule_head; p; p = p->next)
514 if (p->module == submod)
515 return 1;
516 return 0;
517 }
518
519 static void
module_push(struct module * mod)520 module_push(struct module *mod)
521 {
522 struct module_list *p = alloc_entry(sizeof(*p));
523 p->module = mod;
524 p->next = module_stack;
525 module_stack = p;
526 }
527
528 static struct module *
module_pop()529 module_pop()
530 {
531 struct module_list *p = module_stack;
532 struct module *mod;
533 if (p) {
534 mod = p->module;
535 module_stack = p->next;
536 } else
537 mod = NULL;
538 return mod;
539 }
540
541 int
set_top_module(const char * name,const char * file,struct import_rule * import_rules,struct mu_locus_range const * locus)542 set_top_module(const char *name, const char *file,
543 struct import_rule *import_rules,
544 struct mu_locus_range const *locus)
545 {
546 struct module *mod;
547 struct syment *ent;
548 int install = 1;
549 int rc = symtab_lookup_or_install(&ent, stab_module,
550 name, &install);
551 if (rc) {
552 parse_error_locus(locus,
553 _("cannot install module %s: %s"),
554 name, symtab_strerror(rc));
555 abort();
556 }
557 mod = (struct module *) ent;
558 if (!install) {
559 if (!module_has_submodule(top_module, mod))
560 /* Import symbols from mod to top_module */
561 module_import_symbols(top_module, mod, locus);
562 return 1;
563 }
564 module_init(mod, name, file);
565 import_builtin_variables(mod->symtab[namespace_variable]);
566 top_module->import_rules = import_rules;
567 module_add_submodule(top_module, mod);
568 module_push(top_module);
569 top_module = mod;
570 return 0;
571 }
572
573 void
pop_top_module()574 pop_top_module()
575 {
576 if (module_stack) {
577 struct module *mod = top_module;
578 top_module = module_pop();
579 /* Import symbols from mod to top_module */
580 if (mod != top_module) {
581 struct mu_locus_range lr = MU_LOCUS_RANGE_INITIALIZER;
582 module_import_symbols(top_module, mod, &lr); /*FIXME: locus?*/
583 }
584 }
585 }
586
587 static int
_collect_modules(void * ep,void * data)588 _collect_modules(void *ep, void *data)
589 {
590 struct module ***pmod = data;
591 *(*pmod)++ = ep;
592 return 0;
593 }
594
595 static int
_module_comp(const void * a,const void * b)596 _module_comp(const void *a, const void *b)
597 {
598 const struct module *am = a;
599 const struct module *bm = b;
600 return strcmp(am->name, bm->name);
601 }
602
603 void
collect_modules(struct module *** pmodv,size_t * pmodc)604 collect_modules(struct module ***pmodv, size_t *pmodc)
605 {
606 size_t modc = symtab_count_entries(stab_module);
607 struct module **modv = mu_calloc(modc + 1, sizeof(*modv));
608 struct module **tmp = modv + 1;
609
610 modv[0] = top_module;
611 symtab_enumerate(stab_module, _collect_modules, &tmp);
612 qsort(modv + 1, modc, sizeof(modv[0]), _module_comp);
613 modc++;
614 *pmodv = modv;
615 *pmodc = modc;
616 }
617
618
619 static void
free_module_entry(void * ptr)620 free_module_entry(void *ptr)
621 {
622 module_free((struct module *)ptr);
623 }
624
625 void
init_symbols()626 init_symbols()
627 {
628 stab_module = xsymtab_create(sizeof(struct module),
629 SYMTAB_COPY_KEY,
630 alloc_entry, free_module_entry);
631 stab_builtin = xsymtab_create(sizeof(struct builtin),
632 SYMTAB_COPY_KEY,
633 alloc_entry, free_entry);
634 stab_pragma = xsymtab_create(sizeof(struct pragma),
635 SYMTAB_COPY_KEY,
636 alloc_entry, free_entry);
637 stab_literal = xsymtab_create(sizeof(struct literal),
638 SYMTAB_COPY_KEY,
639 alloc_entry, free_entry);
640 top_module = module_create("top", script_file);
641 }
642
643 void
free_symbols()644 free_symbols()
645 {
646 symtab_destroy(&stab_module);
647 symtab_destroy(&stab_builtin);
648 symtab_destroy(&stab_pragma);
649 symtab_destroy(&stab_literal);
650
651 module_free(top_module);
652 top_module = NULL;
653 free_buckets();
654 }
655
656
657
658 void
va_builtin_install(char * name,void (* handler)(eval_environ_t),data_type_t rettype,size_t argcount,...)659 va_builtin_install(char *name,
660 void (*handler) (eval_environ_t),
661 data_type_t rettype,
662 size_t argcount,
663 ...)
664 {
665 struct builtin *builtin;
666 va_list ap;
667 size_t i;
668 data_type_t *argtype = mu_alloc (argcount * sizeof *argtype);
669
670 va_start(ap, argcount);
671 for (i = 0; i < argcount; i++)
672 argtype[i] = va_arg(ap, data_type_t);
673 va_end(ap);
674
675 builtin = xsymtab_install_builtin(name);
676
677 /* new entry */
678 builtin->name = mf_strdup(name);
679 builtin->handler = handler;
680 builtin->parmcount = argcount;
681 builtin->parmtype = argtype;
682 builtin->rettype = rettype;
683 builtin->statemask = 0;
684 builtin->flags = 0;
685 }
686
687 void
va_builtin_install_ex(char * name,void (* handler)(eval_environ_t),unsigned statemsk,data_type_t rettype,size_t argcount,size_t optcount,int flags,...)688 va_builtin_install_ex (char *name,
689 void (*handler) (eval_environ_t),
690 unsigned statemsk,
691 data_type_t rettype,
692 size_t argcount,
693 size_t optcount,
694 int flags,
695 ...)
696 {
697 struct builtin *builtin;
698 va_list ap;
699 size_t i;
700 data_type_t *argtype = mu_alloc (argcount * sizeof *argtype);
701
702 va_start(ap, flags);
703 for (i = 0; i < argcount; i++)
704 argtype[i] = va_arg(ap, data_type_t);
705 va_end(ap);
706
707 builtin = xsymtab_install_builtin(name);
708
709 /* new entry */
710 builtin->name = mf_strdup(name);
711 builtin->handler = handler;
712 builtin->parmcount = argcount;
713 builtin->optcount = optcount;
714 builtin->parmtype = argtype;
715 builtin->rettype = rettype;
716 builtin->statemask = statemsk;
717 builtin->flags = flags;
718 }
719
720 const struct builtin *
builtin_lookup(const char * name)721 builtin_lookup(const char *name)
722 {
723 return (struct builtin *)xsymtab_lookup(stab_builtin, name);
724 }
725
726
727
728 static void
init_variable(struct variable * var)729 init_variable(struct variable *var)
730 {
731 mu_locus_range_init (&var->sym.locus);
732 var->sym.module = top_module;
733 var->sym.flags = 0;
734 var->type = dtype_unspecified;
735 var->storage_class = storage_extern;
736 var->off = 0;
737 var->addrptr = NULL;
738 var->shadowed = NULL;
739 var->initialized = 0;
740 var->xref = NULL;
741 var->next = NULL;
742 }
743
744 struct variable *
variable_install(const char * name)745 variable_install(const char *name)
746 {
747 struct variable *vp;
748 struct syment *ent;
749 int install = 1;
750 int rc = symtab_lookup_or_install(&ent,
751 TOP_MODULE_SYMTAB(namespace_variable),
752 name, &install);
753 if (rc) {
754 parse_error(_("cannot install variable %s: %s"),
755 name, symtab_strerror(rc));
756 abort();
757 }
758
759 vp = (struct variable *) ent;
760 if (install) {
761 init_variable(vp);
762 vp->sym.name = mf_strdup(name);
763 }
764 return vp;
765 }
766
767 struct variable *
variable_replace(const char * name,struct variable * var)768 variable_replace(const char *name, struct variable *var)
769 {
770 if (!var) {
771 var = alloc_entry(sizeof(*var));
772 init_variable(var);
773 var->sym.name = mf_strdup(name);
774 }
775 if (symtab_replace(TOP_MODULE_SYMTAB(namespace_variable),
776 (struct syment*)var, NULL)) {
777 parse_error(_("INTERNAL ERROR: variable %s not found"),
778 name);
779 abort();
780 }
781 return var;
782 }
783
784 struct variable *
variable_lookup(const char * name)785 variable_lookup(const char *name)
786 {
787 struct variable *var = (struct variable *)
788 xsymtab_lookup(TOP_MODULE_SYMTAB(namespace_variable), name);
789 return (struct variable *)symbol_resolve_alias((struct mf_symbol*)var);
790 }
791
792 struct variable *
builtin_variable_install(const char * name,data_type_t type,unsigned flags,size_t * addrptr)793 builtin_variable_install(const char *name, data_type_t type, unsigned flags,
794 size_t *addrptr)
795 {
796 struct variable *var = variable_install(name);
797 var->sym.flags = flags;
798 var->sym.module = NULL;
799 var->type = type;
800 var->addrptr = addrptr;
801 var->next = builtin_variable_list;
802 builtin_variable_list = var;
803 return var;
804 }
805
806
807 static struct function *
function_lookup_or_install(const char * name,struct mu_locus_range const * locus)808 function_lookup_or_install(const char *name, struct mu_locus_range const *locus)
809 {
810 struct function *fp;
811 struct syment *ent;
812 int install = 1;
813 int rc = symtab_lookup_or_install(&ent,
814 TOP_MODULE_SYMTAB(namespace_function),
815 name, &install);
816 if (rc) {
817 parse_error(_("cannot install function %s: %s"),
818 name, symtab_strerror(rc));
819 abort();
820 }
821
822 fp = (struct function*) ent;
823 if (!install) {
824 if (fp->sym.alias) {
825 fp = (struct function *)
826 symbol_resolve_alias((struct mf_symbol*)fp);
827 parse_error_locus(locus,
828 _("redefinition of function %s by alias %s"),
829 fp->sym.name, name);
830 parse_error_locus(&fp->sym.locus,
831 _("previously defined here"));
832 } else {
833 parse_error_locus(locus,
834 _("redefinition of function %s"),
835 name);
836 parse_error_locus(&fp->sym.locus,
837 _("previously defined here"));
838 }
839 }
840 return fp;
841 }
842
843 struct function *
function_install(const char * name,size_t parmcnt,size_t optcnt,int varargs,data_type_t * parmtypes,data_type_t rettype,struct mu_locus_range const * locus)844 function_install(const char *name, size_t parmcnt, size_t optcnt, int varargs,
845 data_type_t *parmtypes, data_type_t rettype,
846 struct mu_locus_range const *locus)
847 {
848 struct function *fp = function_lookup_or_install(name, locus);
849 fp->sym.name = mf_strdup(name);
850 fp->sym.module = top_module;
851 mu_locus_range_copy(&fp->sym.locus, locus);
852 fp->node = NULL;
853 fp->entry = 0;
854 fp->parmcount = parmcnt;
855 fp->optcount = optcnt;
856 fp->varargs = varargs;
857 fp->parmtype = parmtypes;
858 fp->rettype = rettype;
859 fp->exmask = exmask_create();
860 fp->statemask = 0;
861 return fp;
862 }
863
864 struct function *
function_lookup(const char * name)865 function_lookup(const char *name)
866 {
867 struct function *fp = (struct function *)
868 xsymtab_lookup(TOP_MODULE_SYMTAB(namespace_function), name);
869 return (struct function*) symbol_resolve_alias((struct mf_symbol*)fp);
870 }
871
872
873 void
install_alias(const char * name,struct function * fun,struct mu_locus_range const * locus)874 install_alias(const char *name, struct function *fun,
875 struct mu_locus_range const *locus)
876 {
877 struct function *fp = function_lookup_or_install(name, locus);
878 fp->sym.name = mf_strdup(name);
879 fp->sym.module = top_module;
880 mu_locus_range_copy(&fp->sym.locus, locus);
881 fp->sym.alias = (struct mf_symbol*) fun;
882 }
883
884
885 struct literal *
literal_lookup(const char * text)886 literal_lookup(const char *text)
887 {
888 struct literal *lit;
889 struct syment *ent;
890 int install = 1;
891 int rc = symtab_lookup_or_install(&ent, stab_literal, text, &install);
892 if (rc) {
893 parse_error(_("cannot install literal %s: %s"),
894 text, symtab_strerror(rc));
895 abort();
896 }
897
898 lit = (struct literal *)ent;
899 if (install) {
900 lit->flags = 0;
901 lit->regex = NULL;
902 }
903 return lit;
904 }
905
906 struct constant *
define_constant(const char * name,struct value * value,unsigned flags,struct mu_locus_range const * locus)907 define_constant(const char *name, struct value *value, unsigned flags,
908 struct mu_locus_range const *locus)
909 {
910 struct constant *cp;
911 struct syment *ent;
912 int install = 1;
913 int rc = symtab_lookup_or_install(&ent,
914 TOP_MODULE_SYMTAB(namespace_constant),
915 name, &install);
916 if (rc) {
917
918 parse_error(_("cannot install constant %s: %s"),
919 name, symtab_strerror(rc));
920 abort();
921 }
922
923 cp = (struct constant *) ent;
924 if (install) {
925 cp->sym.name = mf_strdup(name);
926 } else {
927 parse_warning_locus(locus,
928 "%s: redefinition of constant",
929 name);
930 parse_warning_locus(&cp->sym.locus,
931 "this is the location of the "
932 "previous definition");
933 }
934 cp->sym.module = top_module;
935 mu_locus_range_copy(&cp->sym.locus, locus);
936 cp->sym.flags = flags;
937 cp->value = *value;
938 return cp;
939 }
940
941 const struct constant *
constant_lookup(const char * name)942 constant_lookup(const char *name)
943 {
944 const struct constant *cp = (const struct constant *)
945 xsymtab_lookup(TOP_MODULE_SYMTAB(namespace_constant), name);
946 return (const struct constant *)
947 symbol_resolve_alias((struct mf_symbol*)cp);
948 }
949
950 const struct value *
constant_lookup_value(const char * name)951 constant_lookup_value(const char *name)
952 {
953 const struct constant *cptr = constant_lookup(name);
954 return cptr ? &cptr->value : NULL;
955 }
956
957
958 struct sym_regex *
install_regex(struct literal * lit,unsigned regflags)959 install_regex(struct literal *lit, unsigned regflags)
960 {
961 struct sym_regex *regex;
962
963 for (regex = lit->regex; regex; regex = regex->next)
964 if (regex->regflags == regflags)
965 return regex;
966
967 /* FIXME: don't use alloc_entry here ...
968 or change sym_regex to match struct syment structure */
969 regex = alloc_entry(sizeof(*regex));
970 regex->lit = lit;
971 regex->regflags = regflags;
972 regex->flags = 0;
973 regex->index = 0;
974 regex->next = lit->regex;
975 lit->regex = regex;
976
977 return regex;
978 }
979
980
981 void
install_pragma(const char * name,int minargs,int maxargs,void (* handler)(int,char **,const char *))982 install_pragma(const char *name, int minargs, int maxargs,
983 void (*handler) (int, char **, const char *))
984 {
985 struct pragma *pragma;
986 struct syment *ent;
987 int install = 1;
988 int rc = symtab_lookup_or_install(&ent, stab_pragma, name, &install);
989 if (rc) {
990 parse_error(_("cannot install pragma %s: %s"),
991 name, symtab_strerror(rc));
992 abort();
993 }
994 if (!install) {
995 parse_error(_("INTERNAL ERROR: pragma %s already defined"),
996 name);
997 abort();
998 }
999
1000 pragma = (struct pragma *)ent;
1001 pragma->name = mf_strdup(name);
1002 pragma->minargs = minargs;
1003 pragma->maxargs = maxargs;
1004 pragma->handler = handler;
1005 }
1006
1007 const struct pragma *
lookup_pragma(const char * name)1008 lookup_pragma(const char *name)
1009 {
1010 return (const struct pragma *)xsymtab_lookup(stab_pragma, name);
1011 }
1012