New upstream version 2.8.1
Fabian Greffrath
6 years ago
0 | /* Getopt for GNU. | |
1 | NOTE: getopt is now part of the C library, so if you don't know what | |
2 | "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu | |
3 | before changing it! | |
4 | ||
5 | Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 | |
6 | Free Software Foundation, Inc. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify it | |
9 | under the terms of the GNU General Public License as published by the | |
10 | Free Software Foundation; either version 2, or (at your option) any | |
11 | later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
21 | ||
22 | ||
23 | #ifdef HAVE_CONFIG_H | |
24 | #include "config.h" | |
25 | #endif | |
26 | ||
27 | #ifndef __STDC__ | |
28 | # ifndef const | |
29 | # define const | |
30 | # endif | |
31 | #endif | |
32 | ||
33 | /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */ | |
34 | #ifndef _NO_PROTO | |
35 | #define _NO_PROTO | |
36 | #endif | |
37 | ||
38 | #include <stdio.h> | |
39 | ||
40 | /* Comment out all this code if we are using the GNU C Library, and are not | |
41 | actually compiling the library itself. This code is part of the GNU C | |
42 | Library, but also included in many other GNU distributions. Compiling | |
43 | and linking in this code is a waste when using the GNU C library | |
44 | (especially if it is a shared library). Rather than having every GNU | |
45 | program understand `configure --with-gnu-libc' and omit the object files, | |
46 | it is simpler to just do this in the source for each such file. */ | |
47 | ||
48 | #if defined (_LIBC) || !defined (__GNU_LIBRARY__) || !__MacOSX__ | |
49 | ||
50 | ||
51 | /* This needs to come after some library #include | |
52 | to get __GNU_LIBRARY__ defined. */ | |
53 | #ifdef __GNU_LIBRARY__ | |
54 | /* Don't include stdlib.h for non-GNU C libraries because some of them | |
55 | contain conflicting prototypes for getopt. */ | |
56 | #include <stdlib.h> | |
57 | #endif /* GNU C library. */ | |
58 | ||
59 | /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a | |
60 | long-named option. Because this is not POSIX.2 compliant, it is | |
61 | being phased out. */ | |
62 | /* #define GETOPT_COMPAT */ | |
63 | ||
64 | /* This version of `getopt' appears to the caller like standard Unix `getopt' | |
65 | but it behaves differently for the user, since it allows the user | |
66 | to intersperse the options with the other arguments. | |
67 | ||
68 | As `getopt' works, it permutes the elements of ARGV so that, | |
69 | when it is done, all the options precede everything else. Thus | |
70 | all application programs are extended to handle flexible argument order. | |
71 | ||
72 | Setting the environment variable POSIXLY_CORRECT disables permutation. | |
73 | Then the behavior is completely standard. | |
74 | ||
75 | GNU application programs can use a third alternative mode in which | |
76 | they can distinguish the relative order of options and other arguments. */ | |
77 | ||
78 | #include "getopt.h" | |
79 | ||
80 | /* For communication from `getopt' to the caller. | |
81 | When `getopt' finds an option that takes an argument, | |
82 | the argument value is returned here. | |
83 | Also, when `ordering' is RETURN_IN_ORDER, | |
84 | each non-option ARGV-element is returned here. */ | |
85 | ||
86 | char *optarg = 0; | |
87 | ||
88 | /* Index in ARGV of the next element to be scanned. | |
89 | This is used for communication to and from the caller | |
90 | and for communication between successive calls to `getopt'. | |
91 | ||
92 | On entry to `getopt', zero means this is the first call; initialize. | |
93 | ||
94 | When `getopt' returns EOF, this is the index of the first of the | |
95 | non-option elements that the caller should itself scan. | |
96 | ||
97 | Otherwise, `optind' communicates from one call to the next | |
98 | how much of ARGV has been scanned so far. */ | |
99 | ||
100 | /* XXX 1003.2 says this must be 1 before any call. */ | |
101 | int optind = 0; | |
102 | ||
103 | /* The next char to be scanned in the option-element | |
104 | in which the last option character we returned was found. | |
105 | This allows us to pick up the scan where we left off. | |
106 | ||
107 | If this is zero, or a null string, it means resume the scan | |
108 | by advancing to the next ARGV-element. */ | |
109 | ||
110 | static char *nextchar; | |
111 | ||
112 | /* Callers store zero here to inhibit the error message | |
113 | for unrecognized options. */ | |
114 | ||
115 | int opterr = 1; | |
116 | ||
117 | /* Set to an option character which was unrecognized. | |
118 | This must be initialized on some systems to avoid linking in the | |
119 | system's own getopt implementation. */ | |
120 | ||
121 | #define BAD_OPTION '\0' | |
122 | int optopt = BAD_OPTION; | |
123 | ||
124 | /* Describe how to deal with options that follow non-option ARGV-elements. | |
125 | ||
126 | If the caller did not specify anything, | |
127 | the default is REQUIRE_ORDER if the environment variable | |
128 | POSIXLY_CORRECT is defined, PERMUTE otherwise. | |
129 | ||
130 | REQUIRE_ORDER means don't recognize them as options; | |
131 | stop option processing when the first non-option is seen. | |
132 | This is what Unix does. | |
133 | This mode of operation is selected by either setting the environment | |
134 | variable POSIXLY_CORRECT, or using `+' as the first character | |
135 | of the list of option characters. | |
136 | ||
137 | PERMUTE is the default. We permute the contents of ARGV as we scan, | |
138 | so that eventually all the non-options are at the end. This allows options | |
139 | to be given in any order, even with programs that were not written to | |
140 | expect this. | |
141 | ||
142 | RETURN_IN_ORDER is an option available to programs that were written | |
143 | to expect options and other ARGV-elements in any order and that care about | |
144 | the ordering of the two. We describe each non-option ARGV-element | |
145 | as if it were the argument of an option with character code 1. | |
146 | Using `-' as the first character of the list of option characters | |
147 | selects this mode of operation. | |
148 | ||
149 | The special argument `--' forces an end of option-scanning regardless | |
150 | of the value of `ordering'. In the case of RETURN_IN_ORDER, only | |
151 | `--' can cause `getopt' to return EOF with `optind' != ARGC. */ | |
152 | ||
153 | static enum | |
154 | { | |
155 | REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER | |
156 | } ordering; | |
157 | ||
158 | #ifdef __GNU_LIBRARY__ | |
159 | /* We want to avoid inclusion of string.h with non-GNU libraries | |
160 | because there are many ways it can cause trouble. | |
161 | On some systems, it contains special magic macros that don't work | |
162 | in GCC. */ | |
163 | #include <string.h> | |
164 | #define my_index strchr | |
165 | #define my_strlen strlen | |
166 | #else | |
167 | ||
168 | /* Avoid depending on library functions or files | |
169 | whose names are inconsistent. */ | |
170 | ||
171 | #if __STDC__ || defined(PROTO) | |
172 | extern char *getenv(const char *name); | |
173 | extern int strcmp (const char *s1, const char *s2); | |
174 | extern int strncmp(const char *s1, const char *s2, unsigned int n); | |
175 | ||
176 | static int my_strlen(const char *s); | |
177 | static char *my_index (const char *str, int chr); | |
178 | #else | |
179 | extern char *getenv (); | |
180 | #endif | |
181 | ||
182 | static int | |
183 | my_strlen (str) | |
184 | const char *str; | |
185 | { | |
186 | int n = 0; | |
187 | while (*str++) | |
188 | n++; | |
189 | return n; | |
190 | } | |
191 | ||
192 | static char * | |
193 | my_index (str, chr) | |
194 | const char *str; | |
195 | int chr; | |
196 | { | |
197 | while (*str) | |
198 | { | |
199 | if (*str == chr) | |
200 | return (char *) str; | |
201 | str++; | |
202 | } | |
203 | return 0; | |
204 | } | |
205 | ||
206 | #endif /* GNU C library. */ | |
207 | ||
208 | /* Handle permutation of arguments. */ | |
209 | ||
210 | /* Describe the part of ARGV that contains non-options that have | |
211 | been skipped. `first_nonopt' is the index in ARGV of the first of them; | |
212 | `last_nonopt' is the index after the last of them. */ | |
213 | ||
214 | static int first_nonopt; | |
215 | static int last_nonopt; | |
216 | ||
217 | /* Exchange two adjacent subsequences of ARGV. | |
218 | One subsequence is elements [first_nonopt,last_nonopt) | |
219 | which contains all the non-options that have been skipped so far. | |
220 | The other is elements [last_nonopt,optind), which contains all | |
221 | the options processed since those non-options were skipped. | |
222 | ||
223 | `first_nonopt' and `last_nonopt' are relocated so that they describe | |
224 | the new indices of the non-options in ARGV after they are moved. | |
225 | ||
226 | To perform the swap, we first reverse the order of all elements. So | |
227 | all options now come before all non options, but they are in the | |
228 | wrong order. So we put back the options and non options in original | |
229 | order by reversing them again. For example: | |
230 | original input: a b c -x -y | |
231 | reverse all: -y -x c b a | |
232 | reverse options: -x -y c b a | |
233 | reverse non options: -x -y a b c | |
234 | */ | |
235 | ||
236 | #if __STDC__ || defined(PROTO) | |
237 | static void exchange (char **argv); | |
238 | #endif | |
239 | ||
240 | static void | |
241 | exchange (argv) | |
242 | char **argv; | |
243 | { | |
244 | char *temp, **first, **last; | |
245 | ||
246 | /* Reverse all the elements [first_nonopt, optind) */ | |
247 | first = &argv[first_nonopt]; | |
248 | last = &argv[optind-1]; | |
249 | while (first < last) { | |
250 | temp = *first; *first = *last; *last = temp; first++; last--; | |
251 | } | |
252 | /* Put back the options in order */ | |
253 | first = &argv[first_nonopt]; | |
254 | first_nonopt += (optind - last_nonopt); | |
255 | last = &argv[first_nonopt - 1]; | |
256 | while (first < last) { | |
257 | temp = *first; *first = *last; *last = temp; first++; last--; | |
258 | } | |
259 | ||
260 | /* Put back the non options in order */ | |
261 | first = &argv[first_nonopt]; | |
262 | last_nonopt = optind; | |
263 | last = &argv[last_nonopt-1]; | |
264 | while (first < last) { | |
265 | temp = *first; *first = *last; *last = temp; first++; last--; | |
266 | } | |
267 | } | |
268 | ||
269 | /* Scan elements of ARGV (whose length is ARGC) for option characters | |
270 | given in OPTSTRING. | |
271 | ||
272 | If an element of ARGV starts with '-', and is not exactly "-" or "--", | |
273 | then it is an option element. The characters of this element | |
274 | (aside from the initial '-') are option characters. If `getopt' | |
275 | is called repeatedly, it returns successively each of the option characters | |
276 | from each of the option elements. | |
277 | ||
278 | If `getopt' finds another option character, it returns that character, | |
279 | updating `optind' and `nextchar' so that the next call to `getopt' can | |
280 | resume the scan with the following option character or ARGV-element. | |
281 | ||
282 | If there are no more option characters, `getopt' returns `EOF'. | |
283 | Then `optind' is the index in ARGV of the first ARGV-element | |
284 | that is not an option. (The ARGV-elements have been permuted | |
285 | so that those that are not options now come last.) | |
286 | ||
287 | OPTSTRING is a string containing the legitimate option characters. | |
288 | If an option character is seen that is not listed in OPTSTRING, | |
289 | return BAD_OPTION after printing an error message. If you set `opterr' to | |
290 | zero, the error message is suppressed but we still return BAD_OPTION. | |
291 | ||
292 | If a char in OPTSTRING is followed by a colon, that means it wants an arg, | |
293 | so the following text in the same ARGV-element, or the text of the following | |
294 | ARGV-element, is returned in `optarg'. Two colons mean an option that | |
295 | wants an optional arg; if there is text in the current ARGV-element, | |
296 | it is returned in `optarg', otherwise `optarg' is set to zero. | |
297 | ||
298 | If OPTSTRING starts with `-' or `+', it requests different methods of | |
299 | handling the non-option ARGV-elements. | |
300 | See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. | |
301 | ||
302 | Long-named options begin with `--' instead of `-'. | |
303 | Their names may be abbreviated as long as the abbreviation is unique | |
304 | or is an exact match for some defined option. If they have an | |
305 | argument, it follows the option name in the same ARGV-element, separated | |
306 | from the option name by a `=', or else the in next ARGV-element. | |
307 | When `getopt' finds a long-named option, it returns 0 if that option's | |
308 | `flag' field is nonzero, the value of the option's `val' field | |
309 | if the `flag' field is zero. | |
310 | ||
311 | The elements of ARGV aren't really const, because we permute them. | |
312 | But we pretend they're const in the prototype to be compatible | |
313 | with other systems. | |
314 | ||
315 | LONGOPTS is a vector of `struct option' terminated by an | |
316 | element containing a name which is zero. | |
317 | ||
318 | LONGIND returns the index in LONGOPT of the long-named option found. | |
319 | It is only valid when a long-named option has been found by the most | |
320 | recent call. | |
321 | ||
322 | If LONG_ONLY is nonzero, '-' as well as '--' can introduce | |
323 | long-named options. */ | |
324 | ||
325 | int | |
326 | _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | |
327 | int argc; | |
328 | char *const *argv; | |
329 | const char *optstring; | |
330 | const struct option *longopts; | |
331 | int *longind; | |
332 | int long_only; | |
333 | { | |
334 | int option_index; | |
335 | ||
336 | optarg = 0; | |
337 | ||
338 | /* Initialize the internal data when the first call is made. | |
339 | Start processing options with ARGV-element 1 (since ARGV-element 0 | |
340 | is the program name); the sequence of previously skipped | |
341 | non-option ARGV-elements is empty. */ | |
342 | ||
343 | if (optind == 0) | |
344 | { | |
345 | first_nonopt = last_nonopt = optind = 1; | |
346 | ||
347 | nextchar = NULL; | |
348 | ||
349 | /* Determine how to handle the ordering of options and nonoptions. */ | |
350 | ||
351 | if (optstring[0] == '-') | |
352 | { | |
353 | ordering = RETURN_IN_ORDER; | |
354 | ++optstring; | |
355 | } | |
356 | else if (optstring[0] == '+') | |
357 | { | |
358 | ordering = REQUIRE_ORDER; | |
359 | ++optstring; | |
360 | } | |
361 | else if (getenv ("POSIXLY_CORRECT") != NULL) | |
362 | ordering = REQUIRE_ORDER; | |
363 | else | |
364 | ordering = PERMUTE; | |
365 | } | |
366 | ||
367 | if (nextchar == NULL || *nextchar == '\0') | |
368 | { | |
369 | if (ordering == PERMUTE) | |
370 | { | |
371 | /* If we have just processed some options following some non-options, | |
372 | exchange them so that the options come first. */ | |
373 | ||
374 | if (first_nonopt != last_nonopt && last_nonopt != optind) | |
375 | exchange ((char **) argv); | |
376 | else if (last_nonopt != optind) | |
377 | first_nonopt = optind; | |
378 | ||
379 | /* Now skip any additional non-options | |
380 | and extend the range of non-options previously skipped. */ | |
381 | ||
382 | while (optind < argc | |
383 | && (argv[optind][0] != '-' || argv[optind][1] == '\0') | |
384 | #ifdef GETOPT_COMPAT | |
385 | && (longopts == NULL | |
386 | || argv[optind][0] != '+' || argv[optind][1] == '\0') | |
387 | #endif /* GETOPT_COMPAT */ | |
388 | ) | |
389 | optind++; | |
390 | last_nonopt = optind; | |
391 | } | |
392 | ||
393 | /* Special ARGV-element `--' means premature end of options. | |
394 | Skip it like a null option, | |
395 | then exchange with previous non-options as if it were an option, | |
396 | then skip everything else like a non-option. */ | |
397 | ||
398 | if (optind != argc && !strcmp (argv[optind], "--")) | |
399 | { | |
400 | optind++; | |
401 | ||
402 | if (first_nonopt != last_nonopt && last_nonopt != optind) | |
403 | exchange ((char **) argv); | |
404 | else if (first_nonopt == last_nonopt) | |
405 | first_nonopt = optind; | |
406 | last_nonopt = argc; | |
407 | ||
408 | optind = argc; | |
409 | } | |
410 | ||
411 | /* If we have done all the ARGV-elements, stop the scan | |
412 | and back over any non-options that we skipped and permuted. */ | |
413 | ||
414 | if (optind == argc) | |
415 | { | |
416 | /* Set the next-arg-index to point at the non-options | |
417 | that we previously skipped, so the caller will digest them. */ | |
418 | if (first_nonopt != last_nonopt) | |
419 | optind = first_nonopt; | |
420 | return EOF; | |
421 | } | |
422 | ||
423 | /* If we have come to a non-option and did not permute it, | |
424 | either stop the scan or describe it to the caller and pass it by. */ | |
425 | ||
426 | if ((argv[optind][0] != '-' || argv[optind][1] == '\0') | |
427 | #ifdef GETOPT_COMPAT | |
428 | && (longopts == NULL | |
429 | || argv[optind][0] != '+' || argv[optind][1] == '\0') | |
430 | #endif /* GETOPT_COMPAT */ | |
431 | ) | |
432 | { | |
433 | if (ordering == REQUIRE_ORDER) | |
434 | return EOF; | |
435 | optarg = argv[optind++]; | |
436 | return 1; | |
437 | } | |
438 | ||
439 | /* We have found another option-ARGV-element. | |
440 | Start decoding its characters. */ | |
441 | ||
442 | nextchar = (argv[optind] + 1 | |
443 | + (longopts != NULL && argv[optind][1] == '-')); | |
444 | } | |
445 | ||
446 | if (longopts != NULL | |
447 | && ((argv[optind][0] == '-' | |
448 | && (argv[optind][1] == '-' || long_only)) | |
449 | #ifdef GETOPT_COMPAT | |
450 | || argv[optind][0] == '+' | |
451 | #endif /* GETOPT_COMPAT */ | |
452 | )) | |
453 | { | |
454 | const struct option *p; | |
455 | char *s = nextchar; | |
456 | int exact = 0; | |
457 | int ambig = 0; | |
458 | const struct option *pfound = NULL; | |
459 | int indfound = 0; | |
460 | ||
461 | while (*s && *s != '=') | |
462 | s++; | |
463 | ||
464 | /* Test all options for either exact match or abbreviated matches. */ | |
465 | for (p = longopts, option_index = 0; p->name; | |
466 | p++, option_index++) | |
467 | if (!strncmp (p->name, nextchar, s - nextchar)) | |
468 | { | |
469 | if (s - nextchar == my_strlen (p->name)) | |
470 | { | |
471 | /* Exact match found. */ | |
472 | pfound = p; | |
473 | indfound = option_index; | |
474 | exact = 1; | |
475 | break; | |
476 | } | |
477 | else if (pfound == NULL) | |
478 | { | |
479 | /* First nonexact match found. */ | |
480 | pfound = p; | |
481 | indfound = option_index; | |
482 | } | |
483 | else | |
484 | /* Second nonexact match found. */ | |
485 | ambig = 1; | |
486 | } | |
487 | ||
488 | if (ambig && !exact) | |
489 | { | |
490 | if (opterr) | |
491 | fprintf (stderr, "%s: option `%s' is ambiguous\n", | |
492 | argv[0], argv[optind]); | |
493 | nextchar += my_strlen (nextchar); | |
494 | optind++; | |
495 | return BAD_OPTION; | |
496 | } | |
497 | ||
498 | if (pfound != NULL) | |
499 | { | |
500 | option_index = indfound; | |
501 | optind++; | |
502 | if (*s) | |
503 | { | |
504 | /* Don't test has_arg with >, because some C compilers don't | |
505 | allow it to be used on enums. */ | |
506 | if (pfound->has_arg) | |
507 | optarg = s + 1; | |
508 | else | |
509 | { | |
510 | if (opterr) | |
511 | { | |
512 | if (argv[optind - 1][1] == '-') | |
513 | /* --option */ | |
514 | fprintf (stderr, | |
515 | "%s: option `--%s' doesn't allow an argument\n", | |
516 | argv[0], pfound->name); | |
517 | else | |
518 | /* +option or -option */ | |
519 | fprintf (stderr, | |
520 | "%s: option `%c%s' doesn't allow an argument\n", | |
521 | argv[0], argv[optind - 1][0], pfound->name); | |
522 | } | |
523 | nextchar += my_strlen (nextchar); | |
524 | return BAD_OPTION; | |
525 | } | |
526 | } | |
527 | else if (pfound->has_arg == 1) | |
528 | { | |
529 | if (optind < argc) | |
530 | optarg = argv[optind++]; | |
531 | else | |
532 | { | |
533 | if (opterr) | |
534 | fprintf (stderr, "%s: option `%s' requires an argument\n", | |
535 | argv[0], argv[optind - 1]); | |
536 | nextchar += my_strlen (nextchar); | |
537 | return optstring[0] == ':' ? ':' : BAD_OPTION; | |
538 | } | |
539 | } | |
540 | nextchar += my_strlen (nextchar); | |
541 | if (longind != NULL) | |
542 | *longind = option_index; | |
543 | if (pfound->flag) | |
544 | { | |
545 | *(pfound->flag) = pfound->val; | |
546 | return 0; | |
547 | } | |
548 | return pfound->val; | |
549 | } | |
550 | /* Can't find it as a long option. If this is not getopt_long_only, | |
551 | or the option starts with '--' or is not a valid short | |
552 | option, then it's an error. | |
553 | Otherwise interpret it as a short option. */ | |
554 | if (!long_only || argv[optind][1] == '-' | |
555 | #ifdef GETOPT_COMPAT | |
556 | || argv[optind][0] == '+' | |
557 | #endif /* GETOPT_COMPAT */ | |
558 | || my_index (optstring, *nextchar) == NULL) | |
559 | { | |
560 | if (opterr) | |
561 | { | |
562 | if (argv[optind][1] == '-') | |
563 | /* --option */ | |
564 | fprintf (stderr, "%s: unrecognized option `--%s'\n", | |
565 | argv[0], nextchar); | |
566 | else | |
567 | /* +option or -option */ | |
568 | fprintf (stderr, "%s: unrecognized option `%c%s'\n", | |
569 | argv[0], argv[optind][0], nextchar); | |
570 | } | |
571 | nextchar = (char *) ""; | |
572 | optind++; | |
573 | return BAD_OPTION; | |
574 | } | |
575 | } | |
576 | ||
577 | /* Look at and handle the next option-character. */ | |
578 | ||
579 | { | |
580 | char c = *nextchar++; | |
581 | char *temp = my_index (optstring, c); | |
582 | ||
583 | /* Increment `optind' when we start to process its last character. */ | |
584 | if (*nextchar == '\0') | |
585 | ++optind; | |
586 | ||
587 | if (temp == NULL || c == ':') | |
588 | { | |
589 | if (opterr) | |
590 | { | |
591 | #if 0 | |
592 | if (c < 040 || c >= 0177) | |
593 | fprintf (stderr, "%s: unrecognized option, character code 0%o\n", | |
594 | argv[0], c); | |
595 | else | |
596 | fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); | |
597 | #else | |
598 | /* 1003.2 specifies the format of this message. */ | |
599 | fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); | |
600 | #endif | |
601 | } | |
602 | optopt = c; | |
603 | return BAD_OPTION; | |
604 | } | |
605 | if (temp[1] == ':') | |
606 | { | |
607 | if (temp[2] == ':') | |
608 | { | |
609 | /* This is an option that accepts an argument optionally. */ | |
610 | if (*nextchar != '\0') | |
611 | { | |
612 | optarg = nextchar; | |
613 | optind++; | |
614 | } | |
615 | else | |
616 | optarg = 0; | |
617 | nextchar = NULL; | |
618 | } | |
619 | else | |
620 | { | |
621 | /* This is an option that requires an argument. */ | |
622 | if (*nextchar != '\0') | |
623 | { | |
624 | optarg = nextchar; | |
625 | /* If we end this ARGV-element by taking the rest as an arg, | |
626 | we must advance to the next element now. */ | |
627 | optind++; | |
628 | } | |
629 | else if (optind == argc) | |
630 | { | |
631 | if (opterr) | |
632 | { | |
633 | #if 0 | |
634 | fprintf (stderr, "%s: option `-%c' requires an argument\n", | |
635 | argv[0], c); | |
636 | #else | |
637 | /* 1003.2 specifies the format of this message. */ | |
638 | fprintf (stderr, "%s: option requires an argument -- %c\n", | |
639 | argv[0], c); | |
640 | #endif | |
641 | } | |
642 | optopt = c; | |
643 | if (optstring[0] == ':') | |
644 | c = ':'; | |
645 | else | |
646 | c = BAD_OPTION; | |
647 | } | |
648 | else | |
649 | /* We already incremented `optind' once; | |
650 | increment it again when taking next ARGV-elt as argument. */ | |
651 | optarg = argv[optind++]; | |
652 | nextchar = NULL; | |
653 | } | |
654 | } | |
655 | return c; | |
656 | } | |
657 | } | |
658 | ||
659 | int | |
660 | getopt (argc, argv, optstring) | |
661 | int argc; | |
662 | char *const *argv; | |
663 | const char *optstring; | |
664 | { | |
665 | return _getopt_internal (argc, argv, optstring, | |
666 | (const struct option *) 0, | |
667 | (int *) 0, | |
668 | 0); | |
669 | } | |
670 | ||
671 | int | |
672 | getopt_long (argc, argv, options, long_options, opt_index) | |
673 | int argc; | |
674 | char *const *argv; | |
675 | const char *options; | |
676 | const struct option *long_options; | |
677 | int *opt_index; | |
678 | { | |
679 | return _getopt_internal (argc, argv, options, long_options, opt_index, 0); | |
680 | } | |
681 | ||
682 | #endif /* _LIBC or not __GNU_LIBRARY__. */ | |
683 | ||
684 | #ifdef TEST | |
685 | ||
686 | /* Compile with -DTEST to make an executable for use in testing | |
687 | the above definition of `getopt'. */ | |
688 | ||
689 | int | |
690 | main (argc, argv) | |
691 | int argc; | |
692 | char **argv; | |
693 | { | |
694 | int c; | |
695 | int digit_optind = 0; | |
696 | ||
697 | while (1) | |
698 | { | |
699 | int this_option_optind = optind ? optind : 1; | |
700 | ||
701 | c = getopt (argc, argv, "abc:d:0123456789"); | |
702 | if (c == EOF) | |
703 | break; | |
704 | ||
705 | switch (c) | |
706 | { | |
707 | case '0': | |
708 | case '1': | |
709 | case '2': | |
710 | case '3': | |
711 | case '4': | |
712 | case '5': | |
713 | case '6': | |
714 | case '7': | |
715 | case '8': | |
716 | case '9': | |
717 | if (digit_optind != 0 && digit_optind != this_option_optind) | |
718 | printf ("digits occur in two different argv-elements.\n"); | |
719 | digit_optind = this_option_optind; | |
720 | printf ("option %c\n", c); | |
721 | break; | |
722 | ||
723 | case 'a': | |
724 | printf ("option a\n"); | |
725 | break; | |
726 | ||
727 | case 'b': | |
728 | printf ("option b\n"); | |
729 | break; | |
730 | ||
731 | case 'c': | |
732 | printf ("option c with value `%s'\n", optarg); | |
733 | break; | |
734 | ||
735 | case BAD_OPTION: | |
736 | break; | |
737 | ||
738 | default: | |
739 | printf ("?? getopt returned character code 0%o ??\n", c); | |
740 | } | |
741 | } | |
742 | ||
743 | if (optind < argc) | |
744 | { | |
745 | printf ("non-option ARGV-elements: "); | |
746 | while (optind < argc) | |
747 | printf ("%s ", argv[optind++]); | |
748 | printf ("\n"); | |
749 | } | |
750 | ||
751 | exit (0); | |
752 | } | |
753 | ||
754 | #endif /* TEST */ |
0 | /* Declarations for getopt. | |
1 | Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. | |
2 | ||
3 | This program is free software; you can redistribute it and/or modify it | |
4 | under the terms of the GNU General Public License as published by the | |
5 | Free Software Foundation; either version 2, or (at your option) any | |
6 | later version. | |
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 | You should have received a copy of the GNU General Public License | |
14 | along with this program; if not, write to the Free Software | |
15 | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
16 | ||
17 | #ifndef _GETOPT_H | |
18 | #define _GETOPT_H 1 | |
19 | ||
20 | #ifdef __cplusplus | |
21 | extern "C" { | |
22 | #endif | |
23 | ||
24 | #ifndef __MacOSX__ | |
25 | ||
26 | /* For communication from `getopt' to the caller. | |
27 | When `getopt' finds an option that takes an argument, | |
28 | the argument value is returned here. | |
29 | Also, when `ordering' is RETURN_IN_ORDER, | |
30 | each non-option ARGV-element is returned here. */ | |
31 | ||
32 | extern char *optarg; | |
33 | ||
34 | /* Index in ARGV of the next element to be scanned. | |
35 | This is used for communication to and from the caller | |
36 | and for communication between successive calls to `getopt'. | |
37 | ||
38 | On entry to `getopt', zero means this is the first call; initialize. | |
39 | ||
40 | When `getopt' returns EOF, this is the index of the first of the | |
41 | non-option elements that the caller should itself scan. | |
42 | ||
43 | Otherwise, `optind' communicates from one call to the next | |
44 | how much of ARGV has been scanned so far. */ | |
45 | ||
46 | extern int optind; | |
47 | ||
48 | /* Callers store zero here to inhibit the error message `getopt' prints | |
49 | for unrecognized options. */ | |
50 | ||
51 | extern int opterr; | |
52 | ||
53 | /* Set to an option character which was unrecognized. */ | |
54 | ||
55 | extern int optopt; | |
56 | #endif | |
57 | ||
58 | /* Describe the long-named options requested by the application. | |
59 | The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector | |
60 | of `struct option' terminated by an element containing a name which is | |
61 | zero. | |
62 | ||
63 | The field `has_arg' is: | |
64 | no_argument (or 0) if the option does not take an argument, | |
65 | required_argument (or 1) if the option requires an argument, | |
66 | optional_argument (or 2) if the option takes an optional argument. | |
67 | ||
68 | If the field `flag' is not NULL, it points to a variable that is set | |
69 | to the value given in the field `val' when the option is found, but | |
70 | left unchanged if the option is not found. | |
71 | ||
72 | To have a long-named option do something other than set an `int' to | |
73 | a compiled-in constant, such as set a value from `optarg', set the | |
74 | option's `flag' field to zero and its `val' field to a nonzero | |
75 | value (the equivalent single-letter option character, if there is | |
76 | one). For long options that have a zero `flag' field, `getopt' | |
77 | returns the contents of the `val' field. */ | |
78 | ||
79 | struct option | |
80 | { | |
81 | #if __STDC__ | |
82 | const char *name; | |
83 | #else | |
84 | char *name; | |
85 | #endif | |
86 | /* has_arg can't be an enum because some compilers complain about | |
87 | type mismatches in all the code that assumes it is an int. */ | |
88 | int has_arg; | |
89 | int *flag; | |
90 | int val; | |
91 | }; | |
92 | ||
93 | /* Names for the values of the `has_arg' field of `struct option'. */ | |
94 | ||
95 | #define no_argument 0 | |
96 | #define required_argument 1 | |
97 | #define optional_argument 2 | |
98 | ||
99 | //#if __STDC__ || defined(PROTO) | |
100 | #if defined(__GNU_LIBRARY__) | |
101 | /* Many other libraries have conflicting prototypes for getopt, with | |
102 | differences in the consts, in stdlib.h. To avoid compilation | |
103 | errors, only prototype getopt for the GNU C library. */ | |
104 | extern int getopt (int argc, char *const *argv, const char *shortopts); | |
105 | #endif /* not __GNU_LIBRARY__ */ | |
106 | extern int getopt_long (int argc, char *const *argv, const char *shortopts, | |
107 | const struct option *longopts, int *longind); | |
108 | extern int getopt_long_only (int argc, char *const *argv, | |
109 | const char *shortopts, | |
110 | const struct option *longopts, int *longind); | |
111 | ||
112 | /* Internal only. Users should not call this directly. */ | |
113 | extern int _getopt_internal (int argc, char *const *argv, | |
114 | const char *shortopts, | |
115 | const struct option *longopts, int *longind, | |
116 | int long_only); | |
117 | //#else /* not __STDC__ */ | |
118 | extern int getopt (int argc, char *const *argv, const char *shortopts); | |
119 | //extern int getopt_long (); | |
120 | //extern int getopt_long_only (); | |
121 | ||
122 | //extern int _getopt_internal (); | |
123 | //#endif /* not __STDC__ */ | |
124 | ||
125 | #ifdef __cplusplus | |
126 | } | |
127 | #endif | |
128 | ||
129 | #endif /* _GETOPT_H */ |
3 | 3 | libmp4ff_a_CFLAGS = -DUSE_TAGGING=1 |
4 | 4 | |
5 | 5 | libmp4ff_a_SOURCES = mp4ff.c mp4atom.c mp4meta.c mp4sample.c mp4util.c \ |
6 | mp4tagupdate.c mp4ff.h mp4ffint.h mp4ff_int_types.h | |
6 | mp4tagupdate.c mp4ff.h mp4ffint.h |
257 | 257 | |
258 | 258 | static int32_t mp4ff_read_stsz(mp4ff_t *f) |
259 | 259 | { |
260 | if (f->total_tracks == 0) | |
261 | return f->error++; | |
262 | ||
260 | 263 | mp4ff_read_char(f); /* version */ |
261 | 264 | mp4ff_read_int24(f); /* flags */ |
262 | 265 | f->track[f->total_tracks - 1]->stsz_sample_size = mp4ff_read_int32(f); |
268 | 271 | f->track[f->total_tracks - 1]->stsz_table = |
269 | 272 | (int32_t*)malloc(f->track[f->total_tracks - 1]->stsz_sample_count*sizeof(int32_t)); |
270 | 273 | |
271 | for (i = 0; i < f->track[f->total_tracks - 1]->stsz_sample_count; i++) | |
274 | if (!f->track[f->total_tracks - 1]->stsz_table) | |
275 | return f->error++; | |
276 | ||
277 | for (i = 0; i < f->track[f->total_tracks - 1]->stsz_sample_count && !f->stream->read_error; i++) | |
272 | 278 | { |
273 | 279 | f->track[f->total_tracks - 1]->stsz_table[i] = mp4ff_read_int32(f); |
274 | 280 | } |
281 | 287 | { |
282 | 288 | uint8_t tag; |
283 | 289 | uint32_t temp; |
290 | ||
291 | if (f->total_tracks == 0) | |
292 | return f->error++; | |
284 | 293 | |
285 | 294 | mp4ff_read_char(f); /* version */ |
286 | 295 | mp4ff_read_int24(f); /* flags */ |
346 | 355 | uint8_t atom_type = 0; |
347 | 356 | uint8_t header_size = 0; |
348 | 357 | |
358 | if (f->total_tracks == 0) | |
359 | return f->error++; | |
360 | ||
349 | 361 | for (i = 0; i < 6; i++) |
350 | 362 | { |
351 | 363 | mp4ff_read_char(f); /* reserved */ |
379 | 391 | int32_t i; |
380 | 392 | uint8_t header_size = 0; |
381 | 393 | |
394 | /* CVE-2017-9218 */ | |
395 | if (f->total_tracks == 0) | |
396 | return f->error++; | |
397 | ||
382 | 398 | mp4ff_read_char(f); /* version */ |
383 | 399 | mp4ff_read_int24(f); /* flags */ |
384 | 400 | |
385 | 401 | f->track[f->total_tracks - 1]->stsd_entry_count = mp4ff_read_int32(f); |
386 | 402 | |
387 | for (i = 0; i < f->track[f->total_tracks - 1]->stsd_entry_count; i++) | |
403 | for (i = 0; i < f->track[f->total_tracks - 1]->stsd_entry_count && !f->stream->read_error; i++) /* CVE-2017-9253 */ | |
388 | 404 | { |
389 | 405 | uint64_t skip = mp4ff_position(f); |
390 | 406 | uint64_t size; |
414 | 430 | { |
415 | 431 | int32_t i; |
416 | 432 | |
433 | if (f->total_tracks == 0) | |
434 | return f->error++; | |
435 | ||
417 | 436 | mp4ff_read_char(f); /* version */ |
418 | 437 | mp4ff_read_int24(f); /* flags */ |
419 | 438 | f->track[f->total_tracks - 1]->stsc_entry_count = mp4ff_read_int32(f); |
425 | 444 | f->track[f->total_tracks - 1]->stsc_sample_desc_index = |
426 | 445 | (int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t)); |
427 | 446 | |
428 | for (i = 0; i < f->track[f->total_tracks - 1]->stsc_entry_count; i++) | |
447 | /* CVE-2017-9219 */ | |
448 | if (!f->track[f->total_tracks - 1]->stsc_first_chunk) | |
449 | { | |
450 | return f->error++; | |
451 | } | |
452 | if (!f->track[f->total_tracks - 1]->stsc_samples_per_chunk) | |
453 | { | |
454 | free(f->track[f->total_tracks - 1]->stsc_first_chunk); | |
455 | f->track[f->total_tracks - 1]->stsc_first_chunk = NULL; | |
456 | return f->error++; | |
457 | } | |
458 | if (!f->track[f->total_tracks - 1]->stsc_sample_desc_index) | |
459 | { | |
460 | free(f->track[f->total_tracks - 1]->stsc_first_chunk); | |
461 | f->track[f->total_tracks - 1]->stsc_first_chunk = NULL; | |
462 | free(f->track[f->total_tracks - 1]->stsc_samples_per_chunk); | |
463 | f->track[f->total_tracks - 1]->stsc_samples_per_chunk = NULL; | |
464 | return f->error++; | |
465 | } | |
466 | ||
467 | for (i = 0; i < f->track[f->total_tracks - 1]->stsc_entry_count && !f->stream->read_error; i++) /* CVE-2017-9255 */ | |
429 | 468 | { |
430 | 469 | f->track[f->total_tracks - 1]->stsc_first_chunk[i] = mp4ff_read_int32(f); |
431 | 470 | f->track[f->total_tracks - 1]->stsc_samples_per_chunk[i] = mp4ff_read_int32(f); |
439 | 478 | { |
440 | 479 | int32_t i; |
441 | 480 | |
481 | if (f->total_tracks == 0) | |
482 | return f->error++; | |
483 | ||
442 | 484 | mp4ff_read_char(f); /* version */ |
443 | 485 | mp4ff_read_int24(f); /* flags */ |
444 | 486 | f->track[f->total_tracks - 1]->stco_entry_count = mp4ff_read_int32(f); |
446 | 488 | f->track[f->total_tracks - 1]->stco_chunk_offset = |
447 | 489 | (int32_t*)malloc(f->track[f->total_tracks - 1]->stco_entry_count*sizeof(int32_t)); |
448 | 490 | |
449 | for (i = 0; i < f->track[f->total_tracks - 1]->stco_entry_count; i++) | |
491 | /* CVE-2017-9220 */ | |
492 | if (!f->track[f->total_tracks - 1]->stco_chunk_offset) | |
493 | return f->error++; | |
494 | ||
495 | for (i = 0; i < f->track[f->total_tracks - 1]->stco_entry_count && !f->stream->read_error; i++) /* CVE-2017-9256 */ | |
450 | 496 | { |
451 | 497 | f->track[f->total_tracks - 1]->stco_chunk_offset[i] = mp4ff_read_int32(f); |
452 | 498 | } |
457 | 503 | static int32_t mp4ff_read_ctts(mp4ff_t *f) |
458 | 504 | { |
459 | 505 | int32_t i; |
460 | mp4ff_track_t * p_track = f->track[f->total_tracks - 1]; | |
461 | ||
506 | mp4ff_track_t * p_track; | |
507 | ||
508 | if (f->total_tracks == 0) | |
509 | return f->error++; | |
510 | ||
511 | p_track = f->track[f->total_tracks - 1]; | |
462 | 512 | if (p_track->ctts_entry_count) return 0; |
463 | 513 | |
464 | 514 | mp4ff_read_char(f); /* version */ |
477 | 527 | } |
478 | 528 | else |
479 | 529 | { |
480 | for (i = 0; i < f->track[f->total_tracks - 1]->ctts_entry_count; i++) | |
530 | for (i = 0; i < f->track[f->total_tracks - 1]->ctts_entry_count && !f->stream->read_error; i++) /* CVE-2017-9257 */ | |
481 | 531 | { |
482 | 532 | p_track->ctts_sample_count[i] = mp4ff_read_int32(f); |
483 | 533 | p_track->ctts_sample_offset[i] = mp4ff_read_int32(f); |
489 | 539 | static int32_t mp4ff_read_stts(mp4ff_t *f) |
490 | 540 | { |
491 | 541 | int32_t i; |
492 | mp4ff_track_t * p_track = f->track[f->total_tracks - 1]; | |
542 | mp4ff_track_t * p_track; | |
543 | ||
544 | /* CVE-2017-9223 */ | |
545 | if (f->total_tracks == 0) | |
546 | return f->error++; | |
547 | ||
548 | p_track = f->track[f->total_tracks - 1]; | |
493 | 549 | |
494 | 550 | if (p_track->stts_entry_count) return 0; |
495 | 551 | |
509 | 565 | } |
510 | 566 | else |
511 | 567 | { |
512 | for (i = 0; i < f->track[f->total_tracks - 1]->stts_entry_count; i++) | |
568 | for (i = 0; i < f->track[f->total_tracks - 1]->stts_entry_count && !f->stream->read_error; i++) /* CVE-2017-9254 */ | |
513 | 569 | { |
514 | 570 | p_track->stts_sample_count[i] = mp4ff_read_int32(f); |
515 | 571 | p_track->stts_sample_delta[i] = mp4ff_read_int32(f); |
595 | 651 | static int32_t mp4ff_read_mdhd(mp4ff_t *f) |
596 | 652 | { |
597 | 653 | uint32_t version; |
654 | ||
655 | /* CVE-2017-9221 */ | |
656 | if (f->total_tracks == 0) | |
657 | return f->error++; | |
598 | 658 | |
599 | 659 | version = mp4ff_read_int32(f); |
600 | 660 | if (version==1) |
41 | 41 | |
42 | 42 | parse_atoms(ff,0); |
43 | 43 | |
44 | if (ff->error) | |
45 | { | |
46 | free(ff); | |
47 | ff = NULL; | |
48 | } | |
49 | ||
44 | 50 | return ff; |
45 | 51 | } |
46 | 52 | |
53 | 59 | ff->stream = f; |
54 | 60 | |
55 | 61 | parse_atoms(ff,1); |
62 | ||
63 | if (ff->error) | |
64 | { | |
65 | free(ff); | |
66 | ff = NULL; | |
67 | } | |
56 | 68 | |
57 | 69 | return ff; |
58 | 70 | } |
100 | 112 | if (ff) free(ff); |
101 | 113 | } |
102 | 114 | |
103 | void mp4ff_track_add(mp4ff_t *f) | |
115 | static void mp4ff_track_add(mp4ff_t *f) | |
104 | 116 | { |
105 | 117 | f->total_tracks++; |
118 | ||
119 | if (f->total_tracks > MAX_TRACKS) | |
120 | { | |
121 | f->total_tracks = 0; | |
122 | f->error++; | |
123 | return; | |
124 | } | |
106 | 125 | |
107 | 126 | f->track[f->total_tracks - 1] = malloc(sizeof(mp4ff_track_t)); |
108 | 127 | |
184 | 203 | uint8_t header_size = 0; |
185 | 204 | |
186 | 205 | f->file_size = 0; |
206 | f->stream->read_error = 0; | |
187 | 207 | |
188 | 208 | while ((size = mp4ff_atom_read_header(f, &atom_type, &header_size)) != 0) |
189 | 209 | { |
34 | 34 | extern "C" { |
35 | 35 | #endif /* __cplusplus */ |
36 | 36 | |
37 | #ifdef HAVE_STDINT_H | |
38 | 37 | #include <stdint.h> |
39 | #else | |
40 | #include "mp4ff_int_types.h" | |
41 | #endif | |
42 | 38 | |
43 | 39 | /* file callback structure */ |
44 | 40 | typedef struct |
46 | 42 | uint32_t (*read)(void *user_data, void *buffer, uint32_t length); |
47 | 43 | uint32_t (*write)(void *udata, void *buffer, uint32_t length); |
48 | 44 | uint32_t (*seek)(void *user_data, uint64_t position); |
49 | uint32_t (*truncate)(void *user_data); | |
45 | uint32_t (*truncate)(void *user_data); | |
50 | 46 | void *user_data; |
47 | uint32_t read_error; | |
51 | 48 | } mp4ff_callback_t; |
52 | 49 | |
50 | #ifdef USE_TAGGING | |
51 | ||
52 | /* metadata tag structure */ | |
53 | typedef struct | |
54 | { | |
55 | char *item; | |
56 | char *value; | |
57 | uint32_t len; | |
58 | } mp4ff_tag_t; | |
59 | ||
60 | /* metadata list structure */ | |
61 | typedef struct | |
62 | { | |
63 | mp4ff_tag_t *tags; | |
64 | uint32_t count; | |
65 | } mp4ff_metadata_t; | |
66 | ||
67 | int32_t mp4ff_meta_update(mp4ff_callback_t *f,const mp4ff_metadata_t * data); | |
68 | ||
69 | #endif | |
70 | ||
71 | ||
72 | #ifndef MP4FF_INTERNAL_H | |
53 | 73 | /* mp4 main file structure */ |
54 | 74 | typedef void* mp4ff_t; |
75 | #else | |
76 | typedef struct | |
77 | { | |
78 | int32_t type; | |
79 | int32_t channelCount; | |
80 | int32_t sampleSize; | |
81 | uint16_t sampleRate; | |
82 | int32_t audioType; | |
83 | ||
84 | /* stsd */ | |
85 | int32_t stsd_entry_count; | |
86 | ||
87 | /* stsz */ | |
88 | int32_t stsz_sample_size; | |
89 | int32_t stsz_sample_count; | |
90 | int32_t *stsz_table; | |
91 | ||
92 | /* stts */ | |
93 | int32_t stts_entry_count; | |
94 | int32_t *stts_sample_count; | |
95 | int32_t *stts_sample_delta; | |
96 | ||
97 | /* stsc */ | |
98 | int32_t stsc_entry_count; | |
99 | int32_t *stsc_first_chunk; | |
100 | int32_t *stsc_samples_per_chunk; | |
101 | int32_t *stsc_sample_desc_index; | |
102 | ||
103 | /* stsc */ | |
104 | int32_t stco_entry_count; | |
105 | int32_t *stco_chunk_offset; | |
106 | ||
107 | /* ctts */ | |
108 | int32_t ctts_entry_count; | |
109 | int32_t *ctts_sample_count; | |
110 | int32_t *ctts_sample_offset; | |
111 | ||
112 | /* esde */ | |
113 | uint8_t *decoderConfig; | |
114 | int32_t decoderConfigLen; | |
115 | ||
116 | uint32_t maxBitrate; | |
117 | uint32_t avgBitrate; | |
118 | ||
119 | uint32_t timeScale; | |
120 | uint64_t duration; | |
121 | ||
122 | } mp4ff_track_t; | |
123 | ||
124 | /* mp4 main file structure */ | |
125 | typedef struct | |
126 | { | |
127 | /* stream to read from */ | |
128 | mp4ff_callback_t *stream; | |
129 | int64_t current_position; | |
130 | ||
131 | int32_t moov_read; | |
132 | uint64_t moov_offset; | |
133 | uint64_t moov_size; | |
134 | uint8_t last_atom; | |
135 | uint64_t file_size; | |
136 | uint32_t error; | |
137 | ||
138 | /* mvhd */ | |
139 | int32_t time_scale; | |
140 | int32_t duration; | |
141 | ||
142 | /* incremental track index while reading the file */ | |
143 | int32_t total_tracks; | |
144 | ||
145 | /* track data */ | |
146 | mp4ff_track_t *track[MAX_TRACKS]; | |
147 | ||
148 | /* metadata */ | |
149 | mp4ff_metadata_t tags; | |
150 | } mp4ff_t; | |
151 | #endif | |
55 | 152 | |
56 | 153 | |
57 | 154 | /* API */ |
109 | 206 | int mp4ff_meta_get_compilation(const mp4ff_t *f, char **value); |
110 | 207 | int mp4ff_meta_get_tempo(const mp4ff_t *f, char **value); |
111 | 208 | int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value); |
112 | #ifdef USE_TAGGING | |
113 | ||
114 | /* metadata tag structure */ | |
115 | typedef struct | |
116 | { | |
117 | char *item; | |
118 | char *value; | |
119 | } mp4ff_tag_t; | |
120 | ||
121 | /* metadata list structure */ | |
122 | typedef struct | |
123 | { | |
124 | mp4ff_tag_t *tags; | |
125 | uint32_t count; | |
126 | } mp4ff_metadata_t; | |
127 | ||
128 | int32_t mp4ff_meta_update(mp4ff_callback_t *f,const mp4ff_metadata_t * data); | |
129 | ||
130 | #endif | |
131 | ||
132 | 209 | |
133 | 210 | #ifdef __cplusplus |
134 | 211 | } |
0 | #ifndef _MP4FF_INT_TYPES_H_ | |
1 | #define _MP4FF_INT_TYPES_H_ | |
2 | ||
3 | #if defined (_WIN32) | |
4 | ||
5 | #ifdef __MINGW32__ | |
6 | #include <stdlib.h> | |
7 | #endif /* #ifdef __MINGW32__ */ | |
8 | ||
9 | typedef signed char int8_t; | |
10 | typedef unsigned char uint8_t; | |
11 | typedef signed short int16_t; | |
12 | typedef unsigned short uint16_t; | |
13 | typedef signed long int32_t; | |
14 | typedef unsigned long uint32_t; | |
15 | ||
16 | typedef signed __int64 int64_t; | |
17 | typedef unsigned __int64 uint64_t; | |
18 | ||
19 | #else | |
20 | ||
21 | #include <stdint.h> | |
22 | ||
23 | #endif | |
24 | ||
25 | ||
26 | #endif |
34 | 34 | extern "C" { |
35 | 35 | #endif /* __cplusplus */ |
36 | 36 | |
37 | #include "mp4ff_int_types.h" | |
38 | 37 | #include <stdlib.h> |
38 | #include <stdint.h> | |
39 | 39 | |
40 | 40 | #define MAX_TRACKS 1024 |
41 | 41 | #define TRACK_UNKNOWN 0 |
135 | 135 | #define strdup _strdup |
136 | 136 | #endif |
137 | 137 | |
138 | /* file callback structure */ | |
139 | typedef struct | |
140 | { | |
141 | uint32_t (*read)(void *user_data, void *buffer, uint32_t length); | |
142 | uint32_t (*write)(void *udata, void *buffer, uint32_t length); | |
143 | uint32_t (*seek)(void *user_data, uint64_t position); | |
144 | uint32_t (*truncate)(void *user_data); | |
145 | void *user_data; | |
146 | } mp4ff_callback_t; | |
147 | ||
148 | ||
149 | /* metadata tag structure */ | |
150 | typedef struct | |
151 | { | |
152 | char *item; | |
153 | char *value; | |
154 | uint32_t len; | |
155 | } mp4ff_tag_t; | |
156 | ||
157 | /* metadata list structure */ | |
158 | typedef struct | |
159 | { | |
160 | mp4ff_tag_t *tags; | |
161 | uint32_t count; | |
162 | } mp4ff_metadata_t; | |
163 | ||
164 | ||
165 | typedef struct | |
166 | { | |
167 | int32_t type; | |
168 | int32_t channelCount; | |
169 | int32_t sampleSize; | |
170 | uint16_t sampleRate; | |
171 | int32_t audioType; | |
172 | ||
173 | /* stsd */ | |
174 | int32_t stsd_entry_count; | |
175 | ||
176 | /* stsz */ | |
177 | int32_t stsz_sample_size; | |
178 | int32_t stsz_sample_count; | |
179 | int32_t *stsz_table; | |
180 | ||
181 | /* stts */ | |
182 | int32_t stts_entry_count; | |
183 | int32_t *stts_sample_count; | |
184 | int32_t *stts_sample_delta; | |
185 | ||
186 | /* stsc */ | |
187 | int32_t stsc_entry_count; | |
188 | int32_t *stsc_first_chunk; | |
189 | int32_t *stsc_samples_per_chunk; | |
190 | int32_t *stsc_sample_desc_index; | |
191 | ||
192 | /* stsc */ | |
193 | int32_t stco_entry_count; | |
194 | int32_t *stco_chunk_offset; | |
195 | ||
196 | /* ctts */ | |
197 | int32_t ctts_entry_count; | |
198 | int32_t *ctts_sample_count; | |
199 | int32_t *ctts_sample_offset; | |
200 | ||
201 | /* esde */ | |
202 | uint8_t *decoderConfig; | |
203 | int32_t decoderConfigLen; | |
204 | ||
205 | uint32_t maxBitrate; | |
206 | uint32_t avgBitrate; | |
207 | ||
208 | uint32_t timeScale; | |
209 | uint64_t duration; | |
210 | ||
211 | } mp4ff_track_t; | |
212 | ||
213 | /* mp4 main file structure */ | |
214 | typedef struct | |
215 | { | |
216 | /* stream to read from */ | |
217 | mp4ff_callback_t *stream; | |
218 | int64_t current_position; | |
219 | ||
220 | int32_t moov_read; | |
221 | uint64_t moov_offset; | |
222 | uint64_t moov_size; | |
223 | uint8_t last_atom; | |
224 | uint64_t file_size; | |
225 | ||
226 | /* mvhd */ | |
227 | int32_t time_scale; | |
228 | int32_t duration; | |
229 | ||
230 | /* incremental track index while reading the file */ | |
231 | int32_t total_tracks; | |
232 | ||
233 | /* track data */ | |
234 | mp4ff_track_t *track[MAX_TRACKS]; | |
235 | ||
236 | /* metadata */ | |
237 | mp4ff_metadata_t tags; | |
238 | } mp4ff_t; | |
239 | ||
240 | ||
241 | ||
138 | #include "mp4ff.h" | |
242 | 139 | |
243 | 140 | /* mp4util.c */ |
244 | 141 | int32_t mp4ff_read_data(mp4ff_t *f, int8_t *data, uint32_t size); |
239 | 239 | uint32_t len = 0; |
240 | 240 | |
241 | 241 | |
242 | while (sumsize < size) | |
242 | while (sumsize < size && !f->stream->read_error) /* CVE-2017-9222 */ | |
243 | 243 | { |
244 | 244 | uint64_t destpos; |
245 | 245 | subsize = mp4ff_atom_read_header(f, &atom_type, &header_size); |
499 | 499 | return mp4ff_meta_find_by_name_and_return_len(f, "cover", value); |
500 | 500 | } |
501 | 501 | |
502 | #endif⏎ | |
502 | #endif |
35 | 35 | int32_t result = 1; |
36 | 36 | |
37 | 37 | result = f->stream->read(f->stream->user_data, data, size); |
38 | ||
39 | if (result < size) | |
40 | f->stream->read_error++; | |
38 | 41 | |
39 | 42 | f->current_position += size; |
40 | 43 |
0 | dnl | |
1 | dnl This is the configure.in for faad2 related to unix creation | |
2 | ||
3 | dnl - libfaad.so | |
4 | dnl - libmp4ff.a (only static for moment) | |
5 | dnl - faad | |
6 | dnl - xmms input mp4/aac plugin | |
7 | dnl - mpeg4ip plugin (requires mpeg4ip's libmp4v2 to be installed) | |
8 | ||
9 | AC_PREREQ(2.50) | |
10 | AC_INIT(faad2, 2.8.1) | |
11 | AC_CONFIG_AUX_DIR(.) | |
12 | AM_INIT_AUTOMAKE([subdir-objects]) | |
13 | ||
14 | AC_PROG_LIBTOOL | |
15 | AC_SUBST(LIBTOOL_DEPS) | |
16 | ||
17 | dnl Checks for programs. | |
18 | AC_PROG_CC | |
19 | AM_PROG_CC_C_O | |
20 | AC_PROG_CPP | |
21 | dnl disable for mpeg4ip plugin | |
22 | AC_PROG_CXX | |
23 | AC_PROG_INSTALL | |
24 | AC_PROG_LN_S | |
25 | AC_PROG_MAKE_SET | |
26 | AC_CHECK_PROGS(RPMBUILD, rpmbuild, rpm) | |
27 | ||
28 | AC_CONFIG_HEADERS([config.h]) | |
29 | ||
30 | AC_ARG_WITH(xmms,[ --with-xmms compile XMMS-1 plugin], | |
31 | WITHXMMS=$withval, WITHXMMS=no) | |
32 | ||
33 | AC_ARG_WITH(drm,[ --with-drm compile libfaad with DRM support], | |
34 | WITHDRM=$withval, WITHDRM=no) | |
35 | ||
36 | AC_ARG_WITH(mpeg4ip, [ --with-mpeg4ip compile mpeg4ip plugin], | |
37 | WITHMPEG4IP=$withval, WITHMPEG4IP=no) | |
38 | ||
39 | dnl Checks for header files required for mp4.h | |
40 | AC_HEADER_STDC | |
41 | AC_CHECK_HEADERS(stdint.h inttypes.h) | |
42 | AC_CHECK_HEADERS(mathf.h) | |
43 | AC_CHECK_HEADERS(float.h) | |
44 | AC_CHECK_FUNCS(strchr memcpy) | |
45 | AC_CHECK_HEADERS(sys/time.h) | |
46 | AC_HEADER_TIME | |
47 | ||
48 | dnl DRMS | |
49 | AC_CHECK_HEADERS(errno.h sys/stat.h sys/types.h limits.h) | |
50 | AC_CHECK_HEADERS(sysfs/libsysfs.h) | |
51 | AC_CHECK_HEADERS(IOKit/IOKitLib.h, | |
52 | [AC_CHECK_LIB(IOKit, main, | |
53 | [AC_DEFINE(HAVE_IOKIT_IOKITLIB_H, 1, [Define if you have the IOKit API]) | |
54 | MP4FF_LIBS="-lIOKit" | |
55 | AC_SUBST(MP4FF_LIBS)])]) | |
56 | AC_CHECK_FUNCS(getpwuid) | |
57 | ||
58 | AC_C_INLINE | |
59 | AC_C_BIGENDIAN | |
60 | ||
61 | AC_TYPE_OFF_T | |
62 | ||
63 | AC_DEFUN([MY_CHECK_TYPEDEF_FROM_INCLUDE], | |
64 | [ | |
65 | AC_MSG_CHECKING([for $1]) | |
66 | AC_TRY_COMPILE([$2], | |
67 | [$1;], | |
68 | libfaad_ok=yes, libfaad_ok=no) | |
69 | if test $libfaad_ok = yes; then | |
70 | AC_DEFINE($3, 1, [Define if needed]) | |
71 | AC_MSG_RESULT([yes]) | |
72 | else | |
73 | AC_MSG_RESULT([no]) | |
74 | fi | |
75 | ]) | |
76 | ||
77 | dnl @synopsis AC_C99_FUNC_LRINTF | |
78 | dnl | |
79 | dnl Check whether C99's lrintf function is available. | |
80 | dnl @version 1.3 Feb 12 2002 | |
81 | dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com> | |
82 | dnl | |
83 | dnl Permission to use, copy, modify, distribute, and sell this file for any | |
84 | dnl purpose is hereby granted without fee, provided that the above copyright | |
85 | dnl and this permission notice appear in all copies. No representations are | |
86 | dnl made about the suitability of this software for any purpose. It is | |
87 | dnl provided "as is" without express or implied warranty. | |
88 | dnl | |
89 | AC_DEFUN([AC_C99_FUNC_LRINTF], | |
90 | [AC_CACHE_CHECK(for lrintf, | |
91 | ac_cv_c99_lrintf, | |
92 | [ | |
93 | lrintf_save_CFLAGS=$CFLAGS | |
94 | CFLAGS="-O -lm" | |
95 | AC_TRY_LINK([ | |
96 | #define _ISOC9X_SOURCE 1 | |
97 | #define _ISOC99_SOURCE 1 | |
98 | #define __USE_ISOC99 1 | |
99 | #define __USE_ISOC9X 1 | |
100 | ||
101 | #include <math.h> | |
102 | ], if (!lrintf(3.14159)) lrintf(2.7183);, ac_cv_c99_lrintf=yes, ac_cv_c99_lrintf=no) | |
103 | ||
104 | CFLAGS=$lrintf_save_CFLAGS | |
105 | ||
106 | ]) | |
107 | ||
108 | if test "$ac_cv_c99_lrintf" = yes; then | |
109 | AC_DEFINE(HAVE_LRINTF, 1, | |
110 | [Define if you have C99's lrintf function.]) | |
111 | fi | |
112 | ])# AC_C99_FUNC_LRINTF | |
113 | AC_C99_FUNC_LRINTF | |
114 | ||
115 | MY_CHECK_TYPEDEF_FROM_INCLUDE([float32_t temp], | |
116 | [#include <sys/types.h>, | |
117 | #include <sys/float.h>], [HAVE_FLOAT32_T]) | |
118 | ||
119 | AC_CHECK_FUNCS(strsep) | |
120 | ||
121 | AC_CHECK_PROG(external_mp4v2, mpeg4ip-config, yes, no) | |
122 | AM_CONDITIONAL(HAVE_MPEG4IP_PLUG, false) | |
123 | if test x$WITHMPEG4IP = xyes; then | |
124 | if test x$external_mp4v2 = xyes; then | |
125 | AM_CONDITIONAL(HAVE_MPEG4IP_PLUG, true) | |
126 | AC_MSG_NOTICE("Building MPEG4IP plugin") | |
127 | else | |
128 | AC_MSG_NOTICE("MPEG4IP libmp4v2 is required for MPEG4IP plugin") | |
129 | fi | |
130 | fi | |
131 | ||
132 | if test x$WITHXMMS = xyes; then | |
133 | AC_CHECK_PROGS(XMMS_CONFIG, xmms-config,"not_found") | |
134 | if test "$XMMS_CONFIG" = "not_found"; then | |
135 | AC_MSG_ERROR("*** xmms-config not found - xmms plugin can't be build") | |
136 | fi | |
137 | AC_CHECK_HEADER(pthread.h,, | |
138 | AC_MSG_ERROR(*** pthread headers support not installed or not found)) | |
139 | AC_CHECK_HEADER(id3.h,, | |
140 | AC_MSG_ERROR(*** id3lib headers support not installed or not found)) | |
141 | AC_CHECK_PROGS(GTK_CONFIG, gtk-config, "not_found") | |
142 | if test "$XGTK_CONFIG" = "not_found"; then | |
143 | AC_MSG_ERROR("*** gtk-config not found - xmms plugin can't be build without") | |
144 | fi | |
145 | ||
146 | AM_CONDITIONAL(HAVE_XMMS, true) | |
147 | else | |
148 | AC_MSG_NOTICE(no xmms build configured) | |
149 | AM_CONDITIONAL(HAVE_XMMS, false) | |
150 | fi | |
151 | ||
152 | if test x$WITHDRM = xyes; then | |
153 | AC_DEFINE(DRM, 1, [Define if you want to use libfaad together with Digital Radio Mondiale (DRM)]) | |
154 | AC_DEFINE(DRM_PS, 1, [Define if you want support for Digital Radio Mondiale (DRM) parametric stereo]) | |
155 | fi | |
156 | ||
157 | AC_CONFIG_FILES(libfaad/Makefile) | |
158 | AC_CONFIG_FILES(common/Makefile) | |
159 | AC_CONFIG_FILES(common/mp4ff/Makefile) | |
160 | AC_CONFIG_FILES(plugins/Makefile) | |
161 | AC_CONFIG_FILES(plugins/xmms/Makefile) | |
162 | AC_CONFIG_FILES(plugins/xmms/src/Makefile) | |
163 | AC_CONFIG_FILES(plugins/mpeg4ip/Makefile) | |
164 | AC_CONFIG_FILES(faad2.spec) | |
165 | AC_CONFIG_FILES(frontend/Makefile) | |
166 | AC_CONFIG_FILES(Makefile) | |
167 | ||
168 | AC_OUTPUT |
0 | dnl | |
1 | dnl This is the configure.in for faad2 related to unix creation | |
2 | ||
3 | dnl - libfaad.so | |
4 | dnl - libmp4ff.a (only static for moment) | |
5 | dnl - faad | |
6 | dnl - xmms input mp4/aac plugin | |
7 | dnl - mpeg4ip plugin (requires mpeg4ip's libmp4v2 to be installed) | |
8 | ||
9 | AC_INIT | |
10 | AC_CONFIG_AUX_DIR(.) | |
11 | AM_INIT_AUTOMAKE(faad2, 2.8.0cvs) | |
12 | ||
13 | AC_PROG_LIBTOOL | |
14 | AC_SUBST(LIBTOOL_DEPS) | |
15 | ||
16 | dnl Checks for programs. | |
17 | AC_PROG_CC | |
18 | AM_PROG_CC_C_O | |
19 | AC_PROG_CPP | |
20 | dnl disable for mpeg4ip plugin | |
21 | AC_PROG_CXX | |
22 | AC_PROG_INSTALL | |
23 | AC_PROG_LN_S | |
24 | AC_PROG_MAKE_SET | |
25 | AC_CHECK_PROGS(RPMBUILD, rpmbuild, rpm) | |
26 | ||
27 | AM_CONFIG_HEADER(config.h) | |
28 | ||
29 | AC_ARG_WITH(xmms,[ --with-xmms compile XMMS-1 plugin], | |
30 | WITHXMMS=$withval, WITHXMMS=no) | |
31 | ||
32 | AC_ARG_WITH(drm,[ --with-drm compile libfaad with DRM support], | |
33 | WITHDRM=$withval, WITHDRM=no) | |
34 | ||
35 | AC_ARG_WITH(mpeg4ip, [ --with-mpeg4ip compile mpeg4ip plugin], | |
36 | WITHMPEG4IP=$withval, WITHMPEG4IP=no) | |
37 | ||
38 | dnl Checks for header files required for mp4.h | |
39 | AC_HEADER_STDC | |
40 | AC_CHECK_HEADERS(stdint.h inttypes.h) | |
41 | AC_CHECK_HEADERS(mathf.h) | |
42 | AC_CHECK_HEADERS(float.h) | |
43 | AC_CHECK_FUNCS(strchr memcpy) | |
44 | AC_CHECK_HEADERS(sys/time.h) | |
45 | AC_HEADER_TIME | |
46 | ||
47 | dnl DRMS | |
48 | AC_CHECK_HEADERS(errno.h sys/stat.h sys/types.h limits.h) | |
49 | AC_CHECK_HEADERS(sysfs/libsysfs.h) | |
50 | AC_CHECK_HEADERS(IOKit/IOKitLib.h, | |
51 | [AC_CHECK_LIB(IOKit, main, | |
52 | [AC_DEFINE(HAVE_IOKIT_IOKITLIB_H, 1, [Define if you have the IOKit API]) | |
53 | MP4FF_LIBS="-lIOKit" | |
54 | AC_SUBST(MP4FF_LIBS)])]) | |
55 | AC_CHECK_FUNCS(getpwuid) | |
56 | ||
57 | AC_C_INLINE | |
58 | AC_C_BIGENDIAN | |
59 | ||
60 | AC_TYPE_OFF_T | |
61 | ||
62 | AC_DEFUN([MY_CHECK_TYPEDEF_FROM_INCLUDE], | |
63 | [ | |
64 | AC_MSG_CHECKING([for $1]) | |
65 | AC_TRY_COMPILE([$2], | |
66 | [$1;], | |
67 | libfaad_ok=yes, libfaad_ok=no) | |
68 | if test $libfaad_ok = yes; then | |
69 | AC_DEFINE($3, 1, [Define if needed]) | |
70 | AC_MSG_RESULT([yes]) | |
71 | else | |
72 | AC_MSG_RESULT([no]) | |
73 | fi | |
74 | ]) | |
75 | ||
76 | dnl @synopsis AC_C99_FUNC_LRINTF | |
77 | dnl | |
78 | dnl Check whether C99's lrintf function is available. | |
79 | dnl @version 1.3 Feb 12 2002 | |
80 | dnl @author Erik de Castro Lopo <erikd AT mega-nerd DOT com> | |
81 | dnl | |
82 | dnl Permission to use, copy, modify, distribute, and sell this file for any | |
83 | dnl purpose is hereby granted without fee, provided that the above copyright | |
84 | dnl and this permission notice appear in all copies. No representations are | |
85 | dnl made about the suitability of this software for any purpose. It is | |
86 | dnl provided "as is" without express or implied warranty. | |
87 | dnl | |
88 | AC_DEFUN([AC_C99_FUNC_LRINTF], | |
89 | [AC_CACHE_CHECK(for lrintf, | |
90 | ac_cv_c99_lrintf, | |
91 | [ | |
92 | lrintf_save_CFLAGS=$CFLAGS | |
93 | CFLAGS="-O -lm" | |
94 | AC_TRY_LINK([ | |
95 | #define _ISOC9X_SOURCE 1 | |
96 | #define _ISOC99_SOURCE 1 | |
97 | #define __USE_ISOC99 1 | |
98 | #define __USE_ISOC9X 1 | |
99 | ||
100 | #include <math.h> | |
101 | ], if (!lrintf(3.14159)) lrintf(2.7183);, ac_cv_c99_lrintf=yes, ac_cv_c99_lrintf=no) | |
102 | ||
103 | CFLAGS=$lrintf_save_CFLAGS | |
104 | ||
105 | ]) | |
106 | ||
107 | if test "$ac_cv_c99_lrintf" = yes; then | |
108 | AC_DEFINE(HAVE_LRINTF, 1, | |
109 | [Define if you have C99's lrintf function.]) | |
110 | fi | |
111 | ])# AC_C99_FUNC_LRINTF | |
112 | AC_C99_FUNC_LRINTF | |
113 | ||
114 | MY_CHECK_TYPEDEF_FROM_INCLUDE([float32_t temp], | |
115 | [#include <sys/types.h>, | |
116 | #include <sys/float.h>], [HAVE_FLOAT32_T]) | |
117 | ||
118 | AC_CHECK_FUNCS(strsep) | |
119 | ||
120 | AC_CHECK_PROG(external_mp4v2, mpeg4ip-config, yes, no) | |
121 | AM_CONDITIONAL(HAVE_MPEG4IP_PLUG, false) | |
122 | if test x$WITHMPEG4IP = xyes; then | |
123 | if test x$external_mp4v2 = xyes; then | |
124 | AM_CONDITIONAL(HAVE_MPEG4IP_PLUG, true) | |
125 | AC_MSG_NOTICE("Building MPEG4IP plugin") | |
126 | else | |
127 | AC_MSG_NOTICE("MPEG4IP libmp4v2 is required for MPEG4IP plugin") | |
128 | fi | |
129 | fi | |
130 | ||
131 | if test x$WITHXMMS = xyes; then | |
132 | AC_CHECK_PROGS(XMMS_CONFIG, xmms-config,"not_found") | |
133 | if test "$XMMS_CONFIG" = "not_found"; then | |
134 | AC_MSG_ERROR("*** xmms-config not found - xmms plugin can't be build") | |
135 | fi | |
136 | AC_CHECK_HEADER(pthread.h,, | |
137 | AC_MSG_ERROR(*** pthread headers support not installed or not found)) | |
138 | AC_CHECK_HEADER(id3.h,, | |
139 | AC_MSG_ERROR(*** id3lib headers support not installed or not found)) | |
140 | AC_CHECK_PROGS(GTK_CONFIG, gtk-config, "not_found") | |
141 | if test "$XGTK_CONFIG" = "not_found"; then | |
142 | AC_MSG_ERROR("*** gtk-config not found - xmms plugin can't be build without") | |
143 | fi | |
144 | ||
145 | AM_CONDITIONAL(HAVE_XMMS, true) | |
146 | else | |
147 | AC_MSG_NOTICE(no xmms build configured) | |
148 | AM_CONDITIONAL(HAVE_XMMS, false) | |
149 | fi | |
150 | ||
151 | if test x$WITHDRM = xyes; then | |
152 | AC_DEFINE(DRM, 1, [Define if you want to use libfaad together with Digital Radio Mondiale (DRM)]) | |
153 | AC_DEFINE(DRM_PS, 1, [Define if you want support for Digital Radio Mondiale (DRM) parametric stereo]) | |
154 | fi | |
155 | ||
156 | AC_CONFIG_FILES(libfaad/Makefile) | |
157 | AC_CONFIG_FILES(common/Makefile) | |
158 | AC_CONFIG_FILES(common/mp4ff/Makefile) | |
159 | AC_CONFIG_FILES(plugins/Makefile) | |
160 | AC_CONFIG_FILES(plugins/xmms/Makefile) | |
161 | AC_CONFIG_FILES(plugins/xmms/src/Makefile) | |
162 | AC_CONFIG_FILES(plugins/mpeg4ip/Makefile) | |
163 | AC_CONFIG_FILES(faad2.spec) | |
164 | AC_CONFIG_FILES(frontend/Makefile) | |
165 | AC_CONFIG_FILES(Makefile) | |
166 | ||
167 | AC_OUTPUT |
229 | 229 | .B NeAACDecAudioSpecificConfig |
230 | 230 | .PP |
231 | 231 | char NEAACDECAPI NeAACDecAudioSpecificConfig(unsigned char *pBuffer, |
232 | unsigned long buffer_size, | |
233 | mp4AudioSpecificConfig *mp4ASC); | |
232 | unsigned long buffer_size, | |
233 | mp4AudioSpecificConfig *mp4ASC); | |
234 | 234 | .PP |
235 | 235 | .B Structures |
236 | 236 | .RS 4 |
0 | 0 | bin_PROGRAMS = faad |
1 | 1 | man1_MANS = faad.man |
2 | 2 | |
3 | INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/common/faad \ | |
4 | -I$(top_srcdir)/common/mp4ff | |
3 | AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/common/mp4ff | |
5 | 4 | |
6 | 5 | faad_LDADD = $(top_builddir)/libfaad/libfaad.la \ |
7 | 6 | $(top_builddir)/common/mp4ff/libmp4ff.a |
8 | 7 | |
9 | faad_SOURCES = main.c \ | |
10 | audio.c audio.h \ | |
11 | $(top_srcdir)/common/faad/getopt.c | |
8 | faad_SOURCES = main.c audio.c audio.h |
0 | /* Getopt for GNU. | |
1 | NOTE: getopt is now part of the C library, so if you don't know what | |
2 | "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu | |
3 | before changing it! | |
4 | ||
5 | Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 | |
6 | Free Software Foundation, Inc. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify it | |
9 | under the terms of the GNU General Public License as published by the | |
10 | Free Software Foundation; either version 2, or (at your option) any | |
11 | later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
21 | ||
22 | ||
23 | #ifdef HAVE_CONFIG_H | |
24 | #include "config.h" | |
25 | #endif | |
26 | ||
27 | #ifndef __STDC__ | |
28 | # ifndef const | |
29 | # define const | |
30 | # endif | |
31 | #endif | |
32 | ||
33 | /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */ | |
34 | #ifndef _NO_PROTO | |
35 | #define _NO_PROTO | |
36 | #endif | |
37 | ||
38 | #include <stdio.h> | |
39 | ||
40 | /* Comment out all this code if we are using the GNU C Library, and are not | |
41 | actually compiling the library itself. This code is part of the GNU C | |
42 | Library, but also included in many other GNU distributions. Compiling | |
43 | and linking in this code is a waste when using the GNU C library | |
44 | (especially if it is a shared library). Rather than having every GNU | |
45 | program understand `configure --with-gnu-libc' and omit the object files, | |
46 | it is simpler to just do this in the source for each such file. */ | |
47 | ||
48 | #if defined (_LIBC) || !defined (__GNU_LIBRARY__) || !__MacOSX__ | |
49 | ||
50 | ||
51 | /* This needs to come after some library #include | |
52 | to get __GNU_LIBRARY__ defined. */ | |
53 | #ifdef __GNU_LIBRARY__ | |
54 | /* Don't include stdlib.h for non-GNU C libraries because some of them | |
55 | contain conflicting prototypes for getopt. */ | |
56 | #include <stdlib.h> | |
57 | #endif /* GNU C library. */ | |
58 | ||
59 | /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a | |
60 | long-named option. Because this is not POSIX.2 compliant, it is | |
61 | being phased out. */ | |
62 | /* #define GETOPT_COMPAT */ | |
63 | ||
64 | /* This version of `getopt' appears to the caller like standard Unix `getopt' | |
65 | but it behaves differently for the user, since it allows the user | |
66 | to intersperse the options with the other arguments. | |
67 | ||
68 | As `getopt' works, it permutes the elements of ARGV so that, | |
69 | when it is done, all the options precede everything else. Thus | |
70 | all application programs are extended to handle flexible argument order. | |
71 | ||
72 | Setting the environment variable POSIXLY_CORRECT disables permutation. | |
73 | Then the behavior is completely standard. | |
74 | ||
75 | GNU application programs can use a third alternative mode in which | |
76 | they can distinguish the relative order of options and other arguments. */ | |
77 | ||
78 | #include "getopt.h" | |
79 | ||
80 | /* For communication from `getopt' to the caller. | |
81 | When `getopt' finds an option that takes an argument, | |
82 | the argument value is returned here. | |
83 | Also, when `ordering' is RETURN_IN_ORDER, | |
84 | each non-option ARGV-element is returned here. */ | |
85 | ||
86 | char *optarg = 0; | |
87 | ||
88 | /* Index in ARGV of the next element to be scanned. | |
89 | This is used for communication to and from the caller | |
90 | and for communication between successive calls to `getopt'. | |
91 | ||
92 | On entry to `getopt', zero means this is the first call; initialize. | |
93 | ||
94 | When `getopt' returns EOF, this is the index of the first of the | |
95 | non-option elements that the caller should itself scan. | |
96 | ||
97 | Otherwise, `optind' communicates from one call to the next | |
98 | how much of ARGV has been scanned so far. */ | |
99 | ||
100 | /* XXX 1003.2 says this must be 1 before any call. */ | |
101 | int optind = 0; | |
102 | ||
103 | /* The next char to be scanned in the option-element | |
104 | in which the last option character we returned was found. | |
105 | This allows us to pick up the scan where we left off. | |
106 | ||
107 | If this is zero, or a null string, it means resume the scan | |
108 | by advancing to the next ARGV-element. */ | |
109 | ||
110 | static char *nextchar; | |
111 | ||
112 | /* Callers store zero here to inhibit the error message | |
113 | for unrecognized options. */ | |
114 | ||
115 | int opterr = 1; | |
116 | ||
117 | /* Set to an option character which was unrecognized. | |
118 | This must be initialized on some systems to avoid linking in the | |
119 | system's own getopt implementation. */ | |
120 | ||
121 | #define BAD_OPTION '\0' | |
122 | int optopt = BAD_OPTION; | |
123 | ||
124 | /* Describe how to deal with options that follow non-option ARGV-elements. | |
125 | ||
126 | If the caller did not specify anything, | |
127 | the default is REQUIRE_ORDER if the environment variable | |
128 | POSIXLY_CORRECT is defined, PERMUTE otherwise. | |
129 | ||
130 | REQUIRE_ORDER means don't recognize them as options; | |
131 | stop option processing when the first non-option is seen. | |
132 | This is what Unix does. | |
133 | This mode of operation is selected by either setting the environment | |
134 | variable POSIXLY_CORRECT, or using `+' as the first character | |
135 | of the list of option characters. | |
136 | ||
137 | PERMUTE is the default. We permute the contents of ARGV as we scan, | |
138 | so that eventually all the non-options are at the end. This allows options | |
139 | to be given in any order, even with programs that were not written to | |
140 | expect this. | |
141 | ||
142 | RETURN_IN_ORDER is an option available to programs that were written | |
143 | to expect options and other ARGV-elements in any order and that care about | |
144 | the ordering of the two. We describe each non-option ARGV-element | |
145 | as if it were the argument of an option with character code 1. | |
146 | Using `-' as the first character of the list of option characters | |
147 | selects this mode of operation. | |
148 | ||
149 | The special argument `--' forces an end of option-scanning regardless | |
150 | of the value of `ordering'. In the case of RETURN_IN_ORDER, only | |
151 | `--' can cause `getopt' to return EOF with `optind' != ARGC. */ | |
152 | ||
153 | static enum | |
154 | { | |
155 | REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER | |
156 | } ordering; | |
157 | ||
158 | #ifdef __GNU_LIBRARY__ | |
159 | /* We want to avoid inclusion of string.h with non-GNU libraries | |
160 | because there are many ways it can cause trouble. | |
161 | On some systems, it contains special magic macros that don't work | |
162 | in GCC. */ | |
163 | #include <string.h> | |
164 | #define my_index strchr | |
165 | #define my_strlen strlen | |
166 | #else | |
167 | ||
168 | /* Avoid depending on library functions or files | |
169 | whose names are inconsistent. */ | |
170 | ||
171 | #if __STDC__ || defined(PROTO) | |
172 | extern char *getenv(const char *name); | |
173 | extern int strcmp (const char *s1, const char *s2); | |
174 | extern int strncmp(const char *s1, const char *s2, unsigned int n); | |
175 | ||
176 | static int my_strlen(const char *s); | |
177 | static char *my_index (const char *str, int chr); | |
178 | #else | |
179 | extern char *getenv (); | |
180 | #endif | |
181 | ||
182 | static int | |
183 | my_strlen (str) | |
184 | const char *str; | |
185 | { | |
186 | int n = 0; | |
187 | while (*str++) | |
188 | n++; | |
189 | return n; | |
190 | } | |
191 | ||
192 | static char * | |
193 | my_index (str, chr) | |
194 | const char *str; | |
195 | int chr; | |
196 | { | |
197 | while (*str) | |
198 | { | |
199 | if (*str == chr) | |
200 | return (char *) str; | |
201 | str++; | |
202 | } | |
203 | return 0; | |
204 | } | |
205 | ||
206 | #endif /* GNU C library. */ | |
207 | ||
208 | /* Handle permutation of arguments. */ | |
209 | ||
210 | /* Describe the part of ARGV that contains non-options that have | |
211 | been skipped. `first_nonopt' is the index in ARGV of the first of them; | |
212 | `last_nonopt' is the index after the last of them. */ | |
213 | ||
214 | static int first_nonopt; | |
215 | static int last_nonopt; | |
216 | ||
217 | /* Exchange two adjacent subsequences of ARGV. | |
218 | One subsequence is elements [first_nonopt,last_nonopt) | |
219 | which contains all the non-options that have been skipped so far. | |
220 | The other is elements [last_nonopt,optind), which contains all | |
221 | the options processed since those non-options were skipped. | |
222 | ||
223 | `first_nonopt' and `last_nonopt' are relocated so that they describe | |
224 | the new indices of the non-options in ARGV after they are moved. | |
225 | ||
226 | To perform the swap, we first reverse the order of all elements. So | |
227 | all options now come before all non options, but they are in the | |
228 | wrong order. So we put back the options and non options in original | |
229 | order by reversing them again. For example: | |
230 | original input: a b c -x -y | |
231 | reverse all: -y -x c b a | |
232 | reverse options: -x -y c b a | |
233 | reverse non options: -x -y a b c | |
234 | */ | |
235 | ||
236 | #if __STDC__ || defined(PROTO) | |
237 | static void exchange (char **argv); | |
238 | #endif | |
239 | ||
240 | static void | |
241 | exchange (argv) | |
242 | char **argv; | |
243 | { | |
244 | char *temp, **first, **last; | |
245 | ||
246 | /* Reverse all the elements [first_nonopt, optind) */ | |
247 | first = &argv[first_nonopt]; | |
248 | last = &argv[optind-1]; | |
249 | while (first < last) { | |
250 | temp = *first; *first = *last; *last = temp; first++; last--; | |
251 | } | |
252 | /* Put back the options in order */ | |
253 | first = &argv[first_nonopt]; | |
254 | first_nonopt += (optind - last_nonopt); | |
255 | last = &argv[first_nonopt - 1]; | |
256 | while (first < last) { | |
257 | temp = *first; *first = *last; *last = temp; first++; last--; | |
258 | } | |
259 | ||
260 | /* Put back the non options in order */ | |
261 | first = &argv[first_nonopt]; | |
262 | last_nonopt = optind; | |
263 | last = &argv[last_nonopt-1]; | |
264 | while (first < last) { | |
265 | temp = *first; *first = *last; *last = temp; first++; last--; | |
266 | } | |
267 | } | |
268 | ||
269 | /* Scan elements of ARGV (whose length is ARGC) for option characters | |
270 | given in OPTSTRING. | |
271 | ||
272 | If an element of ARGV starts with '-', and is not exactly "-" or "--", | |
273 | then it is an option element. The characters of this element | |
274 | (aside from the initial '-') are option characters. If `getopt' | |
275 | is called repeatedly, it returns successively each of the option characters | |
276 | from each of the option elements. | |
277 | ||
278 | If `getopt' finds another option character, it returns that character, | |
279 | updating `optind' and `nextchar' so that the next call to `getopt' can | |
280 | resume the scan with the following option character or ARGV-element. | |
281 | ||
282 | If there are no more option characters, `getopt' returns `EOF'. | |
283 | Then `optind' is the index in ARGV of the first ARGV-element | |
284 | that is not an option. (The ARGV-elements have been permuted | |
285 | so that those that are not options now come last.) | |
286 | ||
287 | OPTSTRING is a string containing the legitimate option characters. | |
288 | If an option character is seen that is not listed in OPTSTRING, | |
289 | return BAD_OPTION after printing an error message. If you set `opterr' to | |
290 | zero, the error message is suppressed but we still return BAD_OPTION. | |
291 | ||
292 | If a char in OPTSTRING is followed by a colon, that means it wants an arg, | |
293 | so the following text in the same ARGV-element, or the text of the following | |
294 | ARGV-element, is returned in `optarg'. Two colons mean an option that | |
295 | wants an optional arg; if there is text in the current ARGV-element, | |
296 | it is returned in `optarg', otherwise `optarg' is set to zero. | |
297 | ||
298 | If OPTSTRING starts with `-' or `+', it requests different methods of | |
299 | handling the non-option ARGV-elements. | |
300 | See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. | |
301 | ||
302 | Long-named options begin with `--' instead of `-'. | |
303 | Their names may be abbreviated as long as the abbreviation is unique | |
304 | or is an exact match for some defined option. If they have an | |
305 | argument, it follows the option name in the same ARGV-element, separated | |
306 | from the option name by a `=', or else the in next ARGV-element. | |
307 | When `getopt' finds a long-named option, it returns 0 if that option's | |
308 | `flag' field is nonzero, the value of the option's `val' field | |
309 | if the `flag' field is zero. | |
310 | ||
311 | The elements of ARGV aren't really const, because we permute them. | |
312 | But we pretend they're const in the prototype to be compatible | |
313 | with other systems. | |
314 | ||
315 | LONGOPTS is a vector of `struct option' terminated by an | |
316 | element containing a name which is zero. | |
317 | ||
318 | LONGIND returns the index in LONGOPT of the long-named option found. | |
319 | It is only valid when a long-named option has been found by the most | |
320 | recent call. | |
321 | ||
322 | If LONG_ONLY is nonzero, '-' as well as '--' can introduce | |
323 | long-named options. */ | |
324 | ||
325 | int | |
326 | _getopt_internal (argc, argv, optstring, longopts, longind, long_only) | |
327 | int argc; | |
328 | char *const *argv; | |
329 | const char *optstring; | |
330 | const struct option *longopts; | |
331 | int *longind; | |
332 | int long_only; | |
333 | { | |
334 | int option_index; | |
335 | ||
336 | optarg = 0; | |
337 | ||
338 | /* Initialize the internal data when the first call is made. | |
339 | Start processing options with ARGV-element 1 (since ARGV-element 0 | |
340 | is the program name); the sequence of previously skipped | |
341 | non-option ARGV-elements is empty. */ | |
342 | ||
343 | if (optind == 0) | |
344 | { | |
345 | first_nonopt = last_nonopt = optind = 1; | |
346 | ||
347 | nextchar = NULL; | |
348 | ||
349 | /* Determine how to handle the ordering of options and nonoptions. */ | |
350 | ||
351 | if (optstring[0] == '-') | |
352 | { | |
353 | ordering = RETURN_IN_ORDER; | |
354 | ++optstring; | |
355 | } | |
356 | else if (optstring[0] == '+') | |
357 | { | |
358 | ordering = REQUIRE_ORDER; | |
359 | ++optstring; | |
360 | } | |
361 | else if (getenv ("POSIXLY_CORRECT") != NULL) | |
362 | ordering = REQUIRE_ORDER; | |
363 | else | |
364 | ordering = PERMUTE; | |
365 | } | |
366 | ||
367 | if (nextchar == NULL || *nextchar == '\0') | |
368 | { | |
369 | if (ordering == PERMUTE) | |
370 | { | |
371 | /* If we have just processed some options following some non-options, | |
372 | exchange them so that the options come first. */ | |
373 | ||
374 | if (first_nonopt != last_nonopt && last_nonopt != optind) | |
375 | exchange ((char **) argv); | |
376 | else if (last_nonopt != optind) | |
377 | first_nonopt = optind; | |
378 | ||
379 | /* Now skip any additional non-options | |
380 | and extend the range of non-options previously skipped. */ | |
381 | ||
382 | while (optind < argc | |
383 | && (argv[optind][0] != '-' || argv[optind][1] == '\0') | |
384 | #ifdef GETOPT_COMPAT | |
385 | && (longopts == NULL | |
386 | || argv[optind][0] != '+' || argv[optind][1] == '\0') | |
387 | #endif /* GETOPT_COMPAT */ | |
388 | ) | |
389 | optind++; | |
390 | last_nonopt = optind; | |
391 | } | |
392 | ||
393 | /* Special ARGV-element `--' means premature end of options. | |
394 | Skip it like a null option, | |
395 | then exchange with previous non-options as if it were an option, | |
396 | then skip everything else like a non-option. */ | |
397 | ||
398 | if (optind != argc && !strcmp (argv[optind], "--")) | |
399 | { | |
400 | optind++; | |
401 | ||
402 | if (first_nonopt != last_nonopt && last_nonopt != optind) | |
403 | exchange ((char **) argv); | |
404 | else if (first_nonopt == last_nonopt) | |
405 | first_nonopt = optind; | |
406 | last_nonopt = argc; | |
407 | ||
408 | optind = argc; | |
409 | } | |
410 | ||
411 | /* If we have done all the ARGV-elements, stop the scan | |
412 | and back over any non-options that we skipped and permuted. */ | |
413 | ||
414 | if (optind == argc) | |
415 | { | |
416 | /* Set the next-arg-index to point at the non-options | |
417 | that we previously skipped, so the caller will digest them. */ | |
418 | if (first_nonopt != last_nonopt) | |
419 | optind = first_nonopt; | |
420 | return EOF; | |
421 | } | |
422 | ||
423 | /* If we have come to a non-option and did not permute it, | |
424 | either stop the scan or describe it to the caller and pass it by. */ | |
425 | ||
426 | if ((argv[optind][0] != '-' || argv[optind][1] == '\0') | |
427 | #ifdef GETOPT_COMPAT | |
428 | && (longopts == NULL | |
429 | || argv[optind][0] != '+' || argv[optind][1] == '\0') | |
430 | #endif /* GETOPT_COMPAT */ | |
431 | ) | |
432 | { | |
433 | if (ordering == REQUIRE_ORDER) | |
434 | return EOF; | |
435 | optarg = argv[optind++]; | |
436 | return 1; | |
437 | } | |
438 | ||
439 | /* We have found another option-ARGV-element. | |
440 | Start decoding its characters. */ | |
441 | ||
442 | nextchar = (argv[optind] + 1 | |
443 | + (longopts != NULL && argv[optind][1] == '-')); | |
444 | } | |
445 | ||
446 | if (longopts != NULL | |
447 | && ((argv[optind][0] == '-' | |
448 | && (argv[optind][1] == '-' || long_only)) | |
449 | #ifdef GETOPT_COMPAT | |
450 | || argv[optind][0] == '+' | |
451 | #endif /* GETOPT_COMPAT */ | |
452 | )) | |
453 | { | |
454 | const struct option *p; | |
455 | char *s = nextchar; | |
456 | int exact = 0; | |
457 | int ambig = 0; | |
458 | const struct option *pfound = NULL; | |
459 | int indfound = 0; | |
460 | ||
461 | while (*s && *s != '=') | |
462 | s++; | |
463 | ||
464 | /* Test all options for either exact match or abbreviated matches. */ | |
465 | for (p = longopts, option_index = 0; p->name; | |
466 | p++, option_index++) | |
467 | if (!strncmp (p->name, nextchar, s - nextchar)) | |
468 | { | |
469 | if (s - nextchar == my_strlen (p->name)) | |
470 | { | |
471 | /* Exact match found. */ | |
472 | pfound = p; | |
473 | indfound = option_index; | |
474 | exact = 1; | |
475 | break; | |
476 | } | |
477 | else if (pfound == NULL) | |
478 | { | |
479 | /* First nonexact match found. */ | |
480 | pfound = p; | |
481 | indfound = option_index; | |
482 | } | |
483 | else | |
484 | /* Second nonexact match found. */ | |
485 | ambig = 1; | |
486 | } | |
487 | ||
488 | if (ambig && !exact) | |
489 | { | |
490 | if (opterr) | |
491 | fprintf (stderr, "%s: option `%s' is ambiguous\n", | |
492 | argv[0], argv[optind]); | |
493 | nextchar += my_strlen (nextchar); | |
494 | optind++; | |
495 | return BAD_OPTION; | |
496 | } | |
497 | ||
498 | if (pfound != NULL) | |
499 | { | |
500 | option_index = indfound; | |
501 | optind++; | |
502 | if (*s) | |
503 | { | |
504 | /* Don't test has_arg with >, because some C compilers don't | |
505 | allow it to be used on enums. */ | |
506 | if (pfound->has_arg) | |
507 | optarg = s + 1; | |
508 | else | |
509 | { | |
510 | if (opterr) | |
511 | { | |
512 | if (argv[optind - 1][1] == '-') | |
513 | /* --option */ | |
514 | fprintf (stderr, | |
515 | "%s: option `--%s' doesn't allow an argument\n", | |
516 | argv[0], pfound->name); | |
517 | else | |
518 | /* +option or -option */ | |
519 | fprintf (stderr, | |
520 | "%s: option `%c%s' doesn't allow an argument\n", | |
521 | argv[0], argv[optind - 1][0], pfound->name); | |
522 | } | |
523 | nextchar += my_strlen (nextchar); | |
524 | return BAD_OPTION; | |
525 | } | |
526 | } | |
527 | else if (pfound->has_arg == 1) | |
528 | { | |
529 | if (optind < argc) | |
530 | optarg = argv[optind++]; | |
531 | else | |
532 | { | |
533 | if (opterr) | |
534 | fprintf (stderr, "%s: option `%s' requires an argument\n", | |
535 | argv[0], argv[optind - 1]); | |
536 | nextchar += my_strlen (nextchar); | |
537 | return optstring[0] == ':' ? ':' : BAD_OPTION; | |
538 | } | |
539 | } | |
540 | nextchar += my_strlen (nextchar); | |
541 | if (longind != NULL) | |
542 | *longind = option_index; | |
543 | if (pfound->flag) | |
544 | { | |
545 | *(pfound->flag) = pfound->val; | |
546 | return 0; | |
547 | } | |
548 | return pfound->val; | |
549 | } | |
550 | /* Can't find it as a long option. If this is not getopt_long_only, | |
551 | or the option starts with '--' or is not a valid short | |
552 | option, then it's an error. | |
553 | Otherwise interpret it as a short option. */ | |
554 | if (!long_only || argv[optind][1] == '-' | |
555 | #ifdef GETOPT_COMPAT | |
556 | || argv[optind][0] == '+' | |
557 | #endif /* GETOPT_COMPAT */ | |
558 | || my_index (optstring, *nextchar) == NULL) | |
559 | { | |
560 | if (opterr) | |
561 | { | |
562 | if (argv[optind][1] == '-') | |
563 | /* --option */ | |
564 | fprintf (stderr, "%s: unrecognized option `--%s'\n", | |
565 | argv[0], nextchar); | |
566 | else | |
567 | /* +option or -option */ | |
568 | fprintf (stderr, "%s: unrecognized option `%c%s'\n", | |
569 | argv[0], argv[optind][0], nextchar); | |
570 | } | |
571 | nextchar = (char *) ""; | |
572 | optind++; | |
573 | return BAD_OPTION; | |
574 | } | |
575 | } | |
576 | ||
577 | /* Look at and handle the next option-character. */ | |
578 | ||
579 | { | |
580 | char c = *nextchar++; | |
581 | char *temp = my_index (optstring, c); | |
582 | ||
583 | /* Increment `optind' when we start to process its last character. */ | |
584 | if (*nextchar == '\0') | |
585 | ++optind; | |
586 | ||
587 | if (temp == NULL || c == ':') | |
588 | { | |
589 | if (opterr) | |
590 | { | |
591 | #if 0 | |
592 | if (c < 040 || c >= 0177) | |
593 | fprintf (stderr, "%s: unrecognized option, character code 0%o\n", | |
594 | argv[0], c); | |
595 | else | |
596 | fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); | |
597 | #else | |
598 | /* 1003.2 specifies the format of this message. */ | |
599 | fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); | |
600 | #endif | |
601 | } | |
602 | optopt = c; | |
603 | return BAD_OPTION; | |
604 | } | |
605 | if (temp[1] == ':') | |
606 | { | |
607 | if (temp[2] == ':') | |
608 | { | |
609 | /* This is an option that accepts an argument optionally. */ | |
610 | if (*nextchar != '\0') | |
611 | { | |
612 | optarg = nextchar; | |
613 | optind++; | |
614 | } | |
615 | else | |
616 | optarg = 0; | |
617 | nextchar = NULL; | |
618 | } | |
619 | else | |
620 | { | |
621 | /* This is an option that requires an argument. */ | |
622 | if (*nextchar != '\0') | |
623 | { | |
624 | optarg = nextchar; | |
625 | /* If we end this ARGV-element by taking the rest as an arg, | |
626 | we must advance to the next element now. */ | |
627 | optind++; | |
628 | } | |
629 | else if (optind == argc) | |
630 | { | |
631 | if (opterr) | |
632 | { | |
633 | #if 0 | |
634 | fprintf (stderr, "%s: option `-%c' requires an argument\n", | |
635 | argv[0], c); | |
636 | #else | |
637 | /* 1003.2 specifies the format of this message. */ | |
638 | fprintf (stderr, "%s: option requires an argument -- %c\n", | |
639 | argv[0], c); | |
640 | #endif | |
641 | } | |
642 | optopt = c; | |
643 | if (optstring[0] == ':') | |
644 | c = ':'; | |
645 | else | |
646 | c = BAD_OPTION; | |
647 | } | |
648 | else | |
649 | /* We already incremented `optind' once; | |
650 | increment it again when taking next ARGV-elt as argument. */ | |
651 | optarg = argv[optind++]; | |
652 | nextchar = NULL; | |
653 | } | |
654 | } | |
655 | return c; | |
656 | } | |
657 | } | |
658 | ||
659 | int | |
660 | getopt (argc, argv, optstring) | |
661 | int argc; | |
662 | char *const *argv; | |
663 | const char *optstring; | |
664 | { | |
665 | return _getopt_internal (argc, argv, optstring, | |
666 | (const struct option *) 0, | |
667 | (int *) 0, | |
668 | 0); | |
669 | } | |
670 | ||
671 | int | |
672 | getopt_long (argc, argv, options, long_options, opt_index) | |
673 | int argc; | |
674 | char *const *argv; | |
675 | const char *options; | |
676 | const struct option *long_options; | |
677 | int *opt_index; | |
678 | { | |
679 | return _getopt_internal (argc, argv, options, long_options, opt_index, 0); | |
680 | } | |
681 | ||
682 | #endif /* _LIBC or not __GNU_LIBRARY__. */ | |
683 | ||
684 | #ifdef TEST | |
685 | ||
686 | /* Compile with -DTEST to make an executable for use in testing | |
687 | the above definition of `getopt'. */ | |
688 | ||
689 | int | |
690 | main (argc, argv) | |
691 | int argc; | |
692 | char **argv; | |
693 | { | |
694 | int c; | |
695 | int digit_optind = 0; | |
696 | ||
697 | while (1) | |
698 | { | |
699 | int this_option_optind = optind ? optind : 1; | |
700 | ||
701 | c = getopt (argc, argv, "abc:d:0123456789"); | |
702 | if (c == EOF) | |
703 | break; | |
704 | ||
705 | switch (c) | |
706 | { | |
707 | case '0': | |
708 | case '1': | |
709 | case '2': | |
710 | case '3': | |
711 | case '4': | |
712 | case '5': | |
713 | case '6': | |
714 | case '7': | |
715 | case '8': | |
716 | case '9': | |
717 | if (digit_optind != 0 && digit_optind != this_option_optind) | |
718 | printf ("digits occur in two different argv-elements.\n"); | |
719 | digit_optind = this_option_optind; | |
720 | printf ("option %c\n", c); | |
721 | break; | |
722 | ||
723 | case 'a': | |
724 | printf ("option a\n"); | |
725 | break; | |
726 | ||
727 | case 'b': | |
728 | printf ("option b\n"); | |
729 | break; | |
730 | ||
731 | case 'c': | |
732 | printf ("option c with value `%s'\n", optarg); | |
733 | break; | |
734 | ||
735 | case BAD_OPTION: | |
736 | break; | |
737 | ||
738 | default: | |
739 | printf ("?? getopt returned character code 0%o ??\n", c); | |
740 | } | |
741 | } | |
742 | ||
743 | if (optind < argc) | |
744 | { | |
745 | printf ("non-option ARGV-elements: "); | |
746 | while (optind < argc) | |
747 | printf ("%s ", argv[optind++]); | |
748 | printf ("\n"); | |
749 | } | |
750 | ||
751 | exit (0); | |
752 | } | |
753 | ||
754 | #endif /* TEST */ |
0 | /* Declarations for getopt. | |
1 | Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. | |
2 | ||
3 | This program is free software; you can redistribute it and/or modify it | |
4 | under the terms of the GNU General Public License as published by the | |
5 | Free Software Foundation; either version 2, or (at your option) any | |
6 | later version. | |
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 | You should have received a copy of the GNU General Public License | |
14 | along with this program; if not, write to the Free Software | |
15 | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
16 | ||
17 | #ifndef _GETOPT_H | |
18 | #define _GETOPT_H 1 | |
19 | ||
20 | #ifdef __cplusplus | |
21 | extern "C" { | |
22 | #endif | |
23 | ||
24 | #ifndef __MacOSX__ | |
25 | ||
26 | /* For communication from `getopt' to the caller. | |
27 | When `getopt' finds an option that takes an argument, | |
28 | the argument value is returned here. | |
29 | Also, when `ordering' is RETURN_IN_ORDER, | |
30 | each non-option ARGV-element is returned here. */ | |
31 | ||
32 | extern char *optarg; | |
33 | ||
34 | /* Index in ARGV of the next element to be scanned. | |
35 | This is used for communication to and from the caller | |
36 | and for communication between successive calls to `getopt'. | |
37 | ||
38 | On entry to `getopt', zero means this is the first call; initialize. | |
39 | ||
40 | When `getopt' returns EOF, this is the index of the first of the | |
41 | non-option elements that the caller should itself scan. | |
42 | ||
43 | Otherwise, `optind' communicates from one call to the next | |
44 | how much of ARGV has been scanned so far. */ | |
45 | ||
46 | extern int optind; | |
47 | ||
48 | /* Callers store zero here to inhibit the error message `getopt' prints | |
49 | for unrecognized options. */ | |
50 | ||
51 | extern int opterr; | |
52 | ||
53 | /* Set to an option character which was unrecognized. */ | |
54 | ||
55 | extern int optopt; | |
56 | #endif | |
57 | ||
58 | /* Describe the long-named options requested by the application. | |
59 | The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector | |
60 | of `struct option' terminated by an element containing a name which is | |
61 | zero. | |
62 | ||
63 | The field `has_arg' is: | |
64 | no_argument (or 0) if the option does not take an argument, | |
65 | required_argument (or 1) if the option requires an argument, | |
66 | optional_argument (or 2) if the option takes an optional argument. | |
67 | ||
68 | If the field `flag' is not NULL, it points to a variable that is set | |
69 | to the value given in the field `val' when the option is found, but | |
70 | left unchanged if the option is not found. | |
71 | ||
72 | To have a long-named option do something other than set an `int' to | |
73 | a compiled-in constant, such as set a value from `optarg', set the | |
74 | option's `flag' field to zero and its `val' field to a nonzero | |
75 | value (the equivalent single-letter option character, if there is | |
76 | one). For long options that have a zero `flag' field, `getopt' | |
77 | returns the contents of the `val' field. */ | |
78 | ||
79 | struct option | |
80 | { | |
81 | #if __STDC__ | |
82 | const char *name; | |
83 | #else | |
84 | char *name; | |
85 | #endif | |
86 | /* has_arg can't be an enum because some compilers complain about | |
87 | type mismatches in all the code that assumes it is an int. */ | |
88 | int has_arg; | |
89 | int *flag; | |
90 | int val; | |
91 | }; | |
92 | ||
93 | /* Names for the values of the `has_arg' field of `struct option'. */ | |
94 | ||
95 | #define no_argument 0 | |
96 | #define required_argument 1 | |
97 | #define optional_argument 2 | |
98 | ||
99 | //#if __STDC__ || defined(PROTO) | |
100 | #if defined(__GNU_LIBRARY__) | |
101 | /* Many other libraries have conflicting prototypes for getopt, with | |
102 | differences in the consts, in stdlib.h. To avoid compilation | |
103 | errors, only prototype getopt for the GNU C library. */ | |
104 | extern int getopt (int argc, char *const *argv, const char *shortopts); | |
105 | #endif /* not __GNU_LIBRARY__ */ | |
106 | extern int getopt_long (int argc, char *const *argv, const char *shortopts, | |
107 | const struct option *longopts, int *longind); | |
108 | extern int getopt_long_only (int argc, char *const *argv, | |
109 | const char *shortopts, | |
110 | const struct option *longopts, int *longind); | |
111 | ||
112 | /* Internal only. Users should not call this directly. */ | |
113 | extern int _getopt_internal (int argc, char *const *argv, | |
114 | const char *shortopts, | |
115 | const struct option *longopts, int *longind, | |
116 | int long_only); | |
117 | //#else /* not __STDC__ */ | |
118 | extern int getopt (int argc, char *const *argv, const char *shortopts); | |
119 | //extern int getopt_long (); | |
120 | //extern int getopt_long_only (); | |
121 | ||
122 | //extern int _getopt_internal (); | |
123 | //#endif /* not __STDC__ */ | |
124 | ||
125 | #ifdef __cplusplus | |
126 | } | |
127 | #endif | |
128 | ||
129 | #endif /* _GETOPT_H */ |
27 | 27 | ** $Id: main.c,v 1.89 2015/01/19 09:46:12 knik Exp $ |
28 | 28 | **/ |
29 | 29 | |
30 | #ifdef HAVE_CONFIG_H | |
31 | #include "config.h" | |
32 | #endif | |
33 | ||
30 | 34 | #ifdef _WIN32 |
31 | 35 | #define WIN32_LEAN_AND_MEAN |
32 | 36 | #include <windows.h> |
48 | 52 | #include <mp4ff.h> |
49 | 53 | |
50 | 54 | #include "audio.h" |
55 | ||
56 | #ifdef HAVE_GETOPT_H | |
57 | # include <getopt.h> | |
58 | #else | |
59 | # include "getopt.h" | |
60 | # include "getopt.c" | |
61 | #endif | |
51 | 62 | |
52 | 63 | #ifndef min |
53 | 64 | #define min(a,b) ( (a) < (b) ? (a) : (b) ) |
420 | 431 | faad_fprintf(stdout, " -w Write output to stdio instead of a file.\n"); |
421 | 432 | faad_fprintf(stdout, " -g Disable gapless decoding.\n"); |
422 | 433 | faad_fprintf(stdout, " -q Quiet - suppresses status messages.\n"); |
434 | faad_fprintf(stdout, " -j X Jump - start output X seconds into track (MP4 files only).\n"); | |
423 | 435 | faad_fprintf(stdout, "Example:\n"); |
424 | 436 | faad_fprintf(stdout, " %s infile.aac\n", progName); |
425 | 437 | faad_fprintf(stdout, " %s infile.mp4\n", progName); |
791 | 803 | |
792 | 804 | static int decodeMP4file(char *mp4file, char *sndfile, char *adts_fn, int to_stdout, |
793 | 805 | int outputFormat, int fileType, int downMatrix, int noGapless, |
794 | int infoOnly, int adts_out, float *song_length) | |
806 | int infoOnly, int adts_out, float *song_length, float seek_to) | |
795 | 807 | { |
796 | 808 | int track; |
797 | 809 | unsigned long samplerate; |
799 | 811 | void *sample_buffer; |
800 | 812 | |
801 | 813 | mp4ff_t *infile; |
802 | long sampleId, numSamples; | |
814 | long sampleId, numSamples, startSampleId; | |
803 | 815 | |
804 | 816 | audio_file *aufile; |
805 | 817 | |
959 | 971 | |
960 | 972 | numSamples = mp4ff_num_samples(infile, track); |
961 | 973 | |
962 | for (sampleId = 0; sampleId < numSamples; sampleId++) | |
974 | startSampleId = 0; | |
975 | if (seek_to > 0.1) { | |
976 | int32_t sample = mp4ff_find_sample(infile, track, (int64_t)(seek_to * timescale), NULL); | |
977 | if (sample > 0 && sample < numSamples) | |
978 | startSampleId = sample; | |
979 | } | |
980 | ||
981 | for (sampleId = startSampleId; sampleId < numSamples; sampleId++) | |
963 | 982 | { |
964 | 983 | int rc; |
965 | 984 | long dur; |
1118 | 1137 | char *aacFileName = NULL; |
1119 | 1138 | char *audioFileName = NULL; |
1120 | 1139 | char *adtsFileName = NULL; |
1140 | float seekTo = 0; | |
1121 | 1141 | unsigned char header[8]; |
1122 | 1142 | float length = 0; |
1123 | 1143 | FILE *hMP4File; |
1150 | 1170 | { "info", 0, 0, 'i' }, |
1151 | 1171 | { "stdio", 0, 0, 'w' }, |
1152 | 1172 | { "stdio", 0, 0, 'g' }, |
1173 | { "seek", 1, 0, 'j' }, | |
1153 | 1174 | { "help", 0, 0, 'h' }, |
1154 | 1175 | { 0, 0, 0, 0 } |
1155 | 1176 | }; |
1156 | 1177 | |
1157 | c = getopt_long(argc, argv, "o:a:s:f:b:l:wgdhitq", | |
1178 | c = getopt_long(argc, argv, "o:a:s:f:b:l:j:wgdhitq", | |
1158 | 1179 | long_options, &option_index); |
1159 | 1180 | |
1160 | 1181 | if (c == -1) |
1245 | 1266 | } |
1246 | 1267 | } |
1247 | 1268 | break; |
1269 | case 'j': | |
1270 | if (optarg) | |
1271 | { | |
1272 | seekTo = atof(optarg); | |
1273 | } | |
1274 | break; | |
1248 | 1275 | case 't': |
1249 | 1276 | old_format = 1; |
1250 | 1277 | break; |
1276 | 1303 | faad_fprintf(stderr, " Build: %s\n", __DATE__); |
1277 | 1304 | faad_fprintf(stderr, " Copyright 2002-2004: Ahead Software AG\n"); |
1278 | 1305 | faad_fprintf(stderr, " http://www.audiocoding.com\n"); |
1306 | faad_fprintf(stderr, "\n Latest version and bug tracking available here:\n"); | |
1307 | faad_fprintf(stderr, " http://sourceforge.net/projects/faac/\n\n"); | |
1279 | 1308 | if (cap & FIXED_POINT_CAP) |
1280 | 1309 | faad_fprintf(stderr, " Fixed point version\n"); |
1281 | 1310 | else |
1367 | 1396 | if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p') |
1368 | 1397 | mp4file = 1; |
1369 | 1398 | |
1399 | if (!mp4file && seekTo != 0) { | |
1400 | faad_fprintf(stderr, "Warning: can only seek in MP4 files"); | |
1401 | } | |
1402 | ||
1370 | 1403 | if (mp4file) |
1371 | 1404 | { |
1372 | 1405 | result = decodeMP4file(aacFileName, audioFileName, adtsFileName, writeToStdio, |
1373 | outputFormat, format, downMatrix, noGapless, infoOnly, adts_out, &length); | |
1406 | outputFormat, format, downMatrix, noGapless, infoOnly, adts_out, &length, seekTo); | |
1374 | 1407 | } else { |
1375 | 1408 | |
1376 | 1409 | if (readFromStdin == 1) { |
72 | 72 | #endif |
73 | 73 | #endif |
74 | 74 | |
75 | #define FAAD2_VERSION "2.7" | |
75 | #define FAAD2_VERSION PACKAGE_VERSION | |
76 | 76 | |
77 | 77 | /* object types for AAC */ |
78 | 78 | #define MAIN 1 |