ptypes.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Implementation of standard PTYPEs
  3. */
  4. #include <assert.h>
  5. #include <stdio.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <errno.h>
  10. #include <faux/str.h>
  11. #include <faux/list.h>
  12. #include <faux/conv.h>
  13. #include <faux/argv.h>
  14. #include <klish/kcontext.h>
  15. #include <klish/kentry.h>
  16. /** @brief PTYPE: Consider ENTRY's name (or "value" field) as a command
  17. */
  18. int klish_ptype_COMMAND(kcontext_t *context)
  19. {
  20. const kentry_t *entry = NULL;
  21. const char *value = NULL;
  22. const char *command_name = NULL;
  23. entry = kcontext_candidate_entry(context);
  24. value = kcontext_candidate_value(context);
  25. command_name = kentry_value(entry);
  26. if (!command_name)
  27. command_name = kentry_name(entry);
  28. if (!command_name)
  29. return -1;
  30. return faux_str_casecmp(value, command_name);
  31. }
  32. /** @brief COMPLETION: Consider ENTRY's name (or "value" field) as a command
  33. */
  34. int klish_completion_COMMAND(kcontext_t *context)
  35. {
  36. const kentry_t *entry = NULL;
  37. const char *value = NULL;
  38. const char *command_name = NULL;
  39. entry = kcontext_candidate_entry(context);
  40. value = kcontext_candidate_value(context);
  41. command_name = kentry_value(entry);
  42. if (!command_name)
  43. command_name = kentry_name(entry);
  44. if (!command_name)
  45. return -1;
  46. return faux_str_casecmp(value, command_name);
  47. }
  48. /** @brief PTYPE: ENTRY's name (or "value" field) as a case sensitive command
  49. */
  50. int klish_ptype_COMMAND_CASE(kcontext_t *context)
  51. {
  52. const kentry_t *entry = NULL;
  53. const char *value = NULL;
  54. const char *command_name = NULL;
  55. entry = kcontext_candidate_entry(context);
  56. value = kcontext_candidate_value(context);
  57. command_name = kentry_value(entry);
  58. if (!command_name)
  59. command_name = kentry_name(entry);
  60. if (!command_name)
  61. return -1;
  62. return strcmp(value, command_name);
  63. }
  64. /** @brief PTYPE: Signed int with optional range
  65. *
  66. * Use long long int for conversion from text.
  67. *
  68. * <ACTION sym="INT">-30 80</ACTION>
  69. * Means range from "-30" to "80"
  70. */
  71. int klish_ptype_INT(kcontext_t *context)
  72. {
  73. const char *script = NULL;
  74. const char *value_str = NULL;
  75. long long int value = 0;
  76. script = kcontext_script(context);
  77. value_str = kcontext_candidate_value(context);
  78. if (!faux_conv_atoll(value_str, &value, 0))
  79. return -1;
  80. // Range is specified
  81. if (!faux_str_is_empty(script)) {
  82. faux_argv_t *argv = faux_argv_new();
  83. const char *str = NULL;
  84. faux_argv_parse(argv, script);
  85. // Min
  86. str = faux_argv_index(argv, 0);
  87. if (str) {
  88. long long int min = 0;
  89. if (!faux_conv_atoll(str, &min, 0) || (value < min)) {
  90. faux_argv_free(argv);
  91. return -1;
  92. }
  93. }
  94. // Max
  95. str = faux_argv_index(argv, 1);
  96. if (str) {
  97. long long int max = 0;
  98. if (!faux_conv_atoll(str, &max, 0) || (value > max)) {
  99. faux_argv_free(argv);
  100. return -1;
  101. }
  102. }
  103. faux_argv_free(argv);
  104. }
  105. return 0;
  106. }
  107. /** @brief PTYPE: Unsigned int with optional range
  108. *
  109. * Use unsigned long long int for conversion from text.
  110. *
  111. * <ACTION sym="UINT">30 80</ACTION>
  112. * Means range from "30" to "80"
  113. */
  114. int klish_ptype_UINT(kcontext_t *context)
  115. {
  116. const char *script = NULL;
  117. const char *value_str = NULL;
  118. unsigned long long int value = 0;
  119. script = kcontext_script(context);
  120. value_str = kcontext_candidate_value(context);
  121. if (!faux_conv_atoull(value_str, &value, 0))
  122. return -1;
  123. // Range is specified
  124. if (!faux_str_is_empty(script)) {
  125. faux_argv_t *argv = faux_argv_new();
  126. const char *str = NULL;
  127. faux_argv_parse(argv, script);
  128. // Min
  129. str = faux_argv_index(argv, 0);
  130. if (str) {
  131. unsigned long long int min = 0;
  132. if (!faux_conv_atoull(str, &min, 0) || (value < min)) {
  133. faux_argv_free(argv);
  134. return -1;
  135. }
  136. }
  137. // Max
  138. str = faux_argv_index(argv, 1);
  139. if (str) {
  140. unsigned long long int max = 0;
  141. if (!faux_conv_atoull(str, &max, 0) || (value > max)) {
  142. faux_argv_free(argv);
  143. return -1;
  144. }
  145. }
  146. faux_argv_free(argv);
  147. }
  148. return 0;
  149. }
  150. /** @brief PTYPE: Arbitrary string
  151. */
  152. int klish_ptype_STRING(kcontext_t *context)
  153. {
  154. // Really any string is a ... (surprise!) string
  155. context = context; // Happy compiler
  156. return 0;
  157. }