Setting up repository
[linux-libre-firmware.git] / b43-tools / assembler / args.c
1 /*
2  *   Copyright (C) 2006-2010  Michael Buesch <m@bues.ch>
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 struct cmdline_args cmdargs = {
26         .debug                  = 0,
27         .print_sizes            = 0,
28         .initvals_fn_extension  = ".initvals",
29         .outformat              = FMT_B43,
30 };
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                       const 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 == NULL) {
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                    const 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(void)
100 {
101         printf("Usage: b43-asm INPUT_FILE OUTPUT_FILE [OPTIONS]\n");
102         printf("  -f|--format FMT     Output file format. FMT must be one of:\n");
103         printf("                      raw-le32, raw-be32, b43\n");
104         printf("  -d|--debug          Print verbose debugging info\n");
105         printf("                      Repeat for more verbose debugging\n");
106         printf("  -s|--psize          Print the size of the code after assembling\n");
107         printf("  -e|--ivalext EXT    Filename extension for the initvals\n");
108         printf("  -h|--help           Print this help\n");
109 }
110
111 int parse_args(int argc, char **argv)
112 {
113         int i;
114         int res;
115         const char *param;
116
117         if (argc < 3)
118                 goto out_usage;
119         infile_name = argv[1];
120         outfile_name = argv[2];
121
122         for (i = 3; i < argc; i++) {
123                 if ((res = cmp_arg(argv, &i, "--help", "-h", NULL)) == ARG_MATCH) {
124                         usage();
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.outformat = FMT_RAW_LE32;
129                         else if (strcasecmp(param, "raw-be32") == 0)
130                                 cmdargs.outformat = FMT_RAW_BE32;
131                         else if (strcasecmp(param, "b43") == 0)
132                                 cmdargs.outformat = FMT_B43;
133                         else {
134                                 fprintf(stderr, "Invalid -f|--format\n\n");
135                                 goto out_usage;
136                         }
137                 } else if ((res = cmp_arg(argv, &i, "--debug", "-d", NULL)) == ARG_MATCH) {
138                         cmdargs.debug++;
139                 } else if ((res = cmp_arg(argv, &i, "--psize", "-s", NULL)) == ARG_MATCH) {
140                         cmdargs.print_sizes = 1;
141                 } else if ((res = cmp_arg(argv, &i, "--ivalext", "-e", &param)) == ARG_MATCH) {
142                         cmdargs.initvals_fn_extension = param;
143                 } else if ((res = cmp_arg(argv, &i, "--__real_infile", NULL, &param)) == ARG_MATCH) {
144                         cmdargs.real_infile_name = param;
145                 } else {
146                         fprintf(stderr, "Unrecognized argument: %s\n", argv[i]);
147                         goto out_usage;
148                 }
149         }
150         if (!cmdargs.real_infile_name)
151                 cmdargs.real_infile_name = infile_name;
152         if (strcmp(cmdargs.real_infile_name, outfile_name) == 0) {
153                 fprintf(stderr, "Error: INPUT and OUTPUT filename must not be the same\n");
154                 goto out_usage;
155         }
156
157         return 0;
158 out_usage:
159         usage();
160         return -1;
161 }
162
163 int open_input_file(void)
164 {
165         int fd;
166         int err;
167
168         if (strcmp(infile_name, "-") == 0) {
169                 /* infile == stdin */
170                 fd = STDIN_FILENO;
171         } else {
172                 fd = open(infile_name, O_RDONLY);
173                 if (fd < 0) {
174                         fprintf(stderr, "Could not open INPUT_FILE %s\n",
175                                 infile_name);
176                         return -1;
177                 }
178                 err = dup2(fd, STDIN_FILENO);
179                 if (err) {
180                         fprintf(stderr, "Could not dup INPUT_FILE %s "
181                                 "to STDIN\n", infile_name);
182                         close(fd);
183                         return -1;
184                 }
185         }
186         infile.fd = fd;
187
188         return 0;
189 }
190
191 void close_input_file(void)
192 {
193         if (strcmp(infile_name, "-") != 0)
194                 close(infile.fd);
195 }