1#include <debug.h> 2#include <cmdline.h> 3#include <stdio.h> 4#include <stdlib.h> 5#include <getopt.h> 6#include <string.h> 7#include <ctype.h> 8 9extern char *optarg; 10extern int optind, opterr, optopt; 11 12static struct option long_options[] = { 13 {"output", required_argument, 0, 'o'}, 14 {"height", required_argument, 0, 'h'}, 15 {"width", required_argument, 0, 'w'}, 16 {"gray", no_argument, 0, 'g'}, 17 {"type", required_argument, 0, 't'}, 18 {"rotate", required_argument, 0, 'r'}, 19 {"verbose", no_argument, 0, 'V'}, 20 {"help", no_argument, 0, 1}, 21 {0, 0, 0, 0}, 22}; 23 24/* This array must parallel long_options[] */ 25static const char *descriptions[] = { 26 "output file", 27 "image height in pixels", 28 "image width in pixels", 29 "process the luma plane only", 30 "encode as one of { 'ppm', 'rgb', or 'argb' }", 31 "rotate (90, -90, 180 degrees)", 32 "print verbose output", 33 "print this help screen", 34}; 35 36void print_help(const char *name) { 37 fprintf(stdout, 38 "Converts yuv 4:2:0 to rgb24 and generates a PPM file.\n" 39 "invokation:\n" 40 "\t%s infile --height <height> --width <width> --output <outfile> -t <ppm|grb|argb> [ --gray ] [ --rotate <degrees> ] [ --verbose ]\n" 41 "\t%s infile --help\n", 42 name, name); 43 fprintf(stdout, "options:\n"); 44 struct option *opt = long_options; 45 const char **desc = descriptions; 46 while (opt->name) { 47 fprintf(stdout, "\t-%c/--%s%s: %s\n", 48 isprint(opt->val) ? opt->val : ' ', 49 opt->name, 50 (opt->has_arg ? " (argument)" : ""), 51 *desc); 52 opt++; 53 desc++; 54 } 55} 56 57int get_options(int argc, char **argv, 58 char **outfile, 59 int *height, 60 int *width, 61 int *gray, 62 char **type, 63 int *rotate, 64 int *verbose) { 65 int c; 66 67 ASSERT(outfile); *outfile = NULL; 68 ASSERT(height); *height = -1; 69 ASSERT(width); *width = -1; 70 ASSERT(gray); *gray = 0; 71 ASSERT(rotate); *rotate = 0; 72 ASSERT(verbose); *verbose = 0; 73 ASSERT(type); *type = NULL; 74 75 while (1) { 76 /* getopt_long stores the option index here. */ 77 int option_index = 0; 78 79 c = getopt_long (argc, argv, 80 "Vgo:h:w:r:t:", 81 long_options, 82 &option_index); 83 /* Detect the end of the options. */ 84 if (c == -1) break; 85 86 if (isgraph(c)) { 87 INFO ("option -%c with value `%s'\n", c, (optarg ?: "(null)")); 88 } 89 90#define SET_STRING_OPTION(name) do { \ 91 ASSERT(optarg); \ 92 (*name) = strdup(optarg); \ 93} while(0) 94 95#define SET_INT_OPTION(val) do { \ 96 ASSERT(optarg); \ 97 if (strlen(optarg) >= 2 && optarg[0] == '0' && optarg[1] == 'x') { \ 98 FAILIF(1 != sscanf(optarg+2, "%x", val), \ 99 "Expecting a hexadecimal argument!\n"); \ 100 } else { \ 101 FAILIF(1 != sscanf(optarg, "%d", val), \ 102 "Expecting a decimal argument!\n"); \ 103 } \ 104} while(0) 105 106 switch (c) { 107 case 0: 108 /* If this option set a flag, do nothing else now. */ 109 if (long_options[option_index].flag != 0) 110 break; 111 INFO ("option %s", long_options[option_index].name); 112 if (optarg) 113 INFO (" with arg %s", optarg); 114 INFO ("\n"); 115 break; 116 case 1: print_help(argv[0]); exit(1); break; 117 case 'o': 118 SET_STRING_OPTION(outfile); 119 break; 120 case 't': 121 SET_STRING_OPTION(type); 122 break; 123 case 'h': 124 SET_INT_OPTION(height); 125 break; 126 case 'w': 127 SET_INT_OPTION(width); 128 break; 129 case 'r': 130 SET_INT_OPTION(rotate); 131 break; 132 case 'g': *gray = 1; break; 133 case 'V': *verbose = 1; break; 134 case '?': 135 /* getopt_long already printed an error message. */ 136 break; 137 138#undef SET_STRING_OPTION 139#undef SET_INT_OPTION 140 141 default: 142 FAILIF(1, "Unknown option"); 143 } 144 } 145 146 return optind; 147} 148