assembler: Fix sparse warnings
[b43-tools.git] / assembler / 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 bool arg_print_sizes;
27 const char *initvals_fn_extension = ".initvals";
28 static const char *real_infile_name;
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                       const 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 == NULL) {
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                    const 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         printf("Usage: %s INPUT_FILE OUTPUT_FILE [OPTIONS]\n", argv[0]);
100         printf("  -h|--help           Print this help\n");
101         printf("  -d|--debug          Print verbose debugging info\n");
102         printf("                      Repeat for more verbose debugging\n");
103         printf("  -s|--psize          Print the size of the code after assembling\n");
104         printf("  -e|--ivalext EXT    Filename extension for the initvals\n");
105 }
106
107 int parse_args(int argc, char **argv)
108 {
109         int i;
110         int res;
111
112         if (argc < 3)
113                 goto out_usage;
114         infile_name = argv[1];
115         outfile_name = argv[2];
116
117         for (i = 3; i < argc; i++) {
118                 if ((res = cmp_arg(argv, &i, "--help", "-h", NULL)) == ARG_MATCH) {
119                         usage(argc, argv);
120                         return 1;
121                 } else if ((res = cmp_arg(argv, &i, "--debug", "-d", NULL)) == ARG_MATCH) {
122                         _debug++;
123                 } else if ((res = cmp_arg(argv, &i, "--psize", "-s", NULL)) == ARG_MATCH) {
124                         arg_print_sizes = 1;
125                 } else if ((res = cmp_arg(argv, &i, "--ivalext", "-e", &initvals_fn_extension)) == ARG_MATCH) {
126                         /* initvals_fn_extension is set to the extension. */
127                 } else if ((res = cmp_arg(argv, &i, "--__real_infile", NULL, &real_infile_name)) == ARG_MATCH) {
128                         /* real_infile_name is set. */
129                 } else {
130                         fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
131                         goto out_usage;
132                 }
133         }
134         if (!real_infile_name)
135                 real_infile_name = infile_name;
136         if (strcmp(real_infile_name, outfile_name) == 0) {
137                 fprintf(stderr, "Error: INPUT and OUTPUT filename must not be the same\n");
138                 goto out_usage;
139         }
140
141         return 0;
142 out_usage:
143         usage(argc, argv);
144         return -1;
145 }
146
147 int open_input_file(void)
148 {
149         int fd;
150         int err;
151
152         if (strcmp(infile_name, "-") == 0) {
153                 /* infile == stdin */
154                 fd = STDIN_FILENO;
155         } else {
156                 fd = open(infile_name, O_RDONLY);
157                 if (fd < 0) {
158                         fprintf(stderr, "Could not open INPUT_FILE %s\n",
159                                 infile_name);
160                         return -1;
161                 }
162                 err = dup2(fd, STDIN_FILENO);
163                 if (err) {
164                         fprintf(stderr, "Could not dup INPUT_FILE %s "
165                                 "to STDIN\n", infile_name);
166                         close(fd);
167                         return -1;
168                 }
169         }
170         infile.fd = fd;
171
172         return 0;
173 }
174
175 void close_input_file(void)
176 {
177         if (strcmp(infile_name, "-") != 0)
178                 close(infile.fd);
179 }