xref: /Universal-ctags/main/script.c (revision 60bb60a89007cd66d1930621cbf4fef6b77b6bb2)
1668e3666SMasatake YAMATO /*
2668e3666SMasatake YAMATO *   Copyright (c) 2020, Masatake YAMATO
3668e3666SMasatake YAMATO *   Copyright (c) 2020, Red Hat, Inc.
4668e3666SMasatake YAMATO *
5668e3666SMasatake YAMATO *   This source code is released for free distribution under the terms of the
6668e3666SMasatake YAMATO *   GNU General Public License version 2 or (at your option) any later version.
7668e3666SMasatake YAMATO *
8668e3666SMasatake YAMATO *   This module contains ctags specific optscript objects
9668e3666SMasatake YAMATO */
10668e3666SMasatake YAMATO 
11668e3666SMasatake YAMATO #include "general.h"  /* must always come first */
12668e3666SMasatake YAMATO 
13668e3666SMasatake YAMATO #include "debug.h"
14668e3666SMasatake YAMATO #include "entry.h"
15668e3666SMasatake YAMATO #include "field_p.h"
16668e3666SMasatake YAMATO #include "htable.h"			/* For HT_PTR_TO_INT */
17668e3666SMasatake YAMATO #include "optscript.h"
188cfef1a8SMasatake YAMATO #include "parse.h"
19668e3666SMasatake YAMATO #include "routines.h"
20ed3202bdSMasatake YAMATO #include "script_p.h"
218cfef1a8SMasatake YAMATO #include "xtag_p.h"
22668e3666SMasatake YAMATO 
23fbb2ceccSMasatake YAMATO #include <ctype.h>
24668e3666SMasatake YAMATO #include <string.h>
25668e3666SMasatake YAMATO 
2675ed607dSMasatake YAMATO EsObject *OPTSCRIPT_ERR_NOTAGENTRY;
278cfef1a8SMasatake YAMATO EsObject *OPTSCRIPT_ERR_UNKNOWNLANGUAGE;
2875ed607dSMasatake YAMATO 
29ed3202bdSMasatake YAMATO int OPT_TYPE_MATCHLOC;
30ed3202bdSMasatake YAMATO static int locEqual (const void *a, const void  *b);
31ed3202bdSMasatake YAMATO static void locPrint (const void *a, MIO *out);
32ed3202bdSMasatake YAMATO 
3334deb294SMasatake YAMATO int OPT_TYPE_TAG;
3434deb294SMasatake YAMATO static void tagFree (void *a);
3534deb294SMasatake YAMATO static int tagEqual (const void *a, const void  *b);
3634deb294SMasatake YAMATO static void tagPrint (const void *a, MIO *out);
3734deb294SMasatake YAMATO 
vStringCatToupperS(vString * str,const char * s)38fbb2ceccSMasatake YAMATO static void vStringCatToupperS (vString *str, const char *s)
39fbb2ceccSMasatake YAMATO {
40fbb2ceccSMasatake YAMATO 	for (const char *tmp = s; *tmp != '\0'; tmp++)
41fbb2ceccSMasatake YAMATO 	{
42fbb2ceccSMasatake YAMATO 		int c = toupper (*tmp);
43fbb2ceccSMasatake YAMATO 		vStringPut (str, c);
44fbb2ceccSMasatake YAMATO 	}
45fbb2ceccSMasatake YAMATO }
46fbb2ceccSMasatake YAMATO 
optscriptInit(void)47668e3666SMasatake YAMATO extern OptVM *optscriptInit (void)
48668e3666SMasatake YAMATO {
49668e3666SMasatake YAMATO 	opt_init ();
50668e3666SMasatake YAMATO 	MIO *in  = mio_new_fp (stdin, NULL);
51*60bb60a8SMasatake YAMATO 
52*60bb60a8SMasatake YAMATO 	/* stdout is for emitting tags.
53*60bb60a8SMasatake YAMATO 	 * The interpreter should not touch it; use only stderr. */
54*60bb60a8SMasatake YAMATO 	MIO *out = mio_new_fp (stderr, NULL);
55668e3666SMasatake YAMATO 	MIO *err = mio_new_fp (stderr, NULL);
56668e3666SMasatake YAMATO 
57668e3666SMasatake YAMATO 	OptVM *optvm = opt_vm_new (in, out, err);
58668e3666SMasatake YAMATO 
59668e3666SMasatake YAMATO 	mio_unref (err);
60668e3666SMasatake YAMATO 	mio_unref (out);
61668e3666SMasatake YAMATO 	mio_unref (in);
62668e3666SMasatake YAMATO 
6375ed607dSMasatake YAMATO 	OPTSCRIPT_ERR_NOTAGENTRY = es_error_intern ("notagentry");
6475ed607dSMasatake YAMATO 
65ed3202bdSMasatake YAMATO 	OPT_TYPE_MATCHLOC = es_type_define_pointer ("matchloc",
66ed3202bdSMasatake YAMATO 												eFreeNoNullCheck,
67ed3202bdSMasatake YAMATO 												locEqual,
68ed3202bdSMasatake YAMATO 												locPrint);
6934deb294SMasatake YAMATO 	OPT_TYPE_TAG = es_type_define_pointer ("tagEntryInfo",
7034deb294SMasatake YAMATO 										   tagFree,
7134deb294SMasatake YAMATO 										   tagEqual,
7234deb294SMasatake YAMATO 										   tagPrint);
73668e3666SMasatake YAMATO 	return optvm;
74668e3666SMasatake YAMATO }
75668e3666SMasatake YAMATO 
lrop_get_field_value(OptVM * vm,EsObject * name)76668e3666SMasatake YAMATO static EsObject* lrop_get_field_value (OptVM *vm, EsObject *name)
77668e3666SMasatake YAMATO {
78668e3666SMasatake YAMATO 	EsObject *nobj = opt_vm_ostack_top (vm);
79668e3666SMasatake YAMATO 	if (!es_integer_p (nobj))
80668e3666SMasatake YAMATO 		return OPT_ERR_TYPECHECK;
81668e3666SMasatake YAMATO 
82668e3666SMasatake YAMATO 	int n = es_integer_get (nobj);
83668e3666SMasatake YAMATO 	tagEntryInfo *e = getEntryInCorkQueue (n);
84668e3666SMasatake YAMATO 	if (e == NULL)
8575ed607dSMasatake YAMATO 		return OPTSCRIPT_ERR_NOTAGENTRY;;
86668e3666SMasatake YAMATO 
87668e3666SMasatake YAMATO 	void * data = es_symbol_get_data (name);
88668e3666SMasatake YAMATO 	fieldType ftype = HT_PTR_TO_INT (data);
89668e3666SMasatake YAMATO 	EsObject *val = getFieldValue (ftype, e);
90668e3666SMasatake YAMATO 	if (es_error_p (val))
91668e3666SMasatake YAMATO 		return val;
92668e3666SMasatake YAMATO 
93668e3666SMasatake YAMATO 	opt_vm_ostack_pop (vm);
94668e3666SMasatake YAMATO 
95668e3666SMasatake YAMATO 	if (isFieldValueAvailableAlways (ftype))
96668e3666SMasatake YAMATO 	{
97668e3666SMasatake YAMATO 		opt_vm_ostack_push (vm, val);
98668e3666SMasatake YAMATO 		es_object_unref (val);
99668e3666SMasatake YAMATO 	}
100668e3666SMasatake YAMATO 	else if (es_null (val))
101668e3666SMasatake YAMATO 	{
102668e3666SMasatake YAMATO 		opt_vm_ostack_push (vm, es_false);
103668e3666SMasatake YAMATO 	}
104668e3666SMasatake YAMATO 	else
105668e3666SMasatake YAMATO 	{
106668e3666SMasatake YAMATO 		opt_vm_ostack_push (vm, val);
107668e3666SMasatake YAMATO 		opt_vm_ostack_push (vm, es_true);
108668e3666SMasatake YAMATO 		es_object_unref (val);
109668e3666SMasatake YAMATO 	}
110668e3666SMasatake YAMATO 	return es_false;
111668e3666SMasatake YAMATO }
112668e3666SMasatake YAMATO 
lrop_set_field_value(OptVM * vm,EsObject * name)113668e3666SMasatake YAMATO static EsObject* lrop_set_field_value (OptVM *vm, EsObject *name)
114668e3666SMasatake YAMATO {
115668e3666SMasatake YAMATO 	EsObject *indexobj = opt_vm_ostack_peek (vm, 1);
116668e3666SMasatake YAMATO 	if (!es_integer_p (indexobj))
117668e3666SMasatake YAMATO 		return OPT_ERR_TYPECHECK;
118668e3666SMasatake YAMATO 
119668e3666SMasatake YAMATO 	int n = es_integer_get (indexobj);
120668e3666SMasatake YAMATO 	tagEntryInfo *e = getEntryInCorkQueue (n);
121668e3666SMasatake YAMATO 	if (e == NULL)
12275ed607dSMasatake YAMATO 		return OPTSCRIPT_ERR_NOTAGENTRY;;
123668e3666SMasatake YAMATO 
124668e3666SMasatake YAMATO 	void * data = es_symbol_get_data (name);
125668e3666SMasatake YAMATO 	fieldType ftype = HT_PTR_TO_INT (data);
126668e3666SMasatake YAMATO 	unsigned int fdata_type = getFieldDataType (ftype);
127668e3666SMasatake YAMATO 
128668e3666SMasatake YAMATO 	EsObject *valobj = opt_vm_ostack_top (vm);
129668e3666SMasatake YAMATO 	int valtype = es_object_get_type (valobj);
130668e3666SMasatake YAMATO 
131668e3666SMasatake YAMATO 	if (hasFieldValueCheckerForSetter (ftype))
132668e3666SMasatake YAMATO 	{
133668e3666SMasatake YAMATO 		EsObject *e = checkFieldValueForSetter (ftype, valobj);
134668e3666SMasatake YAMATO 		if (!es_object_equal (e, es_false))
135668e3666SMasatake YAMATO 			return e;
136668e3666SMasatake YAMATO 	}
137668e3666SMasatake YAMATO 	else
138668e3666SMasatake YAMATO 	{
139668e3666SMasatake YAMATO 		if (! (((fdata_type & FIELDTYPE_STRING) && (valtype == OPT_TYPE_STRING))
140668e3666SMasatake YAMATO 			   || ((fdata_type & FIELDTYPE_BOOL) && (valtype == ES_TYPE_BOOLEAN))
141668e3666SMasatake YAMATO 			   || ((fdata_type & FIELDTYPE_INTEGER) && (valtype == ES_TYPE_INTEGER))))
142668e3666SMasatake YAMATO 			return OPT_ERR_TYPECHECK;
143668e3666SMasatake YAMATO 	}
144668e3666SMasatake YAMATO 
145668e3666SMasatake YAMATO 	EsObject *r = setFieldValue (ftype, e, valobj);
146668e3666SMasatake YAMATO 	if (es_error_p (r))
147668e3666SMasatake YAMATO 		return r;
148668e3666SMasatake YAMATO 
149668e3666SMasatake YAMATO 	opt_vm_ostack_pop (vm);
150668e3666SMasatake YAMATO 	opt_vm_ostack_pop (vm);
151668e3666SMasatake YAMATO 
152668e3666SMasatake YAMATO 	return es_false;
153668e3666SMasatake YAMATO }
154668e3666SMasatake YAMATO 
optscriptInstallFieldGetter(EsObject * dict,fieldType ftype,vString * op_name,vString * op_desc)155668e3666SMasatake YAMATO static void optscriptInstallFieldGetter (EsObject *dict, fieldType ftype,
156668e3666SMasatake YAMATO 										 vString *op_name, vString *op_desc)
157668e3666SMasatake YAMATO {
158668e3666SMasatake YAMATO 	const char *fname = getFieldName (ftype);
159668e3666SMasatake YAMATO 	vStringPut (op_name, ':');
160668e3666SMasatake YAMATO 	vStringCatS (op_name, fname);
161668e3666SMasatake YAMATO 	EsObject *op_sym = es_symbol_intern (vStringValue (op_name));
162668e3666SMasatake YAMATO 	es_symbol_set_data (op_sym, HT_INT_TO_PTR (ftype));
163668e3666SMasatake YAMATO 
164668e3666SMasatake YAMATO 	const char *vtype = getFieldGetterValueType (ftype);
165668e3666SMasatake YAMATO 	unsigned int fdata_type = getFieldDataType (ftype);
166668e3666SMasatake YAMATO 
167668e3666SMasatake YAMATO 	vStringCatS (op_desc, "int :");
168fbb2ceccSMasatake YAMATO 	vStringCatToupperS (op_desc, fname);
169668e3666SMasatake YAMATO 	vStringPut (op_desc, ' ');
170668e3666SMasatake YAMATO 
171668e3666SMasatake YAMATO 	if (vtype)
172668e3666SMasatake YAMATO 		vStringCatS (op_desc, vtype);
173668e3666SMasatake YAMATO 	else
174668e3666SMasatake YAMATO 	{
175668e3666SMasatake YAMATO 		Assert (fdata_type);
176668e3666SMasatake YAMATO 		if (fdata_type & FIELDTYPE_STRING)
177668e3666SMasatake YAMATO 			vStringCatS (op_desc, "string|");
178668e3666SMasatake YAMATO 		if (fdata_type & FIELDTYPE_INTEGER)
179668e3666SMasatake YAMATO 			vStringCatS (op_desc, "int|");
180668e3666SMasatake YAMATO 		if (fdata_type & FIELDTYPE_BOOL)
181668e3666SMasatake YAMATO 			vStringCatS (op_desc, "bool|");
182668e3666SMasatake YAMATO 		vStringChop (op_desc);
183668e3666SMasatake YAMATO 	}
184668e3666SMasatake YAMATO 
185668e3666SMasatake YAMATO 	if (!isFieldValueAvailableAlways (ftype))
186668e3666SMasatake YAMATO 	{
187668e3666SMasatake YAMATO 		vStringPut (op_desc, ' ');
188668e3666SMasatake YAMATO 		vStringCatS (op_desc, "true%");
189668e3666SMasatake YAMATO 		vStringCatS (op_desc, "int :");
190fbb2ceccSMasatake YAMATO 		vStringCatToupperS (op_desc, fname);
191668e3666SMasatake YAMATO 		vStringCatS (op_desc, " false");
192668e3666SMasatake YAMATO 	}
193668e3666SMasatake YAMATO 
194668e3666SMasatake YAMATO 	EsObject *op = opt_operator_new (lrop_get_field_value,
195668e3666SMasatake YAMATO 									 vStringValue (op_name),
196668e3666SMasatake YAMATO 									 1, vStringValue (op_desc));
197668e3666SMasatake YAMATO 	opt_dict_def (dict, op_sym, op);
198668e3666SMasatake YAMATO 	es_object_unref (op);
199668e3666SMasatake YAMATO }
200668e3666SMasatake YAMATO 
optscriptInstallFieldSetter(EsObject * dict,fieldType ftype,vString * op_name,vString * op_desc)201668e3666SMasatake YAMATO static void optscriptInstallFieldSetter (EsObject *dict, fieldType ftype,
202668e3666SMasatake YAMATO 										 vString *op_name, vString *op_desc)
203668e3666SMasatake YAMATO {
204668e3666SMasatake YAMATO 	const char *fname = getFieldName (ftype);
205668e3666SMasatake YAMATO 	vStringCatS (op_name, fname);
206668e3666SMasatake YAMATO 	vStringPut (op_name, ':');
207668e3666SMasatake YAMATO 
208668e3666SMasatake YAMATO 	EsObject *op_sym = es_symbol_intern (vStringValue (op_name));
209668e3666SMasatake YAMATO 	es_symbol_set_data (op_sym, HT_INT_TO_PTR (ftype));
210668e3666SMasatake YAMATO 
211668e3666SMasatake YAMATO 	const char *vtype = getFieldSetterValueType (ftype);
212668e3666SMasatake YAMATO 	unsigned int fdata_type = getFieldDataType (ftype);
213668e3666SMasatake YAMATO 	vStringCatS (op_desc, "int ");
214668e3666SMasatake YAMATO 
215668e3666SMasatake YAMATO 	if (vtype)
216668e3666SMasatake YAMATO 		vStringCatS (op_desc, vtype);
217668e3666SMasatake YAMATO 	else
218668e3666SMasatake YAMATO 	{
219668e3666SMasatake YAMATO 		Assert (fdata_type);
220668e3666SMasatake YAMATO 		if (fdata_type & FIELDTYPE_STRING)
221668e3666SMasatake YAMATO 			vStringCatS (op_desc, "string|");
222668e3666SMasatake YAMATO 		if (fdata_type & FIELDTYPE_INTEGER)
223668e3666SMasatake YAMATO 			vStringCatS (op_desc, "int|");
224668e3666SMasatake YAMATO 		if (fdata_type & FIELDTYPE_BOOL)
225668e3666SMasatake YAMATO 			vStringCatS (op_desc, "bool|");
226668e3666SMasatake YAMATO 		vStringChop (op_desc);
227668e3666SMasatake YAMATO 	}
228668e3666SMasatake YAMATO 
229668e3666SMasatake YAMATO 	vStringPut (op_desc, ' ');
230fbb2ceccSMasatake YAMATO 	vStringCatToupperS (op_desc, fname);
231668e3666SMasatake YAMATO 	vStringCatS (op_desc, ": -");
232668e3666SMasatake YAMATO 
233668e3666SMasatake YAMATO 	EsObject *op = opt_operator_new (lrop_set_field_value,
234668e3666SMasatake YAMATO 									 vStringValue (op_name),
235668e3666SMasatake YAMATO 									 2, vStringValue (op_desc));
236668e3666SMasatake YAMATO 	opt_dict_def (dict, op_sym, op);
237668e3666SMasatake YAMATO 	es_object_unref (op);
238668e3666SMasatake YAMATO }
239668e3666SMasatake YAMATO 
optscriptInstallFieldAccessors(EsObject * dict)240668e3666SMasatake YAMATO static void optscriptInstallFieldAccessors (EsObject *dict)
241668e3666SMasatake YAMATO {
242668e3666SMasatake YAMATO 	vString *op_name = vStringNew ();
243668e3666SMasatake YAMATO 	vString *op_desc = vStringNew ();
244668e3666SMasatake YAMATO 
245668e3666SMasatake YAMATO 	for (fieldType ftype = 0; ftype <= FIELD_BUILTIN_LAST; ftype++)
246668e3666SMasatake YAMATO 	{
247668e3666SMasatake YAMATO 		if (hasFieldGetter (ftype))
248668e3666SMasatake YAMATO 		{
249668e3666SMasatake YAMATO 			optscriptInstallFieldGetter (dict, ftype, op_name, op_desc);
250668e3666SMasatake YAMATO 			vStringClear (op_name);
251668e3666SMasatake YAMATO 			vStringClear (op_desc);
252668e3666SMasatake YAMATO 		}
253668e3666SMasatake YAMATO 		if (hasFieldSetter (ftype))
254668e3666SMasatake YAMATO 		{
255668e3666SMasatake YAMATO 			optscriptInstallFieldSetter (dict, ftype, op_name, op_desc);
256668e3666SMasatake YAMATO 			vStringClear (op_name);
257668e3666SMasatake YAMATO 			vStringClear (op_desc);
258668e3666SMasatake YAMATO 		}
259668e3666SMasatake YAMATO 	}
260668e3666SMasatake YAMATO 
261668e3666SMasatake YAMATO 	vStringDelete (op_name);
262668e3666SMasatake YAMATO 	vStringDelete (op_desc);
263668e3666SMasatake YAMATO }
264668e3666SMasatake YAMATO 
2652bbd136eSMasatake YAMATO /* Define \1, \2,... \9 */
optscriptInstallMatchResultProcs(EsObject * dict,OptOperatorFn fun)2662bbd136eSMasatake YAMATO static void optscriptInstallMatchResultProcs (EsObject *dict,
2672bbd136eSMasatake YAMATO 											  OptOperatorFn fun)
2682bbd136eSMasatake YAMATO {
2692bbd136eSMasatake YAMATO 	char name [] = { [0] = '\\', [2] = '\0' };
2702bbd136eSMasatake YAMATO 	char help [] = "- \\_ string|false";
2712bbd136eSMasatake YAMATO 	char *p = strchr (help, '_');
2722bbd136eSMasatake YAMATO 	for (int i = 1; i <= 9; i++)
2732bbd136eSMasatake YAMATO 	{
2742bbd136eSMasatake YAMATO 		name [1] = '0' + i;
2752bbd136eSMasatake YAMATO 		*p = name [1];
2762bbd136eSMasatake YAMATO 		EsObject *op_sym = es_symbol_intern (name);
2772bbd136eSMasatake YAMATO 		es_symbol_set_data (op_sym, HT_INT_TO_PTR (i));
2782bbd136eSMasatake YAMATO 		EsObject *op = opt_operator_new (fun, name, 0, help);
2792bbd136eSMasatake YAMATO 		opt_dict_def (dict, op_sym, op);
2802bbd136eSMasatake YAMATO 		es_object_unref (op);
2812bbd136eSMasatake YAMATO 	}
2822bbd136eSMasatake YAMATO }
2832bbd136eSMasatake YAMATO 
optscriptInstallProcs(EsObject * dict,OptOperatorFn matchResultAccessor)2842bbd136eSMasatake YAMATO extern void optscriptInstallProcs (EsObject *dict,
2852bbd136eSMasatake YAMATO 								   OptOperatorFn matchResultAccessor)
286668e3666SMasatake YAMATO {
287668e3666SMasatake YAMATO 	optscriptInstallFieldAccessors (dict);
2882bbd136eSMasatake YAMATO 	optscriptInstallMatchResultProcs (dict, matchResultAccessor);
289668e3666SMasatake YAMATO }
290668e3666SMasatake YAMATO 
291668e3666SMasatake YAMATO static EsObject *optscript_CorkIndex_sym = es_nil;
optscriptSetup(OptVM * vm,EsObject * dict,int corkIndex)292668e3666SMasatake YAMATO extern void optscriptSetup (OptVM *vm, EsObject *dict, int corkIndex)
293668e3666SMasatake YAMATO {
294668e3666SMasatake YAMATO 	if (corkIndex != CORK_NIL)
295668e3666SMasatake YAMATO 	{
296668e3666SMasatake YAMATO 		static EsObject *corkIndex_sym = es_nil;
297668e3666SMasatake YAMATO 		if (es_null (corkIndex_sym))
298668e3666SMasatake YAMATO 			corkIndex_sym = es_symbol_intern (".");
299668e3666SMasatake YAMATO 		EsObject *corkIndex_val = es_integer_new (corkIndex);
300668e3666SMasatake YAMATO 		opt_dict_def (dict, corkIndex_sym, corkIndex_val);
301668e3666SMasatake YAMATO 		es_object_unref (corkIndex_val);
302668e3666SMasatake YAMATO 		optscript_CorkIndex_sym = corkIndex_sym;
303668e3666SMasatake YAMATO 	}
304668e3666SMasatake YAMATO }
305668e3666SMasatake YAMATO 
optscriptTeardown(OptVM * vm,EsObject * dict)306668e3666SMasatake YAMATO extern void optscriptTeardown (OptVM *vm, EsObject *dict)
307668e3666SMasatake YAMATO {
308668e3666SMasatake YAMATO 	if (!es_null (optscript_CorkIndex_sym))
309668e3666SMasatake YAMATO 	{
310668e3666SMasatake YAMATO 		opt_dict_undef (dict, optscript_CorkIndex_sym);
311668e3666SMasatake YAMATO 		optscript_CorkIndex_sym = es_nil;
312668e3666SMasatake YAMATO 	}
313668e3666SMasatake YAMATO }
314668e3666SMasatake YAMATO 
optscriptRead(OptVM * vm,const char * src,size_t len)315668e3666SMasatake YAMATO extern EsObject *optscriptRead (OptVM *vm, const char *src, size_t len)
316668e3666SMasatake YAMATO {
317668e3666SMasatake YAMATO 	if (len == 0)
318668e3666SMasatake YAMATO 		len = strlen (src);
319668e3666SMasatake YAMATO 
320668e3666SMasatake YAMATO 	MIO *mio = mio_new_memory ((unsigned char *)src, len, NULL, NULL);
321668e3666SMasatake YAMATO 	EsObject *obj = opt_vm_read (vm, mio);
322668e3666SMasatake YAMATO 	if (es_error_p (obj))
323668e3666SMasatake YAMATO 		opt_vm_report_error (vm, obj, NULL);
324668e3666SMasatake YAMATO 	mio_unref (mio);
325668e3666SMasatake YAMATO 	return obj;
326668e3666SMasatake YAMATO }
327668e3666SMasatake YAMATO 
optscriptEval(OptVM * vm,EsObject * code)328668e3666SMasatake YAMATO extern EsObject* optscriptEval (OptVM *vm, EsObject *code)
329668e3666SMasatake YAMATO {
330668e3666SMasatake YAMATO 	static EsObject *exec = es_nil;
331668e3666SMasatake YAMATO 
332668e3666SMasatake YAMATO 	if (es_null (exec))
333668e3666SMasatake YAMATO 	{
334668e3666SMasatake YAMATO 		MIO *mio = mio_new_memory ((unsigned char*)"//exec", 6, NULL, NULL);
335668e3666SMasatake YAMATO 		exec = opt_vm_read (vm, mio);
336668e3666SMasatake YAMATO 		if (es_error_p (exec))
337668e3666SMasatake YAMATO 		{
338668e3666SMasatake YAMATO 			opt_vm_report_error (vm, exec, NULL);
339668e3666SMasatake YAMATO 			error (FATAL, "failed in converting //exec to an optscript object");
340668e3666SMasatake YAMATO 		}
341668e3666SMasatake YAMATO 		mio_unref (mio);
342668e3666SMasatake YAMATO 	}
343668e3666SMasatake YAMATO 
344668e3666SMasatake YAMATO 	EsObject *o = opt_vm_eval (vm, code);
345668e3666SMasatake YAMATO 	if (es_error_p (o))
346668e3666SMasatake YAMATO 	{
347668e3666SMasatake YAMATO 		opt_vm_report_error (vm, o, NULL);
348668e3666SMasatake YAMATO 		error (FATAL, "failed to push the proc representing the script");
349668e3666SMasatake YAMATO 	}
350668e3666SMasatake YAMATO 	es_object_unref (o);
351668e3666SMasatake YAMATO 
352668e3666SMasatake YAMATO 	EsObject *r = opt_vm_eval (vm, exec);;
353668e3666SMasatake YAMATO 	if (es_error_p (r))
354668e3666SMasatake YAMATO 		opt_vm_report_error (vm, r, NULL);
355668e3666SMasatake YAMATO 	return r;
356668e3666SMasatake YAMATO }
35775ed607dSMasatake YAMATO 
optscriptDefine(EsObject * dict,const char * name,EsObject * obj)35875ed607dSMasatake YAMATO extern EsObject* optscriptDefine (EsObject *dict,
35975ed607dSMasatake YAMATO 								  const char *name, EsObject *obj)
36075ed607dSMasatake YAMATO {
36175ed607dSMasatake YAMATO 	EsObject *sym = es_symbol_intern (name);
36275ed607dSMasatake YAMATO 	opt_dict_def (dict, sym, obj);
36375ed607dSMasatake YAMATO 	return sym;
36475ed607dSMasatake YAMATO }
36575ed607dSMasatake YAMATO 
36675ed607dSMasatake YAMATO 
optscriptLoad(OptVM * vm,MIO * mio)367431a587eSMasatake YAMATO extern EsObject *optscriptLoad (OptVM *vm, MIO *mio)
368431a587eSMasatake YAMATO {
369431a587eSMasatake YAMATO 	while (true)
370431a587eSMasatake YAMATO 	{
371431a587eSMasatake YAMATO 		EsObject *o = opt_vm_read (vm, mio);
372431a587eSMasatake YAMATO 		if (es_object_equal (o, ES_READER_EOF))
373431a587eSMasatake YAMATO 		{
374431a587eSMasatake YAMATO 			es_object_unref (o);
375431a587eSMasatake YAMATO 			return es_false;
376431a587eSMasatake YAMATO 		}
377431a587eSMasatake YAMATO 		else if (es_error_p (o))
378431a587eSMasatake YAMATO 		{
379431a587eSMasatake YAMATO 			opt_vm_report_error (vm, o, NULL);
380431a587eSMasatake YAMATO 			return o;
381431a587eSMasatake YAMATO 		}
382431a587eSMasatake YAMATO 
383431a587eSMasatake YAMATO 		EsObject *e = opt_vm_eval (vm, o);
384431a587eSMasatake YAMATO 		if (es_error_p (e))
385431a587eSMasatake YAMATO 		{
386431a587eSMasatake YAMATO 			opt_vm_report_error (vm, e, NULL);
387431a587eSMasatake YAMATO 			es_object_unref (o);
388431a587eSMasatake YAMATO 			return e;
389431a587eSMasatake YAMATO 		}
390431a587eSMasatake YAMATO 
391431a587eSMasatake YAMATO 		es_object_unref (o);
392431a587eSMasatake YAMATO 	}
393431a587eSMasatake YAMATO }
394431a587eSMasatake YAMATO 
optscriptReadAndEval(OptVM * vm,const char * src,size_t len)39575ed607dSMasatake YAMATO extern EsObject *optscriptReadAndEval   (OptVM *vm, const char *src, size_t len)
39675ed607dSMasatake YAMATO {
39775ed607dSMasatake YAMATO 	EsObject *obj = optscriptRead (vm, src, len);
39875ed607dSMasatake YAMATO 	if (es_error_p (obj))
39975ed607dSMasatake YAMATO 		return obj;
40075ed607dSMasatake YAMATO 
40175ed607dSMasatake YAMATO 	EsObject *r = optscriptEval (vm, obj);
40275ed607dSMasatake YAMATO 	es_object_unref (obj);
40375ed607dSMasatake YAMATO 	return r;
40475ed607dSMasatake YAMATO }
40575ed607dSMasatake YAMATO 
optscriptReadAndDefine(OptVM * vm,EsObject * dict,const char * name,const char * src,size_t len)40675ed607dSMasatake YAMATO extern EsObject *optscriptReadAndDefine (OptVM *vm, EsObject *dict, const char *name,
40775ed607dSMasatake YAMATO 										 const char *src, size_t len)
40875ed607dSMasatake YAMATO {
40975ed607dSMasatake YAMATO 	EsObject *obj = optscriptRead (vm, src, len);
41075ed607dSMasatake YAMATO 	if (es_error_p (obj))
41175ed607dSMasatake YAMATO 		return obj;
41275ed607dSMasatake YAMATO 	return optscriptDefine (dict, name, obj);
41375ed607dSMasatake YAMATO }
414965b7025SMasatake YAMATO 
procdocs_add_key_val(EsObject * proc,EsObject * help_str,void * data)415f02ab9fbSMasatake YAMATO static bool procdocs_add_key_val (EsObject *proc, EsObject *help_str, void *data)
416f02ab9fbSMasatake YAMATO {
417f02ab9fbSMasatake YAMATO 	ptrArray *a = data;
418f02ab9fbSMasatake YAMATO 
419f02ab9fbSMasatake YAMATO 	if (es_object_get_type (help_str) == OPT_TYPE_STRING)
420f02ab9fbSMasatake YAMATO 		ptrArrayAdd (a, proc);
421f02ab9fbSMasatake YAMATO 
422f02ab9fbSMasatake YAMATO 	return true;
423f02ab9fbSMasatake YAMATO }
424f02ab9fbSMasatake YAMATO 
procdocs_get_help_str(EsObject * proc,void * data)425f02ab9fbSMasatake YAMATO static const char* procdocs_get_help_str (EsObject *proc, void *data)
426f02ab9fbSMasatake YAMATO {
427f02ab9fbSMasatake YAMATO 	EsObject *dict = data;
428f02ab9fbSMasatake YAMATO 	const char *name = opt_name_get_cstr (proc);
429f02ab9fbSMasatake YAMATO 	EsObject *help_str = NULL;
430f02ab9fbSMasatake YAMATO 
431f02ab9fbSMasatake YAMATO 	if (opt_dict_known_and_get_cstr (dict, name, &help_str))
432f02ab9fbSMasatake YAMATO 		return opt_string_get_cstr(help_str);
433f02ab9fbSMasatake YAMATO 	return NULL;
434f02ab9fbSMasatake YAMATO }
435f02ab9fbSMasatake YAMATO 
procdocs_add(ptrArray * a,void * data)436f02ab9fbSMasatake YAMATO static void procdocs_add (ptrArray *a, void *data)
437f02ab9fbSMasatake YAMATO {
438f02ab9fbSMasatake YAMATO 	EsObject *dict = data;
439f02ab9fbSMasatake YAMATO 	opt_dict_foreach (dict, procdocs_add_key_val, a);
440f02ab9fbSMasatake YAMATO }
441f02ab9fbSMasatake YAMATO 
442f02ab9fbSMasatake YAMATO static struct OptHelpExtender procdocs_help_extender = {
443f02ab9fbSMasatake YAMATO 	.add = procdocs_add,
444f02ab9fbSMasatake YAMATO 	.get_help_str = procdocs_get_help_str,
445f02ab9fbSMasatake YAMATO };
446f02ab9fbSMasatake YAMATO 
optscriptHelp(OptVM * vm,FILE * fp,EsObject * procdocs)447f02ab9fbSMasatake YAMATO extern void optscriptHelp (OptVM *vm, FILE *fp, EsObject *procdocs)
448965b7025SMasatake YAMATO {
449965b7025SMasatake YAMATO 	MIO *out = mio_new_fp (fp, NULL);
450f02ab9fbSMasatake YAMATO 	opt_vm_help (vm, out, procdocs? &procdocs_help_extender: NULL, procdocs);
451965b7025SMasatake YAMATO 	mio_unref (out);
452965b7025SMasatake YAMATO }
453ed3202bdSMasatake YAMATO 
locEqual(const void * a,const void * b)454ed3202bdSMasatake YAMATO static int locEqual (const void *a, const void  *b)
455ed3202bdSMasatake YAMATO {
456ed3202bdSMasatake YAMATO 	if (a == b)
457ed3202bdSMasatake YAMATO 		return 1;
458ed3202bdSMasatake YAMATO 
459ed3202bdSMasatake YAMATO 	const matchLoc *al = a;
460ed3202bdSMasatake YAMATO 	const matchLoc *bl = b;
461ed3202bdSMasatake YAMATO 
462ed3202bdSMasatake YAMATO 	if (al->line == bl->line
463ed3202bdSMasatake YAMATO 		&& memcmp (&al->pos, &bl->pos, sizeof (al->pos)) == 0)
464ed3202bdSMasatake YAMATO 		return 1;
465ed3202bdSMasatake YAMATO 	return 0;
466ed3202bdSMasatake YAMATO }
467ed3202bdSMasatake YAMATO 
locPrint(const void * a,MIO * out)468ed3202bdSMasatake YAMATO static void locPrint (const void *a, MIO *out)
469ed3202bdSMasatake YAMATO {
470ed3202bdSMasatake YAMATO 	const matchLoc *al = a;
471ed3202bdSMasatake YAMATO 	mio_printf (out, "#<matchloc %p line: %lu>", a, al->line);
472ed3202bdSMasatake YAMATO }
47334deb294SMasatake YAMATO 
tagFree(void * a)47434deb294SMasatake YAMATO static void tagFree (void *a)
47534deb294SMasatake YAMATO {
47634deb294SMasatake YAMATO 	tagEntryInfo *e = a;
47734deb294SMasatake YAMATO 	eFree ((void *)e->name);	/* TODO */
47834deb294SMasatake YAMATO 	eFree (e);
47934deb294SMasatake YAMATO }
48034deb294SMasatake YAMATO 
tagEqual(const void * a,const void * b)48134deb294SMasatake YAMATO static int tagEqual (const void *a, const void  *b)
48234deb294SMasatake YAMATO {
48334deb294SMasatake YAMATO 	if (a == b)
48434deb294SMasatake YAMATO 		return 1;
48534deb294SMasatake YAMATO 	return 0;
48634deb294SMasatake YAMATO }
48734deb294SMasatake YAMATO 
tagPrint(const void * a,MIO * out)48834deb294SMasatake YAMATO static void tagPrint (const void *a, MIO *out)
48934deb294SMasatake YAMATO {
49034deb294SMasatake YAMATO 	const tagEntryInfo *tag = a;
49134deb294SMasatake YAMATO 	mio_printf (out, "#<tagEntryInfo %p name: %s line: %lu>",
49234deb294SMasatake YAMATO 				tag, tag->name, tag->lineNumber);
49334deb294SMasatake YAMATO }
494f13d16e1SMasatake YAMATO 
optscriptRegisterOperators(EsObject * dict,struct optscriptOperatorRegistration regs[],size_t count)495f13d16e1SMasatake YAMATO extern void optscriptRegisterOperators(EsObject * dict,
496f13d16e1SMasatake YAMATO 									   struct optscriptOperatorRegistration regs[], size_t count)
497f13d16e1SMasatake YAMATO {
498f13d16e1SMasatake YAMATO 	EsObject *op;
499f13d16e1SMasatake YAMATO 	EsObject *sym;
500f13d16e1SMasatake YAMATO 
501f13d16e1SMasatake YAMATO 	for (size_t i = 0; i < count; i++)
502f13d16e1SMasatake YAMATO 	{
503f13d16e1SMasatake YAMATO 		sym = es_symbol_intern (regs[i].name);
504f13d16e1SMasatake YAMATO 		op = opt_operator_new (regs[i].fn, es_symbol_get (sym), regs[i].arity,
505f13d16e1SMasatake YAMATO 							   regs[i].help_str);
506f13d16e1SMasatake YAMATO 		opt_dict_def (dict, sym, op);
507f13d16e1SMasatake YAMATO 		es_object_unref (op);
508f13d16e1SMasatake YAMATO 	}
509f13d16e1SMasatake YAMATO }
5108cfef1a8SMasatake YAMATO 
optscriptGetXtagType(const EsObject * extra)5118cfef1a8SMasatake YAMATO extern xtagType optscriptGetXtagType (const EsObject *extra)
5128cfef1a8SMasatake YAMATO {
5138cfef1a8SMasatake YAMATO 	EsObject *extra_sym = es_pointer_get (extra);
5148cfef1a8SMasatake YAMATO 	const char *extra_str = es_symbol_get (extra_sym);
5158cfef1a8SMasatake YAMATO 
5168cfef1a8SMasatake YAMATO 	const char *sep = strchr (extra_str, '.');
5178cfef1a8SMasatake YAMATO 	if (sep)
5188cfef1a8SMasatake YAMATO 	{
5198cfef1a8SMasatake YAMATO 		langType lang = getNamedLanguage (extra_str, sep - extra_str);
5208cfef1a8SMasatake YAMATO 		if (lang == LANG_IGNORE)
5218cfef1a8SMasatake YAMATO 			return XTAG_UNKNOWN;
5228cfef1a8SMasatake YAMATO 
5238cfef1a8SMasatake YAMATO 		return getXtagTypeForNameAndLanguage (sep + 1, lang);
5248cfef1a8SMasatake YAMATO 	}
5258cfef1a8SMasatake YAMATO 	else
5268cfef1a8SMasatake YAMATO 		return getXtagTypeForNameAndLanguage (extra_str, LANG_IGNORE);
5278cfef1a8SMasatake YAMATO }
528