1 cc9bbf61 2020-04-01 op #include "adventure.h"
3 cc9bbf61 2020-04-01 op #include <ctype.h>
4 cc9bbf61 2020-04-01 op #include <string.h>
6 cc9bbf61 2020-04-01 op struct param params[MAX_PARAMS];
8 cc9bbf61 2020-04-01 op static const char *
9 cc9bbf61 2020-04-01 op skip_spaces(const char *src)
11 cc9bbf61 2020-04-01 op while (isspace(*src))
16 cc9bbf61 2020-04-01 op static const char *
17 cc9bbf61 2020-04-01 op match_spaces(const char *src)
19 cc9bbf61 2020-04-01 op return *src == '\0' || isspace(*src) ? skip_spaces(src) : NULL;
22 cc9bbf61 2020-04-01 op static const char *
23 cc9bbf61 2020-04-01 op match_terminal(const char *src, char terminal)
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)
32 cc9bbf61 2020-04-01 op static const char *
33 cc9bbf61 2020-04-01 op match_tag(const char *src, const char *tag)
35 cc9bbf61 2020-04-01 op while (src != NULL && *tag != '\0')
36 cc9bbf61 2020-04-01 op src = match_terminal(src, *tag++);
41 cc9bbf61 2020-04-01 op compare_with_param(const char *tag, enum distance dist, struct param *par)
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)
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)
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;
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;
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;
77 cc9bbf61 2020-04-01 op return rest_of_src;
81 cc9bbf61 2020-04-01 op match_command(const char *src, const char *pattern)
83 cc9bbf61 2020-04-01 op struct param *par;
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;
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 == '?'
99 cc9bbf61 2020-04-01 op : match_terminal(src, *pattern);
102 cc9bbf61 2020-04-01 op return src != NULL && *skip_spaces(src) == '\0';