• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * *****************************************************************************
3  *
4  * Copyright (c) 2018-2019 Gavin D. Howard and contributors.
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * * Redistributions of source code must retain the above copyright notice, this
12  *   list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright notice,
15  *   this list of conditions and the following disclaimer in the documentation
16  *   and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * *****************************************************************************
31  *
32  * Code for processing command-line arguments.
33  *
34  */
35 
36 #include <ctype.h>
37 #include <stdbool.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include <getopt.h>
43 
44 #include <status.h>
45 #include <vector.h>
46 #include <read.h>
47 #include <vm.h>
48 #include <args.h>
49 
50 static const struct option bc_args_lopt[] = {
51 
52 	{ "expression", required_argument, NULL, 'e' },
53 	{ "file", required_argument, NULL, 'f' },
54 	{ "help", no_argument, NULL, 'h' },
55 	{ "interactive", no_argument, NULL, 'i' },
56 	{ "no-prompt", no_argument, NULL, 'P' },
57 #if BC_ENABLED
58 	{ "global-stacks", no_argument, NULL, 'g' },
59 	{ "mathlib", no_argument, NULL, 'l' },
60 	{ "quiet", no_argument, NULL, 'q' },
61 	{ "standard", no_argument, NULL, 's' },
62 	{ "warn", no_argument, NULL, 'w' },
63 #endif // BC_ENABLED
64 	{ "version", no_argument, NULL, 'v' },
65 #if DC_ENABLED
66 	{ "extended-register", no_argument, NULL, 'x' },
67 #endif // DC_ENABLED
68 	{ 0, 0, 0, 0 },
69 
70 };
71 
72 #if !BC_ENABLED
73 static const char* const bc_args_opt = "e:f:hiPvVx";
74 #elif !DC_ENABLED
75 static const char* const bc_args_opt = "e:f:ghilPqsvVw";
76 #else // BC_ENABLED && DC_ENABLED
77 static const char* const bc_args_opt = "e:f:ghilPqsvVwx";
78 #endif // BC_ENABLED && DC_ENABLED
79 
bc_args_exprs(BcVec * exprs,const char * str)80 static void bc_args_exprs(BcVec *exprs, const char *str) {
81 	bc_vec_concat(exprs, str);
82 	bc_vec_concat(exprs, "\n");
83 }
84 
bc_args_file(BcVec * exprs,const char * file)85 static BcStatus bc_args_file(BcVec *exprs, const char *file) {
86 
87 	BcStatus s;
88 	char *buf;
89 
90 	vm->file = file;
91 
92 	s = bc_read_file(file, &buf);
93 	if (BC_ERR(s)) return s;
94 
95 	bc_args_exprs(exprs, buf);
96 	free(buf);
97 
98 	return s;
99 }
100 
bc_args(int argc,char * argv[])101 BcStatus bc_args(int argc, char *argv[]) {
102 
103 	BcStatus s = BC_STATUS_SUCCESS;
104 	int c, i, err = 0;
105 	bool do_exit = false, version = false;
106 
107 	i = optind = 0;
108 
109 	while ((c = getopt_long(argc, argv, bc_args_opt, bc_args_lopt, &i)) != -1) {
110 
111 		switch (c) {
112 
113 			case 0:
114 			{
115 				// This is the case when a long option is found.
116 				break;
117 			}
118 
119 			case 'e':
120 			{
121 				bc_args_exprs(&vm->exprs, optarg);
122 				break;
123 			}
124 
125 			case 'f':
126 			{
127 				s = bc_args_file(&vm->exprs, optarg);
128 				if (BC_ERR(s)) return s;
129 				break;
130 			}
131 
132 			case 'h':
133 			{
134 				bc_vm_info(vm->help);
135 				do_exit = true;
136 				break;
137 			}
138 
139 			case 'i':
140 			{
141 				vm->flags |= BC_FLAG_I;
142 				break;
143 			}
144 
145 			case 'P':
146 			{
147 				vm->flags |= BC_FLAG_P;
148 				break;
149 			}
150 
151 #if BC_ENABLED
152 			case 'g':
153 			{
154 				if (BC_ERR(!BC_IS_BC)) err = c;
155 				vm->flags |= BC_FLAG_G;
156 				break;
157 			}
158 
159 			case 'l':
160 			{
161 				if (BC_ERR(!BC_IS_BC)) err = c;
162 				vm->flags |= BC_FLAG_L;
163 				break;
164 			}
165 
166 			case 'q':
167 			{
168 				if (BC_ERR(!BC_IS_BC)) err = c;
169 				vm->flags |= BC_FLAG_Q;
170 				break;
171 			}
172 
173 			case 's':
174 			{
175 				if (BC_ERR(!BC_IS_BC)) err = c;
176 				vm->flags |= BC_FLAG_S;
177 				break;
178 			}
179 
180 			case 'w':
181 			{
182 				if (BC_ERR(!BC_IS_BC)) err = c;
183 				vm->flags |= BC_FLAG_W;
184 				break;
185 			}
186 #endif // BC_ENABLED
187 
188 			case 'V':
189 			case 'v':
190 			{
191 				do_exit = version = true;
192 				break;
193 			}
194 
195 #if DC_ENABLED
196 			case 'x':
197 			{
198 				if (BC_ERR(BC_IS_BC)) err = c;
199 				vm->flags |= DC_FLAG_X;
200 				break;
201 			}
202 #endif // DC_ENABLED
203 
204 			// Getopt printed an error message, but we should exit.
205 			case '?':
206 			default:
207 			{
208 				return BC_STATUS_ERROR_FATAL;
209 			}
210 		}
211 
212 		if (BC_ERR(err)) {
213 
214 			for (i = 0; bc_args_lopt[i].name != NULL; ++i) {
215 				if (bc_args_lopt[i].val == err) break;
216 			}
217 
218 			return bc_vm_verr(BC_ERROR_FATAL_OPTION, err, bc_args_lopt[i].name);
219 		}
220 	}
221 
222 	if (version) bc_vm_info(NULL);
223 	if (do_exit) exit((int) s);
224 	if (vm->exprs.len > 1 || !BC_IS_BC) vm->flags |= BC_FLAG_Q;
225 	if (argv[optind] != NULL && !strcmp(argv[optind], "--")) ++optind;
226 
227 	for (i = optind; i < argc; ++i) bc_vec_push(&vm->files, argv + i);
228 
229 	return s;
230 }
231