/* * libcaca Colour ASCII-Art library * Copyright (c) 2002-2012 Sam Hocevar * 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://www.wtfpl.net/ for more details. */ /* * getopt.c: getopt_long reimplementation */ #include "config.h" #if !defined __KERNEL__ # include # include # if defined HAVE_GETOPT_H && defined HAVE_GETOPT_LONG # include # 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 }