Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include <stddef.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. #include "getopt.h"
  6.  
  7. char *optarg;
  8. int optind=1, opterr=1, optopt, __optpos, optreset=0;
  9.  
  10. #define optpos __optpos
  11.  
  12. static void __getopt_msg(const char *a, const char *b, const char *c, size_t l)
  13. {
  14.         FILE *f = stderr;
  15. #if !defined(WIN32) && !defined(_WIN32)
  16.         flockfile(f);
  17. #endif
  18.         fputs(a, f);
  19.         fwrite(b, strlen(b), 1, f);
  20.         fwrite(c, 1, l, f);
  21.         fputc('\n', f);
  22. #if !defined(WIN32) && !defined(_WIN32)
  23.         funlockfile(f);
  24. #endif
  25. }
  26.  
  27. int getopt(int argc, char * const argv[], const char *optstring)
  28. {
  29.         int i, c, d;
  30.         int k, l;
  31.         char *optchar;
  32.  
  33.         if (!optind || optreset) {
  34.                 optreset = 0;
  35.                 __optpos = 0;
  36.                 optind = 1;
  37.         }
  38.  
  39.         if (optind >= argc || !argv[optind])
  40.                 return -1;
  41.  
  42.         if (argv[optind][0] != '-') {
  43.                 if (optstring[0] == '-') {
  44.                         optarg = argv[optind++];
  45.                         return 1;
  46.                 }
  47.                 return -1;
  48.         }
  49.  
  50.         if (!argv[optind][1])
  51.                 return -1;
  52.  
  53.         if (argv[optind][1] == '-' && !argv[optind][2])
  54.                 return optind++, -1;
  55.  
  56.         if (!optpos) optpos++;
  57.         c = argv[optind][optpos], k = 1;
  58.         optchar = argv[optind]+optpos;
  59.         optopt = c;
  60.         optpos += k;
  61.  
  62.         if (!argv[optind][optpos]) {
  63.                 optind++;
  64.                 optpos = 0;
  65.         }
  66.  
  67.         if (optstring[0] == '-' || optstring[0] == '+')
  68.                 optstring++;
  69.  
  70.         i = 0;
  71.         d = 0;
  72.         do {
  73.                 d = optstring[i], l = 1;
  74.                 if (l>0) i+=l; else i++;
  75.         } while (l && d != c);
  76.  
  77.         if (d != c) {
  78.                 if (optstring[0] != ':' && opterr)
  79.                         __getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
  80.                 return '?';
  81.         }
  82.         if (optstring[i] == ':') {
  83.                 if (optstring[i+1] == ':') optarg = 0;
  84.                 else if (optind >= argc) {
  85.                         if (optstring[0] == ':') return ':';
  86.                         if (opterr) __getopt_msg(argv[0],
  87.                                 ": option requires an argument: ",
  88.                                 optchar, k);
  89.                         return '?';
  90.                 }
  91.                 if (optstring[i+1] != ':' || optpos) {
  92.                         optarg = argv[optind++] + optpos;
  93.                         optpos = 0;
  94.                 }
  95.         }
  96.         return c;
  97. }
  98.  
  99. static void permute(char *const *argv, int dest, int src)
  100. {
  101.         char **av = (char **)argv;
  102.         char *tmp = av[src];
  103.         int i;
  104.         for (i=src; i>dest; i--)
  105.                 av[i] = av[i-1];
  106.         av[dest] = tmp;
  107. }
  108.  
  109. static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
  110. {
  111.         optarg = 0;
  112.         if (longopts && argv[optind][0] == '-' &&
  113.                 ((longonly && argv[optind][1] && argv[optind][1] != '-') ||
  114.                  (argv[optind][1] == '-' && argv[optind][2])))
  115.         {
  116.                 int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
  117.                 int i, cnt, match = -1;
  118.                 char *opt;
  119.                 for (cnt=i=0; longopts[i].name; i++) {
  120.                         const char *name = longopts[i].name;
  121.                         opt = argv[optind]+1;
  122.                         if (*opt == '-') opt++;
  123.                         for (; *name && *name == *opt; name++, opt++);
  124.                         if (*opt && *opt != '=') continue;
  125.                         match = i;
  126.                         if (!*name) {
  127.                                 cnt = 1;
  128.                                 break;
  129.                         }
  130.                         cnt++;
  131.                 }
  132.                 if (cnt==1) {
  133.                         i = match;
  134.                         optind++;
  135.                         optopt = longopts[i].val;
  136.                         if (*opt == '=') {
  137.                                 if (!longopts[i].has_arg) {
  138.                                         if (colon || !opterr)
  139.                                                 return '?';
  140.                                         __getopt_msg(argv[0],
  141.                                                 ": option does not take an argument: ",
  142.                                                 longopts[i].name,
  143.                                                 strlen(longopts[i].name));
  144.                                         return '?';
  145.                                 }
  146.                                 optarg = opt+1;
  147.                         } else if (longopts[i].has_arg == required_argument) {
  148.                                 if (!(optarg = argv[optind])) {
  149.                                         if (colon) return ':';
  150.                                         if (!opterr) return '?';
  151.                                         __getopt_msg(argv[0],
  152.                                                 ": option requires an argument: ",
  153.                                                 longopts[i].name,
  154.                                                 strlen(longopts[i].name));
  155.                                         return '?';
  156.                                 }
  157.                                 optind++;
  158.                         }
  159.                         if (idx) *idx = i;
  160.                         if (longopts[i].flag) {
  161.                                 *longopts[i].flag = longopts[i].val;
  162.                                 return 0;
  163.                         }
  164.                         return longopts[i].val;
  165.                 }
  166.                 if (argv[optind][1] == '-') {
  167.                         if (!colon && opterr)
  168.                                 __getopt_msg(argv[0], cnt ?
  169.                                         ": option is ambiguous: " :
  170.                                         ": unrecognized option: ",
  171.                                         argv[optind]+2,
  172.                                         strlen(argv[optind]+2));
  173.                         optind++;
  174.                         return '?';
  175.                 }
  176.         }
  177.         return getopt(argc, argv, optstring);
  178. }
  179.  
  180. static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
  181. {
  182.         int ret, skipped, resumed;
  183.         if (!optind || optreset) {
  184.                 optreset = 0;
  185.                 __optpos = 0;
  186.                 optind = 1;
  187.         }
  188.         if (optind >= argc || !argv[optind]) return -1;
  189.         skipped = optind;
  190.         if (optstring[0] != '+' && optstring[0] != '-') {
  191.                 int i;
  192.                 for (i=optind; ; i++) {
  193.                         if (i >= argc || !argv[i]) return -1;
  194.                         if (argv[i][0] == '-' && argv[i][1]) break;
  195.                 }
  196.                 optind = i;
  197.         }
  198.         resumed = optind;
  199.         ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly);
  200.         if (resumed > skipped) {
  201.                 int i, cnt = optind-resumed;
  202.                 for (i=0; i<cnt; i++)
  203.                         permute(argv, skipped, optind-1);
  204.                 optind = skipped + cnt;
  205.         }
  206.         return ret;
  207. }
  208.  
  209. int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
  210. {
  211.         return __getopt_long(argc, argv, optstring, longopts, idx, 0);
  212. }
  213.  
  214. int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
  215. {
  216.         return __getopt_long(argc, argv, optstring, longopts, idx, 1);
  217. }
  218.  
  219.