Crossfire Server, Trunk  R21017
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 }
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)