ssa: move optimizations from P_BinaryOp to P_BinaryConstOp
[ajla.git] / args.c
blob94156ccc2225e785e6edf325e143ec3dcb08e5ab
1 /*
2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
9 * version.
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #include "ajla.h"
21 #include "mem_al.h"
22 #include "obj_reg.h"
23 #include "thread.h"
24 #include "profile.h"
25 #include "funct.h"
26 #include "tick.h"
27 #include "task.h"
28 #include "os.h"
29 #include "ipfn.h"
30 #include "save.h"
32 #include "args.h"
34 const char * const * args_left;
35 int n_args_left;
36 const char *program_name;
37 const char *arg0;
39 static void debug_all(const char attr_unused *str)
41 mem_enable_debugging_option(NULL, 0);
42 obj_registry_enable_debugging_option(NULL, 0);
43 thread_enable_debugging_option(NULL, 0);
46 static void debug_select(const char *str)
48 size_t l;
49 next_param:
50 l = strcspn(str, ",");
51 if ((unsigned)!mem_enable_debugging_option(str, l) &
52 (unsigned)!obj_registry_enable_debugging_option(str, l) &
53 (unsigned)!thread_enable_debugging_option(str, l))
54 warning("invalid debugging option %.*s", (int)l, str);
55 if (str[l] == ',') {
56 str += l + 1;
57 goto next_param;
61 static void profile_all(const char attr_unused *str)
63 function_enable_profile(NULL, 0);
64 mem_al_enable_profile(NULL, 0);
67 static void profile_select(const char *str)
69 size_t l;
70 next_param:
71 l = strcspn(str, ",");
72 if ((unsigned)!function_enable_profile(str, l) &
73 (unsigned)!mem_al_enable_profile(str, l))
74 warning("invalid profiling option %.*s", (int)l, str);
75 if (str[l] == ',') {
76 str += l + 1;
77 goto next_param;
81 static void ipret_set_strict_calls(const char attr_unused *str)
83 ipret_strict_calls = true;
86 static void ipret_set_privileged(const char attr_unused *str)
88 ipret_is_privileged = true;
91 static void ipret_set_compile(const char attr_unused *str)
93 ipret_compile = true;
96 static void set_nosave(const char attr_unused *str)
98 save_disable = true;
101 #define ARG_SWITCH 0
102 #define ARG_STRING 1
103 #define ARG_NUMBER 2
105 struct arg {
106 const char *str;
107 uchar_efficient_t mode;
108 void (*handler)(const char *str);
109 uint32_t *val;
110 uint32_t min;
111 uint32_t max;
114 static const struct arg args[] = {
115 { "--compile", ARG_SWITCH, ipret_set_compile, NULL, 0, 0 },
116 { "--debug", ARG_SWITCH, debug_all, NULL, 0, 0 },
117 { "--debug=", ARG_STRING, debug_select, NULL, 0, 0 },
118 { "--nosave", ARG_SWITCH, set_nosave, NULL, 0, 0 },
119 { "--privileged", ARG_SWITCH, ipret_set_privileged, NULL, 0, 0 },
120 { "--profile", ARG_SWITCH, profile_all, NULL, 0, 0 },
121 { "--profile=", ARG_STRING, profile_select, NULL, 0, 0 },
122 { "--ptrcomp", ARG_SWITCH, mem_al_set_ptrcomp, NULL, 0, 0 },
123 { "--strict-calls", ARG_SWITCH, ipret_set_strict_calls, NULL, 0, 0 },
124 { "--system-malloc", ARG_SWITCH, mem_al_set_system_malloc, NULL, 0, 0 },
125 { "--thread-tick", ARG_SWITCH, NULL, &thread_tick, 0, 0 },
126 { "--threads=", ARG_NUMBER, NULL, &nr_cpus_override, 1, (unsigned)-1 },
127 { "--tick=", ARG_NUMBER, NULL, &tick_us, 1, (uint32_t)-1 },
130 static void process_arg(const char *arg)
132 const struct arg *a;
133 for (a = args; a < args + n_array_elements(args); a++) {
134 size_t sl = strlen(a->str);
135 switch (a->mode) {
136 case ARG_SWITCH:
137 if (!strcmp(arg, a->str)) {
138 if (a->handler)
139 a->handler(NULL);
140 else
141 *a->val = 1;
142 return;
144 break;
145 case ARG_STRING:
146 if (!strncmp(arg, a->str, sl)) {
147 const char *val = arg + sl;
148 a->handler(val);
149 return;
151 break;
152 case ARG_NUMBER:
153 if (!strncmp(arg, a->str, sl)) {
154 unsigned long num;
155 char *endptr;
156 const char *val = arg + sl;
157 if (!*val)
158 goto inv;
159 num = strtoul(val, &endptr, 10);
160 if (*endptr)
161 goto inv;
162 if ((uint32_t)num != num || num < a->min || num > a->max)
163 goto inv;
164 *a->val = num;
165 return;
167 break;
168 default:
169 internal(file_line, "process_arg: unknown mode %u", a->mode);
172 inv:
173 fatal("invalid argument '%s'", arg);
176 void args_init(int argc, const char * const argv[])
178 int i;
179 const char *env;
180 if (unlikely(!argc))
181 fatal("the argument 0 is not present");
182 arg0 = argv[0];
183 if ((env = getenv("AJLA_OPTIONS"))) {
184 while (1) {
185 size_t len = strcspn(env, " ");
186 if (len) {
187 char *a = malloc(len + 1);
188 if (unlikely(!a))
189 fatal("malloc failed");
190 *(char *)mempcpy(a, env, len) = 0;
191 process_arg(a);
192 free(a);
194 env += len;
195 if (!*env)
196 break;
197 env++;
200 for (i = 1; i < argc; i++) {
201 if (likely(argv[i][0] != '-'))
202 break;
203 if (argv[i][0] == '-' && argv[i][1] == '-' && !argv[i][2]) {
204 i++;
205 break;
207 process_arg(argv[i]);
209 args_left = argv + i;
210 n_args_left = argc - i;
211 if (!n_args_left) {
212 program_name = "";
213 } else {
214 const char *p;
215 program_name = args_left[0];
216 for (p = program_name; *p; p++) {
217 if (unlikely(os_is_path_separator(*p)))
218 program_name = p + 1;
223 void args_done(void)