#include <debug.h> #include <cmdline.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <string.h> #include <ctype.h> extern char *optarg; extern int optind, opterr, optopt; static struct option long_options[] = { {"output", required_argument, 0, 'o'}, {"height", required_argument, 0, 'h'}, {"width", required_argument, 0, 'w'}, {"gray", no_argument, 0, 'g'}, {"type", required_argument, 0, 't'}, {"rotate", required_argument, 0, 'r'}, {"verbose", no_argument, 0, 'V'}, {"help", no_argument, 0, 1}, {0, 0, 0, 0}, }; /* This array must parallel long_options[] */ static const char *descriptions[] = { "output file", "image height in pixels", "image width in pixels", "process the luma plane only", "encode as one of { 'ppm', 'rgb', or 'argb' }", "rotate (90, -90, 180 degrees)", "print verbose output", "print this help screen", }; void print_help(const char *name) { fprintf(stdout, "Converts yuv 4:2:0 to rgb24 and generates a PPM file.\n" "invokation:\n" "\t%s infile --height <height> --width <width> --output <outfile> -t <ppm|grb|argb> [ --gray ] [ --rotate <degrees> ] [ --verbose ]\n" "\t%s infile --help\n", name, name); fprintf(stdout, "options:\n"); struct option *opt = long_options; const char **desc = descriptions; while (opt->name) { fprintf(stdout, "\t-%c/--%s%s: %s\n", isprint(opt->val) ? opt->val : ' ', opt->name, (opt->has_arg ? " (argument)" : ""), *desc); opt++; desc++; } } int get_options(int argc, char **argv, char **outfile, int *height, int *width, int *gray, char **type, int *rotate, int *verbose) { int c; ASSERT(outfile); *outfile = NULL; ASSERT(height); *height = -1; ASSERT(width); *width = -1; ASSERT(gray); *gray = 0; ASSERT(rotate); *rotate = 0; ASSERT(verbose); *verbose = 0; ASSERT(type); *type = NULL; while (1) { /* getopt_long stores the option index here. */ int option_index = 0; c = getopt_long (argc, argv, "Vgo:h:w:r:t:", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; if (isgraph(c)) { INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)")); } #define SET_STRING_OPTION(name) do { \ ASSERT(optarg); \ (*name) = strdup(optarg); \ } while(0) #define SET_INT_OPTION(val) do { \ ASSERT(optarg); \ if (strlen(optarg) >= 2 && optarg[0] == '0' && optarg[1] == 'x') { \ FAILIF(1 != sscanf(optarg+2, "%x", val), \ "Expecting a hexadecimal argument!\n"); \ } else { \ FAILIF(1 != sscanf(optarg, "%d", val), \ "Expecting a decimal argument!\n"); \ } \ } while(0) switch (c) { case 0: /* If this option set a flag, do nothing else now. */ if (long_options[option_index].flag != 0) break; INFO ("option %s", long_options[option_index].name); if (optarg) INFO (" with arg %s", optarg); INFO ("\n"); break; case 1: print_help(argv[0]); exit(1); break; case 'o': SET_STRING_OPTION(outfile); break; case 't': SET_STRING_OPTION(type); break; case 'h': SET_INT_OPTION(height); break; case 'w': SET_INT_OPTION(width); break; case 'r': SET_INT_OPTION(rotate); break; case 'g': *gray = 1; break; case 'V': *verbose = 1; break; case '?': /* getopt_long already printed an error message. */ break; #undef SET_STRING_OPTION #undef SET_INT_OPTION default: FAILIF(1, "Unknown option"); } } return optind; }