match.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * ##/%% variable matching code ripped out of ash shell for code sharing
  3. *
  4. * This code is derived from software contributed to Berkeley by
  5. * Kenneth Almquist.
  6. *
  7. * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
  8. *
  9. * Copyright (c) 1989, 1991, 1993, 1994
  10. * The Regents of the University of California. All rights reserved.
  11. *
  12. * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
  13. * was re-ported from NetBSD and debianized.
  14. */
  15. #ifdef STANDALONE
  16. # include <stdbool.h>
  17. # include <stdio.h>
  18. # include <stdlib.h>
  19. # include <string.h>
  20. # include <unistd.h>
  21. #else
  22. # include "libbb.h"
  23. #endif
  24. #include <fnmatch.h>
  25. #include "match.h"
  26. #define pmatch(a, b) !fnmatch((a), (b), 0)
  27. char *scanleft(char *string, char *pattern, bool match_at_left)
  28. {
  29. char c;
  30. char *loc = string;
  31. do {
  32. int match;
  33. const char *s;
  34. c = *loc;
  35. if (match_at_left) {
  36. *loc = '\0';
  37. s = string;
  38. } else
  39. s = loc;
  40. match = pmatch(pattern, s);
  41. *loc = c;
  42. if (match)
  43. return loc;
  44. loc++;
  45. } while (c);
  46. return NULL;
  47. }
  48. char *scanright(char *string, char *pattern, bool match_at_left)
  49. {
  50. char c;
  51. char *loc = string + strlen(string);
  52. while (loc >= string) {
  53. int match;
  54. const char *s;
  55. c = *loc;
  56. if (match_at_left) {
  57. *loc = '\0';
  58. s = string;
  59. } else
  60. s = loc;
  61. match = pmatch(pattern, s);
  62. *loc = c;
  63. if (match)
  64. return loc;
  65. loc--;
  66. }
  67. return NULL;
  68. }
  69. #ifdef STANDALONE
  70. int main(int argc, char *argv[])
  71. {
  72. char *string;
  73. char *op;
  74. char *pattern;
  75. bool match_at_left;
  76. char *loc;
  77. int i;
  78. if (argc == 1) {
  79. puts(
  80. "Usage: match <test> [test...]\n\n"
  81. "Where a <test> is the form: <string><op><match>\n"
  82. "This is to test the shell ${var#val} expression type.\n\n"
  83. "e.g. `match 'abc#a*'` -> bc"
  84. );
  85. return 1;
  86. }
  87. for (i = 1; i < argc; ++i) {
  88. size_t off;
  89. scan_t scan;
  90. printf("'%s': ", argv[i]);
  91. string = strdup(argv[i]);
  92. off = strcspn(string, "#%");
  93. if (!off) {
  94. printf("invalid format\n");
  95. free(string);
  96. continue;
  97. }
  98. op = string + off;
  99. scan = pick_scan(op[0], op[1], &match_at_left);
  100. pattern = op + 1;
  101. if (op[0] == op[1])
  102. op[1] = '\0', ++pattern;
  103. op[0] = '\0';
  104. loc = scan(string, pattern, match_at_left);
  105. if (match_at_left) {
  106. printf("'%s'\n", loc);
  107. } else {
  108. *loc = '\0';
  109. printf("'%s'\n", string);
  110. }
  111. free(string);
  112. }
  113. return 0;
  114. }
  115. #endif