dasm: Rewrite cmdline arg parsing and remove the bin wrapper script.
[b43-tools.git] / disassembler / args.c
1 /*
2  *   Copyright (C) 2006-2007  Michael Buesch <mb@bu3sch.de>
3  *
4  *   This program is free software; you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License version 2
6  *   as published by the Free Software Foundation.
7  *
8  *   This program is distributed in the hope that it will be useful,
9  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *   GNU General Public License for more details.
12  */
13
14 #include "args.h"
15 #include "main.h"
16 #include "util.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23
24
25 int _debug;
26
27 struct cmdline_args cmdargs = {
28         .arch = 5,      /* Default to v5 architecture. */
29 };
30
31 #define ARG_MATCH               0
32 #define ARG_NOMATCH             1
33 #define ARG_ERROR               -1
34
35 static int do_cmp_arg(char **argv, int *pos,
36                       const char *template,
37                       int allow_merged,
38                       char **param)
39 {
40         char *arg;
41         char *next_arg;
42         size_t arg_len, template_len;
43
44         arg = argv[*pos];
45         next_arg = argv[*pos + 1];
46         arg_len = strlen(arg);
47         template_len = strlen(template);
48
49         if (param) {
50                 /* Maybe we have a merged parameter here.
51                  * A merged parameter is "-pfoobar" for example.
52                  */
53                 if (allow_merged && arg_len > template_len) {
54                         if (memcmp(arg, template, template_len) == 0) {
55                                 *param = arg + template_len;
56                                 return ARG_MATCH;
57                         }
58                         return ARG_NOMATCH;
59                 } else if (arg_len != template_len)
60                         return ARG_NOMATCH;
61                 *param = next_arg;
62         }
63         if (strcmp(arg, template) == 0) {
64                 if (param) {
65                         /* Skip the parameter on the next iteration. */
66                         (*pos)++;
67                         if (*param == 0) {
68                                 fprintf(stderr, "%s needs a parameter\n", arg);
69                                 return ARG_ERROR;
70                         }
71                 }
72                 return ARG_MATCH;
73         }
74
75         return ARG_NOMATCH;
76 }
77
78 /* Simple and lean command line argument parsing. */
79 static int cmp_arg(char **argv, int *pos,
80                    const char *long_template,
81                    const char *short_template,
82                    char **param)
83 {
84         int err;
85
86         if (long_template) {
87                 err = do_cmp_arg(argv, pos, long_template, 0, param);
88                 if (err == ARG_MATCH || err == ARG_ERROR)
89                         return err;
90         }
91         err = ARG_NOMATCH;
92         if (short_template)
93                 err = do_cmp_arg(argv, pos, short_template, 1, param);
94         return err;
95 }
96
97 static void usage(int argc, char **argv)
98 {
99         fprintf(stderr, "Usage: %s INPUT_FILE OUTPUT_FILE [OPTIONS]\n", argv[0]);
100         fprintf(stderr, "  -a|--arch ARCH      The architecture type of the input file\n");
101         fprintf(stderr, "  -h|--help           Print this help\n");
102         fprintf(stderr, "  -d|--debug          Print verbose debugging info\n");
103         fprintf(stderr, "                      Repeat for more verbose debugging\n");
104 }
105
106 int parse_args(int argc, char **argv)
107 {
108         int i;
109         int res;
110         char *param;
111
112         infile_name = NULL;
113         outfile_name = NULL;
114
115         for (i = 1; i < argc; i++) {
116                 if ((res = cmp_arg(argv, &i, "--help", "-h", 0)) == ARG_MATCH) {
117                         usage(argc, argv);
118                         return 1;
119                 } else if ((res = cmp_arg(argv, &i, "--debug", "-d", 0)) == ARG_MATCH) {
120                         _debug++;
121                 } else if ((res = cmp_arg(argv, &i, "--arch", "-a", &param)) == ARG_MATCH) {
122                         unsigned long arch;
123                         char *tail;
124
125                         arch = strtol(param, &tail, 0);
126                         if (strlen(tail) || (arch != 5)) {
127                                 fprintf(stderr, "Unsupported architecture \"%s\"\n",
128                                         param);
129                                 return -1;
130                         }
131                         cmdargs.arch = arch;
132                 } else {
133                         if (!infile_name) {
134                                 infile_name = argv[i];
135                                 continue;
136                         }
137                         if (!outfile_name) {
138                                 outfile_name = argv[i];
139                                 continue;
140                         }
141                         fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
142                         goto out_usage;
143                 }
144         }
145         if (!infile_name || !outfile_name)
146                 goto out_usage;
147
148         return 0;
149 out_usage:
150         usage(argc, argv);
151         return -1;
152 }
153
154 int open_input_file(void)
155 {
156         if (strcmp(infile_name, "-") == 0) {
157                 infile = stdin;
158         } else {
159                 infile = fopen(infile_name, "r");
160                 if (!infile) {
161                         fprintf(stderr, "Could not open INPUT_FILE %s\n",
162                                 infile_name);
163                         return -1;
164                 }
165         }
166
167         return 0;
168 }
169
170 void close_input_file(void)
171 {
172         if (strcmp(infile_name, "-") != 0)
173                 fclose(infile);
174 }
175
176 int open_output_file(void)
177 {
178         if (strcmp(outfile_name, "-") == 0) {
179                 outfile = stdout;
180         } else {
181                 outfile = fopen(outfile_name, "w+");
182                 if (!outfile) {
183                         fprintf(stderr, "Could not open OUTPUT_FILE %s\n",
184                                 outfile_name);
185                         return -1;
186                 }
187         }
188
189         return 0;
190 }
191
192 void close_output_file(void)
193 {
194         if (strcmp(outfile_name, "-") != 0)
195                 fclose(outfile);
196 }