From 0b5a470a3894b1cbaaf3970e4416bd35371493d0 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 24 Dec 2011 14:37:00 +0400 Subject: [PATCH 1/8] Add header generation from xml. --- library/CMakeLists.txt | 23 + library/xml/codegen.pl | 905 +++++++++++++++ library/xml/df.building-raws.xml | 58 + library/xml/df.buildings.xml | 403 +++++++ library/xml/df.creature-raws.xml | 592 ++++++++++ library/xml/df.d_init.xml | 129 +++ library/xml/df.history.xml | 120 ++ library/xml/df.init.xml | 138 +++ library/xml/df.item-raws.xml | 303 +++++ library/xml/df.items.xml | 578 ++++++++++ library/xml/df.job-enums.xml | 1785 ++++++++++++++++++++++++++++++ library/xml/df.jobs.xml | 265 +++++ library/xml/df.language.xml | 108 ++ library/xml/df.legends.xml | 317 ++++++ library/xml/df.machines.xml | 97 ++ library/xml/df.map.xml | 247 +++++ library/xml/df.materials.xml | 341 ++++++ library/xml/df.military.xml | 238 ++++ library/xml/df.projectile.xml | 62 ++ library/xml/df.raws.xml | 237 ++++ library/xml/df.refs.xml | 109 ++ library/xml/df.stockpile.xml | 254 +++++ library/xml/df.ui.xml | 604 ++++++++++ library/xml/df.units.xml | 703 ++++++++++++ library/xml/df.viewscreen.xml | 88 ++ library/xml/df.world-data.xml | 374 +++++++ library/xml/df.world.xml | 503 +++++++++ library/xml/list.pl | 33 + 28 files changed, 9614 insertions(+) create mode 100755 library/xml/codegen.pl create mode 100644 library/xml/df.building-raws.xml create mode 100644 library/xml/df.buildings.xml create mode 100644 library/xml/df.creature-raws.xml create mode 100644 library/xml/df.d_init.xml create mode 100644 library/xml/df.history.xml create mode 100644 library/xml/df.init.xml create mode 100644 library/xml/df.item-raws.xml create mode 100644 library/xml/df.items.xml create mode 100644 library/xml/df.job-enums.xml create mode 100644 library/xml/df.jobs.xml create mode 100644 library/xml/df.language.xml create mode 100644 library/xml/df.legends.xml create mode 100644 library/xml/df.machines.xml create mode 100644 library/xml/df.map.xml create mode 100644 library/xml/df.materials.xml create mode 100644 library/xml/df.military.xml create mode 100644 library/xml/df.projectile.xml create mode 100644 library/xml/df.raws.xml create mode 100644 library/xml/df.refs.xml create mode 100644 library/xml/df.stockpile.xml create mode 100644 library/xml/df.ui.xml create mode 100644 library/xml/df.units.xml create mode 100644 library/xml/df.viewscreen.xml create mode 100644 library/xml/df.world-data.xml create mode 100644 library/xml/df.world.xml create mode 100755 library/xml/list.pl diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 195ffa6e1..7e24f3659 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -15,6 +15,10 @@ include_directories (depends/tinyxml) include_directories (depends/tthread) include_directories (private) +execute_process(COMMAND perl xml/list.pl xml include/dfhack/df ";" + WORKING_DIRECTORY ${dfapi_SOURCE_DIR} + OUTPUT_VARIABLE GENERATED_HDRS) + SET(PROJECT_HDRS_INTERNAL private/ContextShared.h private/Internal.h @@ -123,6 +127,24 @@ SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE ) LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS}) +# Generation + +SET_SOURCE_FILES_PROPERTIES(${GENERATED_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE GENERATED TRUE) + +FILE(GLOB GENERATE_INPUT_XMLS ${dfapi_SOURCE_DIR}/xml/*.xml) + +ADD_CUSTOM_COMMAND( + OUTPUT ${dfapi_SOURCE_DIR}/include/dfhack/df/static.inc + COMMAND perl xml/codegen.pl xml include/dfhack/df + WORKING_DIRECTORY ${dfapi_SOURCE_DIR} + MAIN_DEPENDENCY ${dfapi_SOURCE_DIR}/xml/codegen.pl + DEPENDS ${GENERATE_INPUT_XMLS} +) + +ADD_CUSTOM_TARGET(generate_headers DEPENDS ${dfapi_SOURCE_DIR}/include/dfhack/df/static.inc) + +# Compilation + ADD_DEFINITIONS(-DBUILD_DFHACK_LIB) IF(UNIX) @@ -142,6 +164,7 @@ ELSE(WIN32) ENDIF() ADD_LIBRARY(dfhack SHARED ${PROJECT_SRCS}) +ADD_DEPENDENCIES(dfhack generate_headers) IF(WIN32) SET_TARGET_PROPERTIES(dfhack PROPERTIES OUTPUT_NAME "SDL" ) diff --git a/library/xml/codegen.pl b/library/xml/codegen.pl new file mode 100755 index 000000000..33210f616 --- /dev/null +++ b/library/xml/codegen.pl @@ -0,0 +1,905 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use XML::LibXML; + +my $input_dir = $ARGV[0] || '.'; +my $output_dir = $ARGV[1] || 'codegen'; +my $main_namespace = $ARGV[2] || 'df'; +my $export_prefix = 'DFHACK_EXPORT '; + +my %types; +my %type_files; + +# Misc XML analysis + +our $typename; +our $filename; + +sub parse_address($;$) { + my ($str,$in_bits) = @_; + return undef unless defined $str; + + # Parse the format used by offset attributes in xml + $str =~ /^0x([0-9a-f]+)(?:\.([0-7]))?$/ + or die "Invalid address syntax: $str\n"; + my ($full, $bv) = ($1, $2); + die "Bits not allowed: $str\n" unless $in_bits; + return $in_bits ? (hex($full)*8 + ($bv||0)) : hex($full); +} + +sub check_bad_attrs($;$$) { + my ($tag, $allow_size, $allow_align) = @_; + + die "Cannot use size, alignment or offset for ".$tag->nodeName."\n" + if ((!$allow_size && defined $tag->getAttribute('size')) || + defined $tag->getAttribute('offset') || + (!$allow_align && defined $tag->getAttribute('alignment'))); +} + +sub check_name($) { + my ($name) = @_; + $name =~ /^[_a-zA-Z][_a-zA-Z0-9]*$/ + or die "Invalid identifier: $name\n"; + return $name; +} + +sub is_attr_true($$) { + my ($tag, $name) = @_; + return ($tag->getAttribute($name)||'') eq 'true'; +} + +sub type_header_def($) { + my ($name) = @_; + return uc($main_namespace).'_'.uc($name).'_H'; +} + +# Text generation with indentation + +our @lines; +our $indentation = 0; + +sub with_emit(&;$) { + # Executes the code block, and returns emitted lines + my ($blk, $start_indent) = @_; + local @lines; + local $indentation = ($start_indent||0); + $blk->(); + return @lines; +} + +sub emit(@) { + # Emit an indented line to be returned from with_emit + my $line = join('',map { defined($_) ? $_ : '' } @_); + $line = (' 'x$indentation).$line unless length($line) == 0; + push @lines, $line; +} + +sub indent(&) { + # Indent lines emitted from the block by one step + my ($blk) = @_; + local $indentation = $indentation+2; + $blk->(); +} + +sub outdent(&) { + # Unindent lines emitted from the block by one step + my ($blk) = @_; + local $indentation = ($indentation >= 2 ? $indentation-2 : 0); + $blk->(); +} + +sub emit_block(&;$$) { + # Emit a full {...} block with indentation + my ($blk, $prefix, $suffix) = @_; + $prefix ||= ''; + $suffix ||= ''; + emit $prefix,'{'; + &indent($blk); + emit '}',$suffix; +} + +# Static file output + +my @static_lines; +my %static_includes; + +sub with_emit_static(&) { + my ($blk) = @_; + $static_includes{$typename}++; + push @static_lines, &with_emit($blk,2); +} + +# Anonymous variable names + +our $anon_id = 0; +our $anon_prefix; + +sub ensure_name($) { + # If the name is empty, assign an auto-generated one + my ($name) = @_; + unless ($name) { + $name = $anon_prefix.(($anon_id == 0) ? '' : '_'.$anon_id); + $anon_id++; + } + return check_name($name); +} + +sub with_anon(&;$) { + # Establish a new anonymous namespace + my ($blk,$stem) = @_; + local $anon_id = $stem ? 0 : 1; + local $anon_prefix = ($stem||'anon'); + $blk->(); +} + +# Primitive types + +my @primitive_type_list = + qw(int8_t uint8_t int16_t uint16_t + int32_t uint32_t int64_t uint64_t + s-float + bool ptr-string stl-string flag-bit + pointer); + +my %primitive_aliases = ( + 'stl-string' => 'std::string', + 'ptr-string' => 'char*', + 'flag-bit' => 'void', + 'pointer' => 'void*', + 's-float' => 'float', +); + +my %primitive_types; +$primitive_types{$_}++ for @primitive_type_list; + +sub primitive_type_name($) { + my ($tag_name) = @_; + $primitive_types{$tag_name} + or die "Not primitive: $tag_name\n"; + return $primitive_aliases{$tag_name} || $tag_name; +} + +# Type references + +our %weak_refs; +our %strong_refs; + +sub register_ref($;$) { + # Register a reference to another type. + # Strong ones require the type to be included. + my ($ref, $is_strong) = @_; + + if ($ref) { + my $type = $types{$ref} + or die "Unknown type $ref referenced.\n"; + + if ($is_strong) { + $strong_refs{$ref}++; + } else { + $weak_refs{$ref}++; + } + } +} + +# Determines if referenced other types should be included or forward-declared +our $is_strong_ref = 1; + +sub with_struct_block(&$;$%) { + my ($blk, $tag, $name, %flags) = @_; + + my $kwd = (is_attr_true($tag,'is-union') ? "union" : "struct"); + my $exp = $flags{-export} ? $export_prefix : ''; + my $prefix = $kwd.' '.$exp.($name ? $name.' ' : ''); + + emit_block { + local $_; + local $is_strong_ref = 1; # reset the state + if ($flags{-no_anon}) { + $blk->(); + } else { + &with_anon($blk); + } + } $prefix, ";"; +} + +sub decode_type_name_ref($;%) { + # Interpret the type-name field of a tag + my ($tag,%flags) = @_; + my $force_type = $flags{-force_type}; + my $force_strong = $flags{-force_strong}; + my $tname = $tag->getAttribute($flags{-attr_name} || 'type-name') + or return undef; + + if ($primitive_types{$tname}) { + die "Cannot use type $tname as type-name of ".$tag->nodeName."\n" + if ($force_type && $force_type ne 'primitive'); + return primitive_type_name($tname); + } else { + register_ref $tname, ($force_strong||$is_strong_ref); + die "Cannot use type $tname as type-name of ".$tag->nodeName."\n" + if ($force_type && $force_type ne $types{$tname}->nodeName); + return $main_namespace.'::'.$tname; + } +} + +# CONDITIONALS + +sub is_conditional($) { + my ($tag) = @_; + return $tag->nodeName =~ /^(cond-if|cond-elseif)$/; +} + +sub translate_if_cond($) { + my ($tag) = @_; + + my @rules; + if (my $defvar = $tag->getAttribute('defined')) { + push @rules, "defined($defvar)"; + } + if (my $cmpvar = $tag->getAttribute('var')) { + if (my $cmpval = $tag->getAttribute('lt')) { + push @rules, "($cmpvar < $cmpval)"; + } + if (my $cmpval = $tag->getAttribute('le')) { + push @rules, "($cmpvar <= $cmpval)"; + } + if (my $cmpval = $tag->getAttribute('eq')) { + push @rules, "($cmpvar == $cmpval)"; + } + if (my $cmpval = $tag->getAttribute('ge')) { + push @rules, "($cmpvar >= $cmpval)"; + } + if (my $cmpval = $tag->getAttribute('gt')) { + push @rules, "($cmpvar > $cmpval)"; + } + if (my $cmpval = $tag->getAttribute('ne')) { + push @rules, "($cmpvar != $cmpval)"; + } + } + return '('.(join(' && ',@rules) || '1').')'; +} + +our $in_cond = 0; + +sub render_cond_if($$$;@) { + my ($tag, $in_elseif, $render_cb, @tail) = @_; + + local $in_cond = 1; + + { + local $indentation = 0; + my $op = ($in_elseif && $in_elseif >= 2) ? '#elif' : '#if'; + emit $op, ' ', translate_if_cond($tag); + } + + for my $child ($tag->findnodes('child::*')) { + &render_cond($child, $render_cb, @tail); + } + + unless ($in_elseif) { + local $indentation = 0; + emit "#endif"; + } +} + +sub render_cond($$;@) { + my ($tag, $render_cb, @tail) = @_; + + my $tag_name = $tag->nodeName; + if ($tag_name eq 'cond-if') { + render_cond_if($tag, 0, $render_cb, @tail); + } elsif ($tag_name eq 'cond-elseif') { + my $idx = 1; + for my $child ($tag->findnodes('child::*')) { + ($child->nodeName eq 'cond-if') + or die "Only cond-if tags may be inside a cond-switch: ".$child->nodeName."\n"; + render_cond_if($child, $idx++, $render_cb, @tail); + } + { + local $indentation = 0; + emit "#endif"; + } + } else { + local $_ = $tag; + $render_cb->($tag, @tail); + } +} + +# ENUM + +sub render_enum_core($$) { + my ($name,$tag) = @_; + + my $base = 0; + + emit_block { + my @items = $tag->findnodes('child::*'); + my $idx = 0; + + for my $item (@items) { + render_cond $item, sub { + my $tag = $_->nodeName; + return if $tag eq 'enum-attr'; + ($tag eq 'enum-item') + or die "Invalid enum member: ".$item->nodeName."\n"; + + my $name = ensure_name $_->getAttribute('name'); + my $value = $_->getAttribute('value'); + + $base = ($idx == 0 && !$in_cond) ? $value : undef if defined $value; + $idx++; + + emit $name, (defined($value) ? ' = '.$value : ''), ','; + }; + } + + emit "_last_item_of_$name"; + } "enum $name ", ";"; + + return $base; +} + +sub render_enum_tables($$$) { + my ($name,$tag,$base) = @_; + + # Enumerate enum attributes + + my %aidx = ('key' => 0); + my @anames = ('key'); + my @avals = ('NULL'); + my @atypes = ('const char*'); + my @atnames = (undef); + + for my $attr ($tag->findnodes('child::enum-attr')) { + my $name = $attr->getAttribute('name') or die "Unnamed enum-attr.\n"; + my $type = $attr->getAttribute('type-name'); + my $def = $attr->getAttribute('default-value'); + + die "Duplicate attribute $name.\n" if exists $aidx{$name}; + + check_name $name; + $aidx{$name} = scalar @anames; + push @anames, $name; + push @atnames, $type; + + if ($type) { + push @atypes, $type; + push @avals, (defined $def ? $def : "($type)0"); + } else { + push @atypes, 'const char*'; + push @avals, (defined $def ? "\"$def\"" : 'NULL'); + } + } + + # Emit accessor function prototypes + + emit "const $name _first_item_of_$name = ($name)$base;"; + + emit_block { + emit "return (value >= _first_item_of_$name && value < _last_item_of_$name);"; + } "inline bool is_valid($name value) "; + + for (my $i = 0; $i < @anames; $i++) { + emit "${export_prefix}$atypes[$i] get_$anames[$i]($name value);"; + } + + # Emit implementation + + with_emit_static { + emit_block { + emit_block { + # Emit the entry type + emit_block { + for (my $i = 0; $i < @anames; $i++) { + emit "$atypes[$i] $anames[$i];"; + } + } "struct _info_entry ", ";"; + + # Emit the info table + emit_block { + for my $item ($tag->findnodes('child::*')) { + render_cond $item, sub { + my $tag = $_->nodeName; + return if $tag eq 'enum-attr'; + + # Assemble item-specific attr values + my @evals = @avals; + my $name = $_->getAttribute('name'); + $evals[0] = "\"$name\"" if $name; + + for my $attr ($_->findnodes('child::item-attr')) { + my $name = $attr->getAttribute('name') or die "Unnamed item-attr.\n"; + my $value = $attr->getAttribute('value') or die "No-value item-attr.\n"; + my $idx = $aidx{$name} or die "Unknown item-attr: $name\n"; + + if ($atnames[$idx]) { + $evals[$idx] = $value; + } else { + $evals[$idx] = "\"$value\""; + } + } + + emit "{ ",join(', ',@evals)," },"; + }; + } + + emit "{ ",join(', ',@avals)," }"; + } "static const _info_entry _info[] = ", ";"; + + for (my $i = 0; $i < @anames; $i++) { + emit_block { + emit "return is_valid(value) ? _info[value - $base].$anames[$i] : $avals[$i];"; + } "$atypes[$i] get_$anames[$i]($name value) "; + } + } "namespace $name "; + } "namespace enums "; + }; +} + +sub render_enum_type { + my ($tag) = @_; + + emit_block { + emit_block { + my $base = render_enum_core($typename,$tag); + + if (defined $base) { + render_enum_tables($typename,$tag,$base); + } else { + print STDERR "Warning: complex enum: $typename\n"; + } + } "namespace $typename "; + } "namespace enums "; + + emit "using enums::",$typename,"::",$typename,";"; +} + +# BITFIELD + +sub get_primitive_base($;$) { + my ($tag, $default) = @_; + + my $base = $tag->getAttribute('base-type') || $default || 'uint32_t'; + $primitive_types{$base} or die "Must be primitive: $base\n"; + + return $base; +} + +sub render_bitfield_core { + my ($name, $tag) = @_; + + emit_block { + emit get_primitive_base($tag), ' whole;'; + + emit_block { + for my $item ($tag->findnodes('child::*')) { + render_cond $item, sub { + my ($item) = @_; + ($item->nodeName eq 'flag-bit') + or die "Invalid bitfield member:".$item->nodeName."\n"; + + check_bad_attrs($item); + my $name = ensure_name $item->getAttribute('name'); + my $size = $item->getAttribute('count') || 1; + emit "unsigned ", $name, " : ", $size, ";"; + }; + } + } "struct ", " bits;"; + } "union $name ", ";"; +} + +sub render_bitfield_type { + my ($tag) = @_; + render_bitfield_core($typename,$tag); +} + +# STRUCT + +my %struct_field_handlers; + +sub get_struct_fields($) { + # Retrieve subtags that are actual struct fields + my ($struct_tag) = @_; + local $_; + return grep { + my $tag = $_->nodeName; + die "Unknown field tag: $tag\n" + unless exists $struct_field_handlers{$tag}; + $struct_field_handlers{$tag}; + } $struct_tag->findnodes('child::*'); +} + +sub get_struct_field_type($) { + # Dispatch on the tag name, and retrieve the type prefix & suffix + my ($tag) = @_; + my $handler = $struct_field_handlers{$tag->nodeName} + or die "Unexpected tag: ".$tag->nodeName; + return $handler->($tag); +} + +sub do_render_struct_field($) { + my ($tag) = @_; + my $tag_name = $tag->nodeName; + my $field_name = $tag->getAttribute('name'); + + # Special case: anonymous compounds. + if ($tag_name eq 'compound' && !defined $field_name && + !defined $tag->getAttribute('type-name')) + { + check_bad_attrs($tag); + with_struct_block { + render_struct_field($_) for get_struct_fields($tag); + } $tag, undef, -no_anon => 1; + return; + } + + # Otherwise, create the name if necessary, and render + my $name = ensure_name $field_name; + with_anon { + my ($prefix, $postfix) = get_struct_field_type($tag); + emit $prefix, ' ', $name, $postfix, ';'; + } "T_$name"; +} + +sub render_struct_field($) { + my ($tag) = @_; + render_cond $tag, \&do_render_struct_field; +} + +sub emit_typedef($$) { + # Convert a prefix/postfix pair into a single name + my ($pre, $post) = @_; + my $name = ensure_name undef; + emit 'typedef ', $pre, ' ', $name, $post, ';'; + return $name; +} + +sub get_container_item_type($$;$) { + # Interpret the type-name and nested fields for a generic container type + my ($tag,$strong_ref,$allow_void) = @_; + + check_bad_attrs($tag); + + my $prefix; + my $postfix = ''; + local $is_strong_ref = $strong_ref; + + unless ($prefix = decode_type_name_ref($tag)) { + my @fields = get_struct_fields($tag); + + if (scalar(@fields) == 1 && !is_conditional($fields[0])) { + ($prefix, $postfix) = get_struct_field_type($fields[0]); + } elsif (scalar(@fields) == 0) { + $allow_void or die "Empty container: ".$tag->nodeName."\n"; + $prefix = $allow_void; + } else { + $prefix = ensure_name undef; + with_struct_block { + render_struct_field($_) for @fields; + } $tag, $prefix; + } + } + + return ($prefix,$postfix) if wantarray; + return emit_typedef($prefix, $postfix) if $postfix; + return $prefix; +} + +sub get_primitive_field_type { + # Primitive type handler + my ($tag,$fname) = @_; + check_bad_attrs($tag); + my $name = $tag->nodeName; + return (primitive_type_name($name), ""); +} + +sub get_static_string_type { + # Static string handler + my ($tag, $fname) = @_; + check_bad_attrs($tag, 1); + my $count = $tag->getAttribute('size') || 0; + return ('char', "[$count]"); +} + +sub get_padding_type { + # Padding handler. Supports limited alignment. + my ($tag, $fname) = @_; + + check_bad_attrs($tag, 1, 1); + my $count = $tag->getAttribute('size') || 0; + my $align = $tag->getAttribute('alignment') || 1; + + if ($align == 1) { + return ('char', "[$count]"); + } elsif ($align == 2) { + ($count % 2 == 0) or die "Size not aligned in padding: $count at $align\n"; + return ('short', "[".($count/2)."]"); + } elsif ($align == 4) { + ($count % 4 == 0) or die "Size not aligned in padding: $count at $align\n"; + return ('int', "[".($count/4)."]"); + } else { + die "Bad padding alignment $align in $typename in $filename\n"; + } +} + +sub get_static_array_type { + # static-array handler + my ($tag, $fname) = @_; + my ($pre, $post) = get_container_item_type($tag, 1); + my $count = $tag->getAttribute('count') + or die "Count is mandatory for static-array in $typename in $filename\n"; + return ($pre, "[$count]".$post); +} + +sub get_pointer_type($) { + # pointer handler + my ($tag) = @_; + my $item = get_container_item_type($tag, 0, 'void'); + return ($item.'*', ''); +} + +sub get_compound_type($) { + # compound (nested struct) handler + my ($tag) = @_; + check_bad_attrs($tag); + + my $tname = decode_type_name_ref($tag); + unless ($tname) { + $tname = ensure_name undef; + with_struct_block { + render_struct_field($_) for get_struct_fields($tag); + } $tag, $tname; + } + return ($tname,''); +} + +sub get_bitfield_type($) { + # nested bitfield handler + my ($tag) = @_; + check_bad_attrs($tag); + + my $tname = decode_type_name_ref($tag, -force_type => 'bitfield-type'); + unless ($tname) { + $tname = ensure_name undef; + with_anon { + render_bitfield_core($tname, $tag); + }; + } + return ($tname,''); +} + +sub get_enum_type($) { + # nested enum handler + my ($tag) = @_; + check_bad_attrs($tag); + + my $tname = decode_type_name_ref($tag, -force_type => 'enum-type', -force_strong => 1); + my $base = get_primitive_base($tag, 'int32_t'); + unless ($tname) { + $tname = ensure_name undef; + with_anon { + render_enum_core($tname,$tag); + }; + } + return ("enum_field<$tname,$base>", ''); +} + +sub get_stl_vector_type($) { + # STL vector + my ($tag) = @_; + my $item = get_container_item_type($tag,1,'void*'); + $item = 'char' if $item eq 'bool'; + return ("std::vector<$item>", ''); +} + +sub get_stl_bit_vector_type($) { + # STL bit vector + my ($tag) = @_; + check_bad_attrs($tag); + return ("std::vector", ''); +} + +sub get_df_flagarray_type($) { + # DF flag array + my ($tag) = @_; + check_bad_attrs($tag); + my $type = decode_type_name_ref($tag, -attr_name => 'index-enum', -force_type => 'enum-type', -force_strong => 1) || 'int'; + return ("BitArray<$type>", ''); +} + +# Struct dispatch table and core + +%struct_field_handlers = ( + 'comment' => undef, # skip + 'code-helper' => undef, # skip + 'cond-if' => sub { die "cond handling error"; }, + 'cond-elseif' => sub { die "cond handling error"; }, + 'static-string' => \&get_static_string_type, + 'padding' => \&get_padding_type, + 'static-array' => \&get_static_array_type, + 'pointer' => \&get_pointer_type, + 'compound' => \&get_compound_type, + 'bitfield' => \&get_bitfield_type, + 'enum' => \&get_enum_type, + 'stl-vector' => \&get_stl_vector_type, + 'stl-bit-vector' => \&get_stl_bit_vector_type, + 'df-flagarray' => \&get_df_flagarray_type, +); +$struct_field_handlers{$_} ||= \&get_primitive_field_type for @primitive_type_list; + +sub render_struct_type { + my ($tag) = @_; + + my $tag_name = $tag->nodeName; + my $is_class = ($tag_name eq 'class-type'); + my $has_methods = $is_class || is_attr_true($tag, 'has-methods'); + my $inherits = $tag->getAttribute('inherits-from'); + my $original_name = $tag->getAttribute('original-name'); + my $ispec = ''; + + if ($inherits) { + register_ref $inherits, 1; + $ispec = ' : '.$inherits; + } elsif ($is_class) { + $ispec = ' : virtual_class'; + } + + with_struct_block { + render_struct_field($_) for get_struct_fields($tag); + + if ($has_methods) { + if ($is_class) { + emit "static class_virtual_identity<$typename> _identity;"; + with_emit_static { + emit "class_virtual_identity<$typename> ${typename}::_identity(", + "\"$typename\",", + ($original_name ? "\"$original_name\"" : 'NULL'), ',', + ($inherits ? "&${inherits}::_identity" : 'NULL'), + ");"; + } + } + + outdent { + emit "protected:"; + }; + + if ($is_class) { + emit "virtual ~",$typename,"() {}"; + } else { + emit "~",$typename,"() {}"; + } + } + } $tag, "$typename$ispec", -export => 1; +} + +# MAIN BODY + +# Collect all type definitions from XML files + +sub add_type_to_hash($) { + my ($type) = @_; + + my $name = $type->getAttribute('type-name') + or die "Type without a name in $filename\n"; + + die "Duplicate definition of $name in $filename\n" if $types{$name}; + + local $typename = $name; + check_bad_attrs $type; + $types{$name} = $type; + $type_files{$name} = $filename; +} + +for my $fn (glob "$input_dir/*.xml") { + local $filename = $fn; + my $parser = XML::LibXML->new(); + my $doc = $parser->parse_file($filename); + + add_type_to_hash $_ foreach $doc->findnodes('/data-definition/enum-type'); + add_type_to_hash $_ foreach $doc->findnodes('/data-definition/bitfield-type'); + add_type_to_hash $_ foreach $doc->findnodes('/data-definition/struct-type'); + add_type_to_hash $_ foreach $doc->findnodes('/data-definition/class-type'); +} + +# Generate text representations + +my %type_handlers = ( + 'enum-type' => \&render_enum_type, + 'bitfield-type' => \&render_bitfield_type, + 'class-type' => \&render_struct_type, + 'struct-type' => \&render_struct_type, +); + +my %type_data; + +for my $name (sort { $a cmp $b } keys %types) { + local $typename = $name; + local $filename = $type_files{$typename}; + local %weak_refs; + local %strong_refs; + + eval { + my $type = $types{$typename}; + + # Emit the actual type definition + my @code = with_emit { + with_anon { + $type_handlers{$type->nodeName}->($type); + }; + } 2; + + delete $weak_refs{$name}; + delete $strong_refs{$name}; + + # Add wrapping + my @all = with_emit { + my $def = type_header_def($typename); + emit "#ifndef $def"; + emit "#define $def"; + + for my $strong (sort { $a cmp $b } keys %strong_refs) { + my $sdef = type_header_def($strong); + emit "#ifndef $sdef"; + emit "#include \"$strong.h\""; + emit "#endif"; + } + + emit_block { + for my $weak (sort { $a cmp $b } keys %weak_refs) { + next if $strong_refs{$weak}; + my $ttype = $types{$weak}; + my $tstr = 'struct'; + $tstr = 'enum' if $ttype->nodeName eq 'enum-type'; + $tstr = 'union' if $ttype->nodeName eq 'bitfield-type'; + $tstr = 'union' if ($ttype->nodeName eq 'struct-type' && is_attr_true($ttype,'is-union')); + emit $tstr, ' ', $weak, ';'; + } + + push @lines, @code; + } "namespace $main_namespace "; + + emit "#endif"; + }; + + $type_data{$typename} = \@all; + }; + if ($@) { + print 'Error: '.$@."Type $typename in $filename ignored\n"; + } +} + +# Write output files + +mkdir $output_dir; + +{ + # Delete the old files + for my $name (glob "$output_dir/*.h") { + unlink $name; + } + + # Write out the headers + local $, = "\n"; + local $\ = "\n"; + + for my $name (keys %type_data) { + open FH, ">$output_dir/$name.h"; + print FH "/* THIS FILE WAS GENERATED. DO NOT EDIT. */"; + print FH @{$type_data{$name}}; + close FH; + } + + # Write out the static file + open FH, ">$output_dir/static.inc"; + print FH "/* THIS FILE WAS GENERATED. DO NOT EDIT. */"; + for my $name (sort { $a cmp $b } keys %static_includes) { + print FH "#include \"$name.h\""; + } + print FH "namespace $main_namespace {"; + print FH @static_lines; + print FH '}'; + close FH; +} diff --git a/library/xml/df.building-raws.xml b/library/xml/df.building-raws.xml new file mode 100644 index 000000000..bf522ae31 --- /dev/null +++ b/library/xml/df.building-raws.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.buildings.xml b/library/xml/df.buildings.xml new file mode 100644 index 000000000..f54c76eb8 --- /dev/null +++ b/library/xml/df.buildings.xml @@ -0,0 +1,403 @@ + + + + + + + + + + + (find-by-id $global.world.buildings.all $id $) + + + + + + + + + + + + + + + + + 0 - not room; 1 in stockpile; 2 wall; 3 inner; 4 distance boundary. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- stockpile -- + + + + + + + + + + + + + + + + + + + + + + + + + -- zone -- + + + + + + -- actual -- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- workshops -- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- misc -- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.creature-raws.xml b/library/xml/df.creature-raws.xml new file mode 100644 index 000000000..61aa7ed7c --- /dev/null +++ b/library/xml/df.creature-raws.xml @@ -0,0 +1,592 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // 0 around of, 1 around by + + + + + + + + + + + + + + + + + + + $global.world.raws.creatures.all[$$].caste[$] + + + + + + + + + // temporary + + + + fingers[2], nose, ear, head, eyes, mouth, hair, knuckles, lips, cheek, nails, f eet, arms, hands, tongue, leg + + + + + + + + + + + + + + + + + + + + + + + + + + // NOT 32-bit! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $global.world.raws.creatures.all[$] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.d_init.xml b/library/xml/df.d_init.xml new file mode 100644 index 000000000..345fa812a --- /dev/null +++ b/library/xml/df.d_init.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 85266c0 + + + + diff --git a/library/xml/df.history.xml b/library/xml/df.history.xml new file mode 100644 index 000000000..78dd33a3b --- /dev/null +++ b/library/xml/df.history.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + (find-by-id $global.world.history.figures $id $) + + + (describe-obj $.name) + (awhen (find-creature $.race) + (fmt "~:(~A ~A~)" $it.caste[$.caste].caste_id $it.creature_id)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dtor 8532fa0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.init.xml b/library/xml/df.init.xml new file mode 100644 index 000000000..6680b788a --- /dev/null +++ b/library/xml/df.init.xml @@ -0,0 +1,138 @@ + + -- init.h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- texture_handler.h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.item-raws.xml b/library/xml/df.item-raws.xml new file mode 100644 index 000000000..81d9c7671 --- /dev/null +++ b/library/xml/df.item-raws.xml @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.items.xml b/library/xml/df.items.xml new file mode 100644 index 000000000..a49c35ff5 --- /dev/null +++ b/library/xml/df.items.xml @@ -0,0 +1,578 @@ + + -- MISC TYPES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- CORE ITEM + + + (find-by-id $global.world.items.all $id $) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- ACTUAL ITEM + + + -- Important + + + + + + -- Misc + + + + + + + + + + + + + + + + + + + + + + + + + + -- Wielders + + + + + + + + + + + + (if (> $.stack_size 1) (fmt "stack: ~A" $.stack_size)) + (if (> $.wear 0) (fmt "wear: ~A" $.wear)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- CRAFTED ITEM + + + + + + + $.quality + (describe-obj (material-by-id $.matType $.matIndex)) + + + + + + + + + + -- CONSTRUCTED ITEM + + + + + + + + -- BODY COMPONENT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- CRITTER + + + + + + + + + -- LIQUID/POWER + + + + + + + + + + + + + + + + + + -- MISC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- CONSTRUCTED + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.job-enums.xml b/library/xml/df.job-enums.xml new file mode 100644 index 000000000..6a84ec8f5 --- /dev/null +++ b/library/xml/df.job-enums.xml @@ -0,0 +1,1785 @@ + + ----- PROFESSION ----- + + + + + + + -- 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 50 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 80 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 90 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 100 + + + + + + + + + + + + + + + + + + + + + + ----- LABOR ----- + + + + + -- 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 50 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 70 + + + + + + + + + + + + + ----- SKILL ----- + + + + + -- 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 50 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 80 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 90 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 100 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 110 + + + + + + + + + + + + + + + + + + + + + + ----- JOB TYPE ----- + + + -- Declare attributes: + + + + -- 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 20 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 50 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 80 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 90 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 100 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 130 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 150 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 160 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 170 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 180 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 190 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 200 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 210 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 220 + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.jobs.xml b/library/xml/df.jobs.xml new file mode 100644 index 000000000..48163fc48 --- /dev/null +++ b/library/xml/df.jobs.xml @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (find-by-id $global.world.activities.all $id $) + + + + + + + + + + + + + + -- Guess: + + + + + + + + + + + -- Either empty, or same as above: + + + + + + + + -- These are equal to the ones above: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.language.xml b/library/xml/df.language.xml new file mode 100644 index 000000000..347946602 --- /dev/null +++ b/library/xml/df.language.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + $global.world.raws.language_words[$] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $global.world.raws.translations[$] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (when $.has_name + (let* ((nick $.nickname) + (language $global.world.raws.translations[$.language]) + (fname $.first_name) + (lwords $language.words)) + (fmt "~:(~@[~A ~]~@['~A' ~]~{~A~^ ~}~)" + (if (> (length fname) 0) fname) + (if (> (length nick) 0) nick) + (loop for i from 0 below 7 for word = $.words[i] + when (>= word 0) collect $lwords[word].value)))) + + + + + diff --git a/library/xml/df.legends.xml b/library/xml/df.legends.xml new file mode 100644 index 000000000..0b8b8c926 --- /dev/null +++ b/library/xml/df.legends.xml @@ -0,0 +1,317 @@ + + + + + + + + + + + + (find-by-id $global.world.entities.all $id $) + + + (describe-obj $.name) + (describe-obj (find-creature $.race)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (find-by-id $global.world.entity_populations $id $) + + (describe-obj $.name) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (find-by-id $global.world.nemesis.all $id $) + + + + + + + + + + + (describe-obj $.figure) + + + + + + + + + + + + + + + (find-by-id $global.world.artifacts.all $id $) + + + (describe-obj $.name) + + + + + + + + + + + + + + + (find-by-id $global.world.history.events $id $) + + + + diff --git a/library/xml/df.machines.xml b/library/xml/df.machines.xml new file mode 100644 index 000000000..10b41c5a2 --- /dev/null +++ b/library/xml/df.machines.xml @@ -0,0 +1,97 @@ + + -- MACHINE + + + + + + + + + (find-by-id $global.world.machines.all $id $) + + + + + + + + + + + + + + + + + + + + + -- MACHINE COMPONENT BUILDINGS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.map.xml b/library/xml/df.map.xml new file mode 100644 index 000000000..eac8bbeb9 --- /dev/null +++ b/library/xml/df.map.xml @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.materials.xml b/library/xml/df.materials.xml new file mode 100644 index 000000000..f3f5033d5 --- /dev/null +++ b/library/xml/df.materials.xml @@ -0,0 +1,341 @@ + + + + + + + + (describe-material $) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // color token index + + + + + + + + + + + + + (material-by-id $ $$) + (describe-material $) + + + + + + + + + + + + + + + (describe-material $) + + + + + + + + + $global.world.raws.plants.all[$] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $global.world.raws.inorganics.all[$] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.military.xml b/library/xml/df.military.xml new file mode 100644 index 000000000..016b01241 --- /dev/null +++ b/library/xml/df.military.xml @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- May be invalid: + + + + + + + + + + + + + + + (find-by-id $global.world.squads.all $id $) + + + + + + (describe-obj $.name) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (describe-obj $.name) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.projectile.xml b/library/xml/df.projectile.xml new file mode 100644 index 000000000..5fc9b3e4a --- /dev/null +++ b/library/xml/df.projectile.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.raws.xml b/library/xml/df.raws.xml new file mode 100644 index 000000000..ed2745fb5 --- /dev/null +++ b/library/xml/df.raws.xml @@ -0,0 +1,237 @@ + + + -- Materials + + + + + + -- Inorganic + + + + + + + + + -- Plants + + + dtor 852cc20 + + + + + + + + + + + + + + + + + + + + + + + + + -- Creature RAWs + + + + dtor 89bab50 + + + dtor 8527e40 + + + + + + + + + + + + + dtor 89ba980 + + + -- Creatures + + + dtor 81448c0 + + + + + + + + + + + + + + + + -- Item RAWs + + + dtor 852e080 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- Sapient species + + + + + + -- Language RAWs + + dtor 852bc90 + + + + + + + + + + + + + + + + + + + + + + -- Words + + + + + + + + + + + + + + + + + + + + + + + + + + + -- Reaction RAWs + + + + + + -- Workshops + + + + + + + + + + + + + + + + -- Material index + + + + + + diff --git a/library/xml/df.refs.xml b/library/xml/df.refs.xml new file mode 100644 index 000000000..04671dc55 --- /dev/null +++ b/library/xml/df.refs.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.stockpile.xml b/library/xml/df.stockpile.xml new file mode 100644 index 000000000..cfd48e38d --- /dev/null +++ b/library/xml/df.stockpile.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + also 26 + also 31 + also 32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 16 + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + 5 + 5 + + + + + 659 + + + + + + + + 17 + + + + + + + + + + + + + + + + + + + + + + + + 11 + + + + + + + + + + + + + + + 11 + + + + + + + + + + + + + diff --git a/library/xml/df.ui.xml b/library/xml/df.ui.xml new file mode 100644 index 000000000..ca08c3d87 --- /dev/null +++ b/library/xml/df.ui.xml @@ -0,0 +1,604 @@ + + + + + + + + + + + + + + (find-by-id $global.ui.burrows.list $id $) + + (describe-obj $.name) + + + + + + + + + + + + + + + + + + -- 2 + + + + + + + + + + + + + + + -- 14 + + + + + + -- 17 + + + + + + + + -- 22 + + + + + + -- 25 + + + + + + + + + + + -- 33 + + + + + -- 35 + + + + -- 36 + + + + + + + -- 40 + + + + + + + -- 44 + + + + + + + + + + + + + + + + + + + + + + + + + + ctor 86e33c0 x + dtor 8534190 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dtor: 0x85272c0 + + + + diff --git a/library/xml/df.units.xml b/library/xml/df.units.xml new file mode 100644 index 000000000..9889c630f --- /dev/null +++ b/library/xml/df.units.xml @@ -0,0 +1,703 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scuttle creature: causes creature to be killed, leaving a behind + corpse and generating negative thoughts like a real kill. + + + + + + + + + + + (find-by-id $global.world.units.all $id $) + + + (describe-obj $.name) + (awhen (find-creature $.race) + (fmt "~:(~A ~A~)" $it.caste[$.caste].caste_id $it.creature_id)) + + + + + + + + + + + + + + + + E.g. for a dead miner, holds the place where he + was likely hanging around when he got the command + to mine in an aquifer. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- If shot by a ranged weapon: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // fight related + // fight related + + + // increments every tick + + + + + + + + + // 87*0 ? + + + + + // 238*0 + // 238*0 + // 238*0 + // 238*0 + // 238*0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // 490 + + + + + + + + + + + + + + + + + + + + + + + + // 53c decrements every job_counter reroll, set when changing jobs + // 540 current_job unit/walk done when reach -1, decremented every tick + // if set, decrements every job_counter reroll + + + // 54c decrements every tick, unstun at 0 + + + + + // coords ? (-30.000x3) + + + // coords again + + + + + + + + + + + + + + + + + + + + + + + + // counter, decrement to 0 + // same as 58c + + // fluctuate + + + + + + + + + + + + + + + + + + + + + + + + // 0x3e8 (1000) + // 0x3e8 (1000) + + + + + + + + + + + + + + + + // item ids? + + // 6f0: dined in a legendary dinning room, etc + + + + // 710 + + + + + // 738 + + + + // coords (-30000*3) + + + + + + + + + + + // 794 + // 796 + // 798 + // 79a + + + + + + + + + + + + + + + + + + + + + + // combat log? + + + + + + + + + + + + + // item related + + + + + + // age ? incremented every tick + + + + + + + + + + // items ids? + + // same size as 8e8, soldier related? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + (fmt "value=~A" $.value) + + + + + + + + + + + + + + + (describe-obj $.name) + (awhen (find-creature $.race) + (fmt "~:(~A ~A~)" $it.caste[$.caste].caste_id $it.creature_id)) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.viewscreen.xml b/library/xml/df.viewscreen.xml new file mode 100644 index 000000000..3874c445a --- /dev/null +++ b/library/xml/df.viewscreen.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.world-data.xml b/library/xml/df.world-data.xml new file mode 100644 index 000000000..2f0faa3a2 --- /dev/null +++ b/library/xml/df.world-data.xml @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + (describe-obj $.name) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/df.world.xml b/library/xml/df.world.xml new file mode 100644 index 000000000..3058b0a64 --- /dev/null +++ b/library/xml/df.world.xml @@ -0,0 +1,503 @@ + + + dtor 89fff80 + + + dtor 8532540 + + + + + + + + + + + + + + + + + -- + + + + + + + + + + -- Entities + + + + + + + + + + + + -- Unknown + + + + -- Units + + + + + + + + + + + + + + + + + + -- Unknown + + + + + + + + + -- Nemesis + + + + + + + + + + + + + + -- Items + + + dtor 852f4b0 + + + + + + + + + + + + + + + + + + + -- Artifacts + + + + + + + + + + + + -- Jobs and projectiles + + + + + + -- Buildings + + + dtor 85316f0 + + + + + + + + + + + + + + + + + + + + -- Machines (connected groups of gears and so on) + + + + + + + + + + + -- Unknown + + + + + + + + + + + + + + + + + + + + + + + + -- Plants + + + + + + + + + -- Unknown + + + + -- Unknown + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- Drills + + + + + + + + + + + -- Reports and announcements + + + dtor 85356e0 + + + + + + + + + + Written to by code at 0x80fd7b0 + + + + + + + + + + + + + + + + + + + + + + 52cdc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 547f8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- RAWs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ctor 87ae880 + + + + + + + + + + + dtor 83bed90 + + + + + + + + + + + + -- hist figures + + + + + + + + + + + + + + + + Looks like a temporary buffer for pathfinding or something. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 192be0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/library/xml/list.pl b/library/xml/list.pl new file mode 100755 index 000000000..206565843 --- /dev/null +++ b/library/xml/list.pl @@ -0,0 +1,33 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use XML::LibXML; + +my $input_dir = $ARGV[0] || '.'; +my $output_dir = $ARGV[1] || 'codegen'; +my $separator = $ARGV[2] || "\n"; + +print "$output_dir/static.inc"; + +for my $filename (glob "$input_dir/*.xml") { + my $parser = XML::LibXML->new(); + my $doc = $parser->parse_file($filename); + + my @nodes = ( + $doc->findnodes('/data-definition/enum-type'), + $doc->findnodes('/data-definition/bitfield-type'), + $doc->findnodes('/data-definition/struct-type'), + $doc->findnodes('/data-definition/class-type') + ); + + for my $node (@nodes) { + my $name = $node->getAttribute('type-name') + or die "Unnamed type in $filename\n"; + print "$separator$output_dir/$name.h"; + } +} + +print $separator if $separator eq "\n"; + From 79ac2a781a3bfd3395a5785098a16403c1a9d3ce Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 24 Dec 2011 14:51:58 +0400 Subject: [PATCH 2/8] Add infrastructure necessary to use the generated headers. As a usage example, allow toggling water level display and idlers, and implement a ui tweak for easily copying stockpiles. Also disable df2mc by default - default options shouldn't require anything not in the base package. --- .gitignore | 1 + Memory.xml | 21 ++++ library/CMakeLists.txt | 3 + library/Core.cpp | 5 + library/DataDefs.cpp | 136 ++++++++++++++++++++++++ library/DataStatics.cpp | 5 + library/include/dfhack/Core.h | 7 ++ library/include/dfhack/DataDefs.h | 151 +++++++++++++++++++++++++++ library/include/dfhack/df/.gitignore | 2 + plugins/CMakeLists.txt | 6 +- plugins/initflags.cpp | 60 +++++++++++ plugins/stockpiles.cpp | 87 +++++++++++++++ 12 files changed, 482 insertions(+), 2 deletions(-) create mode 100644 library/DataDefs.cpp create mode 100644 library/DataStatics.cpp create mode 100644 library/include/dfhack/DataDefs.h create mode 100644 library/include/dfhack/df/.gitignore create mode 100644 plugins/initflags.cpp create mode 100644 plugins/stockpiles.cpp diff --git a/.gitignore b/.gitignore index 702a6490c..a19302fe4 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ build/CMakeCache.txt build/cmake_install.cmake build/CMakeFiles build/doc +build/lua build/bin build/library build/tools diff --git a/Memory.xml b/Memory.xml index 366dc48ba..b4f7ce1f3 100644 --- a/Memory.xml +++ b/Memory.xml @@ -1078,6 +1078,13 @@
+ +
+
+
+
+
+ @@ -2309,6 +2316,13 @@
+ +
+
+
+
+
+ cmake item vector: @@ -3174,6 +3188,13 @@
+ +
+
+
+
+
+ diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 7e24f3659..9a87db9af 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -29,6 +29,7 @@ SET(PROJECT_HDRS include/DFHack.h include/dfhack/Console.h include/dfhack/Core.h +include/dfhack/DataDefs.h include/dfhack/Error.h include/dfhack/Export.h include/dfhack/FakeSDL.h @@ -64,6 +65,8 @@ include/dfhack/modules/Graphic.h SET(PROJECT_SRCS Core.cpp +DataDefs.cpp +DataStatics.cpp PluginManager.cpp TileTypes.cpp VersionInfo.cpp diff --git a/library/Core.cpp b/library/Core.cpp index f218f2756..5296a057e 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -37,6 +37,7 @@ using namespace std; #include "dfhack/Error.h" #include "dfhack/Process.h" #include "dfhack/Core.h" +#include "dfhack/DataDefs.h" #include "dfhack/Console.h" #include "dfhack/Module.h" #include "dfhack/VersionInfoFactory.h" @@ -494,6 +495,10 @@ bool Core::Init() dump << vinfo->PrintOffsets(); dump.close(); } + + // initialize data defs + virtual_identity::Init(); + InitDataDefGlobals(this); // create mutex for syncing with interactive tasks StackMutex = new mutex(); diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp new file mode 100644 index 000000000..2de8c156e --- /dev/null +++ b/library/DataDefs.cpp @@ -0,0 +1,136 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "Internal.h" + +#include +#include +#include + +#include "dfhack/Process.h" +#include "dfhack/Core.h" +#include "dfhack/DataDefs.h" +#include "dfhack/VersionInfo.h" +#include "tinythread.h" + +using namespace DFHack; + +/* The order of global object constructor calls is + * undefined between compilation units. Therefore, + * this list has to be plain data, so that it gets + * initialized by the loader in the initial mmap. + */ +virtual_identity *virtual_identity::list = NULL; + +virtual_identity::virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent) + : dfhack_name(dfhack_name), original_name(original_name), parent(parent), + prev(NULL), vtable_ptr(NULL), has_children(true) +{ + // Link into the static list. Nothing else can be safely done at this point. + next = list; list = this; +} + +/* Vtable to identity lookup. */ +static tthread::mutex *known_mutex = NULL; +std::map virtual_identity::known; + +virtual_identity *virtual_identity::get(virtual_class *instance_ptr) +{ + if (!instance_ptr) return NULL; + + // Actually, a reader/writer lock would be sufficient, + // since the table is only written once per class. + tthread::lock_guard lock(*known_mutex); + + void *vtable = get_vtable(instance_ptr); + std::map::iterator it = known.find(vtable); + + if (it != known.end()) + return it->second; + + // If using a reader/writer lock, re-grab as write here, and recheck + Core &core = Core::getInstance(); + std::string name = core.p->doReadClassName(vtable); + + virtual_identity *actual = NULL; + + for (virtual_identity *p = list; p; p = p->next) { + if (strcmp(name.c_str(), p->getOriginalName()) != 0) continue; + known[vtable] = p; + p->vtable_ptr = vtable; + return p; + } + + known[vtable] = NULL; + return NULL; +} + +bool virtual_identity::check_instance(virtual_class *instance_ptr, bool allow_subclasses) +{ + virtual_identity *actual = get(instance_ptr); + + if (actual == this) return true; + if (!allow_subclasses || !actual) return false; + + do { + actual = actual->parent; + if (actual == this) return true; + } while (actual); + + return false; +} + +void virtual_identity::Init() +{ + if (!known_mutex) + known_mutex = new tthread::mutex(); + + // This cannot be done in the constructors, because + // they are called in an undefined order. + for (virtual_identity *p = list; p; p = p->next) { + p->has_children = false; + p->children.clear(); + } + for (virtual_identity *p = list; p; p = p->next) { + if (p->parent) { + p->parent->children.push_back(p); + p->parent->has_children = true; + } + } +} + +#define GLOBAL(name,tname) \ + df::tname *df::global::name = NULL; +DF_KNOWN_GLOBALS +#undef GLOBAL + +void DFHack::InitDataDefGlobals(Core *core) { + OffsetGroup *global_table = core->vinfo->getGroup("global"); + uint32_t tmp; + +#define GLOBAL(name,tname) \ + if (global_table->getSafeAddress(#name,tmp)) df::global::name = (df::tname*)tmp; +DF_KNOWN_GLOBALS +#undef GLOBAL +} diff --git a/library/DataStatics.cpp b/library/DataStatics.cpp new file mode 100644 index 000000000..57aeb779c --- /dev/null +++ b/library/DataStatics.cpp @@ -0,0 +1,5 @@ +#include "Internal.h" +#include "dfhack/DataDefs.h" + +// Instantiate all the static objects +#include "dfhack/df/static.inc" diff --git a/library/include/dfhack/Core.h b/library/include/dfhack/Core.h index 2d7941af2..64eae5d3e 100644 --- a/library/include/dfhack/Core.h +++ b/library/include/dfhack/Core.h @@ -190,4 +190,11 @@ namespace DFHack tthread::mutex * misc_data_mutex; std::map misc_data_map; }; + + class CoreSuspender { + Core *core; + public: + CoreSuspender(Core *core) : core(core) { core->Suspend(); } + ~CoreSuspender() { core->Resume(); } + }; } diff --git a/library/include/dfhack/DataDefs.h b/library/include/dfhack/DataDefs.h new file mode 100644 index 000000000..aa325958c --- /dev/null +++ b/library/include/dfhack/DataDefs.h @@ -0,0 +1,151 @@ +/* +https://github.com/peterix/dfhack +Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#pragma once + +#include +#include +#include + +#include "dfhack/Core.h" +#include "dfhack/BitArray.h" + +namespace DFHack +{ + class virtual_class {}; + + class DFHACK_EXPORT virtual_identity { + static virtual_identity *list; + static std::map known; + + virtual_identity *prev, *next; + const char *dfhack_name; + const char *original_name; + virtual_identity *parent; + std::vector children; + + void *vtable_ptr; + bool has_children; + + protected: + virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent); + + bool check_instance(virtual_class *instance_ptr, bool allow_subclasses); + + static void *get_vtable(virtual_class *instance_ptr) { return *(void**)instance_ptr; } + + public: + const char *getName() { return dfhack_name; } + const char *getOriginalName() { return original_name ? original_name : dfhack_name; } + + virtual_identity *getParent() { return parent; } + const std::vector &getChildren() { return children; } + + static virtual_identity *get(virtual_class *instance_ptr); + + bool is_instance(virtual_class *instance_ptr) { + if (!instance_ptr) return false; + if (vtable_ptr) { + void *vtable = get_vtable(instance_ptr); + if (vtable == vtable_ptr) return true; + if (!has_children) return false; + } + return check_instance(instance_ptr, true); + } + + bool is_direct_instance(virtual_class *instance_ptr) { + if (!instance_ptr) return false; + return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr)) + : check_instance(instance_ptr, false); + } + + static void Init(); + }; + + template + inline T *virtual_cast(virtual_class *ptr) { + return T::_identity.is_instance(ptr) ? static_cast(ptr) : NULL; + } + + template + inline T *strict_virtual_cast(virtual_class *ptr) { + return T::_identity.is_direct_instance(ptr) ? static_cast(ptr) : NULL; + } + + void InitDataDefGlobals(Core *core); + + template + T *ifnull(T *a, T *b) { return a ? a : b; } +} + +namespace df +{ + using DFHack::virtual_class; + using DFHack::BitArray; + + template + class class_virtual_identity : public DFHack::virtual_identity { + public: + class_virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent) + : virtual_identity(dfhack_name, original_name, parent) {}; + }; + + template + struct enum_field { + IntType value; + + enum_field() {} + enum_field(EnumType ev) : value(IntType(ev)) {} + template + enum_field(enum_field ev) : value(IntType(ev.value)) {} + + operator EnumType () { return EnumType(value); } + enum_field &operator=(EnumType ev) { + value = IntType(ev); return *this; + } + }; + + namespace enums {} +} + +#define ENUM_ATTR(enum,attr,val) (df::enums::enum::get_##attr(val)) +#define ENUM_ATTR_STR(enum,attr,val) DFHack::ifnull(ENUM_ATTR(enum,attr,val),"?") +#define ENUM_KEY_STR(enum,val) ENUM_ATTR_STR(enum,key,val) +#define ENUM_FIRST_ITEM(enum) (df::enums::enum::_first_item_of_##enum) +#define ENUM_LAST_ITEM(enum) (df::enums::enum::_last_item_of_##enum) + +namespace df { +#define DF_KNOWN_GLOBALS \ + GLOBAL(world,world) \ + GLOBAL(ui,ui) \ + GLOBAL(gview,interface) \ + GLOBAL(init,init) \ + GLOBAL(d_init,d_init) + +#define GLOBAL(name,tname) \ + struct tname; \ + namespace global { extern DFHACK_EXPORT tname *name; } +DF_KNOWN_GLOBALS +#undef GLOBAL +} diff --git a/library/include/dfhack/df/.gitignore b/library/include/dfhack/df/.gitignore new file mode 100644 index 000000000..11c5ffbb1 --- /dev/null +++ b/library/include/dfhack/df/.gitignore @@ -0,0 +1,2 @@ +*.h +*.inc diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index c08bcd9e1..ab7e039a4 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -30,7 +30,7 @@ if(BUILD_SERVER) add_subdirectory (server) endif() -OPTION(BUILD_DF2MC "Build DF2MC (needs a checkout first)." ON) +OPTION(BUILD_DF2MC "Build DF2MC (needs a checkout first)." OFF) if(BUILD_DF2MC) add_subdirectory (df2mc) endif() @@ -57,7 +57,9 @@ DFHACK_PLUGIN(deramp deramp.cpp) DFHACK_PLUGIN(flows flows.cpp) DFHACK_PLUGIN(filltraffic filltraffic.cpp) DFHACK_PLUGIN(seedwatch seedwatch.cpp) -DFHACK_PLUGIN(versionosd versionosd.cpp) +DFHACK_PLUGIN(initflags initflags.cpp) +DFHACK_PLUGIN(stockpiles stockpiles.cpp) +#DFHACK_PLUGIN(versionosd versionosd.cpp) # this is the skeleton plugin. If you want to make your own, make a copy and then change it OPTION(BUILD_SKELETON "Build the skeleton plugin." OFF) diff --git a/plugins/initflags.cpp b/plugins/initflags.cpp new file mode 100644 index 000000000..f27a318ae --- /dev/null +++ b/plugins/initflags.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include + +#include +#include + +using std::vector; +using std::string; +using std::endl; +using namespace DFHack; +using namespace df::enums; + +using df::global::d_init; + +DFhackCExport command_result twaterlvl(Core * c, vector & parameters); +DFhackCExport command_result tidlers(Core * c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "initflags"; +} + +DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +{ + commands.clear(); + if (d_init) { + commands.push_back(PluginCommand("twaterlvl", "Toggle display of water/magma depth.", twaterlvl)); + commands.push_back(PluginCommand("tidlers", "Toggle display of idlers.", tidlers)); + } + std::cerr << "d_init: " << sizeof(df::d_init) << endl; + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} + +DFhackCExport command_result twaterlvl(Core * c, vector & parameters) +{ + c->Suspend(); + df::global::d_init->flags1.toggle(d_init_flags1::SHOW_FLOW_AMOUNTS); + c->con << "Toggled the display of water/magma depth." << endl; + c->Resume(); + return CR_OK; +} + +DFhackCExport command_result tidlers(Core * c, vector & parameters) +{ + c->Suspend(); + df::d_init_idlers iv = df::d_init_idlers(int(d_init->idlers) + 1); + if (!d_init_idlers::is_valid(iv)) + iv = ENUM_FIRST_ITEM(d_init_idlers); + d_init->idlers = iv; + c->con << "Toggled the display of idlers to " << ENUM_KEY_STR(d_init_idlers, iv) << endl; + c->Resume(); + return CR_OK; +} diff --git a/plugins/stockpiles.cpp b/plugins/stockpiles.cpp new file mode 100644 index 000000000..5cd153335 --- /dev/null +++ b/plugins/stockpiles.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +using std::vector; +using std::string; +using std::endl; +using namespace DFHack; +using namespace df::enums; + +using df::global::world; +using df::global::ui; + +using df::building_stockpilest; + +DFhackCExport command_result copystock(Core * c, vector & parameters); + +DFhackCExport const char * plugin_name ( void ) +{ + return "stockpiles"; +} + +DFhackCExport command_result plugin_init (Core *c, std::vector &commands) +{ + commands.clear(); + if (world && ui) { + commands.push_back(PluginCommand("copystock", "Copy stockpile under cursor.", copystock)); + } + std::cerr << "world: " << sizeof(df::world) << " ui: " << sizeof(df::ui) + << " b_stock: " << sizeof(building_stockpilest) << endl; + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( Core * c ) +{ + return CR_OK; +} + +bool inSelectMode() { + using namespace ui_sidebar_mode; + + switch (ui->main.mode) { + case BuildingItems: + case QueryBuilding: + return true; + default: + return false; + } +} + +DFhackCExport command_result copystock(Core * c, vector & parameters) +{ + CoreSuspender suspend(c); + + // For convenience: when used in the stockpiles mode, switch to 'q' + if (ui->main.mode == ui_sidebar_mode::Stockpiles) { + world->selected_building = NULL; // just in case it contains some kind of garbage + ui->main.mode = ui_sidebar_mode::QueryBuilding; + + c->con << "Switched back to query building." << endl; + return CR_OK; + } + + if (!inSelectMode()) { + c->con << "Cannot copy stockpile in mode " << ENUM_KEY_STR(ui_sidebar_mode, ui->main.mode) << endl; + return CR_OK; + } + + building_stockpilest *sp = virtual_cast(world->selected_building); + if (!sp) { + c->con << "Selected building isn't a stockpile." << endl; + return CR_OK; + } + + ui->stockpile.custom_settings = sp->settings; + ui->main.mode = ui_sidebar_mode::Stockpiles; + world->selected_stockpile_type = stockpile_category::Custom; + + c->con << "Stockpile options copied." << endl; + return CR_OK; +} From cfd2c95eab0df91d643a1dace5f571c5b8cd2619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sat, 24 Dec 2011 12:27:34 +0100 Subject: [PATCH 3/8] Slight reformat in versionosd. --- plugins/versionosd.cpp | 136 ++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/plugins/versionosd.cpp b/plugins/versionosd.cpp index b4d354ce5..466c4a45b 100644 --- a/plugins/versionosd.cpp +++ b/plugins/versionosd.cpp @@ -36,16 +36,16 @@ DFhackCExport const char * plugin_name ( void ) DFTileSurface* createTile(int x, int y) { - DFTileSurface* tile = new DFTileSurface; - tile->paintOver = true; - tile->rect = new DFSDL_Rect; - tile->rect->x = x*16; - tile->rect->y = y*16; - tile->rect->w = 16; - tile->rect->h = 16; - tile->surface = surface; - tile->dstResize = NULL; - return tile; + DFTileSurface* tile = new DFTileSurface; + tile->paintOver = true; + tile->rect = new DFSDL_Rect; + tile->rect->x = x*16; + tile->rect->y = y*16; + tile->rect->w = 16; + tile->rect->h = 16; + tile->surface = surface; + tile->dstResize = NULL; + return tile; } DFhackCExport command_result plugin_init ( Core * c, std::vector &commands) @@ -55,72 +55,72 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector "Toggles displaying version in DF window", df_versionosd)); - HMODULE SDLImageLib = LoadLibrary("SDL_image.dll"); - _IMG_LoadPNG_RW = (DFHack::DFSDL_Surface* (*)(void*))GetProcAddress(SDLImageLib, "IMG_LoadPNG_RW"); + HMODULE SDLImageLib = LoadLibrary("SDL_image.dll"); + _IMG_LoadPNG_RW = (DFHack::DFSDL_Surface* (*)(void*))GetProcAddress(SDLImageLib, "IMG_LoadPNG_RW"); - HMODULE realSDLlib = LoadLibrary("SDLreal.dll"); - _SDL_RWFromFile = (void*(*)(const char*, const char*))GetProcAddress(realSDLlib,"SDL_RWFromFile"); - _SDL_SetAlpha = (int (*)(void*, uint32_t, uint8_t))GetProcAddress(realSDLlib,"SDL_SetAlpha"); + HMODULE realSDLlib = LoadLibrary("SDLreal.dll"); + _SDL_RWFromFile = (void*(*)(const char*, const char*))GetProcAddress(realSDLlib,"SDL_RWFromFile"); + _SDL_SetAlpha = (int (*)(void*, uint32_t, uint8_t))GetProcAddress(realSDLlib,"SDL_SetAlpha"); _SDL_SetColorKey = (int (*)(void*, uint32_t, uint32_t))GetProcAddress(realSDLlib,"SDL_SetColorKey"); - _SDL_MapRGB = (uint32_t (*)(void*, uint8_t, uint8_t, uint8_t))GetProcAddress(realSDLlib,"SDL_MapRGB"); + _SDL_MapRGB = (uint32_t (*)(void*, uint8_t, uint8_t, uint8_t))GetProcAddress(realSDLlib,"SDL_MapRGB"); - void* RWop = _SDL_RWFromFile(file, "rb"); - surface = _IMG_LoadPNG_RW(RWop); + void* RWop = _SDL_RWFromFile(file, "rb"); + surface = _IMG_LoadPNG_RW(RWop); - if ( !surface ) - { - c->con.print("Couldnt load image from file %s", file); - return CR_FAILURE; - } + if ( !surface ) + { + c->con.print("Couldnt load image from file %s", file); + return CR_FAILURE; + } - UINT32 pink = _SDL_MapRGB(vPtr(surface->format), 0xff, 0x00, 0xff); + UINT32 pink = _SDL_MapRGB(vPtr(surface->format), 0xff, 0x00, 0xff); - _SDL_SetColorKey((vPtr)surface, 4096, pink); - _SDL_SetAlpha((vPtr)surface, 65536, 255); + _SDL_SetColorKey((vPtr)surface, 4096, pink); + _SDL_SetAlpha((vPtr)surface, 65536, 255); - // setup tiles - tiles[0] = createTile(4, 4); // D - tiles[1] = createTile(6, 4); // F - tiles[2] = createTile(8, 4); // H - tiles[3] = createTile(1, 6); // a - tiles[4] = createTile(3, 6); // c - tiles[5] = createTile(11, 6); // k - tiles[6] = createTile(0, 0); // " " - // FIXME: it should get REAL version not hardcoded one - tiles[7] = createTile(2, 7); // r - tiles[8] = createTile(8, 3); // 8 + // setup tiles + tiles[0] = createTile(4, 4); // D + tiles[1] = createTile(6, 4); // F + tiles[2] = createTile(8, 4); // H + tiles[3] = createTile(1, 6); // a + tiles[4] = createTile(3, 6); // c + tiles[5] = createTile(11, 6); // k + tiles[6] = createTile(0, 0); // " " + // FIXME: it should get REAL version not hardcoded one + tiles[7] = createTile(2, 7); // r + tiles[8] = createTile(8, 3); // 8 - tiles[9] = createTile(9, 0); // o + tiles[9] = createTile(9, 0); // o - gui = c->getGui(); + gui = c->getGui(); - Graphic* g = c->getGraphic(); - g->Register(gettile); + Graphic* g = c->getGraphic(); + g->Register(gettile); return CR_OK; } DFhackCExport command_result plugin_shutdown ( Core * c ) { - Graphic* g = c->getGraphic(); - g->Unregister(gettile); - delete surface; + Graphic* g = c->getGraphic(); + g->Unregister(gettile); + delete surface; - for (int i=0; i<10; i++) - { - delete tiles[i]; - } - delete [] tiles; + for (int i=0; i<10; i++) + { + delete tiles[i]; + } + delete [] tiles; return CR_OK; } DFhackCExport command_result df_versionosd (Core * c, vector & parameters) { - On = !On; - c->Suspend(); + On = !On; + c->Suspend(); c->con.print("Version OSD is %s\n", On ? "On" : "Off"); c->Resume(); return CR_OK; @@ -128,21 +128,21 @@ DFhackCExport command_result df_versionosd (Core * c, vector & paramete DFTileSurface* gettile (int x, int y) { - if ( !On ) return NULL; - - if ( x == 0 && y-4 >= 0 && y-4 < 9 ) - { - return tiles[y-4]; - } - - int32_t cx, cy, cz; - int32_t vx, vy, vz; - if ( !gui->getViewCoords(vx, vy, vz) ) return NULL; - if ( !gui->getCursorCoords(cx, cy, cz) ) return NULL; - if ( cx-vx+1 == x && cy-vy+1 == y ) - { - return tiles[9]; - } - - return NULL; + if ( !On ) return NULL; + + if ( x == 0 && y-4 >= 0 && y-4 < 9 ) + { + return tiles[y-4]; + } + + int32_t cx, cy, cz; + int32_t vx, vy, vz; + if ( !gui->getViewCoords(vx, vy, vz) ) return NULL; + if ( !gui->getCursorCoords(cx, cy, cz) ) return NULL; + if ( cx-vx+1 == x && cy-vy+1 == y ) + { + return tiles[9]; + } + + return NULL; } \ No newline at end of file From 81ad287c0621e3655782696b2ce1369ef6ae8e8e Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sat, 24 Dec 2011 16:22:10 +0400 Subject: [PATCH 4/8] Generate very simple static functions to find objects in global vectors. --- library/DataStatics.cpp | 12 +++++++++ library/include/dfhack/MiscUtils.h | 20 +++++++++++++- library/xml/codegen.pl | 39 +++++++++++++++++++++++++++ library/xml/df.buildings.xml | 4 +-- library/xml/df.history.xml | 12 ++++++--- library/xml/df.items.xml | 5 ++-- library/xml/df.jobs.xml | 4 +-- library/xml/df.language.xml | 42 ++++++++++++++---------------- library/xml/df.legends.xml | 24 +++-------------- library/xml/df.machines.xml | 5 ++-- library/xml/df.materials.xml | 8 +++--- library/xml/df.military.xml | 4 +-- library/xml/df.ui.xml | 3 +-- library/xml/df.units.xml | 4 +-- 14 files changed, 117 insertions(+), 69 deletions(-) diff --git a/library/DataStatics.cpp b/library/DataStatics.cpp index 57aeb779c..e3a448eac 100644 --- a/library/DataStatics.cpp +++ b/library/DataStatics.cpp @@ -1,5 +1,17 @@ #include "Internal.h" #include "dfhack/DataDefs.h" +#include "dfhack/MiscUtils.h" + +#include "dfhack/df/world.h" +#include "dfhack/df/world_data.h" +#include "dfhack/df/ui.h" + +namespace { + template + inline T &_toref(T &r) { return r; } + template + inline T &_toref(T *&p) { return *p; } +} // Instantiate all the static objects #include "dfhack/df/static.inc" diff --git a/library/include/dfhack/MiscUtils.h b/library/include/dfhack/MiscUtils.h index 2bdab10c6..dfac76665 100644 --- a/library/include/dfhack/MiscUtils.h +++ b/library/include/dfhack/MiscUtils.h @@ -187,6 +187,7 @@ void print_bits ( T val, DFHack::Console& out ) strs << endl; out.print(strs.str().c_str()); } + /* // this is probably completely bogus std::string PrintSplatterType (int16_t mat1, int32_t mat2, vector &creature_types) @@ -247,4 +248,21 @@ std::string PrintSplatterType (int16_t mat1, int32_t mat2, vector +CT *binsearch_in_vector(std::vector &vec, FT CT::*field, AT value) { + int min = -1, max = (int)vec.size(); + CT **p = vec.data(); + FT key = (FT)value; + for (;;) { + int mid = (min + max)>>1; + if (mid == min) + return NULL; + FT midv = p[mid]->*field; + if (midv == key) + return p[mid]; + else if (midv < key) + min = mid; + else + max = mid; + } +} diff --git a/library/xml/codegen.pl b/library/xml/codegen.pl index 33210f616..05684732b 100755 --- a/library/xml/codegen.pl +++ b/library/xml/codegen.pl @@ -56,6 +56,17 @@ sub type_header_def($) { return uc($main_namespace).'_'.uc($name).'_H'; } +sub translate_lookup($) { + my ($str) = @_; + return undef unless $str && $str =~ /^\$global((\.[_a-zA-Z0-9]+)+)$/; + my @fields = split /\./, substr($1,1); + my $expr = "df::global::".shift(@fields); + for my $fn (@fields) { + $expr = "_toref($expr).$fn"; + } + return $expr; +} + # Text generation with indentation our @lines; @@ -730,6 +741,32 @@ sub get_df_flagarray_type($) { ); $struct_field_handlers{$_} ||= \&get_primitive_field_type for @primitive_type_list; +sub emit_find_instance { + my ($tag) = @_; + + my $instance_vector = translate_lookup $tag->getAttribute('instance-vector'); + if ($instance_vector) { + emit "static std::vector<$typename*> &get_vector();"; + emit "static $typename *find(int id);"; + + with_emit_static { + emit_block { + emit "return ", $instance_vector, ";"; + } "std::vector<$typename*>& ${typename}::get_vector() "; + + emit_block { + emit "std::vector<$typename*> &vec_ = get_vector();"; + + if (my $id = $tag->getAttribute('key-field')) { + emit "return binsearch_in_vector(vec_, &${typename}::$id, id_);"; + } else { + emit "return (id_ >= 0 && id_ < vec_.size()) ? vec_[id_] : NULL;"; + } + } "$typename *${typename}::find(int id_) "; + } + } +} + sub render_struct_type { my ($tag) = @_; @@ -750,6 +787,8 @@ sub render_struct_type { with_struct_block { render_struct_field($_) for get_struct_fields($tag); + emit_find_instance($tag); + if ($has_methods) { if ($is_class) { emit "static class_virtual_identity<$typename> _identity;"; diff --git a/library/xml/df.buildings.xml b/library/xml/df.buildings.xml index f54c76eb8..74df09eb7 100644 --- a/library/xml/df.buildings.xml +++ b/library/xml/df.buildings.xml @@ -7,8 +7,8 @@ - - (find-by-id $global.world.buildings.all $id $) + diff --git a/library/xml/df.history.xml b/library/xml/df.history.xml index 78dd33a3b..700329ea8 100644 --- a/library/xml/df.history.xml +++ b/library/xml/df.history.xml @@ -1,5 +1,5 @@ - + @@ -17,8 +17,6 @@ - (find-by-id $global.world.history.figures $id $) - (describe-obj $.name) (awhen (find-creature $.race) @@ -44,6 +42,14 @@ + + + + + + + diff --git a/library/xml/df.items.xml b/library/xml/df.items.xml index a49c35ff5..c1b989b23 100644 --- a/library/xml/df.items.xml +++ b/library/xml/df.items.xml @@ -66,9 +66,8 @@ -- CORE ITEM - - (find-by-id $global.world.items.all $id $) - + diff --git a/library/xml/df.jobs.xml b/library/xml/df.jobs.xml index 48163fc48..8c6c6d849 100644 --- a/library/xml/df.jobs.xml +++ b/library/xml/df.jobs.xml @@ -190,9 +190,7 @@ - - (find-by-id $global.world.activities.all $id $) - + diff --git a/library/xml/df.language.xml b/library/xml/df.language.xml index 347946602..961057f2d 100644 --- a/library/xml/df.language.xml +++ b/library/xml/df.language.xml @@ -18,28 +18,24 @@ - - - - $global.world.raws.language_words[$] - - - - - - + + + + + + + + + + + - + + - + $.word - - - - - - - + @@ -48,10 +44,10 @@ - + - $global.world.raws.translations[$] + $.name @@ -78,7 +74,9 @@ - + + + diff --git a/library/xml/df.legends.xml b/library/xml/df.legends.xml index 0b8b8c926..a9d2e4a65 100644 --- a/library/xml/df.legends.xml +++ b/library/xml/df.legends.xml @@ -1,5 +1,5 @@ - + @@ -9,8 +9,6 @@ - (find-by-id $global.world.entities.all $id $) - (describe-obj $.name) (describe-obj (find-creature $.race)) @@ -225,10 +223,9 @@ - + - (find-by-id $global.world.entity_populations $id $) (describe-obj $.name) @@ -258,11 +255,9 @@ - + - (find-by-id $global.world.nemesis.all $id $) - @@ -284,11 +279,9 @@ - + - (find-by-id $global.world.artifacts.all $id $) - (describe-obj $.name) @@ -298,15 +291,6 @@ - - - - - - - - (find-by-id $global.world.history.events $id $) -