Crossfire Server, Branches 1.12  R18729
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  { "can_use_rod", "FLAG_USE_ROD" },
170  { "can_use_horn", "FLAG_USE_HORN" },
171  { "make_invisible", "FLAG_MAKE_INVIS" },
172  { "inv_locked", "FLAG_INV_LOCKED" },
173  { "is_wooded", "FLAG_IS_WOODED" },
174  { "is_hilly", "FLAG_IS_HILLY" },
175  { "has_ready_skill", "FLAG_READY_SKILL" },
176  { "has_ready_weapon", "FLAG_READY_WEAPON" },
177  { "no_skill_ident", "FLAG_NO_SKILL_IDENT" },
178  { "is_blind", "FLAG_BLIND" },
179  { "can_see_in_dark", "FLAG_SEE_IN_DARK" },
180  { "is_cauldron", "FLAG_IS_CAULDRON" },
181  { "no_steal", "FLAG_NO_STEAL" },
182  { "one_hit", "FLAG_ONE_HIT" },
183  { "berserk", "FLAG_BERSERK" },
184  { "neutral", "FLAG_NEUTRAL" },
185  { "no_attack", "FLAG_NO_ATTACK" },
186  { "no_damage", "FLAG_NO_DAMAGE" },
187  { "activate_on_push", "FLAG_ACTIVATE_ON_PUSH" },
188  { "activate_on_release", "FLAG_ACTIVATE_ON_RELEASE" },
189  { "is_water", "FLAG_IS_WATER" },
190  { "use_content_on_gen", "FLAG_CONTENT_ON_GEN" },
191  { "is_buildable", "FLAG_IS_BUILDABLE" },
192  { "blessed", "FLAG_BLESSED" },
193  { "known_blessed", "FLAG_KNOWN_BLESSED" },
194  { NULL, NULL }
195 };
196 
198 const flag_definition *find_flag(const char *name) {
199  int flag;
200 
201  for (flag = 0; flags[flag].field; flag++)
202  if (!strcmp(flags[flag].field, name))
203  return &flags[flag];
204  return NULL;
205 }
206 
207 typedef struct {
208  const char *code_name;
209  int value;
210 } type_name;
211 
212 static type_name type_names[] = {
213  { "PLAYER", PLAYER },
214  { "TRANSPORT", TRANSPORT },
215  { "ROD", ROD },
216  { "TREASURE", TREASURE },
217  { "POTION", POTION },
218  { "FOOD", FOOD },
219  { "POISON", POISON },
220  { "BOOK", BOOK },
221  { "CLOCK", CLOCK },
222  { "ARROW", ARROW },
223  { "BOW", BOW },
224  { "WEAPON", WEAPON },
225  { "ARMOUR", ARMOUR },
226  { "PEDESTAL", PEDESTAL },
227  { "ALTAR", ALTAR },
228  { "LOCKED_DOOR", LOCKED_DOOR },
229  { "SPECIAL_KEY", SPECIAL_KEY },
230  { "MAP", MAP },
231  { "DOOR", DOOR },
232  { "KEY", KEY },
233  { "TIMED_GATE", TIMED_GATE },
234  { "TRIGGER", TRIGGER },
235  { "GRIMREAPER", GRIMREAPER },
236  { "MAGIC_EAR", MAGIC_EAR },
237  { "TRIGGER_BUTTON", TRIGGER_BUTTON },
238  { "TRIGGER_ALTAR", TRIGGER_ALTAR },
239  { "TRIGGER_PEDESTAL", TRIGGER_PEDESTAL },
240  { "SHIELD", SHIELD },
241  { "HELMET", HELMET },
242  { "HORN", HORN },
243  { "MONEY", MONEY },
244  { "CLASS", CLASS },
245  { "AMULET", AMULET },
246  { "PLAYERMOVER", PLAYERMOVER },
247  { "TELEPORTER", TELEPORTER },
248  { "CREATOR", CREATOR },
249  { "SKILL", SKILL },
250  { "EXPERIENCE", EXPERIENCE },
251  { "EARTHWALL", EARTHWALL },
252  { "GOLEM", GOLEM },
253  { "THROWN_OBJ", THROWN_OBJ },
254  { "BLINDNESS", BLINDNESS },
255  { "GOD", GOD },
256  { "DETECTOR", DETECTOR },
257  { "TRIGGER_MARKER", TRIGGER_MARKER },
258  { "DEAD_OBJECT", DEAD_OBJECT },
259  { "DRINK", DRINK },
260  { "MARKER", MARKER },
261  { "HOLY_ALTAR", HOLY_ALTAR },
262  { "PLAYER_CHANGER", PLAYER_CHANGER },
263  { "BATTLEGROUND", BATTLEGROUND },
264  { "PEACEMAKER", PEACEMAKER },
265  { "GEM", GEM },
266  { "FIREWALL", FIREWALL },
267  { "CHECK_INV", CHECK_INV },
268  { "MOOD_FLOOR", MOOD_FLOOR },
269  { "EXIT", EXIT },
270  { "ENCOUNTER", ENCOUNTER },
271  { "SHOP_FLOOR", SHOP_FLOOR },
272  { "SHOP_MAT", SHOP_MAT },
273  { "RING", RING },
274  { "FLOOR", FLOOR },
275  { "FLESH", FLESH },
276  { "INORGANIC", INORGANIC },
277  { "SKILL_TOOL", SKILL_TOOL },
278  { "LIGHTER", LIGHTER },
279  { "WALL", WALL },
280  { "MISC_OBJECT", MISC_OBJECT },
281  { "MONSTER", MONSTER },
282  { "LAMP", LAMP },
283  { "DUPLICATOR", DUPLICATOR },
284  { "SPELLBOOK", SPELLBOOK },
285  { "CLOAK", CLOAK },
286  { "SPINNER", SPINNER },
287  { "GATE", GATE },
288  { "BUTTON", BUTTON },
289  { "CF_HANDLE", CF_HANDLE },
290  { "HOLE", HOLE },
291  { "TRAPDOOR", TRAPDOOR },
292  { "SIGN", SIGN },
293  { "BOOTS", BOOTS },
294  { "GLOVES", GLOVES },
295  { "SPELL", SPELL },
296  { "SPELL_EFFECT", SPELL_EFFECT },
297  { "CONVERTER", CONVERTER },
298  { "BRACERS", BRACERS },
299  { "POISONING", POISONING },
300  { "SAVEBED", SAVEBED },
301  { "WAND", WAND },
302  { "SCROLL", SCROLL },
303  { "DIRECTOR", DIRECTOR },
304  { "GIRDLE", GIRDLE },
305  { "FORCE", FORCE },
306  { "POTION_EFFECT", POTION_EFFECT },
307  { "EVENT_CONNECTOR", EVENT_CONNECTOR },
308  { "CLOSE_CON", CLOSE_CON },
309  { "CONTAINER", CONTAINER },
310  { "ARMOUR_IMPROVER", ARMOUR_IMPROVER },
311  { "WEAPON_IMPROVER", WEAPON_IMPROVER },
312  { "SKILLSCROLL", SKILLSCROLL },
313  { "DEEP_SWAMP", DEEP_SWAMP },
314  { "IDENTIFY_ALTAR", IDENTIFY_ALTAR },
315  { "SHOP_INVENTORY", SHOP_INVENTORY },
316  { "RUNE", RUNE },
317  { "TRAP", TRAP },
318  { "POWER_CRYSTAL", POWER_CRYSTAL },
319  { "CORPSE", CORPSE },
320  { "DISEASE", DISEASE },
321  { "SYMPTOM", SYMPTOM },
322  { "BUILDER", BUILDER },
323  { "MATERIAL", MATERIAL },
324  { NULL, 0 }
325 };
326 
328  type_attribute *ret = calloc(1, sizeof(type_attribute));
329  ret->field = strdup(attr->field);
330  ret->name = strdup(attr->name);
331  ret->description = strdup(attr->description);
332  return ret;
333 }
334 
336  free(attr->field);
337  free(attr->name);
338  free(attr->description);
339  free(attr);
340 }
341 
346 type_attribute *get_attribute_for_type(type_definition *type, const char *attribute, int clean) {
347  type_attribute *ret;
348  int test;
349 
350  for (test = 0; test < type->attribute_count; test++) {
351  if (!strcmp(type->attributes[test]->field, attribute)) {
352  ret = type->attributes[test];
353  if (clean) {
354  free(ret->name);
355  ret->name = NULL;
356  free(ret->description);
357  ret->description = NULL;
358  }
359  return ret;
360  }
361  }
362  ret = calloc(1, sizeof(type_attribute));
363  ret->field = strdup(attribute);
364 
365  type->attribute_count++;
366  type->attributes = realloc(type->attributes, type->attribute_count*sizeof(type_attribute *));
367  type->attributes[type->attribute_count-1] = ret;
368 
369  return ret;
370 }
371 
372 void copy_attributes(const type_definition *source, type_definition *type) {
373  int attr;
374  type_attribute *add;
375 
376  assert(source);
377  if (source->attribute_count == 0)
378  return;
379 
380  for (attr = 0; attr < source->attribute_count; attr++) {
381  add = get_attribute_for_type(type, source->attributes[attr]->field, 1);
382  add->name = strdup(source->attributes[attr]->name);
383  if (source->attributes[attr]->description)
384  add->description = strdup(source->attributes[attr]->description);
385  }
386 }
387 
389  if (!default_type)
390  return;
391  copy_attributes(default_type, type);
392 }
393 
398  type_definition *ret = calloc(1, sizeof(type_definition));
399 
400  ret->attribute_count = 0;
401  ret->attributes = NULL;
402  assert(ret->description == NULL);
403 
404  if (default_type)
406 
407  return ret;
408 }
409 
414  int type;
415 
416  for (type = 0; type < type_count; type++) {
417  if (!strcmp(types[type]->name, name))
418  return types[type];
419  }
420  printf("type not found: %s\n", name);
421  return NULL;
422 }
423 
425 int sort_type_attribute(const void *a, const void *b) {
426  const type_attribute **la = (const type_attribute **)a;
427  const type_attribute **lb = (const type_attribute **)b;
428 
429  return strcmp((*la)->name, (*lb)->name);
430 }
431 
432 ignore_list *find_ignore_list(const char *name) {
433  int list;
434 
435  for (list = 0; list < list_count; list++) {
436  if (strcmp(lists[list]->name, name) == 0)
437  return lists[list];
438  }
439  return NULL;
440 }
441 
445 char *read_line(char *buffer, int size, FILE *file) {
446  return fgets(buffer, 200, file);
447 }
448 
450 void ignore_attribute(type_definition *type, const char *attribute) {
451  int find;
452 
453  for (find = 0; find < type->attribute_count; find++) {
454  if (!strcmp(attribute, type->attributes[find]->field)) {
455  /*printf("rem %s from %s\n", list->fields[attr], type->name);*/
456  free_attribute(type->attributes[find]);
457  if (find < type->attribute_count-1)
458  type->attributes[find] = type->attributes[type->attribute_count-1];
459  type->attribute_count--;
460  return;
461  }
462  }
463 }
464 
467  int attr;
468 
469  if (!list) {
470  printf("empty ignore list?\n");
471  return;
472  }
473 
474  for (attr = 0; attr < list->count; attr++) {
475  ignore_attribute(type, list->fields[attr]);
476  }
477 }
478 
480 void add_required_parameter(type_definition *type, const char *buf) {
481  char *sn, *en, *sv, *ev;
482  char value[200], name[200], temp[200];
483  const flag_definition *flag;
484 
485  if (type == fallback_type)
486  /* the "Misc" type has dummy requirements, don't take that into account. */
487  return;
488 
489  sn = strstr(buf, "arch");
490  if (!sn)
491  return;
492  sn = strchr(sn, '"');
493  en = strchr(sn+1, '"');
494  sv = strstr(buf, "value");
495  sv = strchr(sv, '"');
496  ev = strchr(sv+1, '"');
497 
498  name[en-sn-1] = '\0';
499  strncpy(name, sn+1, en-sn-1);
500  value[ev-sv-1] = '\0';
501  strncpy(value, sv+1, ev-sv-1);
502 
503  type->require_count++;
504  type->required = realloc(type->required, type->require_count*sizeof(char *));
505 
506  flag = find_flag(name);
507  if (flag)
508  snprintf(temp, 200, "@ref %s %s", flag->code_name, strcmp(value, "0") ? "set" : "unset");
509  else
510  snprintf(temp, 200, "@ref object::%s = %s", name, value);
511  type->required[type->require_count-1] = strdup(temp);
512 }
513 
515 void read_type(type_definition *type, FILE *file, const char *block_end) {
516  char buf[200], tmp[200];
517  char *find, *end;
518  type_attribute *attr;
519 
520  while (read_line(buf, 200, file)) {
521  if (strstr(buf, block_end) != NULL) {
522  if (type->attribute_count)
523  qsort(type->attributes, type->attribute_count, sizeof(type_attribute *), sort_type_attribute);
524  return;
525  }
526  if (strstr(buf, "<description>") != NULL) {
527  while (read_line(buf, 200, file)) {
528  if (strstr(buf, "</description>") != NULL)
529  break;
530 
531  if (type->description) {
532  type->description = realloc(type->description, strlen(type->description)+strlen(buf)+1);
533  strcat(type->description, buf);
534  }
535  else
536  type->description = strdup(buf);
537  }
538  find = strstr(type->description, "]]>");
539  if (find)
540  type->description[find-type->description] = '\0';
541  while (type->description[strlen(type->description)-1] == '\n')
542  type->description[strlen(type->description)-1] = '\0';
543  /*printf(" => desc = %s\n", type->description);*/
544  }
545 
546  if (strstr(buf, "<ignore_list") != NULL) {
547  find = strstr(buf, "name=");
548  if (!find)
549  return;
550  find = strchr(find+1, '"');
551  if (!find)
552  return;
553  end = strchr(find+1, '"');
554  if (!end)
555  return;
556  tmp[end-find-1] = '\0';
557  strncpy(tmp, find+1, end-find-1);
559  }
560 
561  if (strstr(buf, "<ignore>") != NULL) {
562  while (read_line(buf, 200, file)) {
563  if (strstr(buf, "</ignore>") != NULL)
564  break;
565  find = strstr(buf, "arch=");
566  if (!find)
567  continue;
568  find = strchr(find+1, '"');
569  if (!find)
570  continue;
571  end = strchr(find+1, '"');
572  if (!end)
573  continue;
574  tmp[end-find-1] = '\0';
575  strncpy(tmp, find+1, end-find-1);
576  ignore_attribute(type, tmp);
577  }
578  }
579 
580  if (strstr(buf, "<required>") != NULL) {
581  while (read_line(buf, 200, file)) {
582  if (strstr(buf, "</required>") != NULL)
583  break;
584  add_required_parameter(type, buf);
585  }
586  }
587 
588  if (strstr(buf, "<import_type") != NULL) {
589  type_definition *import;
590 
591  find = strstr(buf, "name=");
592  if (!find)
593  return;
594  find = strchr(find+1, '"');
595  if (!find)
596  return;
597  end = strchr(find+1, '"');
598  if (!end)
599  return;
600  tmp[end-find-1] = '\0';
601  strncpy(tmp, find+1, end-find-1);
602  import = find_type_definition(tmp);
603  if (import) {
604  /*printf("%s import %s\n", type->name, tmp);*/
605  copy_attributes(import, type);
606  }
607  else
608  printf("%s: import %s not found\n", type->name, tmp);
609  }
610 
611  if (strstr(buf, "<attribute") != NULL) {
612  if (strstr(buf, "/>") != NULL)
613  continue;
614  find = strstr(buf, "arch");
615  if (!find)
616  continue;
617  find = strchr(find, '"');
618  end = strchr(find+1, '"');
619  if (end == find+1)
620  /* empty arch, meaning inventory or such, ignore. */
621  continue;
622 
623  tmp[end-find-1] = '\0';
624  strncpy(tmp, find+1, end-find-1);
625  /*printf(" => attr %s\n", tmp);*/
626 
627  attr = get_attribute_for_type(type, tmp, 1);
628 
629  find = strstr(buf, "editor");
630  find = strchr(find, '"');
631  end = strchr(find+1, '"');
632  tmp[end-find-1] = '\0';
633  strncpy(tmp, find+1, end-find-1);
634  attr->name = strdup(tmp);
635 
636  while (read_line(buf, 200, file)) {
637  if (strstr(buf, "</attribute>") != NULL)
638  break;
639  if (attr->description) {
640  attr->description = realloc(attr->description, strlen(attr->description)+strlen(buf)+1);
641  strcat(attr->description, buf);
642  }
643  else
644  attr->description = strdup(buf);
645  }
646  if (attr->description)
647  while (attr->description[strlen(attr->description)-1] == '\n')
648  attr->description[strlen(attr->description)-1] = '\0';
649 
650  }
651  }
652 }
653 
655  int attr;
656 
657  printf("type: %s [%d]\n", type->name, type->number);
658  printf(" attributes:\n");
659  for (attr = 0; attr < type->attribute_count; attr++) {
660  printf(" %30s: %s\n", type->attributes[attr]->field, type->attributes[attr]->name);
661  printf(" %s\n", type->attributes[attr]->description);
662  }
663 }
664 
665 void dump_types(void) {
666  int t;
667  type_definition *type;
668 
669  for (t = 0; t < type_count; t++) {
670  type = types[t];
671  dump_type(type);
672  }
673 }
674 
677  int attr;
679 
680  for (attr = 0; attr < attribute_count; attr++) {
681  if (!strcmp(attributes[attr]->field, name))
682  return attributes[attr];
683  }
684 
685  ret = calloc(1, sizeof(attribute_definition));
686  attribute_count++;
687  attributes = realloc(attributes, attribute_count*sizeof(attribute_definition *));
688  attributes[attribute_count-1] = ret;
689 
690  ret->field = strdup(name);
691 
692  return ret;
693 }
694 
697  int desc;
698  attribute_type *add;
699 
700  for (desc = 0; desc < attribute->type_count; desc++) {
701  if (!description && !attribute->types[desc]->description)
702  return attribute->types[desc];
703  if (description && attribute->types[desc]->description && !strcmp(description, attribute->types[desc]->description))
704  return attribute->types[desc];
705  }
706 
707  add = calloc(1, sizeof(attribute_type));
708  attribute->type_count++;
709  attribute->types = realloc(attribute->types, attribute->type_count*sizeof(attribute_type));
710  attribute->types[attribute->type_count-1] = add;
711 
712  if (description)
713  add->description = strdup(description);
714 
715  return add;
716 }
717 
718 void add_type_to_attribute(attribute_definition *attribute, type_definition *type, int attr) {
719  attribute_type *att;
720 
721  att = get_description_for_attribute(attribute, type->attributes[attr]->description);
722  att->count++;
723  att->type = realloc(att->type, att->count*sizeof(const char *));
724  att->number = realloc(att->number, att->count*sizeof(int));
725  att->type[att->count-1] = strdup(type->name);
726  att->number[att->count-1] = type->number;
727 }
728 
730 void read_ignore_list(const char *name, FILE *file) {
731  char buf[200], tmp[200];
732  char *start, *end;
733  ignore_list *list;
734 
735  /*printf("il %s:", name);*/
736  list = calloc(1, sizeof(ignore_list));
737  list_count++;
738  lists = realloc(lists, list_count*sizeof(ignore_list *));
739  lists[list_count-1] = list;
740  list->name = strdup(name);
741 
742  while (read_line(buf, 200, file)) {
743  if (strstr(buf, "</ignore_list>") != NULL) {
744  /*printf("\n");*/
745  return;
746  }
747  start = strstr(buf, "arch=");
748  if (!start)
749  continue;
750  start = strchr(start+1, '"');
751  if (!start)
752  continue;
753  end = strchr(start+1, '"');
754  if (!end)
755  continue;
756 
757  tmp[end-start-1] = '\0';
758  strncpy(tmp, start+1, end-start-1);
759  /*printf(" %s", tmp);*/
760 
761  list->count++;
762  list->fields = realloc(list->fields, list->count*sizeof(char *));
763  list->fields[list->count-1] = strdup(tmp);
764  }
765 }
766 
767 void dump_ignore_lists(void) {
768  int list, field;
769 
770  printf("ignore lists:\n");
771  for (list = 0; list < list_count; list++) {
772  printf(" %s:", lists[list]->name);
773  for (field = 0; field < lists[list]->count; field++)
774  printf(" %s", lists[list]->fields[field]);
775  printf("\n");
776  }
777 }
778 
780 static const char *in_living[] = {
781  "Str",
782  "Dex",
783  "Con",
784  "Wis",
785  "Cha",
786  "Int",
787  "Pow",
788  "wc",
789  "ac",
790  "hp",
791  "maxhp",
792  "sp",
793  "maxsp",
794  "grace",
795  "maxgrace",
796  "exp",
797  "food",
798  "dam",
799  "luck",
800  NULL
801 };
802 
804 static const char *custom_attributes[] = {
805  /* transports */
806  "weight_speed_ratio",
807  "base_speed",
808  "passenger_limit",
809  "face_full",
810  "anim_full",
811  NULL
812 };
813 
814 int is_custom_attribute(const char *attribute) {
815  int val;
816 
817  for (val = 0; custom_attributes[val] != NULL; val++) {
818  if (!strcmp(custom_attributes[val], attribute)) {
819  return 1;
820  }
821  }
822  return 0;
823 }
824 
826 void write_attribute_reference(const char *attribute, FILE *file) {
827  const flag_definition *flag = find_flag(attribute);
828  int val;
829 
830  if (flag) {
831  fprintf(file, "%s", flag->code_name);
832  return;
833  }
834  for (val = 0; in_living[val] != NULL; val++) {
835  if (!strcmp(in_living[val], attribute)) {
836  fprintf(file, "liv::%s", attribute);
837  return;
838  }
839  }
840  if (is_custom_attribute(attribute)) {
841  fprintf(file, "page_custom_attributes \"%s\"", attribute);
842  return;
843  }
844  if (strstr(attribute, "resist_")) {
845  fprintf(file, "obj::resist");
846  return;
847  }
848  if (!strcmp(attribute, "connected")) {
849  fprintf(file, "page_connected \"connection value\"");
850  return;
851  }
852  fprintf(file, "obj::%s", attribute);
853 }
854 
857  FILE *file;
858  char buf[200];
859  int attr, req;
860 
861  snprintf(buf, 200, "%s/%s/type_%d.dox", destination_dir, type_dir, type->number);
862  file = fopen(buf, "w+");
863 
864  fprintf(file, "/**\n");
865 
866  /* auto-generate documentation for the type, so no need to change define.h */
867  if (type->number > 0) {
868  for (req = 0; type_names[req].code_name != NULL; req++) {
869  if (type_names[req].value == type->number) {
870  fprintf(file, "@var %s\nSee @ref page_type_%d\n*/\n\n/**\n", type_names[req].qcode_name, type->number);
871  break;
872  }
873  }
874  }
875 
876  fprintf(file, "@page page_type_%d %s\n\n", type->number, type->name);
877  fprintf(file, "\n@section Description\n");
878  fprintf(file, "%s\n\n", type->description);
879  if (type != fallback_type) {
880  fprintf(file, "\n\nType defined by:\n");
881  if (type->number && type->number < OBJECT_TYPE_MAX)
882  fprintf(file, "- @ref object::type = %d\n", type->number);
883  for (req = 0; req < type->require_count; req++)
884  fprintf(file, "- %s\n", type->required[req]);
885  }
886 
887  fprintf(file, "\n\n@section Attributes\n\n");
888  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");
889  for (attr = 0; attr < type->attribute_count; attr++) {
890  fprintf(file, "\t<tr>\n\t\t<td>%s</td>\n\t\t<td>@ref ", type->attributes[attr]->name);
891  write_attribute_reference(type->attributes[attr]->field, file);
892  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)");
893  }
894 
895  fprintf(file, "</table>\n*/\n");
896 
897  fclose(file);
898 }
899 
901 void write_type_index(void) {
902  FILE *index;
903  int type;
904  char buf[200];
905 
906  snprintf(buf, 200, "%s/%s/types.dox", destination_dir, type_dir);
907  index = fopen(buf, "w+");
908  fprintf(index, "/**\n@page type_index Type index\n");
909 
910  fprintf(index, "Types not listed here have the attributes defined in @ref page_type_0 \"this page\".\n\n");
911 
912  for (type = 0; type < type_count; type++) {
913  fprintf(index, "-@ref page_type_%d \"%s\"\n", types[type]->number, types[type]->name);
914  }
915 
916  fprintf(index, "*/\n");
917 
918  fclose(index);
919 }
920 
923  FILE *file;
924  char buf[200];
925  int type, desc;
926  const char *end;
927 
928  snprintf(buf, 200, "%s/%s/field_%s.dox", destination_dir, field_dir, attribute->field);
929  file = fopen(buf, "w+");
930 
931  fprintf(file, "/**\n@fn ");
932  write_attribute_reference(attribute->field, file);
933 
934  /* resistances are special, they'll be merged in the obj::resist paragraph, so specify the name. */
935  if (strstr(attribute->field, "resist_"))
936  fprintf(file, "\n@section %s %s resistance\n", attribute->field, attribute->field+7);
937  else
938  fprintf(file, "\n@section Use\n");
939 
940  fprintf(file, "<table>\n\t<tr>\n\t\t<th>Type(s)</th>\n\t\t<th>Description</th>\n\t</tr>");
941 
942  for (desc = 0; desc < attribute->type_count; desc++) {
943  assert(attribute->types[desc]->count > 0);
944 
945  fprintf(file, "\t<tr>\n\t\t<td>\n");
946 
947  for (type = 0; type < attribute->types[desc]->count; type++) {
948  if (type < attribute->types[desc]->count-1)
949  end = ", ";
950  else
951  end = "\n";
952  fprintf(file, "@ref page_type_%d%s", attribute->types[desc]->number[type], end);
953  }
954  fprintf(file, "\t\t</td><td>%s</td>\n\t</tr>\n", attribute->types[desc]->description ? attribute->types[desc]->description : "(no description)");
955  }
956 
957  fprintf(file, "\n*/\n");
958 
959  fclose(file);
960 }
961 
962 int main(int argc, char **argv) {
963  FILE *xml;
964  int number, attr, dummy;
965  char buf[200], tmp[200];
966  char *start, *end;
967  type_definition *type;
968 
969  if (argc < 2) {
970  printf("Syntax: %s /path/to/Gridarta/types.xml\n", argv[0]);
971  return 1;
972  }
973 
974  /* dummy type number for special types. */
975  dummy = OBJECT_TYPE_MAX+50;
976 
977  xml = fopen(argv[1], "r");
978  while (read_line(buf, 200, xml) != NULL) {
979  if (buf[0] == '#')
980  continue;
981  if (strstr(buf, "<default_type>")) {
982  default_type = get_type_definition();
983  default_type->name = strdup("(default type)");
984  read_type(default_type, xml, "</default_type>");
985  continue;
986  }
987 
988  if (strstr(buf, "<ignore_list") != NULL) {
989  start = strstr(buf, "name=");
990  start = strchr(start+1, '"');
991  end = strchr(start+1, '"');
992  tmp[end-start-1] = '\0';
993  strncpy(tmp, start+1, end-start-1);
994  read_ignore_list(tmp, xml);
995  continue;
996  }
997 
998  start = strstr(buf, "<type number");
999  if (start) {
1000  start = strchr(start, '"');
1001  /*if (!start)
1002  break;*/
1003  end = strchr(start+1, '"');
1004  /*if (!end)
1005  break;*/
1006  tmp[end-start-1] = '\0';
1007  strncpy(tmp, start+1, end-start-1);
1008  /*printf("type %s ", tmp);*/
1009 
1010  number = atoi(tmp);
1011  start = strstr(end, "name=");
1012  start = strchr(start, '"');
1013  end = strchr(start+1, '"');
1014  tmp[end-start-1] = '\0';
1015  strncpy(tmp, start+1, end-start-1);
1016 
1017  if (!strcmp(tmp, "Misc")) {
1018  fallback_type = get_type_definition();
1019  type = fallback_type;
1020  }
1021  else {
1022  if (number == 0)
1023  number = dummy++;
1024  type = get_type_definition();
1025  type_count++;
1026  types = realloc(types, type_count*sizeof(type_definition *));
1027  types[type_count-1] = type;
1028  }
1029 
1030 #if 0
1031  if (!number || number >= OBJECT_TYPE_MAX || types[number] != NULL) {
1032  /*printf("=> skip\n");*/
1033  while (read_line(buf, 200, xml) != NULL && strstr(buf, "</type>") == NULL)
1034  /*printf(" => skip %s\n", buf)*/;
1035  /*printf(" => end of skip\n");*/
1036  continue;
1037  }
1038 #endif
1039 
1040  type->number = number;
1041 
1042  /*printf("nom %s\n", tmp);*/
1043  type->name = strdup(tmp);
1044 
1045  read_type(type, xml, "</type>");
1046  }
1047  }
1048 
1049  if (fallback_type->description)
1050  free(fallback_type->description);
1051  fallback_type->description = strdup("This type regroups all types who don't have a specific definition.");
1052 
1053  for (number = 0; number < type_count; number++) {
1054  for (attr = 0; attr < types[number]->attribute_count; attr++)
1055  add_type_to_attribute(get_attribute(types[number]->attributes[attr]->field), types[number], attr);
1056  }
1057 
1058 /* dump_types();*/
1059 /* dump_type(default_type);*/
1060 /* dump_ignore_lists();*/
1061 
1062  write_type_index();
1063  for (number = 0; number < type_count; number++)
1064  write_type_file(types[number]);
1065  write_type_file(fallback_type);
1066 
1067  for (attr = 0; attr < attribute_count; attr++)
1068  if (!is_custom_attribute(attributes[attr]->field))
1069  write_attribute_file(attributes[attr]);
1070 
1071  fclose(xml);
1072  free(types);
1073  return 0;
1074 }
#define SKILLSCROLL
Definition: define.h:313
int is_custom_attribute(const char *attribute)
#define FOOD
Definition: define.h:118
void free_attribute(type_attribute *attr)
#define RING
Definition: define.h:232
#define DISEASE
Definition: define.h:331
#define CHECK_INV
Definition: define.h:206
#define BUTTON
Definition: define.h:274
#define DEAD_OBJECT
Definition: define.h:186
#define TRAPDOOR
Definition: define.h:277
const char * field_dir
#define TELEPORTER
Definition: define.h:155
void copy_attributes(const type_definition *source, type_definition *type)
type_attribute * get_attribute_for_type(type_definition *type, const char *attribute, int clean)
void read_type(type_definition *type, FILE *file, const char *block_end)
ignore_list * find_ignore_list(const char *name)
#define EARTHWALL
Definition: define.h:167
#define CLOSE_CON
Definition: define.h:303
void write_attribute_reference(const char *attribute, FILE *file)
attribute_definition * get_attribute(const char *name)
#define ENCOUNTER
Definition: define.h:229
#define TRAP
Definition: define.h:326
#define WAND
Definition: define.h:291
#define MISC_OBJECT
Definition: define.h:248
#define CORPSE
Definition: define.h:329
#define MONEY
Definition: define.h:148
#define LIGHTER
Definition: define.h:237
#define DOOR
Definition: define.h:135
#define MAP
Definition: define.h:134
#define POTION
Definition: define.h:117
type_attribute * duplicate_attribute(type_attribute *attr)
#define SCROLL
Definition: define.h:293
#define EXPERIENCE
Definition: define.h:158
#define RUNE
Definition: define.h:325
#define BOOTS
Definition: define.h:281
#define GOLEM
Definition: define.h:168
const flag_definition * find_flag(const char *name)
#define CLOAK
Definition: define.h:268
#define GIRDLE
Definition: define.h:295
type_definition * default_type
#define PEACEMAKER
Definition: define.h:197
#define OBJECT_TYPE_MAX
Definition: define.h:339
#define ARMOUR
Definition: define.h:128
void read_ignore_list(const char *name, FILE *file)
#define PLAYER
Definition: define.h:113
#define POTION_EFFECT
Definition: define.h:297
#define MAGIC_EAR
Definition: define.h:141
void add_required_parameter(type_definition *type, const char *buf)
#define SPECIAL_KEY
Definition: define.h:133
#define POISONING
Definition: define.h:287
#define AMULET
Definition: define.h:153
#define SPINNER
Definition: define.h:272
const char * destination_dir
void write_type_index(void)
char * read_line(char *buffer, int size, FILE *file)
#define POISON
Definition: define.h:119
#define SHOP_FLOOR
Definition: define.h:230
#define SYMPTOM
Definition: define.h:332
#define CREATOR
Definition: define.h:156
#define TRANSPORT
Definition: define.h:114
#define WEAPON_IMPROVER
Definition: define.h:308
int main(int argc, char **argv)
#define WALL
Definition: define.h:244
#define KEY
Definition: define.h:136
void write_attribute_file(attribute_definition *attribute)
#define HORN
Definition: define.h:147
type_attribute ** attributes
#define MOOD_FLOOR
Definition: define.h:207
int attribute_count
type_definition ** types
#define GRIMREAPER
Definition: define.h:140
int type_count
#define SPELL
Definition: define.h:283
#define FLESH
Definition: define.h:234
#define PEDESTAL
Definition: define.h:129
#define DEEP_SWAMP
Definition: define.h:316
#define BATTLEGROUND
Definition: define.h:195
void write_type_file(type_definition *type)
#define BLINDNESS
Definition: define.h:171
ignore_list ** lists
#define GOD
Definition: define.h:172
#define LOCKED_DOOR
Definition: define.h:132
#define SHOP_MAT
Definition: define.h:231
#define WEAPON
Definition: define.h:127
#define MARKER
Definition: define.h:188
#define TRIGGER_MARKER
Definition: define.h:181
#define TRIGGER_PEDESTAL
Definition: define.h:144
int list_count
static type_name type_names[]
#define TRIGGER
Definition: define.h:139
#define TRIGGER_BUTTON
Definition: define.h:142
#define GEM
Definition: define.h:202
#define EXIT
Definition: define.h:228
#define GLOVES
Definition: define.h:282
static const char * in_living[]
#define BUILDER
Definition: define.h:334
#define BOOK
Definition: define.h:120
#define BRACERS
Definition: define.h:286
#define DUPLICATOR
Definition: define.h:264
#define SIGN
Definition: define.h:280
#define SHOP_INVENTORY
Definition: define.h:319
#define CLASS
Definition: define.h:149
#define LAMP
Definition: define.h:263
void ignore_attributes(type_definition *type, ignore_list *list)
static const flag_definition flags[]
void ignore_attribute(type_definition *type, const char *attribute)
#define TIMED_GATE
Definition: define.h:138
#define THROWN_OBJ
Definition: define.h:170
#define FLOOR
Definition: define.h:233
int sort_type_attribute(const void *a, const void *b)
#define TRIGGER_ALTAR
Definition: define.h:143
#define SHIELD
Definition: define.h:145
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
attribute_definition ** attributes
#define FORCE
Definition: define.h:296
#define SAVEBED
Definition: define.h:288
#define INORGANIC
Definition: define.h:235
#define ALTAR
Definition: define.h:130
#define CONTAINER
Definition: define.h:306
#define FIREWALL
Definition: define.h:204
#define DETECTOR
Definition: define.h:174
#define PLAYERMOVER
Definition: define.h:154
#define SKILL
Definition: define.h:157
#define CF_HANDLE
Definition: define.h:275
#define ARMOUR_IMPROVER
Definition: define.h:307
type_definition * get_type_definition(void)
#define CLOCK
Definition: define.h:121
#define SPELL_EFFECT
Definition: define.h:284
void add_type_to_attribute(attribute_definition *attribute, type_definition *type, int attr)
type_definition * fallback_type
void dump_types(void)
void dump_type(type_definition *type)
#define MONSTER
Definition: define.h:261
#define BOW
Definition: define.h:126
#define EVENT_CONNECTOR
Definition: define.h:300
#define DRINK
Definition: define.h:187
#define TREASURE
Definition: define.h:116
#define HELMET
Definition: define.h:146
#define SPELLBOOK
Definition: define.h:266
#define DIRECTOR
Definition: define.h:294
#define ARROW
Definition: define.h:125
void dump_ignore_lists(void)
#define ROD
Definition: define.h:115
#define IDENTIFY_ALTAR
Definition: define.h:317
#define HOLE
Definition: define.h:276
#define SKILL_TOOL
Definition: define.h:236
static const char * custom_attributes[]
type_definition * find_type_definition(const char *name)
const char * code_name
#define HOLY_ALTAR
Definition: define.h:193
#define MATERIAL
Definition: define.h:337
#define GATE
Definition: define.h:273
attribute_type * get_description_for_attribute(attribute_definition *attribute, const char *description)
#define PLAYER_CHANGER
Definition: define.h:194
#define CONVERTER
Definition: define.h:285
const char * type_dir
#define POWER_CRYSTAL
Definition: define.h:328
void copy_default_attributes(type_definition *type)