xref: /Universal-ctags/extra-cmds/optscript-repl.c (revision 949ffdd12289052d6ebaedba8ca86ca01569327d)
1d8f6b0edSMasatake YAMATO /*
2d8f6b0edSMasatake YAMATO *   Copyright (c) 2020, Masatake YAMATO
3d8f6b0edSMasatake YAMATO *   Copyright (c) 2020, Red Hat, Inc.
4d8f6b0edSMasatake YAMATO *
5d8f6b0edSMasatake YAMATO *   This source code is released for free distribution under the terms of the
6d8f6b0edSMasatake YAMATO *   GNU General Public License version 2 or (at your option) any later version.
7d8f6b0edSMasatake YAMATO */
8d8f6b0edSMasatake YAMATO 
9d8f6b0edSMasatake YAMATO #include "general.h"
10d8f6b0edSMasatake YAMATO 
11d8f6b0edSMasatake YAMATO #include "optscript.h"
12d8f6b0edSMasatake YAMATO #include "mio.h"
13d8f6b0edSMasatake YAMATO #include "routines.h"
14d8f6b0edSMasatake YAMATO 
15d8f6b0edSMasatake YAMATO #include <string.h>
16d8f6b0edSMasatake YAMATO #include <stdlib.h>
17d8f6b0edSMasatake YAMATO 
18d8f6b0edSMasatake YAMATO static void
help(const char * progname,int exit_status)19d8f6b0edSMasatake YAMATO help (const char* progname, int exit_status)
20d8f6b0edSMasatake YAMATO {
21d8f6b0edSMasatake YAMATO 	FILE *out = stderr;
22d8f6b0edSMasatake YAMATO 	if (exit_status == 0)
23d8f6b0edSMasatake YAMATO 		out = stdout;
24d8f6b0edSMasatake YAMATO 
25d8f6b0edSMasatake YAMATO 	fprintf (out, "Usage: %s [options] [file|-]\n\n", progname);
26*949ffdd1SMasatake YAMATO 	fputs   (     "  -h|--help             Print this option summary\n", out);
27d8f6b0edSMasatake YAMATO 	fputs   (     "  -l|--list-operators   List built-in operators\n", out);
28d8f6b0edSMasatake YAMATO 	fputs   (     "  -e|--eval CODE        Evaluate the CODE\n", out);
29d8f6b0edSMasatake YAMATO 	fputc   ('\n', out);
30d8f6b0edSMasatake YAMATO 	exit (exit_status);
31d8f6b0edSMasatake YAMATO }
32d8f6b0edSMasatake YAMATO 
33d8f6b0edSMasatake YAMATO static EsObject*
op_renew(OptVM * vm,EsObject * name)34d8f6b0edSMasatake YAMATO op_renew (OptVM *vm, EsObject *name)
35d8f6b0edSMasatake YAMATO {
36d8f6b0edSMasatake YAMATO 	bool *app_data = opt_vm_get_app_data (vm);
37d8f6b0edSMasatake YAMATO 	*app_data = true;
38d8f6b0edSMasatake YAMATO 	return OPT_ERR_QUIT;
39d8f6b0edSMasatake YAMATO }
40d8f6b0edSMasatake YAMATO 
41d8f6b0edSMasatake YAMATO int
optscript_run(OptVM * vm,char * prompt,void * app_data)42d8f6b0edSMasatake YAMATO optscript_run (OptVM *vm, char *prompt, void *app_data)
43d8f6b0edSMasatake YAMATO {
44d8f6b0edSMasatake YAMATO 	int r = 0;
45d8f6b0edSMasatake YAMATO 	void *old_app_data = opt_vm_set_app_data (vm, app_data);
46d8f6b0edSMasatake YAMATO 	char *old_prompt = opt_vm_set_prompt (vm, prompt);
47d8f6b0edSMasatake YAMATO 
48d8f6b0edSMasatake YAMATO 	opt_vm_print_prompt (vm);
49d8f6b0edSMasatake YAMATO 
50d8f6b0edSMasatake YAMATO 	while (true)
51d8f6b0edSMasatake YAMATO 	{
52d8f6b0edSMasatake YAMATO 		EsObject *o = opt_vm_read (vm, NULL);
53d8f6b0edSMasatake YAMATO 		if (es_object_equal (o, ES_READER_EOF))
54d8f6b0edSMasatake YAMATO 		{
55d8f6b0edSMasatake YAMATO 			es_object_unref (o);
56d8f6b0edSMasatake YAMATO 			break;
57d8f6b0edSMasatake YAMATO 		}
58d8f6b0edSMasatake YAMATO 		EsObject *e = opt_vm_eval (vm, o);
59d8f6b0edSMasatake YAMATO 		es_object_unref (o);
60d8f6b0edSMasatake YAMATO 
61d8f6b0edSMasatake YAMATO 		if (es_error_p (e))
62d8f6b0edSMasatake YAMATO 		{
63d8f6b0edSMasatake YAMATO 			if (!es_object_equal (e, OPT_ERR_QUIT))
64d8f6b0edSMasatake YAMATO 			{
65d8f6b0edSMasatake YAMATO 				opt_vm_report_error (vm, e, NULL);
66d8f6b0edSMasatake YAMATO 				r = 1;
67d8f6b0edSMasatake YAMATO 			}
68d8f6b0edSMasatake YAMATO 			break;
69d8f6b0edSMasatake YAMATO 		}
70d8f6b0edSMasatake YAMATO 	}
71d8f6b0edSMasatake YAMATO 
72d8f6b0edSMasatake YAMATO 	opt_vm_set_prompt (vm, old_prompt);
73d8f6b0edSMasatake YAMATO 	opt_vm_set_app_data (vm, old_app_data);
74d8f6b0edSMasatake YAMATO 	return r;
75d8f6b0edSMasatake YAMATO }
76d8f6b0edSMasatake YAMATO 
77d8f6b0edSMasatake YAMATO int
main(int argc,char ** argv)78d8f6b0edSMasatake YAMATO main(int argc, char **argv)
79d8f6b0edSMasatake YAMATO {
80d8f6b0edSMasatake YAMATO 	MIO *in = NULL;
81d8f6b0edSMasatake YAMATO 	const char *file = NULL;
82d8f6b0edSMasatake YAMATO 	bool help_ops = false;
83d8f6b0edSMasatake YAMATO 
84d8f6b0edSMasatake YAMATO 	for (int i = 1; i < argc; i++)
85d8f6b0edSMasatake YAMATO 	{
86d8f6b0edSMasatake YAMATO 		if (strcmp (argv[i], "-h") == 0
87d8f6b0edSMasatake YAMATO 			|| strcmp (argv[i], "--help") == 0)
88d8f6b0edSMasatake YAMATO 			help (argv[0], 0);
89d8f6b0edSMasatake YAMATO 		else if (strcmp (argv[i], "-l") == 0
90d8f6b0edSMasatake YAMATO 				 || strcmp (argv[i], "--list-operators") == 0)
91d8f6b0edSMasatake YAMATO 			help_ops = true;
92d8f6b0edSMasatake YAMATO 		else if (strcmp (argv[i], "-e") == 0
93d8f6b0edSMasatake YAMATO 				 || strcmp (argv[i], "--eval") == 0)
94d8f6b0edSMasatake YAMATO 		{
95d8f6b0edSMasatake YAMATO 			if (file)
96d8f6b0edSMasatake YAMATO 			{
97d8f6b0edSMasatake YAMATO 				fprintf (stderr, "Don't specify multiple input: %s, %s\n",
98d8f6b0edSMasatake YAMATO 						 file, argv[i]);
99d8f6b0edSMasatake YAMATO 				exit (2);
100d8f6b0edSMasatake YAMATO 			}
101d8f6b0edSMasatake YAMATO 
102d8f6b0edSMasatake YAMATO 			if (i == argc -1)
103d8f6b0edSMasatake YAMATO 			{
104d8f6b0edSMasatake YAMATO 				fprintf (stderr, "no code for %s\n", argv[i]);
105d8f6b0edSMasatake YAMATO 				exit (2);
106d8f6b0edSMasatake YAMATO 			}
107d8f6b0edSMasatake YAMATO 			file = "<cmdline>";
108d8f6b0edSMasatake YAMATO 			i++;
109d8f6b0edSMasatake YAMATO 			in = mio_new_memory ((unsigned char *)eStrdup(argv[i]), strlen (argv[i]), eRealloc, eFree);
110d8f6b0edSMasatake YAMATO 			if (!in)
111d8f6b0edSMasatake YAMATO 			{
112d8f6b0edSMasatake YAMATO 				fprintf (stderr, "failed to create mio from memory\n");
113d8f6b0edSMasatake YAMATO 				exit (1);
114d8f6b0edSMasatake YAMATO 			}
115d8f6b0edSMasatake YAMATO 		}
116d8f6b0edSMasatake YAMATO 		else if (argv[i][0] == '-' && argv[i][1] == '\0')
117d8f6b0edSMasatake YAMATO 		{
118d8f6b0edSMasatake YAMATO 			if (file)
119d8f6b0edSMasatake YAMATO 			{
120d8f6b0edSMasatake YAMATO 				fprintf (stderr, "Don't specify multiple input: %s, %s\n",
121d8f6b0edSMasatake YAMATO 						 file, argv[i]);
122d8f6b0edSMasatake YAMATO 				exit (2);
123d8f6b0edSMasatake YAMATO 			}
124d8f6b0edSMasatake YAMATO 
125d8f6b0edSMasatake YAMATO 			file = "<stdin>";
126d8f6b0edSMasatake YAMATO 			in = mio_new_fp (stdin, NULL);
127d8f6b0edSMasatake YAMATO 			if (!in)
128d8f6b0edSMasatake YAMATO 			{
129d8f6b0edSMasatake YAMATO 				fprintf (stderr, "failed to use <stdin>\n");
130d8f6b0edSMasatake YAMATO 				exit (1);
131d8f6b0edSMasatake YAMATO 			}
132d8f6b0edSMasatake YAMATO 		}
133d8f6b0edSMasatake YAMATO 		else if (argv[i][0] == '-')
134d8f6b0edSMasatake YAMATO 		{
135d8f6b0edSMasatake YAMATO 			fprintf (stderr, "unknown option: %s\n", argv[i]);
136d8f6b0edSMasatake YAMATO 			exit (2);
137d8f6b0edSMasatake YAMATO 		}
138d8f6b0edSMasatake YAMATO 		else if (in)
139d8f6b0edSMasatake YAMATO 		{
140d8f6b0edSMasatake YAMATO 			fprintf (stderr, "too many arugments\n");
141d8f6b0edSMasatake YAMATO 			mio_unref (in);
142d8f6b0edSMasatake YAMATO 			exit (2);
143d8f6b0edSMasatake YAMATO 		}
144d8f6b0edSMasatake YAMATO 		else
145d8f6b0edSMasatake YAMATO 		{
146d8f6b0edSMasatake YAMATO 			if (file)
147d8f6b0edSMasatake YAMATO 			{
148d8f6b0edSMasatake YAMATO 				fprintf (stderr, "Don't specify multiple input: %s, %s\n",
149d8f6b0edSMasatake YAMATO 						 file, argv[i]);
150d8f6b0edSMasatake YAMATO 				exit (2);
151d8f6b0edSMasatake YAMATO 			}
152d8f6b0edSMasatake YAMATO 
153d8f6b0edSMasatake YAMATO 			file = argv[i];
154d8f6b0edSMasatake YAMATO 			in = mio_new_file (file, "r");
155d8f6b0edSMasatake YAMATO 			if (!in)
156d8f6b0edSMasatake YAMATO 			{
157d8f6b0edSMasatake YAMATO 				fprintf (stderr, "failed to open: %s\n", file);
158d8f6b0edSMasatake YAMATO 				exit (1);
159d8f6b0edSMasatake YAMATO 			}
160d8f6b0edSMasatake YAMATO 		}
161d8f6b0edSMasatake YAMATO 	}
162d8f6b0edSMasatake YAMATO 
163d8f6b0edSMasatake YAMATO 	opt_init ();
164d8f6b0edSMasatake YAMATO 
165d8f6b0edSMasatake YAMATO 	if (!in)
166d8f6b0edSMasatake YAMATO 		in = mio_new_fp (stdin, NULL);
167d8f6b0edSMasatake YAMATO 	if (in == NULL)
168d8f6b0edSMasatake YAMATO 	{
169d8f6b0edSMasatake YAMATO 		fprintf (stderr, "failed to open input stream\n");
170d8f6b0edSMasatake YAMATO 		exit (1);
171d8f6b0edSMasatake YAMATO 	}
172d8f6b0edSMasatake YAMATO 
173d8f6b0edSMasatake YAMATO 	MIO *out = mio_new_fp (stdout, NULL);
174d8f6b0edSMasatake YAMATO 	if (!out)
175d8f6b0edSMasatake YAMATO 	{
176d8f6b0edSMasatake YAMATO 		mio_unref (in);
177d8f6b0edSMasatake YAMATO 		fprintf (stderr, "failed to open output stream\n");
178d8f6b0edSMasatake YAMATO 		exit (1);
179d8f6b0edSMasatake YAMATO 	}
180d8f6b0edSMasatake YAMATO 	MIO *err = mio_new_fp (stderr, NULL);
181d8f6b0edSMasatake YAMATO 	if (!err)
182d8f6b0edSMasatake YAMATO 	{
183d8f6b0edSMasatake YAMATO 		mio_unref (out);
184d8f6b0edSMasatake YAMATO 		mio_unref (in);
185d8f6b0edSMasatake YAMATO 		fprintf (stderr, "failed to open error stream\n");
186d8f6b0edSMasatake YAMATO 		exit (1);
187d8f6b0edSMasatake YAMATO 	}
188d8f6b0edSMasatake YAMATO 
189d8f6b0edSMasatake YAMATO 	OptVM *vm = opt_vm_new (in, out, err);
190d8f6b0edSMasatake YAMATO 
191d8f6b0edSMasatake YAMATO 	int r;
192d8f6b0edSMasatake YAMATO 
193d8f6b0edSMasatake YAMATO 	EsObject *dict = opt_dict_new (47);
194d8f6b0edSMasatake YAMATO 	{
195d8f6b0edSMasatake YAMATO 		EsObject *op;
196d8f6b0edSMasatake YAMATO 		EsObject *sym;
197d8f6b0edSMasatake YAMATO 
198d8f6b0edSMasatake YAMATO 		op = opt_operator_new (op_renew, "_renew", 0, ":clear the state of vm%- _RENEW -");
199d8f6b0edSMasatake YAMATO 		sym = es_symbol_intern ("_renew");
200d8f6b0edSMasatake YAMATO 		opt_dict_def (dict, sym, op);
201d8f6b0edSMasatake YAMATO 		es_object_unref (op);
202d8f6b0edSMasatake YAMATO 	}
203d8f6b0edSMasatake YAMATO 
204d8f6b0edSMasatake YAMATO 	opt_vm_dstack_push (vm, dict);
205d8f6b0edSMasatake YAMATO 	if (help_ops)
206d8f6b0edSMasatake YAMATO 		r = opt_vm_help (vm, NULL, NULL, NULL);
207d8f6b0edSMasatake YAMATO 	else
208d8f6b0edSMasatake YAMATO 	{
209d8f6b0edSMasatake YAMATO 		bool renew = false;
210d8f6b0edSMasatake YAMATO 	renew:
211d8f6b0edSMasatake YAMATO 		r = optscript_run (vm, file? NULL: "OPT", &renew);
212d8f6b0edSMasatake YAMATO 		if (renew)
213d8f6b0edSMasatake YAMATO 		{
214d8f6b0edSMasatake YAMATO 			opt_vm_clear (vm);
215d8f6b0edSMasatake YAMATO 			opt_vm_dstack_push (vm, dict);
216d8f6b0edSMasatake YAMATO 			renew = false;
217d8f6b0edSMasatake YAMATO 			goto renew;
218d8f6b0edSMasatake YAMATO 		}
219d8f6b0edSMasatake YAMATO 	}
220d8f6b0edSMasatake YAMATO 	es_object_unref (dict);
221d8f6b0edSMasatake YAMATO 
222d8f6b0edSMasatake YAMATO 	opt_vm_delete (vm);
223d8f6b0edSMasatake YAMATO 
224d8f6b0edSMasatake YAMATO 	mio_unref (err);
225d8f6b0edSMasatake YAMATO 	mio_unref (out);
226d8f6b0edSMasatake YAMATO 	mio_unref (in);
227d8f6b0edSMasatake YAMATO 
228d8f6b0edSMasatake YAMATO 	return r;
229d8f6b0edSMasatake YAMATO }
230