getopt.c 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #include <unistd.h>
  2. #include <wchar.h>
  3. #include <string.h>
  4. #include <limits.h>
  5. #include <stdlib.h>
  6. #include "libc.h"
  7. char *optarg;
  8. int optind=1, opterr=1, optopt, __optpos, __optreset=0;
  9. #define optpos __optpos
  10. weak_alias(__optreset, optreset);
  11. int getopt(int argc, char * const argv[], const char *optstring)
  12. {
  13. int i;
  14. wchar_t c, d;
  15. int k, l;
  16. char *optchar;
  17. if (!optind || __optreset) {
  18. __optreset = 0;
  19. __optpos = 0;
  20. optind = 1;
  21. }
  22. if (optind >= argc || !argv[optind] || argv[optind][0] != '-' || !argv[optind][1])
  23. return -1;
  24. if (argv[optind][1] == '-' && !argv[optind][2])
  25. return optind++, -1;
  26. if (!optpos) optpos++;
  27. if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) {
  28. k = 1;
  29. c = 0xfffd; /* replacement char */
  30. }
  31. optchar = argv[optind]+optpos;
  32. optopt = c;
  33. optpos += k;
  34. if (!argv[optind][optpos]) {
  35. optind++;
  36. optpos = 0;
  37. }
  38. for (i=0; (l = mbtowc(&d, optstring+i, MB_LEN_MAX)) && d!=c; i+=l>0?l:1);
  39. if (d != c) {
  40. if (optstring[0] != ':' && opterr) {
  41. write(2, argv[0], strlen(argv[0]));
  42. write(2, ": illegal option: ", 18);
  43. write(2, optchar, k);
  44. write(2, "\n", 1);
  45. }
  46. return '?';
  47. }
  48. if (optstring[i+1] == ':') {
  49. if (optstring[i+2] == ':') optarg = 0;
  50. else if (optind >= argc) {
  51. if (optstring[0] == ':') return ':';
  52. if (opterr) {
  53. write(2, argv[0], strlen(argv[0]));
  54. write(2, ": option requires an argument: ", 31);
  55. write(2, optchar, k);
  56. write(2, "\n", 1);
  57. }
  58. return '?';
  59. }
  60. if (optstring[i+2] != ':' || optpos) {
  61. optarg = argv[optind++] + optpos;
  62. optpos = 0;
  63. }
  64. }
  65. return c;
  66. }
  67. weak_alias(getopt, __posix_getopt);