getopt.h 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
  2. /*
  3. * getopt function definitions for NOLIBC, adapted from musl libc
  4. * Copyright (C) 2005-2020 Rich Felker, et al.
  5. * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
  6. */
  7. /* make sure to include all global symbols */
  8. #include "nolibc.h"
  9. #ifndef _NOLIBC_GETOPT_H
  10. #define _NOLIBC_GETOPT_H
  11. struct FILE;
  12. static struct FILE *const stderr;
  13. static int fprintf(struct FILE *stream, const char *fmt, ...);
  14. __attribute__((weak,unused,section(".data.nolibc_getopt")))
  15. char *optarg;
  16. __attribute__((weak,unused,section(".data.nolibc_getopt")))
  17. int optind = 1, opterr = 1, optopt;
  18. static __attribute__((unused))
  19. int getopt(int argc, char * const argv[], const char *optstring)
  20. {
  21. static int __optpos;
  22. int i;
  23. char c, d;
  24. char *optchar;
  25. if (!optind) {
  26. __optpos = 0;
  27. optind = 1;
  28. }
  29. if (optind >= argc || !argv[optind])
  30. return -1;
  31. if (argv[optind][0] != '-') {
  32. if (optstring[0] == '-') {
  33. optarg = argv[optind++];
  34. return 1;
  35. }
  36. return -1;
  37. }
  38. if (!argv[optind][1])
  39. return -1;
  40. if (argv[optind][1] == '-' && !argv[optind][2])
  41. return optind++, -1;
  42. if (!__optpos)
  43. __optpos++;
  44. c = argv[optind][__optpos];
  45. optchar = argv[optind] + __optpos;
  46. __optpos++;
  47. if (!argv[optind][__optpos]) {
  48. optind++;
  49. __optpos = 0;
  50. }
  51. if (optstring[0] == '-' || optstring[0] == '+')
  52. optstring++;
  53. i = 0;
  54. d = 0;
  55. do {
  56. d = optstring[i++];
  57. } while (d && d != c);
  58. if (d != c || c == ':') {
  59. optopt = c;
  60. if (optstring[0] != ':' && opterr)
  61. fprintf(stderr, "%s: unrecognized option: %c\n", argv[0], *optchar);
  62. return '?';
  63. }
  64. if (optstring[i] == ':') {
  65. optarg = NULL;
  66. if (optstring[i + 1] != ':' || __optpos) {
  67. optarg = argv[optind++];
  68. if (__optpos)
  69. optarg += __optpos;
  70. __optpos = 0;
  71. }
  72. if (optind > argc) {
  73. optopt = c;
  74. if (optstring[0] == ':')
  75. return ':';
  76. if (opterr)
  77. fprintf(stderr, "%s: option requires argument: %c\n",
  78. argv[0], *optchar);
  79. return '?';
  80. }
  81. }
  82. return c;
  83. }
  84. #endif /* _NOLIBC_GETOPT_H */