]> de.git.xonotic.org Git - xonotic/gmqcc.git/blob - main.c
Print out all the information parsed from the commandline
[xonotic/gmqcc.git] / main.c
1 /*
2  * Copyright (C) 2012
3  *     Dale Weiler
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is furnished to do
10  * so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 #include "gmqcc.h"
24
25 uint32_t    opt_flags[1 + (NUM_F_FLAGS / 32)];
26
27 uint32_t    opt_O        = 1;
28 const char *opt_output   = "progs.dat";
29 int         opt_standard = STD_DEF;
30
31 typedef struct { char *filename; int type; } argitem;
32 VECTOR_MAKE(argitem, items);
33
34 #define TYPE_QC  0
35 #define TYPE_ASM 1
36 #define TYPE_SRC 2
37
38 static const char *app_name;
39
40 static int usage() {
41     printf("usage: %s [options] [files...]", app_name);
42     printf("options:\n"
43            "  -h, --help             show this help message\n"
44            "  -o, --output=file      output file, defaults to progs.dat\n"
45            "  -a filename            add an asm file to be assembled\n"
46            "  -s filename            add a progs.src file to be used\n");
47     printf("  -fflag                 enable a flag\n"
48            "  -fno-flag              disable a flag\n"
49            "  -std standard          select one of the following standards\n"
50            "       -std=qcc          original QuakeC\n"
51            "       -std=fteqcc       fteqcc QuakeC\n"
52            "       -std=gmqcc        this compiler (default)\n");
53     printf("\n");
54     printf("flags:\n"
55            "  -fdarkplaces-string-table-bug\n"
56            "            patch the string table to work with some bugged darkplaces versions\n"
57            "  -fomit-nullbytes\n"
58            "            omits certain null-bytes for a smaller output - requires a patched engine\n"
59            );
60     return -1;
61 }
62
63 static bool options_setflag(const char *name, bool on) {
64     size_t i;
65
66     for (i = 0; i < opt_flag_list_count; ++i) {
67         if (!strcmp(name, opt_flag_list[i].name)) {
68             longbit lb = opt_flag_list[i].bit;
69 #if 0
70             if (on)
71                 opt_flags[lb.idx] |= (1<<(lb.bit));
72             else
73                 opt_flags[lb.idx] &= ~(1<<(lb.bit));
74 #else
75             if (on)
76                 opt_flags[0] |= (1<<lb);
77             else
78                 opt_flags[0] &= ~(1<<(lb));
79 #endif
80             return true;
81         }
82     }
83     return false;
84 }
85
86 static bool options_witharg(int *argc_, char ***argv_, char **out) {
87     int  argc   = *argc_;
88     char **argv = *argv_;
89
90     if (argv[0][2]) {
91         *out = argv[0]+2;
92         return true;
93     }
94     /* eat up the next */
95     if (argc < 2) /* no parameter was provided */
96         return false;
97
98     *out = argv[1];
99     --*argc_;
100     ++*argv_;
101     return true;
102 }
103
104 static bool options_long_witharg_all(const char *optname, int *argc_, char ***argv_, char **out, int ds, bool split) {
105     int  argc   = *argc_;
106     char **argv = *argv_;
107
108     size_t len = strlen(optname);
109
110     if (strncmp(argv[0]+ds, optname, len))
111         return false;
112
113     /* it's --optname, check how the parameter is supplied */
114     if (argv[0][ds+len] == '=') {
115         /* using --opt=param */
116         *out = argv[0]+ds+len+1;
117         return true;
118     }
119
120     if (!split || argc < ds) /* no parameter was provided, or only single-arg form accepted */
121         return false;
122
123     /* using --opt param */
124     *out = argv[1];
125     --*argc_;
126     ++*argv_;
127     return true;
128 }
129 static bool options_long_witharg(const char *optname, int *argc_, char ***argv_, char **out) {
130     return options_long_witharg_all(optname, argc_, argv_, out, 2, true);
131 }
132 static bool options_long_gcc(const char *optname, int *argc_, char ***argv_, char **out) {
133     return options_long_witharg_all(optname, argc_, argv_, out, 1, false);
134 }
135
136 static bool options_parse(int argc, char **argv) {
137     bool argend = false;
138     while (!argend && argc > 1) {
139         char *argarg;
140         argitem item;
141
142         ++argv;
143         --argc;
144
145         if (argv[0][0] == '-') {
146     /* All gcc-type long options */
147             if (options_long_gcc("std", &argc, &argv, &argarg)) {
148                 if      (!strcmp(argarg, "gmqcc") || !strcmp(argarg, "default"))
149                     opt_standard = STD_DEF;
150                 else if (!strcmp(argarg, "qcc"))
151                     opt_standard = STD_QCC;
152                 else if (!strcmp(argarg, "fte") || !strcmp(argarg, "fteqcc"))
153                     opt_standard = STD_FTE;
154                 else {
155                     printf("Unknown standard: %s\n", argarg);
156                     return false;
157                 }
158                 continue;
159             }
160
161             switch (argv[0][1]) {
162                 /* -h, show usage but exit with 0 */
163                 case 'h':
164                     usage();
165                     exit(0);
166                     break;
167
168                 /* handle all -fflags */
169                 case 'f':
170                     if (!strncmp(argv[0]+2, "no-", 3)) {
171                         if (!options_setflag(argv[0]+5, false)) {
172                             printf("unknown flag: %s\n", argv[0]+2);
173                             return false;
174                         }
175                     }
176                     else if (!options_setflag(argv[0]+2, true)) {
177                         printf("unknown flag: %s\n", argv[0]+2);
178                         return false;
179                     }
180                     break;
181
182                 case 'O':
183                     if (!options_witharg(&argc, &argv, &argarg)) {
184                         printf("option -O requires a numerical argument\n");
185                         return false;
186                     }
187                     opt_O = atoi(argarg);
188                     break;
189
190                 case 'o':
191                     if (!options_witharg(&argc, &argv, &argarg)) {
192                         printf("option -o requires an argument: the output file name\n");
193                         return false;
194                     }
195                     opt_output = argarg;
196                     break;
197
198                 case 'a':
199                 case 's':
200                     item.type = argv[0][1] == 'a' ? TYPE_ASM : TYPE_SRC;
201                     if (!options_witharg(&argc, &argv, &argarg)) {
202                         printf("option -a requires a filename %s\n",
203                                 (argv[0][1] == 'a' ? "containing QC-asm" : "containing a progs.src formatted list"));
204                         return false;
205                     }
206                     item.filename = argarg;
207                     items_add(item);
208                     break;
209
210                 case '-':
211                     if (!argv[0][2]) {
212                         /* anything following -- is considered a non-option argument */
213                         argend = true;
214                         break;
215                     }
216             /* All long options without arguments */
217                     else if (!strcmp(argv[0]+2, "help")) {
218                         usage();
219                         exit(0);
220                     }
221                     else {
222             /* All long options with arguments */
223                         if (options_long_witharg("output", &argc, &argv, &argarg))
224                             opt_output = argarg;
225                         else
226                         {
227                             printf("Unknown parameter: %s\n", argv[0]);
228                             return false;
229                         }
230                     }
231                     break;
232
233                 default:
234                     printf("Unknown parameter: %s\n", argv[0]);
235                     return false;
236             }
237         }
238         else
239         {
240             /* it's a QC filename */
241             argitem item;
242             item.filename = argv[0];
243             item.type     = TYPE_QC;
244             items_add(item);
245         }
246     }
247     return true;
248 }
249
250 int main(int argc, char **argv) {
251     size_t itr;
252     app_name = argv[0];
253
254     if (!options_parse(argc, argv)) {
255         return usage();
256     }
257
258     for (itr = 0; itr < opt_flag_list_count; ++itr) {
259         printf("Flag %s = %i\n", opt_flag_list[itr].name, OPT_FLAG(itr));
260     }
261     printf("output = %s\n", opt_output);
262     printf("optimization level = %i\n", (int)opt_O);
263     printf("standard = %i\n", opt_standard);
264
265     if (items_elements) {
266         printf("Mode: manual\n");
267         printf("There are %i items to compile:\n", items_elements);
268         for (itr = 0; itr < items_elements; ++itr) {
269             printf("  item: %s (%s)\n",
270                    items_data[itr].filename,
271                    ( (items_data[itr].type == TYPE_QC ? "qc" :
272                      (items_data[itr].type == TYPE_ASM ? "asm" :
273                      (items_data[itr].type == TYPE_SRC ? "progs.src" :
274                      ("unknown"))))));
275         }
276     } else {
277         printf("Mode: progs.src\n");
278     }
279
280     util_debug("COM", "starting ...\n");
281
282     /* stuff */
283
284     util_debug("COM", "cleaning ...\n");
285
286     util_meminfo();
287     return 0;
288 }