Blame


1 cc9bbf61 2020-04-01 op #include <ctype.h>
2 cc9bbf61 2020-04-01 op #include <string.h>
3 cc9bbf61 2020-04-01 op
4 7f40f3f5 2020-04-03 op #include "adventure.h"
5 7f40f3f5 2020-04-03 op
6 cc9bbf61 2020-04-01 op struct param params[MAX_PARAMS];
7 cc9bbf61 2020-04-01 op
8 cc9bbf61 2020-04-01 op static const char *
9 cc9bbf61 2020-04-01 op skip_spaces(const char *src)
10 cc9bbf61 2020-04-01 op {
11 cc9bbf61 2020-04-01 op while (isspace(*src))
12 cc9bbf61 2020-04-01 op src++;
13 cc9bbf61 2020-04-01 op return src;
14 cc9bbf61 2020-04-01 op }
15 cc9bbf61 2020-04-01 op
16 cc9bbf61 2020-04-01 op static const char *
17 cc9bbf61 2020-04-01 op match_spaces(const char *src)
18 cc9bbf61 2020-04-01 op {
19 cc9bbf61 2020-04-01 op return *src == '\0' || isspace(*src) ? skip_spaces(src) : NULL;
20 cc9bbf61 2020-04-01 op }
21 cc9bbf61 2020-04-01 op
22 cc9bbf61 2020-04-01 op static const char *
23 cc9bbf61 2020-04-01 op match_terminal(const char *src, char terminal)
24 cc9bbf61 2020-04-01 op {
25 cc9bbf61 2020-04-01 op return terminal == ' '
26 cc9bbf61 2020-04-01 op ? match_spaces(src)
27 7f40f3f5 2020-04-03 op : tolower(*src) == tolower(terminal) ? src + 1 : NULL;
28 cc9bbf61 2020-04-01 op }
29 cc9bbf61 2020-04-01 op
30 cc9bbf61 2020-04-01 op static const char *
31 cc9bbf61 2020-04-01 op match_tag(const char *src, const char *tag)
32 cc9bbf61 2020-04-01 op {
33 cc9bbf61 2020-04-01 op while (src != NULL && *tag != '\0')
34 cc9bbf61 2020-04-01 op src = match_terminal(src, *tag++);
35 cc9bbf61 2020-04-01 op return src;
36 cc9bbf61 2020-04-01 op }
37 cc9bbf61 2020-04-01 op
38 cc9bbf61 2020-04-01 op static int
39 cc9bbf61 2020-04-01 op compare_with_param(const char *tag, enum distance dist, struct param *par)
40 cc9bbf61 2020-04-01 op {
41 cc9bbf61 2020-04-01 op int diff = strlen(tag) - strlen(par->tag);
42 cc9bbf61 2020-04-01 op if (diff == 0)
43 cc9bbf61 2020-04-01 op diff = par->distance - dist;
44 cc9bbf61 2020-04-01 op if (diff == 0)
45 cc9bbf61 2020-04-01 op par->count++;
46 cc9bbf61 2020-04-01 op return diff;
47 cc9bbf61 2020-04-01 op }
48 cc9bbf61 2020-04-01 op
49 cc9bbf61 2020-04-01 op static const char *
50 cc9bbf61 2020-04-01 op match_param(const char *src, struct param *par, int loose)
51 cc9bbf61 2020-04-01 op {
52 cc9bbf61 2020-04-01 op struct object *obj;
53 cc9bbf61 2020-04-01 op const char *rest_of_src = loose ? src + strlen(src) : NULL;
54 cc9bbf61 2020-04-01 op
55 cc9bbf61 2020-04-01 op par->tag = src;
56 7f40f3f5 2020-04-03 op par->distance
57 7f40f3f5 2020-04-03 op = *src == '\0' ? dist_no_obj_specified : dist_unknown_obj;
58 cc9bbf61 2020-04-01 op
59 8852ffaf 2020-04-03 op foreach_obj (obj) {
60 cc9bbf61 2020-04-01 op const char **tag;
61 cc9bbf61 2020-04-01 op enum distance dist = distance_to(obj);
62 cc9bbf61 2020-04-01 op for (tag = obj->tags; *tag != NULL; ++tag) {
63 cc9bbf61 2020-04-01 op const char *behind_match = match_tag(src, *tag);
64 7f40f3f5 2020-04-03 op if (behind_match != NULL
65 7f40f3f5 2020-04-03 op && compare_with_param(*tag, dist, par) > 0
66 7f40f3f5 2020-04-03 op && (!loose
67 7f40f3f5 2020-04-03 op || *skip_spaces(behind_match)
68 7f40f3f5 2020-04-03 op == '\0')) {
69 cc9bbf61 2020-04-01 op par->tag = *tag;
70 cc9bbf61 2020-04-01 op par->object = obj;
71 cc9bbf61 2020-04-01 op par->distance = dist;
72 cc9bbf61 2020-04-01 op par->count = 1;
73 cc9bbf61 2020-04-01 op rest_of_src = behind_match;
74 cc9bbf61 2020-04-01 op }
75 cc9bbf61 2020-04-01 op }
76 cc9bbf61 2020-04-01 op }
77 cc9bbf61 2020-04-01 op
78 cc9bbf61 2020-04-01 op return rest_of_src;
79 cc9bbf61 2020-04-01 op }
80 cc9bbf61 2020-04-01 op
81 cc9bbf61 2020-04-01 op int
82 cc9bbf61 2020-04-01 op match_command(const char *src, const char *pattern)
83 cc9bbf61 2020-04-01 op {
84 cc9bbf61 2020-04-01 op struct param *par;
85 cc9bbf61 2020-04-01 op
86 cc9bbf61 2020-04-01 op /* clean params */
87 cc9bbf61 2020-04-01 op for (par = params; par < params + MAX_PARAMS; ++par) {
88 cc9bbf61 2020-04-01 op par->object = NULL;
89 cc9bbf61 2020-04-01 op par->distance = dist_no_obj_specified;
90 cc9bbf61 2020-04-01 op par->count = 0;
91 cc9bbf61 2020-04-01 op }
92 cc9bbf61 2020-04-01 op
93 cc9bbf61 2020-04-01 op /* actual parsing */
94 7f40f3f5 2020-04-03 op for (src = skip_spaces(src); src != NULL && *pattern != '\0';
95 7f40f3f5 2020-04-03 op ++pattern) {
96 cc9bbf61 2020-04-01 op src = isupper(*pattern)
97 cc9bbf61 2020-04-01 op ? match_param(src, param_by_letter(*pattern),
98 7f40f3f5 2020-04-03 op pattern[1] == '?')
99 7f40f3f5 2020-04-03 op : *pattern == '?' ? src
100 7f40f3f5 2020-04-03 op : match_terminal(src, *pattern);
101 cc9bbf61 2020-04-01 op }
102 cc9bbf61 2020-04-01 op
103 cc9bbf61 2020-04-01 op return src != NULL && *skip_spaces(src) == '\0';
104 cc9bbf61 2020-04-01 op }