45a39b0266fbf8774f762ce84521060eff6f3041
[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,
29         .informat = FMT_B43,
30         .print_addresses = 0,
31         .unknown_decode = 0,
32 };
33
34 #define ARG_MATCH               0
35 #define ARG_NOMATCH             1
36 #define ARG_ERROR               -1
37
38 static int do_cmp_arg(char **argv, int *pos,
39                       const char *template,
40                       int allow_merged,
41                       char **param)
42 {
43         char *arg;
44         char *next_arg;
45         size_t arg_len, template_len;
46
47         arg = argv[*pos];
48         next_arg = argv[*pos + 1];
49         arg_len = strlen(arg);
50         template_len = strlen(template);
51
52         if (param) {
53                 /* Maybe we have a merged parameter here.
54                  * A merged parameter is "-pfoobar" for example.
55                  */
56                 if (allow_merged && arg_len > template_len) {
57                         if (memcmp(arg, template, template_len) == 0) {
58                                 *param = arg + template_len;
59                                 return ARG_MATCH;
60                         }
61                         return ARG_NOMATCH;
62                 } else if (arg_len != template_len)
63                         return ARG_NOMATCH;
64                 *param = next_arg;
65         }
66         if (strcmp(arg, template) == 0) {
67                 if (param) {
68                         /* Skip the parameter on the next iteration. */
69                         (*pos)++;
70                         if (*param == NULL) {
71                                 fprintf(stderr, "%s needs a parameter\n", arg);
72                                 return ARG_ERROR;
73                         }
74                 }
75                 return ARG_MATCH;
76         }
77
78         return ARG_NOMATCH;
79 }
80
81 /* Simple and lean command line argument parsing. */
82 static int cmp_arg(char **argv, int *pos,
83                    const char *long_template,
84                    const char *short_template,
85                    char **param)
86 {
87         int err;
88
89         if (long_template) {
90                 err = do_cmp_arg(argv, pos, long_template, 0, param);
91                 if (err == ARG_MATCH || err == ARG_ERROR)
92                         return err;
93         }
94         err = ARG_NOMATCH;
95         if (short_template)
96                 err = do_cmp_arg(argv, pos, short_template, 1, param);
97         return err;
98 }
99
100 static void usage(FILE *fd, int argc, char **argv)
101 {
102         fprintf(fd, "Usage: %s INPUT_FILE OUTPUT_FILE [OPTIONS]\n", argv[0]);
103         fprintf(fd, "  -a|--arch ARCH      The architecture type of the input file (5 or 15)\n");
104         fprintf(fd, "  -f|--format FMT     Input file format. FMT must be one of:\n");
105         fprintf(fd, "                      raw-le32, raw-be32, b43\n");
106         fprintf(fd, "  --paddr             Print the code addresses\n");
107         fprintf(fd, "  -u|--unkdec         Decode operands of unknown instructions\n");
108         fprintf(fd, "  -d|--debug          Print verbose debugging info\n");
109         fprintf(fd, "                      Repeat for more verbose debugging\n");
110         fprintf(fd, "  -h|--help           Print this help\n");
111 }
112
113 int parse_args(int argc, char **argv)
114 {
115         int i;
116         int res;
117         char *param;
118
119         infile_name = NULL;
120         outfile_name = NULL;
121
122         for (i = 1; i < argc; i++) {
123                 if ((res = cmp_arg(argv, &i, "--help", "-h", NULL)) == ARG_MATCH) {
124                         usage(stdout, argc, argv);
125                         return 1;
126                 } else if ((res = cmp_arg(argv, &i, "--format", "-f", &param)) == ARG_MATCH) {
127                         if (strcasecmp(param, "raw-le32") == 0)
128                                 cmdargs.informat = FMT_RAW_LE32;
129                         else if (strcasecmp(param, "raw-be32") == 0)
130                                 cmdargs.informat = FMT_RAW_BE32;
131                         else if (strcasecmp(param, "b43") == 0)
132                                 cmdargs.informat = FMT_B43;
133                         else {
134                                 fprintf(stderr, "Invalid -f|--format\n");
135                                 return -1;
136                         }
137                 } else if ((res = cmp_arg(argv, &i, "--paddr", NULL, NULL)) == ARG_MATCH) {
138                         cmdargs.print_addresses = 1;
139                 } else if ((res = cmp_arg(argv, &i, "--unkdec", "-u", NULL)) == ARG_MATCH) {
140                         cmdargs.unknown_decode = 1;
141                 } else if ((res = cmp_arg(argv, &i, "--debug", "-d", NULL)) == ARG_MATCH) {
142                         _debug++;
143                 } else if ((res = cmp_arg(argv, &i, "--arch", "-a", &param)) == ARG_MATCH) {
144                         unsigned long arch;
145                         char *tail;
146
147                         arch = strtol(param, &tail, 0);
148                         if (strlen(tail) || (arch != 5 && arch != 15)) {
149                                 fprintf(stderr, "Unsupported architecture \"%s\"\n",
150                                         param);
151                                 return -1;
152                         }
153                         cmdargs.arch = arch;
154                 } else {
155                         if (!infile_name) {
156                                 infile_name = argv[i];
157                                 continue;
158                         }
159                         if (!outfile_name) {
160                                 outfile_name = argv[i];
161                                 continue;
162                         }
163                         fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
164                         goto out_usage;
165                 }
166         }
167         if (!infile_name || !outfile_name)
168                 goto out_usage;
169
170         return 0;
171 out_usage:
172         usage(stderr, argc, argv);
173         return -1;
174 }
175
176 int open_input_file(void)
177 {
178         if (strcmp(infile_name, "-") == 0) {
179                 infile = stdin;
180         } else {
181                 infile = fopen(infile_name, "r");
182                 if (!infile) {
183                         fprintf(stderr, "Could not open INPUT_FILE %s\n",
184                                 infile_name);
185                         return -1;
186                 }
187         }
188
189         return 0;
190 }
191
192 void close_input_file(void)
193 {
194         if (strcmp(infile_name, "-") != 0)
195                 fclose(infile);
196 }
197
198 int open_output_file(void)
199 {
200         if (strcmp(outfile_name, "-") == 0) {
201                 outfile = stdout;
202         } else {
203                 outfile = fopen(outfile_name, "w+");
204                 if (!outfile) {
205                         fprintf(stderr, "Could not open OUTPUT_FILE %s\n",
206                                 outfile_name);
207                         return -1;
208                 }
209         }
210
211         return 0;
212 }
213
214 void close_output_file(void)
215 {
216         if (strcmp(outfile_name, "-") != 0)
217                 fclose(outfile);
218 }