Atrinik Client  4.0
cmd_aliases.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <toolkit/string.h>
34 #include <toolkit/path.h>
35 
39 typedef struct cmd_alias_struct {
43  char *name;
44 
48  char *arg;
49 
54  char *noarg;
55 
59  UT_hash_handle hh;
61 
66 
72 static void cmd_aliases_load(const char *path)
73 {
74  FILE *fp = path_fopen(path, "r");
75  if (fp == NULL) {
76  return;
77  }
78 
79  cmd_alias_struct *cmd_alias = NULL;
80 
81  char buf[HUGE_BUF];
82  uint64_t linenum = 0;
83 
84  while (fgets(VS(buf), fp)) {
85  linenum++;
86 
87  if (*buf == '#' || *buf == '\n') {
88  continue;
89  }
90 
91  char *cp = buf;
92  string_skip_whitespace(cp);
93  string_strip_newline(cp);
94 
95  const char *key = cp, *value = NULL, *error_str;
96 
97  if (string_startswith(cp, "[") && string_endswith(cp, "]")) {
98  if (cmd_alias != NULL) {
99  HASH_ADD_KEYPTR(hh, cmd_aliases, cmd_alias->name,
100  strlen(cmd_alias->name), cmd_alias);
101  }
102 
103  cmd_alias = ecalloc(1, sizeof(*cmd_alias));
104  cmd_alias->name = string_sub(cp, 1, -1);
105 
106  if (string_isempty(cmd_alias->name)) {
107  error_str = "empty command alias name";
108  goto error;
109  }
110 
111  continue;
112  }
113 
114  char *cps[2];
115  if (string_split(cp, cps, arraysize(cps), '=') != 2) {
116  error_str = "malformed line";
117  goto error;
118  }
119 
120  string_whitespace_trim(cps[0]);
121  string_whitespace_trim(cps[1]);
122  key = cps[0];
123  value = cps[1];
124 
125  if (string_isempty(key)) {
126  error_str = "empty key";
127  goto error;
128  } else if (string_isempty(value)) {
129  error_str = "empty value";
130  goto error;
131  }
132 
133  if (cmd_alias == NULL) {
134  error_str = "expected command alias definition";
135  goto error;
136  } else if (strcmp(key, "arg") == 0) {
137  cmd_alias->arg = estrdup(value);
138  } else if (strcmp(key, "noarg") == 0) {
139  cmd_alias->noarg = estrdup(value);
140  } else {
141  error_str = "unknown attribute";
142  goto error;
143  }
144 
145  continue;
146 
147 error:
148  LOG(ERROR, "Error parsing %s, line %" PRIu64 ", %s: %s%s%s", path,
149  linenum, error_str, key, value != NULL ? " = " : "",
150  value != NULL ? value : "");
151  exit(1);
152  }
153 
154  if (cmd_alias != NULL) {
155  HASH_ADD_KEYPTR(hh, cmd_aliases, cmd_alias->name,
156  strlen(cmd_alias->name), cmd_alias);
157  }
158 
159  fclose(fp);
160 }
161 
166 {
167  cmd_aliases_load("data/cmd_aliases.cfg");
168  cmd_aliases_load("settings/cmd_aliases.cfg");
169 }
170 
175 {
176  cmd_alias_struct *curr, *tmp;
177 
178  HASH_ITER(hh, cmd_aliases, curr, tmp)
179  {
180  HASH_DEL(cmd_aliases, curr);
181 
182  efree(curr->name);
183 
184  if (curr->arg) {
185  efree(curr->arg);
186  }
187 
188  if (curr->noarg) {
189  efree(curr->noarg);
190  }
191 
192  efree(curr);
193  }
194 }
195 
203 static void cmd_aliases_execute(const char *cmd, const char *params)
204 {
205  char word[MAX_BUF], *cp, *func_end;
206  StringBuffer *sb;
207  size_t pos;
208 
209  pos = 0;
210  sb = stringbuffer_new();
211 
212  while (string_get_word(cmd, &pos, ' ', word, sizeof(word), 0)) {
213  if (stringbuffer_length(sb)) {
214  stringbuffer_append_string(sb, " ");
215  }
216 
217  func_end = strchr(word, '>');
218 
219  if (string_startswith(word, "<") && func_end) {
220  char *func, *cps[2];
221 
222  func = string_sub(word, 1, func_end - word);
223 
224  if (string_split(func, cps, arraysize(cps), ':') == 2) {
225  if (strcmp(cps[0], "get") == 0) {
226  char *str, *cps2[2];
227 
228  if (string_split(cps[1], cps2, arraysize(cps2), ';') < 1) {
229  continue;
230  }
231 
232  if (strcmp(cps2[0], "arg") == 0) {
233  str = estrdup(params ? params : "");
234  } else if (strcmp(cps2[0], "mplayer") == 0) {
236  str = estrdup(sound_get_bg_music_basename());
237  } else {
238  str = estrdup("nothing");
239  }
240  } else {
241  str = estrdup("???");
242  }
243 
244  if (cps2[1]) {
245  if (strcmp(cps2[1], "upper") == 0) {
246  string_toupper(str);
247  } else if (strcmp(cps2[1], "lower") == 0) {
248  string_tolower(str);
249  } else if (strcmp(cps2[1], "capitalize") == 0) {
250  string_capitalize(str);
251  } else if (strcmp(cps2[1], "titlecase") == 0) {
252  string_title(str);
253  }
254  }
255 
256  stringbuffer_append_string(sb, str);
257  efree(str);
258  } else if (strcmp(cps[0], "gender") == 0) {
259  if (strcmp(cps[1], "possessive") == 0) {
260  stringbuffer_append_string(sb, gender_possessive[cpl.gender]);
261  } else if (strcmp(cps[1], "reflexive") == 0) {
262  stringbuffer_append_string(sb, gender_reflexive[cpl.gender]);
263  } else if (strcmp(cps[1], "subjective") == 0) {
264  stringbuffer_append_string(sb, gender_subjective[cpl.gender]);
265  }
266  } else if (strcmp(cps[0], "choice") == 0) {
267  UT_array *strs;
268  char *s, **p;
269  size_t idx;
270 
271  utarray_new(strs, &ut_str_icd);
272 
273  s = strtok(cps[1], ",");
274 
275  while (s) {
276  utarray_push_back(strs, &s);
277  s = strtok(NULL, ",");
278  }
279 
280  idx = rndm(1, utarray_len(strs)) - 1;
281  p = (char **) utarray_eltptr(strs, idx);
282 
283  if (p) {
284  stringbuffer_append_string(sb, *p);
285  }
286 
287  utarray_free(strs);
288  } else if (strcmp(cps[0], "rndm") == 0) {
289  int min, max;
290 
291  if (sscanf(cps[1], "%d-%d", &min, &max) == 2) {
292  stringbuffer_append_printf(sb, "%d", rndm(min, max));
293  }
294  }
295  }
296 
297  efree(func);
298 
299  stringbuffer_append_string(sb, func_end + 1);
300  } else {
301  stringbuffer_append_string(sb, word);
302  }
303  }
304 
305  cp = stringbuffer_finish(sb);
306  send_command(cp);
307  efree(cp);
308 }
309 
317 int cmd_aliases_handle(const char *cmd)
318 {
319  if (cmd[0] == '/' && cmd[1] != '\0') {
320  char *cp;
321  size_t cmd_len;
322  const char *params;
323  cmd_alias_struct *cmd_alias;
324 
325  cmd++;
326  cp = strchr(cmd, ' ');
327 
328  if (cp) {
329  cmd_len = cp - cmd;
330  params = cp + 1;
331 
332  if (*params == '\0') {
333  params = NULL;
334  }
335  } else {
336  cmd_len = strlen(cmd);
337  params = NULL;
338  }
339 
340  HASH_FIND(hh, cmd_aliases, cmd, cmd_len, cmd_alias);
341 
342  if (cmd_alias) {
343  if (params && cmd_alias->arg) {
344  cmd_aliases_execute(cmd_alias->arg, params);
345  } else if (cmd_alias->noarg) {
346  cmd_aliases_execute(cmd_alias->noarg, params);
347  }
348 
349  return 1;
350  }
351  }
352 
353  return 0;
354 }
const char * sound_get_bg_music_basename(void)
Definition: sound.c:587
const char * gender_subjective[GENDER_MAX]
Definition: player.c:49
uint8_t sound_map_background(int val)
Definition: sound.c:608
void cmd_aliases_deinit(void)
Definition: cmd_aliases.c:174
int sound_playing_music(void)
Definition: sound.c:903
void cmd_aliases_init(void)
Definition: cmd_aliases.c:165
struct cmd_alias_struct cmd_alias_struct
uint8_t gender
Definition: player.h:212
void send_command(const char *command)
Definition: player.c:175
UT_hash_handle hh
Definition: cmd_aliases.c:59
static cmd_alias_struct * cmd_aliases
Definition: cmd_aliases.c:65
static void cmd_aliases_load(const char *path)
Definition: cmd_aliases.c:72
Client_Player cpl
Definition: client.c:50
const char * gender_possessive[GENDER_MAX]
Definition: player.c:67
const char * gender_reflexive[GENDER_MAX]
Definition: player.c:73
static void cmd_aliases_execute(const char *cmd, const char *params)
Definition: cmd_aliases.c:203
int cmd_aliases_handle(const char *cmd)
Definition: cmd_aliases.c:317