Crossfire Server, Trunk  R20513
gridarta-types-convert.c
Go to the documentation of this file.
1 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
28 
29 #include "define.h"
30 
31 const char *destination_dir = "../doc/Developers";
32 const char *field_dir = "fields";
33 const char *type_dir = "types";
36 typedef struct {
37  char *field;
38  char *name;
39  char *description;
41 
43 typedef struct {
44  int number;
45  char *name;
46  char *description;
47  char *use;
50  char **required;
53 
56 
57 int type_count = 0;
58 
61 
64 
66 typedef struct {
67  char *name;
68  int count;
69  char **fields;
70 } ignore_list;
71 
72 ignore_list **lists = NULL;
73 int list_count = 0;
74 
76 typedef struct {
77  char **type;
78  int *number;
79  int count;
80  char *description;
82 
84 typedef struct {
85  char *field;
89 
92 
94 typedef struct {
95  const char *field;
96  const char *code_name;
98 
100 static const flag_definition flags[] = {
101  { "alive", "FLAG_ALIVE" },
102  { "wiz", "FLAG_WIZ" },
103  { "was_wiz", "FLAG_WAS_WIZ" },
104  { "applied", "FLAG_APPLIED" },
105  { "unpaid", "FLAG_UNPAID" },
106  { "can_use_shield", "FLAG_USE_SHIELD" },
107  { "no_pick", "FLAG_NO_PICK" },
108  { "client_anim_sync", "FLAG_CLIENT_ANIM_SYNC" },
109  { "client_anim_random", "FLAG_CLIENT_ANIM_RANDOM" },
110  { "is_animated", "FLAG_ANIMATE" },
111  { "monster", "FLAG_MONSTER" },
112  { "friendly", "FLAG_FRIENDLY" },
113  { "generator", "FLAG_GENERATOR" },
114  { "is_thrown", "FLAG_IS_THROWN" },
115  { "auto_apply", "FLAG_AUTO_APPLY" },
116  { "treasure", "FLAG_TREASURE" },
117  { "player sold", "FLAG_PLAYER_SOLD" },
118  { "see_invisible", "FLAG_SEE_INVISIBLE" },
119  { "can_roll", "FLAG_CAN_ROLL" },
120  { "overlay_floor", "FLAG_OVERLAY_FLOOR" },
121  { "is_turnable", "FLAG_IS_TURNABLE" },
122  { "is_used_up", "FLAG_IS_USED_UP" },
123  { "identified", "FLAG_IDENTIFIED" },
124  { "reflecting", "FLAG_REFLECTING" },
125  { "changing", "FLAG_CHANGING" },
126  { "splitting", "FLAG_SPLITTING" },
127  { "hitback", "FLAG_HITBACK" },
128  { "startequip", "FLAG_STARTEQUIP" },
129  { "blocksview", "FLAG_BLOCKSVIEW" },
130  { "undead", "FLAG_UNDEAD" },
131  { "scared", "FLAG_SCARED" },
132  { "unaggressive", "FLAG_UNAGGRESSIVE" },
133  { "reflect_missile", "FLAG_REFL_MISSILE" },
134  { "reflect_spell", "FLAG_REFL_SPELL" },
135  { "no_magic", "FLAG_NO_MAGIC" },
136  { "no_fix_player", "FLAG_NO_FIX_PLAYER" },
137  { "is_lightable", "FLAG_IS_LIGHTABLE" },
138  { "tear_down", "FLAG_TEAR_DOWN" },
139  { "run_away", "FLAG_RUN_AWAY" },
140  { "unique", "FLAG_UNIQUE" },
141  { "no_drop", "FLAG_NO_DROP" },
142  { "can_cast_spell", "FLAG_CAST_SPELL" },
143  { "can_use_scroll", "FLAG_USE_SCROLL" },
144  { "can_use_range", "FLAG_USE_RANGE" },
145  { "can_use_bow", "FLAG_USE_BOW" },
146  { "can_use_armour", "FLAG_USE_ARMOUR" },
147  { "can_use_weapon", "FLAG_USE_WEAPON" },
148  { "can_use_ring", "FLAG_USE_RING" },
149  { "has_ready_range", "FLAG_READY_RANGE" },
150  { "has_ready_bow", "FLAG_READY_BOW" },
151  { "xrays", "FLAG_XRAYS" },
152  { "is_floor", "FLAG_IS_FLOOR" },
153  { "lifesave", "FLAG_LIFESAVE" },
154  { "no_strength", "FLAG_NO_STRENGTH" },
155  { "sleep", "FLAG_SLEEP" },
156  { "stand_still", "FLAG_STAND_STILL" },
157  { "random_movement", "FLAG_RANDOM_MOVE" },
158  { "only_attack", "FLAG_ONLY_ATTACK" },
159  { "confused", "FLAG_CONFUSED" },
160  { "stealth", "FLAG_STEALTH" },
161  { "cursed", "FLAG_CURSED" },
162  { "damned", "FLAG_DAMNED" },
163  { "see_anywhere", "FLAG_SEE_ANYWHERE" },
164  { "known_magical", "FLAG_KNOWN_MAGICAL" },
165  { "known_cursed", "FLAG_KNOWN_CURSED" },
166  { "can_use_skill", "FLAG_CAN_USE_SKILL" },
167  { "been_applied", "FLAG_BEEN_APPLIED" },
168  { "has_ready_scroll", "FLAG_READY_SCROLL" },
169  { "make_invisible", "FLAG_MAKE_INVIS" },
170  { "inv_locked", "FLAG_INV_LOCKED" },
171  { "is_wooded", "FLAG_IS_WOODED" },
172  { "is_hilly", "FLAG_IS_HILLY" },
173  { "has_ready_skill", "FLAG_READY_SKILL" },
174  { "has_ready_weapon", "FLAG_READY_WEAPON" },
175  { "no_skill_ident", "FLAG_NO_SKILL_IDENT" },
176  { "is_blind", "FLAG_BLIND" },
177  { "can_see_in_dark", "FLAG_SEE_IN_DARK" },
178  { "is_cauldron", "FLAG_IS_CAULDRON" },
179  { "no_steal", "FLAG_NO_STEAL" },
180  { "one_hit", "FLAG_ONE_HIT" },
181  { "berserk", "FLAG_BERSERK" },
182  { "neutral", "FLAG_NEUTRAL" },
183  { "no_attack", "FLAG_NO_ATTACK" },
184  { "no_damage", "FLAG_NO_DAMAGE" },
185  { "activate_on_push", "FLAG_ACTIVATE_ON_PUSH" },
186  { "activate_on_release", "FLAG_ACTIVATE_ON_RELEASE" },
187  { "is_water", "FLAG_IS_WATER" },
188  { "use_content_on_gen", "FLAG_CONTENT_ON_GEN" },
189  { "is_buildable", "FLAG_IS_BUILDABLE" },
190  { "blessed", "FLAG_BLESSED" },
191  { "known_blessed", "FLAG_KNOWN_BLESSED" },
192  { NULL, NULL }
193 };
194 
196 const flag_definition *find_flag(const char *name) {
197  int flag;
198 
199  for (flag = 0; flags[flag].field; flag++)
200  if (!strcmp(flags[flag].field, name))
201  return &flags[flag];
202  return NULL;
203 }
204 
205 typedef struct {
206  const char *code_name;
207  int value;
208 } type_name;
209 
210 static type_name type_names[] = {
211  { "PLAYER", PLAYER },
212  { "TRANSPORT", TRANSPORT },
213  { "ROD", ROD },
214  { "TREASURE", TREASURE },
215  { "POTION", POTION },
216  { "FOOD", FOOD },
217  { "POISON", POISON },
218  { "BOOK", BOOK },
219  { "CLOCK", CLOCK },
220  { "ARROW", ARROW },
221  { "BOW", BOW },
222  { "WEAPON", WEAPON },
223  { "ARMOUR", ARMOUR },
224  { "PEDESTAL", PEDESTAL },
225  { "ALTAR", ALTAR },
226  { "LOCKED_DOOR", LOCKED_DOOR },
227  { "SPECIAL_KEY", SPECIAL_KEY },
228  { "MAP", MAP },
229  { "DOOR", DOOR },
230  { "KEY", KEY },
231  { "TIMED_GATE", TIMED_GATE },
232  { "TRIGGER", TRIGGER },
233  { "GRIMREAPER", GRIMREAPER },
234  { "MAGIC_EAR", MAGIC_EAR },
235  { "TRIGGER_BUTTON", TRIGGER_BUTTON },
236  { "TRIGGER_ALTAR", TRIGGER_ALTAR },
237  { "TRIGGER_PEDESTAL", TRIGGER_PEDESTAL },
238  { "SHIELD", SHIELD },
239  { "HELMET", HELMET },
240  { "MONEY", MONEY },
241  { "CLASS", CLASS },
242  { "AMULET", AMULET },
243  { "PLAYERMOVER", PLAYERMOVER },
244  { "TELEPORTER", TELEPORTER },
245  { "CREATOR", CREATOR },
246  { "SKILL", SKILL },
247  { "EARTHWALL", EARTHWALL },
248  { "GOLEM", GOLEM },
249  { "THROWN_OBJ", THROWN_OBJ },
250  { "BLINDNESS", BLINDNESS },
251  { "GOD", GOD },
252  { "DETECTOR", DETECTOR },
253  { "TRIGGER_MARKER", TRIGGER_MARKER },
254  { "DEAD_OBJECT", DEAD_OBJECT },
255  { "DRINK", DRINK },
256  { "MARKER", MARKER },
257  { "HOLY_ALTAR", HOLY_ALTAR },
258  { "PLAYER_CHANGER", PLAYER_CHANGER },
259  { "BATTLEGROUND", BATTLEGROUND },
260  { "PEACEMAKER", PEACEMAKER },
261  { "GEM", GEM },
262  { "FIREWALL", FIREWALL },
263  { "CHECK_INV", CHECK_INV },
264  { "MOOD_FLOOR", MOOD_FLOOR },
265  { "EXIT", EXIT },
266  { "ENCOUNTER", ENCOUNTER },
267  { "SHOP_FLOOR", SHOP_FLOOR },
268  { "SHOP_MAT", SHOP_MAT },
269  { "RING", RING },
270  { "FLOOR", FLOOR },
271  { "FLESH", FLESH },
272  { "INORGANIC", INORGANIC },
273  { "SKILL_TOOL", SKILL_TOOL },
274  { "LIGHTER", LIGHTER },
275  { "WALL", WALL },
276  { "MISC_OBJECT", MISC_OBJECT },
277  { "MONSTER", MONSTER },
278  { "LAMP", LAMP },
279  { "DUPLICATOR", DUPLICATOR },
280  { "SPELLBOOK", SPELLBOOK },
281  { "CLOAK", CLOAK },
282  { "SPINNER", SPINNER },
283  { "GATE", GATE },
284  { "BUTTON", BUTTON },
285  { "CF_HANDLE", CF_HANDLE },
286  { "HOLE", HOLE },
287  { "TRAPDOOR", TRAPDOOR },
288  { "SIGN", SIGN },
289  { "BOOTS", BOOTS },
290  { "GLOVES", GLOVES },
291  { "SPELL", SPELL },
292  { "SPELL_EFFECT", SPELL_EFFECT },
293  { "CONVERTER", CONVERTER },
294  { "BRACERS", BRACERS },
295  { "POISONING", POISONING },
296  { "SAVEBED", SAVEBED },
297  { "WAND", WAND },
298  { "SCROLL", SCROLL },
299  { "DIRECTOR", DIRECTOR },
300  { "GIRDLE", GIRDLE },
301  { "FORCE", FORCE },
302  { "POTION_RESIST_EFFECT", POTION_RESIST_EFFECT },
303  { "EVENT_CONNECTOR", EVENT_CONNECTOR },
304  { "CLOSE_CON", CLOSE_CON },
305  { "CONTAINER", CONTAINER },
306  { "ARMOUR_IMPROVER", ARMOUR_IMPROVER },
307  { "WEAPON_IMPROVER", WEAPON_IMPROVER },
308  { "SKILLSCROLL", SKILLSCROLL },
309  { "DEEP_SWAMP", DEEP_SWAMP },
310  { "IDENTIFY_ALTAR", IDENTIFY_ALTAR },
311  { "SHOP_INVENTORY", SHOP_INVENTORY },
312  { "RUNE", RUNE },
313  { "TRAP", TRAP },
314  { "POWER_CRYSTAL", POWER_CRYSTAL },
315  { "CORPSE", CORPSE },
316  { "DISEASE", DISEASE },
317  { "SYMPTOM", SYMPTOM },
318  { "BUILDER", BUILDER },
319  { "MATERIAL", MATERIAL },
320  { NULL, 0 }
321 };
322 
324  type_attribute *ret = calloc(1, sizeof(type_attribute));
325  ret->field = strdup(attr->field);
326  ret->name = strdup(attr->name);
327  ret->description = strdup(attr->description);
328  return ret;
329 }
330 
332  free(attr->field);
333  free(attr->name);
334  free(attr->description);
335  free(attr);
336 }
337 
342 type_attribute *get_attribute_for_type(type_definition *type, const char *attribute, int clean) {
343  type_attribute *ret;
344  int test;
345 
346  for (test = 0; test < type->attribute_count; test++) {
347  if (!strcmp(type->attributes[test]->field, attribute)) {
348  ret = type->attributes[test];
349  if (clean) {
350  free(ret->name);
351  ret->name = NULL;
352  free(ret->description);
353  ret->description = NULL;
354  }
355  return ret;
356  }
357  }
358  ret = calloc(1, sizeof(type_attribute));
359  ret->field = strdup(attribute);
360 
361  type->attribute_count++;
362  type->attributes = realloc(type->attributes, type->attribute_count*sizeof(type_attribute *));
363  type->attributes[type->attribute_count-1] = ret;
364 
365  return ret;
366 }
367 
368 void copy_attributes(const type_definition *source, type_definition *type) {
369  int attr;
370  type_attribute *add;
371 
372  assert(source);
373  if (source->attribute_count == 0)
374  return;
375 
376  for (attr = 0; attr < source->attribute_count; attr++) {
377  add = get_attribute_for_type(type, source->attributes[attr]->field, 1);
378  add->name = strdup(source->attributes[attr]->name);
379  if (source->attributes[attr]->description)
380  add->description = strdup(source->attributes[attr]->description);
381  }
382 }
383 
385  if (!default_type)
386  return;
387  copy_attributes(default_type, type);
388 }
389 
394  type_definition *ret = calloc(1, sizeof(type_definition));
395 
396  ret->attribute_count = 0;
397  ret->attributes = NULL;
398  assert(ret->description == NULL);
399 
400  if (default_type)
402 
403  return ret;
404 }
405 
410  int type;
411 
412  for (type = 0; type < type_count; type++) {
413  if (!strcmp(types[type]->name, name))
414  return types[type];
415  }
416  printf("type not found: %s\n", name);
417  return NULL;
418 }
419 
421 int sort_type_attribute(const void *a, const void *b) {
422  const type_attribute **la = (const type_attribute **)a;
423  const type_attribute **lb = (const type_attribute **)b;
424 
425  return strcmp((*la)->name, (*lb)->name);
426 }
427 
428 ignore_list *find_ignore_list(const char *name) {
429  int list;
430 
431  for (list = 0; list < list_count; list++) {
432  if (strcmp(lists[list]->name, name) == 0)
433  return lists[list];
434  }
435  return NULL;
436 }
437 
441 char *read_line(char *buffer, int size, FILE *file) {
442  return fgets(buffer, 200, file);
443 }
444 
446 void ignore_attribute(type_definition *type, const char *attribute) {
447  int find;
448 
449  for (find = 0; find < type->attribute_count; find++) {
450  if (!strcmp(attribute, type->attributes[find]->field)) {
451  /*printf("rem %s from %s\n", list->fields[attr], type->name);*/
452  free_attribute(type->attributes[find]);
453  if (find < type->attribute_count-1)
454  type->attributes[find] = type->attributes[type->attribute_count-1];
455  type->attribute_count--;
456  return;
457  }
458  }
459 }
460 
463  int attr;
464 
465  if (!list) {
466  printf("empty ignore list?\n");
467  return;
468  }
469 
470  for (attr = 0; attr < list->count; attr++) {
471  ignore_attribute(type, list->fields[attr]);
472  }
473 }
474 
476 void add_required_parameter(type_definition *type, const char *buf) {
477  char *sn, *en, *sv, *ev;
478  char value[200], name[200], temp[200];
479  const flag_definition *flag;
480 
481  if (type == fallback_type)
482  /* the "Misc" type has dummy requirements, don't take that into account. */
483  return;
484 
485  sn = strstr(buf, "arch");
486  if (!sn)
487  return;
488  sn = strchr(sn, '"');
489  en = strchr(sn+1, '"');
490  sv = strstr(buf, "value");
491  sv = strchr(sv, '"');
492  ev = strchr(sv+1, '"');
493 
494  name[en-sn-1] = '\0';
495  strncpy(name, sn+1, en-sn-1);
496  value[ev-sv-1] = '\0';
497  strncpy(value, sv+1, ev-sv-1);
498 
499  type->require_count++;
500  type->required = realloc(type->required, type->require_count*sizeof(char *));
501 
502  flag = find_flag(name);
503  if (flag)
504  snprintf(temp, 200, "@ref %s %s", flag->code_name, strcmp(value, "0") ? "set" : "unset");
505  else
506  snprintf(temp, 200, "@ref object::%s = %s", name, value);
507  type->required[type->require_count-1] = strdup(temp);
508 }
509 
511 void read_type(type_definition *type, FILE *file, const char *block_end) {
512  char buf[200], tmp[200];
513  char *find, *end;
514  type_attribute *attr;
515 
516  while (read_line(buf, 200, file)) {
517  if (strstr(buf, block_end) != NULL) {
518  if (type->attribute_count)
519  qsort(type->attributes, type->attribute_count, sizeof(type_attribute *), sort_type_attribute);
520  return;
521  }
522  if (strstr(buf, "<description>") != NULL) {
523  while (read_line(buf, 200, file)) {
524  if (strstr(buf, "</description>") != NULL)
525  break;
526 
527  if (type->description) {
528  type->description = realloc(type->description, strlen(type->description)+strlen(buf)+1);
529  strcat(type->description, buf);
530  }
531  else
532  type->description = strdup(buf);
533  }
534  find = strstr(type->description, "]]>");
535  if (find)
536  type->description[find-type->description] = '\0';
537  while (type->description[strlen(type->description)-1] == '\n')
538  type->description[strlen(type->description)-1] = '\0';
539  /*printf(" => desc = %s\n", type->description);*/
540  }
541 
542  if (strstr(buf, "<ignore_list") != NULL) {
543  find = strstr(buf, "name=");
544  if (!find)
545  return;
546  find = strchr(find+1, '"');
547  if (!find)
548  return;
549  end = strchr(find+1, '"');
550  if (!end)
551  return;
552  tmp[end-find-1] = '\0';
553  strncpy(tmp, find+1, end-find-1);
555  }
556 
557  if (strstr(buf, "<ignore>") != NULL) {
558  while (read_line(buf, 200, file)) {
559  if (strstr(buf, "</ignore>") != NULL)
560  break;
561  find = strstr(buf, "arch=");
562  if (!find)
563  continue;
564  find = strchr(find+1, '"');
565  if (!find)
566  continue;
567  end = strchr(find+1, '"');
568  if (!end)
569  continue;
570  tmp[end-find-1] = '\0';
571  strncpy(tmp, find+1, end-find-1);
572  ignore_attribute(type, tmp);
573  }
574  }
575 
576  if (strstr(buf, "<required>") != NULL) {
577  while (read_line(buf, 200, file)) {
578  if (strstr(buf, "</required>") != NULL)
579  break;
580  add_required_parameter(type, buf);
581  }
582  }
583 
584  if (strstr(buf, "<import_type") != NULL) {
585  type_definition *import;
586 
587  find = strstr(buf, "name=");
588  if (!find)
589  return;
590  find = strchr(find+1, '"');
591  if (!find)
592  return;
593  end = strchr(find+1, '"');
594  if (!end)
595  return;
596  tmp[end-find-1] = '\0';
597  strncpy(tmp, find+1, end-find-1);
598  import = find_type_definition(tmp);
599  if (import) {
600  /*printf("%s import %s\n", type->name, tmp);*/
601  copy_attributes(import, type);
602  }
603  else
604  printf("%s: import %s not found\n", type->name, tmp);
605  }
606 
607  if (strstr(buf, "<attribute") != NULL) {
608  find = strstr(buf, "arch");
609  if (!find)
610  continue;
611  find = strchr(find, '"');
612  end = strchr(find+1, '"');
613  if (end == find+1)
614  /* empty arch, meaning inventory or such, ignore. */
615  continue;
616 
617  tmp[end-find-1] = '\0';
618  strncpy(tmp, find+1, end-find-1);
619  /*printf(" => attr %s\n", tmp);*/
620 
621  find = strstr(buf, "editor");
622  if (find == NULL)
623  /* fixed or other, ignore */
624  continue;
625  attr = get_attribute_for_type(type, tmp, 1);
626  find = strchr(find, '"');
627  end = strchr(find+1, '"');
628  tmp[end-find-1] = '\0';
629  strncpy(tmp, find+1, end-find-1);
630  attr->name = strdup(tmp);
631 
632  /* Description can be empty, with end tag on the same line. */
633  if (strstr(buf, "</attribute>") == NULL && strstr(buf, "/>") == NULL) {
634  while (read_line(buf, 200, file)) {
635  if (strstr(buf, "<![CDATA[<html>") != NULL)
636  /* some data is in HTML, that's ok */
637  continue;
638  if (strstr(buf, "]]>") != NULL)
639  /* end of cdata html */
640  continue;
641  if (strstr(buf, "</attribute>") != NULL)
642  break;
643  if (attr->description) {
644  attr->description = realloc(attr->description, strlen(attr->description)+strlen(buf)+1);
645  strcat(attr->description, buf);
646  }
647  else
648  attr->description = strdup(buf);
649  }
650  }
651  if (attr->description)
652  while (attr->description[strlen(attr->description)-1] == '\n')
653  attr->description[strlen(attr->description)-1] = '\0';
654 
655  }
656  }
657 }
658 
660  int attr;
661 
662  printf("type: %s [%d]\n", type->name, type->number);
663  printf(" attributes:\n");
664  for (attr = 0; attr < type->attribute_count; attr++) {
665  printf(" %30s: %s\n", type->attributes[attr]->field, type->attributes[attr]->name);
666  printf(" %s\n", type->attributes[attr]->description);
667  }
668 }
669 
670 void dump_types(void) {
671  int t;
672  type_definition *type;
673 
674  for (t = 0; t < type_count; t++) {
675  type = types[t];
676  dump_type(type);
677  }
678 }
679 
682  int attr;
684 
685  for (attr = 0; attr < attribute_count; attr++) {
686  if (!strcmp(attributes[attr]->field, name))
687  return attributes[attr];
688  }
689 
690  ret = calloc(1, sizeof(attribute_definition));
691  attribute_count++;
692  attributes = realloc(attributes, attribute_count*sizeof(attribute_definition *));
693  attributes[attribute_count-1] = ret;
694 
695  ret->field = strdup(name);
696 
697  return ret;
698 }
699 
702  int desc;
703  attribute_type *add;
704 
705  for (desc = 0; desc < attribute->type_count; desc++) {
706  if (!description && !attribute->types[desc]->description)
707  return attribute->types[desc];
708  if (description && attribute->types[desc]->description && !strcmp(description, attribute->types[desc]->description))
709  return attribute->types[desc];
710  }
711 
712  add = calloc(1, sizeof(attribute_type));
713  attribute->type_count++;
714  attribute->types = realloc(attribute->types, attribute->type_count*sizeof(attribute_type));
715  attribute->types[attribute->type_count-1] = add;
716 
717  if (description)
718  add->description = strdup(description);
719 
720  return add;
721 }
722 
723 void add_type_to_attribute(attribute_definition *attribute, type_definition *type, int attr) {
724  attribute_type *att;
725 
726  att = get_description_for_attribute(attribute, type->attributes[attr]->description);
727  att->count++;
728  att->type = realloc(att->type, att->count*sizeof(const char *));
729  att->number = realloc(att->number, att->count*sizeof(int));
730  att->type[att->count-1] = strdup(type->name);
731  att->number[att->count-1] = type->number;
732 }
733 
735 void read_ignore_list(const char *name, FILE *file) {
736  char buf[200], tmp[200];
737  char *start, *end;
738  ignore_list *list;
739 
740  /*printf("il %s:", name);*/
741  list = calloc(1, sizeof(ignore_list));
742  list_count++;
743  lists = realloc(lists, list_count*sizeof(ignore_list *));
744  lists[list_count-1] = list;
745  list->name = strdup(name);
746 
747  while (read_line(buf, 200, file)) {
748  if (strstr(buf, "</ignore_list>") != NULL) {
749  /*printf("\n");*/
750  return;
751  }
752  start = strstr(buf, "arch=");
753  if (!start)
754  continue;
755  start = strchr(start+1, '"');
756  if (!start)
757  continue;
758  end = strchr(start+1, '"');
759  if (!end)
760  continue;
761 
762  tmp[end-start-1] = '\0';
763  strncpy(tmp, start+1, end-start-1);
764  /*printf(" %s", tmp);*/
765 
766  list->count++;
767  list->fields = realloc(list->fields, list->count*sizeof(char *));
768  list->fields[list->count-1] = strdup(tmp);
769  }
770 }
771 
772 void dump_ignore_lists(void) {
773  int list, field;
774 
775  printf("ignore lists:\n");
776  for (list = 0; list < list_count; list++) {
777  printf(" %s:", lists[list]->name);
778  for (field = 0; field < lists[list]->count; field++)
779  printf(" %s", lists[list]->fields[field]);
780  printf("\n");
781  }
782 }
783 
785 static const char *in_living[] = {
786  "Str",
787  "Dex",
788  "Con",
789  "Wis",
790  "Cha",
791  "Int",
792  "Pow",
793  "wc",
794  "ac",
795  "hp",
796  "maxhp",
797  "sp",
798  "maxsp",
799  "grace",
800  "maxgrace",
801  "exp",
802  "food",
803  "dam",
804  "luck",
805  NULL
806 };
807 
809 static const char *custom_attributes[] = {
810  /* transports */
811  "weight_speed_ratio",
812  "base_speed",
813  "passenger_limit",
814  "face_full",
815  "anim_full",
816  /* misc */
817  "accept_alive",
818  "death_animation",
819  "face_opened",
820  "generator_code",
821  "generator_limit",
822  "generator_max_map",
823  "generator_radius",
824  "no_mood_change",
825  "on_use_yield",
826  "race_restriction",
827  "wc_increase_rate",
828  "price_adjustment",
829  "price_adjustment_buy",
830  "price_adjustment_sell",
831  "casting_requirements",
832  "identified_name",
833  "identified_name_pl",
834  "identified_face",
835  "identified_animation",
836  "identified_anim_speed",
837  "identified_anim_random",
838  "immunity_chance",
839  "elevation",
840  NULL
841 };
842 
843 int is_custom_attribute(const char *attribute) {
844  int val;
845 
846  for (val = 0; custom_attributes[val] != NULL; val++) {
847  if (!strcmp(custom_attributes[val], attribute)) {
848  return 1;
849  }
850  }
851  return 0;
852 }
853 
855 void write_attribute_reference(const char *attribute, FILE *file) {
856  const flag_definition *flag = find_flag(attribute);
857  int val;
858 
859  if (flag) {
860  fprintf(file, "%s", flag->code_name);
861  return;
862  }
863  for (val = 0; in_living[val] != NULL; val++) {
864  if (!strcmp(in_living[val], attribute)) {
865  fprintf(file, "liv::%s", attribute);
866  return;
867  }
868  }
869  if (is_custom_attribute(attribute)) {
870  fprintf(file, "page_custom_attribute_%s \"%s\"", attribute, attribute);
871  return;
872  }
873  if (strstr(attribute, "resist_")) {
874  fprintf(file, "obj::resist");
875  return;
876  }
877  if (!strcmp(attribute, "connected")) {
878  fprintf(file, "page_connected \"connection value\"");
879  return;
880  }
881  fprintf(file, "obj::%s", attribute);
882 }
883 
886  FILE *file;
887  char buf[200];
888  int attr, req;
889 
890  snprintf(buf, 200, "%s/%s/type_%d.dox", destination_dir, type_dir, type->number);
891  file = fopen(buf, "w+");
892 
893  fprintf(file, "/**\n");
894 
895  /* auto-generate documentation for the type, so no need to change define.h */
896  if (type->number > 0) {
897  for (req = 0; type_names[req].code_name != NULL; req++) {
898  if (type_names[req].value == type->number) {
899  fprintf(file, "@var %s\nSee @ref page_type_%d\n*/\n\n/**\n", type_names[req].code_name, type->number);
900  break;
901  }
902  }
903  }
904 
905  fprintf(file, "@page page_type_%d %s\n\n", type->number, type->name);
906  fprintf(file, "\n@section Description\n");
907  fprintf(file, "%s\n\n", type->description);
908  if (type != fallback_type) {
909  fprintf(file, "\n\nType defined by:\n");
910  if (type->number && type->number < OBJECT_TYPE_MAX)
911  fprintf(file, "- @ref object::type = %d\n", type->number);
912  for (req = 0; req < type->require_count; req++)
913  fprintf(file, "- %s\n", type->required[req]);
914  }
915 
916  fprintf(file, "\n\n@section Attributes\n\n");
917  fprintf(file, "<table>\n\t<tr>\n\t\t<th>Attribute</th>\n\t\t<th>Field</th>\n\t\t<th>Description</th>\n\t</tr>\n");
918  for (attr = 0; attr < type->attribute_count; attr++) {
919  fprintf(file, "\t<tr>\n\t\t<td>%s</td>\n\t\t<td>@ref ", type->attributes[attr]->name);
920  write_attribute_reference(type->attributes[attr]->field, file);
921  fprintf(file, "</td>\n\t\t<td>%s\n\t\t</td>\n\t</tr>\n", type->attributes[attr]->description ? type->attributes[attr]->description : "(no description)");
922  }
923 
924  fprintf(file, "</table>\n*/\n");
925 
926  fclose(file);
927 }
928 
930 void write_type_index(void) {
931  FILE *index;
932  int type;
933  char buf[200];
934 
935  snprintf(buf, 200, "%s/%s/types.dox", destination_dir, type_dir);
936  index = fopen(buf, "w+");
937  fprintf(index, "/**\n@page type_index Type index\n");
938 
939  fprintf(index, "Types not listed here have the attributes defined in @ref page_type_0 \"this page\".\n\n");
940 
941  for (type = 0; type < type_count; type++) {
942  fprintf(index, "- @ref page_type_%d \"%s\"\n", types[type]->number, types[type]->name);
943  }
944 
945  fprintf(index, "*/\n");
946 
947  fclose(index);
948 }
949 
952  FILE *index;
953  int attribute;
954  char buf[200];
955 
956  snprintf(buf, 200, "%s/%s/fields.dox", destination_dir, field_dir);
957  index = fopen(buf, "w+");
958  fprintf(index, "/**\n@page field_index Field index\n");
959 
960  fprintf(index, "This page lists all attributes.\n\n");
961 
962  for (attribute = 0; attribute < attribute_count; attribute++) {
963  fprintf(index, "- @ref ");
964  write_attribute_reference(attributes[attribute]->field, index);
965  fprintf(index, "\n");
966  }
967 
968  fprintf(index, "*/\n");
969 
970  fclose(index);
971 }
972 
975  FILE *file;
976  char buf[200];
977  int type, desc;
978  const char *end;
979 
980  snprintf(buf, 200, "%s/%s/field_%s.dox", destination_dir, field_dir, attribute->field);
981  file = fopen(buf, "w+");
982 
983  if (is_custom_attribute(attribute->field)) {
984  fprintf(file, "/**\n@page page_custom_attribute_%s %s", attribute->field, attribute->field);
985  fprintf(file, "\nThis is a @ref page_custom_attributes \"custom attribute\".\n");
986  } else {
987  if (strcmp(attribute->field, "connected") == 0)
988  fprintf(file, "/**\n@page ");
989  else
990  fprintf(file, "/**\n@fn ");
991  write_attribute_reference(attribute->field, file);
992  }
993 
994  /* resistances are special, they'll be merged in the obj::resist paragraph, so specify the name. */
995  if (strstr(attribute->field, "resist_"))
996  fprintf(file, "\n@section %s %s resistance\n", attribute->field, attribute->field+7);
997  else
998  fprintf(file, "\n@section Use\n");
999 
1000  fprintf(file, "<table>\n\t<tr>\n\t\t<th>Type(s)</th>\n\t\t<th>Description</th>\n\t</tr>");
1001 
1002  for (desc = 0; desc < attribute->type_count; desc++) {
1003  assert(attribute->types[desc]->count > 0);
1004 
1005  fprintf(file, "\t<tr>\n\t\t<td>\n");
1006 
1007  for (type = 0; type < attribute->types[desc]->count; type++) {
1008  if (type < attribute->types[desc]->count-1)
1009  end = ", ";
1010  else
1011  end = "\n";
1012  fprintf(file, "@ref page_type_%d%s", attribute->types[desc]->number[type], end);
1013  }
1014  fprintf(file, "\t\t</td><td>%s</td>\n\t</tr>\n", attribute->types[desc]->description ? attribute->types[desc]->description : "(no description)");
1015  }
1016 
1017  fprintf(file, "\n*/\n");
1018 
1019  fclose(file);
1020 }
1021 
1022 int main(int argc, char **argv) {
1023  FILE *xml;
1024  int number, attr, dummy;
1025  char buf[200], tmp[200];
1026  char *start, *end;
1027  type_definition *type;
1028 
1029  if (argc < 2) {
1030  printf("Syntax: %s /path/to/Gridarta/types.xml\n", argv[0]);
1031  return 1;
1032  }
1033 
1034  /* dummy type number for special types. */
1035  dummy = OBJECT_TYPE_MAX+50;
1036 
1037  xml = fopen(argv[1], "r");
1038 
1039  if (!xml) {
1040  printf("Could not find file %s\n", argv[1]);
1041  return 1;
1042  }
1043 
1044  while (read_line(buf, 200, xml) != NULL) {
1045  if (buf[0] == '#')
1046  continue;
1047  if (strstr(buf, "<default_type>")) {
1048  default_type = get_type_definition();
1049  default_type->name = strdup("(default type)");
1050  read_type(default_type, xml, "</default_type>");
1051  continue;
1052  }
1053 
1054  if (strstr(buf, "<ignore_list") != NULL) {
1055  start = strstr(buf, "name=");
1056  start = strchr(start+1, '"');
1057  end = strchr(start+1, '"');
1058  tmp[end-start-1] = '\0';
1059  strncpy(tmp, start+1, end-start-1);
1060  read_ignore_list(tmp, xml);
1061  continue;
1062  }
1063 
1064  start = strstr(buf, "<type number");
1065  if (start) {
1066  start = strchr(start, '"');
1067  /*if (!start)
1068  break;*/
1069  end = strchr(start+1, '"');
1070  /*if (!end)
1071  break;*/
1072  tmp[end-start-1] = '\0';
1073  strncpy(tmp, start+1, end-start-1);
1074  /*printf("type %s ", tmp);*/
1075 
1076  number = atoi(tmp);
1077  start = strstr(end, "name=");
1078  start = strchr(start, '"');
1079  end = strchr(start+1, '"');
1080  tmp[end-start-1] = '\0';
1081  strncpy(tmp, start+1, end-start-1);
1082 
1083  if (!strcmp(tmp, "Misc")) {
1084  fallback_type = get_type_definition();
1085  type = fallback_type;
1086  }
1087  else {
1088  if (number == 0)
1089  number = dummy++;
1090  type = get_type_definition();
1091  type_count++;
1092  types = realloc(types, type_count*sizeof(type_definition *));
1093  types[type_count-1] = type;
1094  }
1095 
1096 #if 0
1097  if (!number || number >= OBJECT_TYPE_MAX || types[number] != NULL) {
1098  /*printf("=> skip\n");*/
1099  while (read_line(buf, 200, xml) != NULL && strstr(buf, "</type>") == NULL)
1100  /*printf(" => skip %s\n", buf)*/;
1101  /*printf(" => end of skip\n");*/
1102  continue;
1103  }
1104 #endif
1105 
1106  type->number = number;
1107 
1108  /*printf("nom %s\n", tmp);*/
1109  type->name = strdup(tmp);
1110 
1111  read_type(type, xml, "</type>");
1112  }
1113  }
1114 
1115  free(fallback_type->description);
1116  fallback_type->description = strdup("This type regroups all types who don't have a specific definition.");
1117 
1118  for (number = 0; number < type_count; number++) {
1119  for (attr = 0; attr < types[number]->attribute_count; attr++)
1120  add_type_to_attribute(get_attribute(types[number]->attributes[attr]->field), types[number], attr);
1121  }
1122 
1123 /* dump_types();*/
1124 /* dump_type(default_type);*/
1125 /* dump_ignore_lists();*/
1126 
1127  write_type_index();
1128  for (number = 0; number < type_count; number++)
1129  write_type_file(types[number]);
1130  write_type_file(fallback_type);
1131 
1133  for (attr = 0; attr < attribute_count; attr++)
1134  write_attribute_file(attributes[attr]);
1135 
1136  fclose(xml);
1137  free(types);
1138  return 0;
1139 }
See Pedestal.
Definition: object.h:121
int is_custom_attribute(const char *attribute)
void free_attribute(type_attribute *attr)
see doc/Developers/objects
Definition: object.h:108
const char * field_dir
Where the files about the fields will be stored.
See Key.
Definition: object.h:127
See Ring.
Definition: object.h:185
void copy_attributes(const type_definition *source, type_definition *type)
Definition: object.h:125
type_attribute * get_attribute_for_type(type_definition *type, const char *attribute, int clean)
Gets the attribute for the specified type.
void read_type(type_definition *type, FILE *file, const char *block_end)
Read all lines related to a type, stop when "block_end" is found on a line.
ignore_list * find_ignore_list(const char *name)
Eneq((at)csd.uu.se): Id for close_container archetype.
Definition: object.h:229
See Bracers.
Definition: object.h:217
void write_attribute_reference(const char *attribute, FILE *file)
Write the part to the right of a @ref for the specified attribute.
attribute_definition * get_attribute(const char *name)
Get an attribute, create it if it doesn&#39;t exist yet.
See Scroll.
Definition: object.h:221
See Cloak.
Definition: object.h:204
See Food.
Definition: object.h:112
See Projectile.
Definition: object.h:117
Update if you add new types.
Definition: object.h:250
See Holy Altar.
Definition: object.h:161
See Spellbook.
Definition: object.h:203
See Money.
Definition: object.h:137
See Rune.
Definition: object.h:240
See Creator.
Definition: object.h:142
See Weapon.
Definition: object.h:119
See Helmet.
Definition: object.h:136
type_attribute * duplicate_attribute(type_attribute *attr)
Object for applying character class modifications to someone.
Definition: object.h:138
See Altar Trigger.
Definition: object.h:133
See Rod.
Definition: object.h:109
See Power Crystal.
Definition: object.h:242
See Button Trigger.
Definition: object.h:132
See Drink.
Definition: object.h:157
See Girdle.
Definition: object.h:223
const flag_definition * find_flag(const char *name)
Return flag if exists, NULL else.
See Amulet.
Definition: object.h:139
Wall.
Definition: object.h:191
Duplicator/multiplier object.
Definition: object.h:202
type_definition * default_type
Definitions all types have by default.
animal &#39;body parts&#39; -b.t.
Definition: object.h:187
See Boots.
Definition: object.h:212
peterm: detector is an object which notices the presense of another object and is triggered like butt...
Definition: object.h:149
See Mover.
Definition: object.h:140
See Wand & Staff.
Definition: object.h:220
void read_ignore_list(const char *name, FILE *file)
Read the contents of a <ignore_list> tag.
void add_required_parameter(type_definition *type, const char *buf)
Add a required parameter to the specified type.
See Magic Ear.
Definition: object.h:131
Allows the use of a skill.
Definition: object.h:189
Generic item builder, see subtypes below.
Definition: object.h:246
See Trap.
Definition: object.h:241
const char * destination_dir
Root destination dir.
void write_type_index(void)
Write index of all types.
char * read_line(char *buffer, int size, FILE *file)
Floor tile -> native layer 0.
Definition: object.h:186
See Shooting Weapon.
Definition: object.h:118
See Sign & Magic Mouth.
Definition: object.h:211
See Book.
Definition: object.h:114
See Exit.
Definition: object.h:181
battleground, by Andreas Vogl
Definition: object.h:163
inserts an invisible, weightless force into a player with a specified string.
Definition: object.h:158
See Treasure.
Definition: object.h:110
int main(int argc, char **argv)
See Special Key.
Definition: object.h:124
A real, living creature.
Definition: object.h:200
inserts an invisible, weightless force into a player with a specified string WHEN TRIGGERED...
Definition: object.h:153
See Clock.
Definition: object.h:115
#define snprintf
Definition: win32.h:46
void write_attribute_file(attribute_definition *attribute)
Write the description of a field.
One object type.
type_attribute ** attributes
int attribute_count
type_definition ** types
Defined types.
int type_count
Definition: object.h:145
void write_type_file(type_definition *type)
Write a type definition file.
See Trapdoor.
Definition: object.h:210
ignore_list ** lists
See Potion.
Definition: object.h:111
See Shop Mat.
Definition: object.h:184
int list_count
See Spell.
Definition: object.h:214
static type_name type_names[]
See Handle Trigger.
Definition: object.h:129
See Locked Door.
Definition: object.h:123
See Spinner.
Definition: object.h:205
See Door.
Definition: object.h:126
static const char * in_living[]
Fields part of the living structure.
See Magic Wall.
Definition: object.h:168
Object owned by a player which can convert a monster into a peaceful being incapable of attack...
Definition: object.h:164
See Converter.
Definition: object.h:216
can add a skill to player&#39;s inventory -bt.
Definition: object.h:234
Lamp.
Definition: object.h:201
One type for an attribute.
See Container.
Definition: object.h:231
void ignore_attributes(type_definition *type, ignore_list *list)
Remove all attributes in the specified list from the type.
static const flag_definition flags[]
Flag mapping.
void ignore_attribute(type_definition *type, const char *attribute)
Remove an attribute from the type.
int sort_type_attribute(const void *a, const void *b)
To sort attributes.
See Player.
Definition: object.h:107
See Poison Food.
Definition: object.h:113
attribute_definition ** attributes
See Shield.
Definition: object.h:135
See Floor (Encounter).
Definition: object.h:182
Mark Wedel (mark@pyramid.com) Shop inventories.
Definition: object.h:238
See Altar.
Definition: object.h:122
Definition: object.h:243
Also see SKILL_TOOL (74) below.
Definition: object.h:143
See Shop Floor.
Definition: object.h:183
See Button.
Definition: object.h:207
See Gate.
Definition: object.h:206
misc.
Definition: object.h:193
void write_attribute_index(void)
Write the index of all attributes.
Material for building.
Definition: object.h:248
type_definition * get_type_definition(void)
Returns a new type_definition having the default attributes.
See Handle.
Definition: object.h:208
See Timed Gate.
Definition: object.h:128
void add_type_to_attribute(attribute_definition *attribute, type_definition *type, int attr)
type_definition * fallback_type
Dummy object type that non defined objects use.
void dump_types(void)
void dump_type(type_definition *type)
Lauwenmark: an invisible object holding a plugin event hook.
Definition: object.h:227
char * strdup(const char *str)
Portable implementation of strdup(3).
Definition: porting.c:200
See Monster (Grimreaper).
Definition: object.h:130
See Gloves.
Definition: object.h:213
A force, holding the effect of a resistance potion.
Definition: object.h:225
void dump_ignore_lists(void)
metals, minerals, dragon scales
Definition: object.h:188
static const char * custom_attributes[]
Custom attributes we know about, to point to the right page.
See Pit.
Definition: object.h:209
type_definition * find_type_definition(const char *name)
Used for type import.
const char * code_name
See Swamp.
Definition: object.h:236
One attribute in a type.
See Jewel.
Definition: object.h:167
See Breastplate Armor.
Definition: object.h:120
One list of fields to ignore.
Definition: object.h:148
See Disease.
Definition: object.h:244
attribute_type * get_description_for_attribute(attribute_definition *attribute, const char *description)
Gets a type description for specified attribute, create it if doesn&#39;t exist.
See Director.
Definition: object.h:222
See Teleporter.
Definition: object.h:141
const char * type_dir
Where the files about types will be stored.
b.t.
Definition: object.h:170
See Savebed.
Definition: object.h:219
b.t.
Definition: object.h:169
Core defines: object types, flags, etc.
Definition: object.h:224
void copy_default_attributes(type_definition *type)