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