Blame


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