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