1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
/*
* libcaca Colour ASCII-Art library
* Copyright (c) 2002-2010 Sam Hocevar <sam@hocevar.net>
* All Rights Reserved
*
* This program is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://sam.zoy.org/wtfpl/COPYING for more details.
*/
/*
* getopt.c: getopt_long reimplementation
*/
#include "config.h"
#if !defined __KERNEL__
# include <stdio.h>
# include <string.h>
# if defined HAVE_GETOPT_H && defined HAVE_GETOPT_LONG
# include <getopt.h>
# endif
#endif
#include "caca.h"
#include "caca_internals.h"
int caca_optind = 1;
char *caca_optarg = NULL;
int caca_getopt(int argc, char * const _argv[], char const *optstring,
struct caca_option const *longopts, int *longindex)
{
#if defined HAVE_GETOPT_LONG
int ret;
optind = caca_optind;
optarg = caca_optarg;
ret = getopt_long(argc, _argv, optstring,
(struct option const *)longopts, longindex);
caca_optind = optind;
caca_optarg = optarg;
return ret;
#else
/* XXX: this getopt_long implementation should not be trusted for other
* applications without any serious peer reviewing. It “just works” with
* zzuf and a few libcaca programs but may fail miserably in other
* programs. */
char **argv = (char **)(uintptr_t)_argv;
char *flag;
int i;
if(caca_optind >= argc)
return -1;
flag = argv[caca_optind];
if(flag[0] == '-' && flag[1] != '-')
{
char *tmp;
int ret = flag[1];
if(ret == '\0')
return -1;
tmp = strchr(optstring, ret);
if(!tmp || ret == ':')
return '?';
caca_optind++;
if(tmp[1] == ':')
{
if(flag[2] != '\0')
caca_optarg = flag + 2;
else
caca_optarg = argv[caca_optind++];
return ret;
}
if(flag[2] != '\0')
{
flag[1] = '-';
caca_optind--;
argv[caca_optind]++;
}
return ret;
}
if(flag[0] == '-' && flag[1] == '-')
{
if(flag[2] == '\0')
return -1;
for(i = 0; longopts[i].name; i++)
{
size_t l = strlen(longopts[i].name);
if(strncmp(flag + 2, longopts[i].name, l))
continue;
switch(flag[2 + l])
{
case '=':
if(!longopts[i].has_arg)
goto bad_opt;
if(longindex)
*longindex = i;
caca_optind++;
caca_optarg = flag + 2 + l + 1;
return longopts[i].val;
case '\0':
if(longindex)
*longindex = i;
caca_optind++;
if(longopts[i].has_arg)
caca_optarg = argv[caca_optind++];
return longopts[i].val;
default:
break;
}
}
bad_opt:
fprintf(stderr, "%s: unrecognized option `%s'\n", argv[0], flag);
return '?';
}
return -1;
#endif
}
|