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