Conflicts:
	library/xml
develop
Japa 2014-04-26 09:23:21 +05:30
commit b74d0da872
151 changed files with 5062 additions and 1396 deletions

10
.gitmodules vendored

@ -1,15 +1,15 @@
[submodule "plugins/stonesense"]
path = plugins/stonesense
url = git://github.com/peterix/stonesense.git
url = git://github.com/DFHack/stonesense.git
[submodule "plugins/isoworld"]
path = plugins/isoworld
url = git://github.com/peterix/isoworld.git
url = git://github.com/DFHack/isoworld.git
[submodule "plugins/df2mc"]
path = plugins/df2mc
url = git://github.com/peterix/DF2MC.git
url = git://github.com/DFHack/DF2MC.git
[submodule "library/xml"]
path = library/xml
url = git://github.com/peterix/df-structures.git
url = git://github.com/DFHack/df-structures.git
[submodule "depends/clsocket"]
path = depends/clsocket
url = git://github.com/peterix/clsocket.git
url = git://github.com/DFHack/clsocket.git

@ -3,13 +3,13 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Building DFHACK</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7514 2012-09-14 14:27:12Z milde $
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
@ -313,6 +313,21 @@ table.docutils th.field-name, table.docinfo th.docinfo-name {
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
@ -333,26 +348,27 @@ ul.auto-toc {
<li><a class="reference internal" href="#how-to-get-the-code" id="id5">How to get the code</a></li>
<li><a class="reference internal" href="#dependencies" id="id6">Dependencies</a></li>
<li><a class="reference internal" href="#build" id="id7">Build</a></li>
<li><a class="reference internal" href="#fixing-the-libstdc-version-bug" id="id8">Fixing the libstdc++ version bug</a></li>
</ul>
</li>
<li><a class="reference internal" href="#mac-os-x" id="id8">Mac OS X</a><ul>
<li><a class="reference internal" href="#snow-leopard-changes" id="id9">Snow Leopard Changes</a></li>
<li><a class="reference internal" href="#mac-os-x" id="id9">Mac OS X</a><ul>
<li><a class="reference internal" href="#snow-leopard-changes" id="id10">Snow Leopard Changes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#windows" id="id10">Windows</a><ul>
<li><a class="reference internal" href="#id1" id="id11">How to get the code</a></li>
<li><a class="reference internal" href="#id2" id="id12">Dependencies</a></li>
<li><a class="reference internal" href="#id3" id="id13">Build</a></li>
<li><a class="reference internal" href="#windows" id="id11">Windows</a><ul>
<li><a class="reference internal" href="#id1" id="id12">How to get the code</a></li>
<li><a class="reference internal" href="#id2" id="id13">Dependencies</a></li>
<li><a class="reference internal" href="#id3" id="id14">Build</a></li>
</ul>
</li>
<li><a class="reference internal" href="#build-types" id="id14">Build types</a></li>
<li><a class="reference internal" href="#using-the-library-as-a-developer" id="id15">Using the library as a developer</a><ul>
<li><a class="reference internal" href="#df-data-structure-definitions" id="id16">DF data structure definitions</a></li>
<li><a class="reference internal" href="#remote-access-interface" id="id17">Remote access interface</a></li>
<li><a class="reference internal" href="#contributing-to-dfhack" id="id18">Contributing to DFHack</a><ul>
<li><a class="reference internal" href="#coding-style" id="id19">Coding style</a></li>
<li><a class="reference internal" href="#how-to-get-new-code-into-dfhack" id="id20">How to get new code into DFHack</a></li>
<li><a class="reference internal" href="#memory-research" id="id21">Memory research</a></li>
<li><a class="reference internal" href="#build-types" id="id15">Build types</a></li>
<li><a class="reference internal" href="#using-the-library-as-a-developer" id="id16">Using the library as a developer</a><ul>
<li><a class="reference internal" href="#df-data-structure-definitions" id="id17">DF data structure definitions</a></li>
<li><a class="reference internal" href="#remote-access-interface" id="id18">Remote access interface</a></li>
<li><a class="reference internal" href="#contributing-to-dfhack" id="id19">Contributing to DFHack</a><ul>
<li><a class="reference internal" href="#coding-style" id="id20">Coding style</a></li>
<li><a class="reference internal" href="#how-to-get-new-code-into-dfhack" id="id21">How to get new code into DFHack</a></li>
<li><a class="reference internal" href="#memory-research" id="id22">Memory research</a></li>
</ul>
</li>
</ul>
@ -407,9 +423,26 @@ extra options.</p>
<p>You can also use a cmake-friendly IDE like KDevelop 4 or the cmake-gui
program.</p>
</div>
<div class="section" id="fixing-the-libstdc-version-bug">
<h2><a class="toc-backref" href="#id8">Fixing the libstdc++ version bug</a></h2>
<p>When compiling dfhack yourself, it builds against your system libc.
When Dwarf Fortress runs, it uses a libstdc++ shipped with the binary, which
is usually way older, and incompatible with your dfhack. This manifests with
the error message:</p>
<pre class="literal-block">
./libs/Dwarf_Fortress: /pathToDF/libs/libstdc++.so.6: version
`GLIBCXX_3.4.15' not found (required by ./hack/libdfhack.so)
</pre>
<p>To fix this, simply remove the libstdc++ shipped with DF, it will fall back
to your system lib and everything will work fine:</p>
<pre class="literal-block">
cd /path/to/DF/
rm libs/libstdc++.so.6
</pre>
</div>
</div>
<div class="section" id="mac-os-x">
<h1><a class="toc-backref" href="#id8">Mac OS X</a></h1>
<h1><a class="toc-backref" href="#id9">Mac OS X</a></h1>
<p>If you are building on 10.6, please read the subsection below titled &quot;Snow Leopard Changes&quot; FIRST.</p>
<ol class="arabic">
<li><p class="first">Download and unpack a copy of the latest DF</p>
@ -418,16 +451,27 @@ program.</p>
</li>
<li><p class="first">Open Xcode, go to Preferences &gt; Downloads, and install the Command Line Tools.</p>
</li>
<li><p class="first">Install MacPorts.</p>
</li>
<li><p class="first">Install dependencies from MacPorts:</p>
<ul>
<li><p class="first"><tt class="docutils literal">sudo port install gcc45 +universal cmake +universal <span class="pre">git-core</span> +universal</tt></p>
<p>This will take some time—maybe hours, depending on your machine.</p>
</li>
<li><p class="first">At some point during this process, it may ask you to install a Java environment; let it do so.</p>
</li>
<li><p class="first">Install dependencies</p>
<blockquote>
<p>Option 1: Using MacPorts:</p>
<blockquote>
<ul class="simple">
<li><a class="reference external" href="http://www.macports.org/">Install MacPorts</a></li>
<li>Run <tt class="docutils literal">sudo port install gcc45 +universal cmake +universal <span class="pre">git-core</span> +universal</tt>
This will take some time—maybe hours, depending on your machine.</li>
</ul>
<p>At some point during this process, it may ask you to install a Java environment; let it do so.</p>
</blockquote>
<p>Option 2: Using Homebrew:</p>
<blockquote>
<ul class="simple">
<li><a class="reference external" href="http://brew.sh/">Install Homebrew</a> and run:</li>
<li><tt class="docutils literal">brew install git</tt></li>
<li><tt class="docutils literal">brew install cmake</tt></li>
<li><tt class="docutils literal">brew install gcc45 <span class="pre">--enable-multilib</span></tt></li>
</ul>
</blockquote>
</blockquote>
</li>
<li><p class="first">Install perl dependencies</p>
<blockquote>
@ -451,12 +495,26 @@ git submodule init
git submodule update
</pre>
</li>
<li><p class="first">Set environment variables:</p>
</li>
</ol>
<blockquote>
<p>Macports:</p>
<pre class="literal-block">
export CC=/opt/local/bin/gcc-mp-4.5
export CXX=/opt/local/bin/g++-mp-4.5
</pre>
<p>Homebrew:</p>
<pre class="literal-block">
export CC=/usr/local/bin/gcc-4.5
export CXX=/usr/local/bin/g++-4.5
</pre>
</blockquote>
<ol class="arabic" start="8">
<li><p class="first">Build dfhack:</p>
<pre class="literal-block">
mkdir build-osx
cd build-osx
export CC=/opt/local/bin/gcc-mp-4.5
export CXX=/opt/local/bin/g++-mp-4.5
cmake .. -DCMAKE_BUILD_TYPE:string=Release -DCMAKE_INSTALL_PREFIX=/path/to/DF/directory
make
make install
@ -464,7 +522,7 @@ make install
</li>
</ol>
<div class="section" id="snow-leopard-changes">
<h2><a class="toc-backref" href="#id9">Snow Leopard Changes</a></h2>
<h2><a class="toc-backref" href="#id10">Snow Leopard Changes</a></h2>
<ol class="arabic">
<li><dl class="first docutils">
<dt>Add a step 6.2a (before Install XML::LibXSLT)::</dt>
@ -487,10 +545,10 @@ make install
</div>
</div>
<div class="section" id="windows">
<h1><a class="toc-backref" href="#id10">Windows</a></h1>
<h1><a class="toc-backref" href="#id11">Windows</a></h1>
<p>On Windows, DFHack replaces the SDL library distributed with DF.</p>
<div class="section" id="id1">
<h2><a class="toc-backref" href="#id11">How to get the code</a></h2>
<h2><a class="toc-backref" href="#id12">How to get the code</a></h2>
<p>DFHack doesn't have any kind of system of code snapshots in place, so you will have to get code from the github repository using git.
You will need some sort of Windows port of git, or a GUI. Some examples:</p>
<blockquote>
@ -511,13 +569,14 @@ git submodule update
<p>If you want to get really involved with the development, create an account on github, make a clone there and then use that as your remote repository instead. Detailed instructions are beyond the scope of this document. If you need help, join us on IRC (#dfhack channel on freenode).</p>
</div>
<div class="section" id="id2">
<h2><a class="toc-backref" href="#id12">Dependencies</a></h2>
<h2><a class="toc-backref" href="#id13">Dependencies</a></h2>
<p>First, you need <tt class="docutils literal">cmake</tt>. Get the win32 installer version from the official
site: <a class="reference external" href="http://www.cmake.org/cmake/resources/software.html">http://www.cmake.org/cmake/resources/software.html</a></p>
<p>It has the usual installer wizard. Make sure you let it add its binary folder
to your binary search PATH so the tool can be later run from anywhere.</p>
<p>You'll need a copy of Microsoft Visual C++ 2010. The Express version is sufficient.
Grab it from Microsoft's site.</p>
<p>You'll also need the Visual Studio 2010 SP1 update.</p>
<p>For the code generation parts, you'll need perl and XML::LibXML. You can install them like this:</p>
<ul class="simple">
<li>download and install strawberry perl from <a class="reference external" href="http://strawberryperl.com/">http://strawberryperl.com/</a></li>
@ -528,7 +587,7 @@ Grab it from Microsoft's site.</p>
<p>If you already have a different version of perl (for example the one from cygwin), you can run into some trouble. Either remove the other perl install from PATH, or install libxml and libxslt for it instead. Strawberry perl works though and has all the required packages.</p>
</div>
<div class="section" id="id3">
<h2><a class="toc-backref" href="#id13">Build</a></h2>
<h2><a class="toc-backref" href="#id14">Build</a></h2>
<p>There are several different batch files in the <tt class="docutils literal">build</tt> folder along with a script that's used for picking the DF path.</p>
<p>First, run set_df_path.vbs and point the dialog that pops up at your DF folder that you want to use for development.
Next, run one of the scripts with <tt class="docutils literal">generate</tt> prefix. These create the MSVC solution file(s):</p>
@ -550,7 +609,7 @@ So pick either Release or RelWithDebInfo build and build the INSTALL target.</p>
</div>
</div>
<div class="section" id="build-types">
<h1><a class="toc-backref" href="#id14">Build types</a></h1>
<h1><a class="toc-backref" href="#id15">Build types</a></h1>
<p><tt class="docutils literal">cmake</tt> allows you to pick a build type by changing this
variable: <tt class="docutils literal">CMAKE_BUILD_TYPE</tt></p>
<pre class="literal-block">
@ -562,7 +621,7 @@ cmake .. -DCMAKE_BUILD_TYPE:string=BUILD_TYPE
'RelWithDebInfo'. 'Debug' is not available on Windows.</p>
</div>
<div class="section" id="using-the-library-as-a-developer">
<h1><a class="toc-backref" href="#id15">Using the library as a developer</a></h1>
<h1><a class="toc-backref" href="#id16">Using the library as a developer</a></h1>
<p>Currently, the most direct way to use the library is to write a plugin that can be loaded by it.
All the plugins can be found in the 'plugins' folder. There's no in-depth documentation
on how to write one yet, but it should be easy enough to copy one and just follow the pattern.</p>
@ -580,29 +639,29 @@ The main license is zlib/libpng, some bits are MIT licensed, and some are BSD li
<p>Feel free to add your own extensions and plugins. Contributing back to
the dfhack repository is welcome and the right thing to do :)</p>
<div class="section" id="df-data-structure-definitions">
<h2><a class="toc-backref" href="#id16">DF data structure definitions</a></h2>
<h2><a class="toc-backref" href="#id17">DF data structure definitions</a></h2>
<p>DFHack uses information about the game data structures, represented via xml files in the library/xml/ submodule.</p>
<p>Data structure layouts are described in files following the df.*.xml name pattern. This information is transformed by a perl script into C++ headers describing the structures, and associated metadata for the Lua wrapper. These headers and data are then compiled into the DFHack libraries, thus necessitating a compatibility break every time layouts change; in return it significantly boosts the efficiency and capabilities of DFHack code.</p>
<p>Global object addresses are stored in symbols.xml, which is copied to the dfhack release package and loaded as data at runtime.</p>
</div>
<div class="section" id="remote-access-interface">
<h2><a class="toc-backref" href="#id17">Remote access interface</a></h2>
<h2><a class="toc-backref" href="#id18">Remote access interface</a></h2>
<p>DFHack supports remote access by exchanging Google protobuf messages via a TCP socket. Both the core and plugins can define remotely accessible methods. The <tt class="docutils literal"><span class="pre">dfhack-run</span></tt> command uses this interface to invoke ordinary console commands.</p>
<p>Currently the supported set of requests is limited, because the developers don't know what exactly is most useful.</p>
<p>Protocol client implementations exist for Java and C#.</p>
</div>
<div class="section" id="contributing-to-dfhack">
<h2><a class="toc-backref" href="#id18">Contributing to DFHack</a></h2>
<h2><a class="toc-backref" href="#id19">Contributing to DFHack</a></h2>
<p>Several things should be kept in mind when contributing to DFHack.</p>
<div class="section" id="coding-style">
<h3><a class="toc-backref" href="#id19">Coding style</a></h3>
<h3><a class="toc-backref" href="#id20">Coding style</a></h3>
<p>DFhack uses ANSI formatting and four spaces as indentation. Line
endings are UNIX. The files use UTF-8 encoding. Code not following this
won't make me happy, because I'll have to fix it. There's a good chance
I'll make <em>you</em> fix it ;)</p>
</div>
<div class="section" id="how-to-get-new-code-into-dfhack">
<h3><a class="toc-backref" href="#id20">How to get new code into DFHack</a></h3>
<h3><a class="toc-backref" href="#id21">How to get new code into DFHack</a></h3>
<p>You can send patches or make a clone of the github repo and ask me on
the IRC channel to pull your code in. I'll review it and see if there
are any problems. I'll fix them if they are minor.</p>
@ -612,7 +671,7 @@ this is also a good place to dump new ideas and/or bugs that need
fixing.</p>
</div>
<div class="section" id="memory-research">
<h3><a class="toc-backref" href="#id21">Memory research</a></h3>
<h3><a class="toc-backref" href="#id22">Memory research</a></h3>
<p>If you want to do memory research, you'll need some tools and some knowledge.
In general, you'll need a good memory viewer and optionally something
to look at machine code without getting crazy :)</p>

@ -89,16 +89,24 @@ If you are building on 10.6, please read the subsection below titled "Snow Leopa
1. Download and unpack a copy of the latest DF
2. Install Xcode from Mac App Store
3. Open Xcode, go to Preferences > Downloads, and install the Command Line Tools.
4. Install MacPorts.
5. Install dependencies from MacPorts:
4. Install dependencies
* ``sudo port install gcc45 +universal cmake +universal git-core +universal``
Option 1: Using MacPorts:
This will take some time—maybe hours, depending on your machine.
* `Install MacPorts <http://www.macports.org/>`_
* Run ``sudo port install gcc45 +universal cmake +universal git-core +universal``
This will take some time—maybe hours, depending on your machine.
* At some point during this process, it may ask you to install a Java environment; let it do so.
At some point during this process, it may ask you to install a Java environment; let it do so.
6. Install perl dependencies
Option 2: Using Homebrew:
* `Install Homebrew <http://brew.sh/>`_ and run:
* ``brew install git``
* ``brew install cmake``
* ``brew install gcc45 --enable-multilib``
5. Install perl dependencies
1. ``sudo cpan``
@ -108,19 +116,29 @@ If you are building on 10.6, please read the subsection below titled "Snow Leopa
2. ``install XML::LibXML``
3. ``install XML::LibXSLT``
7. Get the dfhack source::
6. Get the dfhack source::
git clone https://github.com/danaris/dfhack.git
cd dfhack
git submodule init
git submodule update
7. Set environment variables:
Macports::
export CC=/opt/local/bin/gcc-mp-4.5
export CXX=/opt/local/bin/g++-mp-4.5
Homebrew::
export CC=/usr/local/bin/gcc-4.5
export CXX=/usr/local/bin/g++-4.5
8. Build dfhack::
mkdir build-osx
cd build-osx
export CC=/opt/local/bin/gcc-mp-4.5
export CXX=/opt/local/bin/g++-mp-4.5
cmake .. -DCMAKE_BUILD_TYPE:string=Release -DCMAKE_INSTALL_PREFIX=/path/to/DF/directory
make
make install
@ -174,6 +192,8 @@ to your binary search PATH so the tool can be later run from anywhere.
You'll need a copy of Microsoft Visual C++ 2010. The Express version is sufficient.
Grab it from Microsoft's site.
You'll also need the Visual Studio 2010 SP1 update.
For the code generation parts, you'll need perl and XML::LibXML. You can install them like this:
* download and install strawberry perl from http://strawberryperl.com/

@ -3,13 +3,13 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.9.1: http://docutils.sourceforge.net/" />
<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
<title>Contributors</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7434 2012-05-11 21:06:27Z milde $
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
@ -77,7 +77,7 @@ div.tip p.admonition-title {
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
@ -253,13 +253,14 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { /* line numbers */
color: grey;
}
.code {
background-color: #eeeeee
}
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
@ -312,6 +313,21 @@ table.docutils th.field-name, table.docinfo th.docinfo-name {
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }

@ -1119,6 +1119,12 @@ can be omitted.</p>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.TranslateName(name[,in_english,only_last_name])</span></tt></p>
<p>Convert a language_name or only the last name part to string.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.df2utf(string)</tt></p>
<p>Convert a string from DF's CP437 encoding to UTF-8.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.utf2df(string)</tt></p>
<p>Convert a string from UTF-8 to DF's CP437 encoding.</p>
</li>
</ul>
<div class="section" id="gui-module">
<h3><a class="toc-backref" href="#id20">Gui module</a></h3>
@ -1154,6 +1160,26 @@ the container itself.</p>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.gui.getSelectedBuilding([silent])</span></tt></p>
<p>Returns the building selected via <em>'q'</em>, <em>'t'</em>, <em>'k'</em> or <em>'i'</em>.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.gui.writeToGamelog(text)</tt></p>
<p>Writes a string to gamelog.txt without doing an announcement.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.gui.makeAnnouncement(type,flags,pos,text,color[,is_bright])</span></tt></p>
<p>Adds an announcement with given announcement_type, text, color, and brightness.
The is_bright boolean actually seems to invert the brightness.</p>
<p>The announcement is written to gamelog.txt. The announcement_flags
argument provides a custom set of announcements.txt options,
which specify if the message should actually be displayed in the
announcement list, and whether to recenter or show a popup.</p>
<p>Returns the index of the new announcement in <tt class="docutils literal">df.global.world.status.reports</tt>, or -1.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.gui.addCombatReport(unit,slot,report_index)</tt></p>
<p>Adds the report with the given index (returned by makeAnnouncement)
to the specified group of the given unit. Returns <em>true</em> on success.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.gui.addCombatReportAuto(unit,flags,report_index)</tt></p>
<p>Adds the report with the given index to the appropriate group(s)
of the given unit, as requested by the flags.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.gui.showAnnouncement(text,color[,is_bright])</span></tt></p>
<p>Adds a regular announcement with given text, color, and brightness.
The is_bright boolean actually seems to invert the brightness.</p>
@ -1164,9 +1190,9 @@ The is_bright boolean actually seems to invert the brightness.</p>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.gui.showPopupAnnouncement(text,color[,is_bright])</span></tt></p>
<p>Pops up a titan-style modal announcement window.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.gui.showAutoAnnouncement(type,pos,text,color[,is_bright])</span></tt></p>
<p>Uses the type to look up options from announcements.txt, and calls the
above operations accordingly. If enabled, pauses and zooms to position.</p>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.gui.showAutoAnnouncement(type,pos,text,color[,is_bright,unit1,unit2])</span></tt></p>
<p>Uses the type to look up options from announcements.txt, and calls the above
operations accordingly. The units are used to call <tt class="docutils literal">addCombatReportAuto</tt>.</p>
</li>
</ul>
</div>
@ -1194,6 +1220,14 @@ above operations accordingly. If enabled, pauses and zooms to position.</p>
<li><p class="first"><tt class="docutils literal">dfhack.job.getWorker(job)</tt></p>
<p>Returns the unit performing the job.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.job.setJobCooldown(building,worker,timeout)</tt></p>
<p>Prevent the worker from taking jobs at the specified workshop for the specified time.
This doesn't decrease the timeout in any circumstances.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.job.removeWorker(job,timeout)</tt></p>
<p>Removes the worker from the specified workshop job, and sets the cooldown.
Returns <em>true</em> on success.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.job.checkBuildingsNow()</tt></p>
<p>Instructs the game to check buildings for jobs next frame and assign workers.</p>
</li>
@ -1300,6 +1334,10 @@ is <em>true</em>, subtracts the rust penalty.</p>
<li><p class="first"><tt class="docutils literal">dfhack.units.computeMovementSpeed(unit)</tt></p>
<p>Computes number of frames * 100 it takes the unit to move in its current state of mind and body.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.units.computeSlowdownFactor(unit)</tt></p>
<p>Meandering and floundering in liquid introduces additional slowdown. It is
random, but the function computes and returns the expected mean factor as a float.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.units.getNoblePositions(unit)</tt></p>
<p>Returns a list of tables describing noble position assignments, or <em>nil</em>.
Every table has fields <tt class="docutils literal">entity</tt>, <tt class="docutils literal">assignment</tt> and <tt class="docutils literal">position</tt>.</p>
@ -1904,6 +1942,10 @@ Returns: <em>step_idx, sum_idx, found_ptr</em>, or <em>nil</em> if not found.</p
The oldval, newval or delta arguments may be used to specify additional constraints.
Returns: <em>found_index</em>, or <em>nil</em> if end reached.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.internal.getDir(path)</tt></p>
<p>List files in a directory.
Returns: <em>file_names</em> or empty table if not found.</p>
</li>
</ul>
</div>
</div>
@ -2115,6 +2157,9 @@ for i = 1,#order do output[i] = data[order[i]] end
way enables applying the same permutation to multiple arrays.
This function is used by the sort plugin.</p>
</li>
<li><p class="first"><tt class="docutils literal">for link,item in utils.listpairs(list)</tt></p>
<p>Iterates a df-list structure, for example <tt class="docutils literal">df.global.world.job_list</tt>.</p>
</li>
<li><p class="first"><tt class="docutils literal">utils.assign(tgt, src)</tt></p>
<p>Does a recursive assignment of src into tgt.
Uses <tt class="docutils literal">df.assign</tt> if tgt is a native object ref; otherwise
@ -3260,8 +3305,9 @@ The <tt class="docutils literal">name</tt> argument should be the name stem, as
<div class="section" id="save-init-script">
<h2><a class="toc-backref" href="#id62">Save init script</a></h2>
<p>If a save directory contains a file called <tt class="docutils literal">raw/init.lua</tt>, it is
automatically loaded and executed every time the save is loaded. It
can also define the following functions to be called by dfhack:</p>
automatically loaded and executed every time the save is loaded.
The same applies to any files called <tt class="docutils literal"><span class="pre">raw/init.d/*.lua</span></tt>. Every
such script can define the following functions to be called by dfhack:</p>
<ul>
<li><p class="first"><tt class="docutils literal">function onStateChange(op) ... end</tt></p>
<p>Automatically called from the regular onStateChange event as long
@ -3271,7 +3317,8 @@ cleanup concerns.</p>
</li>
<li><p class="first"><tt class="docutils literal">function onUnload() ... end</tt></p>
<p>Called when the save containing the script is unloaded. This function
should clean up any global hooks installed by the script.</p>
should clean up any global hooks installed by the script. Note that
when this is called, the world is already completely unloaded.</p>
</li>
</ul>
<p>Within the init script, the path to the save directory is available as <tt class="docutils literal">SAVE_PATH</tt>.</p>

@ -812,6 +812,14 @@ can be omitted.
Convert a language_name or only the last name part to string.
* ``dfhack.df2utf(string)``
Convert a string from DF's CP437 encoding to UTF-8.
* ``dfhack.utf2df(string)``
Convert a string from UTF-8 to DF's CP437 encoding.
Gui module
----------
@ -854,6 +862,32 @@ Gui module
Returns the building selected via *'q'*, *'t'*, *'k'* or *'i'*.
* ``dfhack.gui.writeToGamelog(text)``
Writes a string to gamelog.txt without doing an announcement.
* ``dfhack.gui.makeAnnouncement(type,flags,pos,text,color[,is_bright])``
Adds an announcement with given announcement_type, text, color, and brightness.
The is_bright boolean actually seems to invert the brightness.
The announcement is written to gamelog.txt. The announcement_flags
argument provides a custom set of announcements.txt options,
which specify if the message should actually be displayed in the
announcement list, and whether to recenter or show a popup.
Returns the index of the new announcement in ``df.global.world.status.reports``, or -1.
* ``dfhack.gui.addCombatReport(unit,slot,report_index)``
Adds the report with the given index (returned by makeAnnouncement)
to the specified group of the given unit. Returns *true* on success.
* ``dfhack.gui.addCombatReportAuto(unit,flags,report_index)``
Adds the report with the given index to the appropriate group(s)
of the given unit, as requested by the flags.
* ``dfhack.gui.showAnnouncement(text,color[,is_bright])``
Adds a regular announcement with given text, color, and brightness.
@ -867,10 +901,10 @@ Gui module
Pops up a titan-style modal announcement window.
* ``dfhack.gui.showAutoAnnouncement(type,pos,text,color[,is_bright])``
* ``dfhack.gui.showAutoAnnouncement(type,pos,text,color[,is_bright,unit1,unit2])``
Uses the type to look up options from announcements.txt, and calls the
above operations accordingly. If enabled, pauses and zooms to position.
Uses the type to look up options from announcements.txt, and calls the above
operations accordingly. The units are used to call ``addCombatReportAuto``.
Job module
@ -904,6 +938,16 @@ Job module
Returns the unit performing the job.
* ``dfhack.job.setJobCooldown(building,worker,timeout)``
Prevent the worker from taking jobs at the specified workshop for the specified time.
This doesn't decrease the timeout in any circumstances.
* ``dfhack.job.removeWorker(job,timeout)``
Removes the worker from the specified workshop job, and sets the cooldown.
Returns *true* on success.
* ``dfhack.job.checkBuildingsNow()``
Instructs the game to check buildings for jobs next frame and assign workers.
@ -1033,6 +1077,11 @@ Units module
Computes number of frames * 100 it takes the unit to move in its current state of mind and body.
* ``dfhack.units.computeSlowdownFactor(unit)``
Meandering and floundering in liquid introduces additional slowdown. It is
random, but the function computes and returns the expected mean factor as a float.
* ``dfhack.units.getNoblePositions(unit)``
Returns a list of tables describing noble position assignments, or *nil*.
@ -1760,6 +1809,10 @@ and are only documented here for completeness:
The oldval, newval or delta arguments may be used to specify additional constraints.
Returns: *found_index*, or *nil* if end reached.
* ``dfhack.internal.getDir(path)``
List files in a directory.
Returns: *file_names* or empty table if not found.
Core interpreter context
========================
@ -1992,6 +2045,10 @@ utils
way enables applying the same permutation to multiple arrays.
This function is used by the sort plugin.
* ``for link,item in utils.listpairs(list)``
Iterates a df-list structure, for example ``df.global.world.job_list``.
* ``utils.assign(tgt, src)``
Does a recursive assignment of src into tgt.
@ -3187,8 +3244,9 @@ Save init script
================
If a save directory contains a file called ``raw/init.lua``, it is
automatically loaded and executed every time the save is loaded. It
can also define the following functions to be called by dfhack:
automatically loaded and executed every time the save is loaded.
The same applies to any files called ``raw/init.d/*.lua``. Every
such script can define the following functions to be called by dfhack:
* ``function onStateChange(op) ... end``
@ -3200,6 +3258,7 @@ can also define the following functions to be called by dfhack:
* ``function onUnload() ... end``
Called when the save containing the script is unloaded. This function
should clean up any global hooks installed by the script.
should clean up any global hooks installed by the script. Note that
when this is called, the world is already completely unloaded.
Within the init script, the path to the save directory is available as ``SAVE_PATH``.

28
NEWS

@ -1,6 +1,32 @@
DFHack future
- Is not yet known.
Internals:
- support for calling a lua function via a protobuf request (demonstrated by dfhack-run --lua).
- Lua API for listing files in directory. Needed for mod-manager.
- Lua API for creating unit combat reports and writing to gamelog.
- support for multiple raw/init.d/*.lua init scripts in one save.
New scripts:
- gui/mod-manager: allows installing/uninstalling mods into df from df/mods directory.
- gui/clone-uniform: duplicates the currently selected uniform in the military screen.
- fix/build-location: partial work-around for bug 5991 (trying to build wall while standing on it)
New commands:
- move the 'grow', 'extirpate' and 'immolate' commands as 'plant' subcommands
- 'plant create' - spawn a new shrub under the cursor
- command-prompt: a dfhack command prompt in df.
Misc improvements:
- digfort: improved csv parsing, add start() comment handling
- exterminate: allow specifying a caste (exterminate gob:male)
- createitem: in adventure mode it now defaults to the controlled unit as maker.
Siege engine plugin:
- engine quality and distance to target now affect accuracy
- firing the siege engine at a target produces a combat report
- improved movement speed computation for meandering units
- operators in Prepare To Fire mode are released from duty once
hungry/thirsty if there is a free replacement
DFHack v0.34.11-r4

File diff suppressed because it is too large Load Diff

@ -28,15 +28,15 @@ All new releases are announced in the bay12 thread: http://tinyurl.com/dfhack-ng
=============
Compatibility
=============
DFHack works on Windows XP, Vista, 7 or any modern Linux distribution.
OSX is not supported due to lack of developers with a Mac.
DFHack works on Windows XP, Vista, 7, any modern Linux distribution, or OS X
10.6.8-10.9.
Currently, version 0.34.11 is supported (and tested). If you need DFHack
for older versions, look for older releases.
On Windows, you have to use the SDL version of DF.
It is possible to use the Windows DFHack under wine/OSX.
It is also possible to use the Windows DFHack with Wine under Linux and OS X.
====================
Installation/Removal
@ -329,6 +329,13 @@ Options:
The building must be one of stockpile, workshop, furnace, trap,
siege engine or an activity zone.
command-prompt
--------------
A one line command prompt in df. Same as entering command into dfhack console. Best
used as a keybinding. Can be called with optional "entry" that will start prompt with
that pre-filled.
.. image:: images/command-prompt.png
Adventure mode
==============
@ -489,7 +496,7 @@ Options:
createitem
----------
Allows creating new items of arbitrary types and made of arbitrary materials.
Any items created are spawned at the feet of the selected unit.
By default, items created are spawned at the feet of the selected unit.
Specify the item and material information as you would indicate them in custom reaction raws, with the following differences:
* Separate the item and material with a space rather than a colon
@ -506,6 +513,14 @@ Examples:
``createitem FISH FISH_SHAD:MALE 5``
Create a stack of 5 cleaned shad, ready to eat.
To change where new items are placed, first run the command with a destination type while an appropriate destination is selected.
Options:
:floor: Subsequent items will be placed on the floor beneath the selected unit's feet.
:item: Subsequent items will be stored inside the currently selected item.
:building: Subsequent items will become part of the currently selected building. Best used for loading traps; do not use with workshops, or you will need to deconstruct the building to use the item.
deramp (by zilpin)
------------------
Removes all ramps designated for removal from the map. This is useful for replicating the old channel digging designation.
@ -676,29 +691,39 @@ tile. Can be used from a hotkey.
tubefill
--------
Fills all the adamantine veins again. Veins that were empty will be filled in
too, but might still trigger a demon invasion (this is a known bug).
extirpate
---------
A tool for getting rid of trees and shrubs. By default, it only kills
a tree/shrub under the cursor. The plants are turned into ashes instantly.
Fills all the adamantine veins again. Veins that were hollow will be left
alone.
Options:
:hollow: fill in naturally hollow veins too
Beware that filling in hollow veins will trigger a demon invasion on top of
your miner when you dig into the region that used to be hollow.
plant
-----
A tool for creating shrubs, growing, or getting rid of them.
Subcommands:
:create: Create a new shrub/sapling.
:grow: Make saplings grow into trees.
:extirpate: Kills trees and shrubs, turning them into ashes instantly.
:immolate: Similar to extirpate, but sets the plants on fire instead. The fires can and *will* spread ;)
``create`` creates a new sapling under the cursor. Takes a raw ID as
argument (e.g. TOWER_CAP). The cursor must be located on a dirt or grass
floor tile.
``grow`` works on the sapling under the cursor, and turns it into a tree.
Works on all shrubs of the map if the cursor is hidden.
``extirpate`` and ``immolate`` work only on the plant under the cursor.
For mass effects, use one of the additional options:
:shrubs: affect all shrubs on the map
:trees: affect all trees on the map
:all: affect every plant!
grow
----
Makes all saplings present on the map grow into trees (almost) instantly.
immolate
--------
Very similar to extirpate, but additionally sets the plants on fire. The fires
can and *will* spread ;)
regrass
-------
Regrows grass. Not much to it ;)
@ -1959,6 +1984,21 @@ Usage:
:misery disable: stop adding new negative thoughts. This will not remove existing duplicated thoughts. Equivalent to "misery 1"
:misery clear: remove fake thoughts added in this session of DF. Saving makes them permanent! Does not change factor.
strangemood
-----------
Creates a strange mood job the same way the game itself normally does it.
Options:
:-force: Ignore normal strange mood preconditions (no recent mood, minimum moodable population, artifact limit not reached).
:-unit: Make the strange mood strike the selected unit instead of picking one randomly. Unit eligibility is still enforced.
:-type T: Force the mood to be of a particular type instead of choosing randomly based on happiness.
Valid values are "fey", "secretive", "possessed", "fell", and "macabre".
:-skill S: Force the mood to use a specific skill instead of choosing the highest moodable skill.
Valid values are "miner", "carpenter", "engraver", "mason", "tanner", "weaver", "clothier", "weaponsmith", "armorsmith", "metalsmith", "gemcutter", "gemsetter", "woodcrafter", "stonecrafter", "metalcrafter", "glassmaker", "leatherworker", "bonecarver", "bowyer", and "mechanic".
Known limitations: if the selected unit is currently performing a job, the mood will not be started.
=======
Scripts
=======
@ -2009,6 +2049,13 @@ Scripts in this subdirectory fix various bugs and issues, some of them obscure.
every time a save game is loaded; putting ``fix/cloth-stockpile enable``
in ``dfhack.init`` makes it run automatically.
* fix/build-location
Fixes construction jobs that are stuck trying to build a wall while standing
on the same exact tile (bug 5991), designates the tile restricted traffic to
hopefully avoid jamming it again, and unsuspends them.
gui/*
=====
@ -2092,6 +2139,9 @@ With the special argument ``him``, targets only the selected creature.
With the special argument ``undead``, targets all undeads on the map,
regardless of their race.
When specifying a race, a caste can be specified to further restrict the
targeting. To do that, append and colon and the caste name after the race.
Any non-dead non-caged unit of the specified race gets its ``blood_count``
set to 0, which means immediate death at the next game tick. For creatures
such as vampires, it also sets animal.vanish_countdown to 2.
@ -2107,6 +2157,7 @@ but ignore caged/chained creatures.
Ex::
exterminate gob
exterminate gob:male
To kill a single creature, select the unit with the 'v' cursor and::
@ -2171,7 +2222,12 @@ Unrecognized characters are ignored (eg the 'skip this tile' in the sample).
Empty lines and data after a ``#`` are ignored as comments.
To skip a row in your design, use a single ``;``.
The script takes the plan filename, starting from the root df folder.
One comment in the file may contain the phrase ``start(3,5)``. It is interpreted
as an offset for the pattern: instead of starting at the cursor, it will start
3 tiles left and 5 tiles up from the cursor.
The script takes the plan filename, starting from the root df folder (where
Dwarf Fortress.exe is found).
invasion-now
============
@ -2185,6 +2241,7 @@ Triggers an invasion, or several in the near future.
`invasion-now civName start end` trigger an invasion from civName in about 10*start ticks, and continue triggering invasions every ten ticks afterward until about 10*end ticks have passed
Probably fails if the start time of a triggered invasion is later than the start of the next year.
digmat
======
Designates a tile for digging. Monitors the tile, and when it is dug out, add
@ -2357,12 +2414,16 @@ are mostly implemented by lua scripts.
As an exception, the tweak plugin described above does not follow this
guideline because it arguably just fixes small usability bugs in the game UI.
All of these tools are disabled by default - in order to make them available,
you must enable the plugins which provide them.
Dwarf Manipulator
=================
Implemented by the manipulator plugin. To activate, open the unit screen and
press 'l'.
Implemented by the 'manipulator' plugin.
To activate, open the unit screen and press 'l'.
.. image:: images/manipulator.png
@ -2412,6 +2473,8 @@ directly to the main dwarf mode screen.
Search
======
Implemented by the 'search' plugin.
The search plugin adds search to the Stocks, Animals, Trading, Stockpile,
Noble (assignment candidates), Military (position candidates), Burrows
(unit list), Rooms, Announcements, Job List and Unit List screens.
@ -2452,9 +2515,11 @@ using Permit Fats again while the list is filtered.
AutoMaterial
============
The automaterial plugin makes building constructions (walls, floors, fortifications,
etc) a little bit easier by saving you from having to trawl through long lists of
materials each time you place one.
Implemented by the 'automaterial' plugin.
This makes building constructions (walls, floors, fortifications, etc) a little bit
easier by saving you from having to trawl through long lists of materials each time
you place one.
Firstly, it moves the last used material for a given construction type to the top of
the list, if there are any left. So if you build a wall with chalk blocks, the next
@ -2585,6 +2650,16 @@ Rationale: individual choice seems to be unreliable when there is a weapon short
and may lead to inappropriate weapons being selected.
gui/clone-uniform
=================
Bind to a key (the example config uses Ctrl-C), and activate in the Uniforms
page of the military screen with the cursor in the leftmost list.
When invoked, the script duplicates the currently selected uniform template,
and selects the newly created copy.
gui/guide-path
==============
@ -2739,7 +2814,7 @@ of currently assigned racks for every valid squad.
gui/advfort
=============
===========
This script allows to perform jobs in adventure mode. For more complete help
press '?' while script is running. It's most confortable to use this as a
@ -2754,22 +2829,31 @@ keybinding. (e.g. keybinding set Ctrl-T gui/advfort). Possible arguments:
* job - selects that job (e.g. Dig or FellTree)
An example of player digging in adventure mode:
.. image:: images/advfort.png
.. admonition:: DISCLAIMER
advfort changes only persist in non procedural sites. Namely: player forts, caves, camps.
gui/companion-order
=======================
===================
A script to issue orders for companions. Select companions with lower case chars, issue orders with upper
case. Must be in look or talk mode to issue command on tile.
.. image:: images/companion-order.png
* move - orders selected companions to move to location. If companions are following they will move no more than 3 tiles from you.
* equip - try to equip items on the ground.
* pick-up - try to take items into hand (also wield)
* unequip - remove and drop equipment
* unwield - drop held items
* wait - temporarely remove from party
* wait - temporarily remove from party
* follow - rejoin the party after "wait"
* leave - remove from party (can be rejoined by talking)
gui/gm-editor
=============
@ -2779,14 +2863,26 @@ There are three ways to open this editor:
or viewed (e.g. unit/item description screen)
* using gui/gm-editor <lua command> - executes lua command and opens editor on
it's results (e.g. gui/gm-editor "df.global.world.items.all" shows all items)
its results (e.g. gui/gm-editor "df.global.world.items.all" shows all items)
* using gui/gm-editor dialog - shows an in game dialog to input lua command. Works
the same as version above.
.. image:: images/gm-editor.png
This editor allows to change and modify almost anything in df. Press '?' for an
in-game help.
gui/mod-manager
===============
A way to simply install and remove small mods. It looks for specially formated mods in
df subfolder 'mods'. Mods are not included, for example mods see: `github mini mod repository <https://github.com/warmist/df-mini-mods>`_
.. image:: images/mod-manager.png
=============
Behavior Mods
=============

@ -1,5 +1,5 @@
/*
** $Id: lapi.h,v 2.7 2009/11/27 15:37:59 roberto Exp $
** $Id: lapi.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lauxlib.h,v 1.120 2011/11/29 15:55:08 roberto Exp $
** $Id: lauxlib.h,v 1.120.1.1 2013/04/12 18:48:47 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lcode.h,v 1.58 2011/08/30 16:26:41 roberto Exp $
** $Id: lcode.h,v 1.58.1.1 2013/04/12 18:48:47 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $
** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $
** 'ctype' functions for Lua
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: ldebug.h,v 2.7 2011/10/07 20:45:19 roberto Exp $
** $Id: ldebug.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: ldo.h,v 2.20 2011/11/29 15:55:08 roberto Exp $
** $Id: ldo.h,v 2.20.1.1 2013/04/12 18:48:47 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lfunc.h,v 2.8 2012/05/08 13:53:33 roberto Exp $
** $Id: lfunc.h,v 2.8.1.1 2013/04/12 18:48:47 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lgc.h,v 2.56 2012/05/23 15:43:14 roberto Exp $
** $Id: lgc.h,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@ -50,14 +50,24 @@
#define isgenerational(g) ((g)->gckind == KGC_GEN)
/*
** macro to tell when main invariant (white objects cannot point to black
** macros to tell when main invariant (white objects cannot point to black
** ones) must be kept. During a non-generational collection, the sweep
** phase may break the invariant, as objects turned white may point to
** still-black objects. The invariant is restored when sweep ends and
** all objects are white again. During a generational collection, the
** invariant must be kept all times.
*/
#define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic)
#define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic)
/*
** Outside the collector, the state in generational mode is kept in
** 'propagate', so 'keepinvariant' is always true.
*/
#define keepinvariantout(g) \
check_exp(g->gcstate == GCSpropagate || !isgenerational(g), \
g->gcstate <= GCSatomic)
/*

@ -1,5 +1,5 @@
/*
** $Id: llex.h,v 1.72 2011/11/30 12:43:51 roberto Exp $
** $Id: llex.h,v 1.72.1.1 2013/04/12 18:48:47 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: llimits.h,v 1.99 2012/05/28 20:32:28 roberto Exp $
** $Id: llimits.h,v 1.103.1.1 2013/04/12 18:48:47 roberto Exp $
** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@ -200,7 +200,7 @@ typedef lu_int32 Instruction;
** both small and large values (outside the range of integers).
*/
#if defined(MS_ASMTRICK) /* { */
#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */
/* trick with Microsoft assembler for X86 */
#define lua_number2int(i,n) __asm {__asm fld n __asm fistp i}
@ -256,7 +256,7 @@ union luai_Cast { double l_d; LUA_INT32 l_p[2]; };
#if !defined(lua_number2unsigned) /* { */
/* the following definition assures proper modulo behavior */
#if defined(LUA_NUMBER_DOUBLE)
#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT)
#include <math.h>
#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1)
#define lua_number2unsigned(i,n) \
@ -282,7 +282,7 @@ union luai_Cast { double l_d; LUA_INT32 l_p[2]; };
#include <math.h>
#define luai_hashnum(i,n) { int e; \
n = frexp(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \
n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \
lua_number2int(i, n); i += e; }
#endif

@ -1,5 +1,5 @@
/*
** $Id: lmem.h,v 1.38 2011/12/02 13:26:54 roberto Exp $
** $Id: lmem.h,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
@ -14,10 +14,17 @@
#include "lua.h"
/*
** This macro avoids the runtime division MAX_SIZET/(e), as 'e' is
** always constant.
** The macro is somewhat complex to avoid warnings:
** +1 avoids warnings of "comparison has constant result";
** cast to 'void' avoids warnings of "value unused".
*/
#define luaM_reallocv(L,b,on,n,e) \
((cast(size_t, (n)+1) > MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \
(luaM_toobig(L), (void *)0) : \
luaM_realloc_(L, (b), (on)*(e), (n)*(e)))
(cast(void, \
(cast(size_t, (n)+1) > MAX_SIZET/(e)) ? (luaM_toobig(L), 0) : 0), \
luaM_realloc_(L, (b), (on)*(e), (n)*(e)))
#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0)
#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0)

@ -1,5 +1,5 @@
/*
** $Id: lobject.h,v 2.70 2012/05/11 14:10:50 roberto Exp $
** $Id: lobject.h,v 2.71.1.1 2013/04/12 18:48:47 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@ -52,8 +52,7 @@
#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */
/*
** LUA_TSTRING variants */
/* Variant tags for strings */
#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */
#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */
@ -188,8 +187,6 @@ typedef struct lua_TValue TValue;
#define setnvalue(obj,x) \
{ TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); }
#define changenvalue(o,x) check_exp(ttisnumber(o), num_(o)=(x))
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
#define setfvalue(obj,x) \

@ -1,5 +1,5 @@
/*
** $Id: lopcodes.h,v 1.142 2011/07/15 12:50:29 roberto Exp $
** $Id: lopcodes.h,v 1.142.1.1 2013/04/12 18:48:47 roberto Exp $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lparser.h,v 1.70 2012/05/08 13:53:33 roberto Exp $
** $Id: lparser.h,v 1.70.1.1 2013/04/12 18:48:47 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 2.81 2012/06/08 15:14:04 roberto Exp $
** $Id: lstate.h,v 2.82.1.1 2013/04/12 18:48:47 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@ -137,7 +137,7 @@ typedef struct global_State {
UpVal uvhead; /* head of double-linked list of all open upvalues */
Mbuffer buff; /* temporary buffer for string concatenation */
int gcpause; /* size of pause between successive GCs */
int gcmajorinc; /* how much to wait for a major GC (only in gen. mode) */
int gcmajorinc; /* pause between major collections (only in gen. mode) */
int gcstepmul; /* GC `granularity' */
lua_CFunction panic; /* to be called in unprotected errors */
struct lua_State *mainthread;

@ -1,5 +1,5 @@
/*
** $Id: lstring.h,v 1.49 2012/02/01 21:57:15 roberto Exp $
** $Id: lstring.h,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $
** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: ltable.h,v 2.16 2011/08/17 20:26:47 roberto Exp $
** $Id: ltable.h,v 2.16.1.2 2013/08/30 15:49:41 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@ -17,6 +17,10 @@
#define invalidateTMcache(t) ((t)->flags = 0)
/* returns the key, given the value of a table entry */
#define keyfromval(v) \
(gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val))))
LUAI_FUNC const TValue *luaH_getint (Table *t, int key);
LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value);

@ -1,5 +1,5 @@
/*
** $Id: ltm.h,v 2.11 2011/02/28 17:32:10 roberto Exp $
** $Id: ltm.h,v 2.11.1.1 2013/04/12 18:48:47 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lua.h,v 1.283 2012/04/20 13:18:26 roberto Exp $
** $Id: lua.h,v 1.285.1.2 2013/11/11 12:09:16 roberto Exp $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
@ -19,11 +19,11 @@
#define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "2"
#define LUA_VERSION_NUM 502
#define LUA_VERSION_RELEASE "1"
#define LUA_VERSION_RELEASE "3"
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2012 Lua.org, PUC-Rio"
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2013 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
@ -119,6 +119,11 @@ typedef LUA_UNSIGNED lua_Unsigned;
#endif
/*
** RCS ident string
*/
extern const char lua_ident[];
/*
** state manipulation
@ -413,7 +418,7 @@ struct lua_Debug {
/******************************************************************************
* Copyright (C) 1994-2012 Lua.org, PUC-Rio.
* Copyright (C) 1994-2013 Lua.org, PUC-Rio.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the

@ -1,5 +1,5 @@
/*
** $Id: luaconf.h,v 1.172 2012/05/11 14:14:42 roberto Exp $
** $Id: luaconf.h,v 1.176.1.1 2013/04/12 18:48:47 roberto Exp $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
@ -44,7 +44,7 @@
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#define LUA_USE_READLINE /* needs some extra libraries */
#define LUA_USE_STRTODHEX /* assume 'strtod' handles hexa formats */
#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */
#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
#define LUA_USE_LONGLONG /* assume support for long long */
#endif
@ -53,7 +53,7 @@
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* does not need -ldl */
#define LUA_USE_READLINE /* needs an extra library: -lreadline */
#define LUA_USE_STRTODHEX /* assume 'strtod' handles hexa formats */
#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */
#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */
#define LUA_USE_LONGLONG /* assume support for long long */
#endif
@ -106,6 +106,8 @@
LUA_CDIR"?.so;" "./?.so"
#endif /* } */
#define LUA_PATH "DFHACK_LUA_PATH"
#define LUA_CPATH "DFHACK_LUA_CPATH"
/*
@@ LUA_DIRSEP is the directory separator (for submodules).
@ -405,10 +407,16 @@
#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
/*
@@ l_mathop allows the addition of an 'l' or 'f' to all math operations
*/
#define l_mathop(x) (x)
/*
@@ lua_str2number converts a decimal numeric string to a number.
@@ lua_strx2number converts an hexadecimal numeric string to a number.
** In C99, 'strtod' do both conversions. C89, however, has no function
** In C99, 'strtod' does both conversions. C89, however, has no function
** to convert floating hexadecimal strings to numbers. For these
** systems, you can leave 'lua_strx2number' undefined and Lua will
** provide its own implementation.
@ -427,8 +435,8 @@
/* the following operations need the math library */
#if defined(lobject_c) || defined(lvm_c)
#include <math.h>
#define luai_nummod(L,a,b) ((a) - floor((a)/(b))*(b))
#define luai_numpow(L,a,b) (pow(a,b))
#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b))
#define luai_numpow(L,a,b) (l_mathop(pow)(a,b))
#endif
/* these are quite standard operations */
@ -465,13 +473,12 @@
** Some tricks with doubles
*/
#if defined(LUA_CORE) && \
defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
/*
** The next definitions activate some tricks to speed up the
** conversion from doubles to integer types, mainly to LUA_UNSIGNED.
**
@@ MS_ASMTRICK uses Microsoft assembler to avoid clashes with a
@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a
** DirectX idiosyncrasy.
**
@@ LUA_IEEE754TRICK uses a trick that should work on any machine
@ -495,7 +502,7 @@
/* Microsoft compiler on a Pentium (32 bit) ? */
#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */
#define MS_ASMTRICK
#define LUA_MSASMTRICK
#define LUA_IEEEENDIAN 0
#define LUA_NANTRICK

@ -1,5 +1,5 @@
/*
** $Id: lualib.h,v 1.43 2011/12/08 12:11:37 roberto Exp $
** $Id: lualib.h,v 1.43.1.1 2013/04/12 18:48:47 roberto Exp $
** Lua standard libraries
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lundump.h,v 1.39 2012/05/08 13:53:33 roberto Exp $
** $Id: lundump.h,v 1.39.1.1 2013/04/12 18:48:47 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lvm.h,v 2.17 2011/05/31 18:27:56 roberto Exp $
** $Id: lvm.h,v 2.18.1.1 2013/04/12 18:48:47 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@ -19,8 +19,7 @@
#define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2))
#define luaV_rawequalobj(t1,t2) \
(ttisequal(t1,t2) && luaV_equalobj_(NULL,t1,t2))
#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2)
/* not to called directly */

@ -1,5 +1,5 @@
/*
** $Id: lzio.h,v 1.26 2011/07/15 12:48:03 roberto Exp $
** $Id: lzio.h,v 1.26.1.1 2013/04/12 18:48:47 roberto Exp $
** Buffered streams
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lapi.c,v 2.164 2012/06/08 15:14:04 roberto Exp $
** $Id: lapi.c,v 2.171.1.1 2013/04/12 18:48:47 roberto Exp $
** Lua API
** See Copyright Notice in lua.h
*/
@ -40,7 +40,16 @@ const char lua_ident[] =
/* corresponding test */
#define isvalid(o) ((o) != luaO_nilobject)
#define api_checkvalidindex(L, i) api_check(L, isvalid(i), "invalid index")
/* test for pseudo index */
#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX)
/* test for valid but not pseudo index */
#define isstackindex(i, o) (isvalid(o) && !ispseudo(i))
#define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index")
#define api_checkstackindex(L, i, o) \
api_check(L, isstackindex(i, o), "index not in the stack")
static TValue *index2addr (lua_State *L, int idx) {
@ -51,7 +60,7 @@ static TValue *index2addr (lua_State *L, int idx) {
if (o >= L->top) return NONVALIDVALUE;
else return o;
}
else if (idx > LUA_REGISTRYINDEX) {
else if (!ispseudo(idx)) { /* negative index */
api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
return L->top + idx;
}
@ -142,7 +151,7 @@ LUA_API const lua_Number *lua_version (lua_State *L) {
** convert an acceptable stack index into an absolute index
*/
LUA_API int lua_absindex (lua_State *L, int idx) {
return (idx > 0 || idx <= LUA_REGISTRYINDEX)
return (idx > 0 || ispseudo(idx))
? idx
: cast_int(L->top - L->ci->func + idx);
}
@ -174,7 +183,7 @@ LUA_API void lua_remove (lua_State *L, int idx) {
StkId p;
lua_lock(L);
p = index2addr(L, idx);
api_checkvalidindex(L, p);
api_checkstackindex(L, idx, p);
while (++p < L->top) setobjs2s(L, p-1, p);
L->top--;
lua_unlock(L);
@ -186,8 +195,9 @@ LUA_API void lua_insert (lua_State *L, int idx) {
StkId q;
lua_lock(L);
p = index2addr(L, idx);
api_checkvalidindex(L, p);
for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);
api_checkstackindex(L, idx, p);
for (q = L->top; q > p; q--) /* use L->top as a temporary */
setobjs2s(L, q, q - 1);
setobjs2s(L, p, L->top);
lua_unlock(L);
}
@ -217,7 +227,6 @@ LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
TValue *fr;
lua_lock(L);
fr = index2addr(L, fromidx);
api_checkvalidindex(L, fr);
moveto(L, fr, toidx);
lua_unlock(L);
}
@ -281,7 +290,7 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
}
LUA_API void lua_arith (lua_State *L, int op) {
LUA_API void lua_arith (lua_State *L, int op) {
StkId o1; /* 1st operand */
StkId o2; /* 2nd operand */
lua_lock(L);
@ -295,7 +304,7 @@ LUA_API void lua_arith (lua_State *L, int op) {
o1 = L->top - 2;
o2 = L->top - 1;
if (ttisnumber(o1) && ttisnumber(o2)) {
changenvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2)));
setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2)));
}
else
luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD));
@ -611,7 +620,6 @@ LUA_API void lua_gettable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
api_checkvalidindex(L, t);
luaV_gettable(L, t, L->top - 1, L->top - 1);
lua_unlock(L);
}
@ -621,7 +629,6 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
api_checkvalidindex(L, t);
setsvalue2s(L, L->top, luaS_new(L, k));
api_incr_top(L);
luaV_gettable(L, t, L->top - 1, L->top - 1);
@ -709,7 +716,6 @@ LUA_API void lua_getuservalue (lua_State *L, int idx) {
StkId o;
lua_lock(L);
o = index2addr(L, idx);
api_checkvalidindex(L, o);
api_check(L, ttisuserdata(o), "userdata expected");
if (uvalue(o)->env) {
sethvalue(L, L->top, uvalue(o)->env);
@ -743,7 +749,6 @@ LUA_API void lua_settable (lua_State *L, int idx) {
lua_lock(L);
api_checknelems(L, 2);
t = index2addr(L, idx);
api_checkvalidindex(L, t);
luaV_settable(L, t, L->top - 2, L->top - 1);
L->top -= 2; /* pop index and value */
lua_unlock(L);
@ -755,7 +760,6 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
lua_lock(L);
api_checknelems(L, 1);
t = index2addr(L, idx);
api_checkvalidindex(L, t);
setsvalue2s(L, L->top++, luaS_new(L, k));
luaV_settable(L, t, L->top - 1, L->top - 2);
L->top -= 2; /* pop value and key */
@ -811,7 +815,6 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
lua_lock(L);
api_checknelems(L, 1);
obj = index2addr(L, objindex);
api_checkvalidindex(L, obj);
if (ttisnil(L->top - 1))
mt = NULL;
else {
@ -821,9 +824,10 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
switch (ttypenv(obj)) {
case LUA_TTABLE: {
hvalue(obj)->metatable = mt;
if (mt)
if (mt) {
luaC_objbarrierback(L, gcvalue(obj), mt);
luaC_checkfinalizer(L, gcvalue(obj), mt);
}
break;
}
case LUA_TUSERDATA: {
@ -850,7 +854,6 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) {
lua_lock(L);
api_checknelems(L, 1);
o = index2addr(L, idx);
api_checkvalidindex(L, o);
api_check(L, ttisuserdata(o), "userdata expected");
if (ttisnil(L->top - 1))
uvalue(o)->env = NULL;
@ -937,7 +940,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
func = 0;
else {
StkId o = index2addr(L, errfunc);
api_checkvalidindex(L, o);
api_checkstackindex(L, errfunc, o);
func = savestack(L, o);
}
c.func = L->top - (nargs+1); /* function to be called */
@ -1006,7 +1009,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
}
LUA_API int lua_status (lua_State *L) {
LUA_API int lua_status (lua_State *L) {
return L->status;
}
@ -1103,7 +1106,7 @@ LUA_API int lua_error (lua_State *L) {
lua_lock(L);
api_checknelems(L, 1);
luaG_errormsg(L);
lua_unlock(L);
/* code unreachable; will unlock when control actually leaves the kernel */
return 0; /* to avoid warnings */
}

@ -1,5 +1,5 @@
/*
** $Id: lauxlib.c,v 1.244 2012/05/31 20:28:45 roberto Exp $
** $Id: lauxlib.c,v 1.248.1.1 2013/04/12 18:48:47 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@ -84,7 +84,7 @@ static void pushfuncname (lua_State *L, lua_Debug *ar) {
if (*ar->namewhat != '\0') /* is there a name? */
lua_pushfstring(L, "function " LUA_QS, ar->name);
else if (*ar->what == 'm') /* main? */
lua_pushfstring(L, "main chunk");
lua_pushliteral(L, "main chunk");
else if (*ar->what == 'C') {
if (pushglobalfuncname(L, ar)) {
lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
@ -158,7 +158,8 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
if (strcmp(ar.namewhat, "method") == 0) {
narg--; /* do not count `self' */
if (narg == 0) /* error is in the self argument itself? */
return luaL_error(L, "calling " LUA_QS " on bad self", ar.name);
return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
ar.name, extramsg);
}
if (ar.name == NULL)
ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?";
@ -214,7 +215,7 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
if (fname)
lua_pushfstring(L, "%s: %s", fname, strerror(en));
else
lua_pushfstring(L, "%s", strerror(en));
lua_pushstring(L, strerror(en));
lua_pushinteger(L, en);
return 3;
}
@ -438,7 +439,7 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
if (B->size - B->n < sz) { /* not enough space? */
char *newbuff;
size_t newsize = B->size * 2; /* double buffer size */
if (newsize - B->n < sz) /* not bit enough? */
if (newsize - B->n < sz) /* not big enough? */
newsize = B->n + sz;
if (newsize < B->n || newsize - B->n < sz)
luaL_error(L, "buffer too large");
@ -598,7 +599,7 @@ static int skipBOM (LoadF *lf) {
lf->n = 0;
do {
c = getc(lf->f);
if (c == EOF || c != *(unsigned char *)p++) return c;
if (c == EOF || c != *(const unsigned char *)p++) return c;
lf->buff[lf->n++] = c; /* to be read by the parser */
} while (*p != '\0');
lf->n = 0; /* prefix matched; discard it */

@ -1,5 +1,5 @@
/*
** $Id: lbaselib.c,v 1.274 2012/04/27 14:13:19 roberto Exp $
** $Id: lbaselib.c,v 1.276.1.1 2013/04/12 18:48:47 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
@ -242,10 +242,16 @@ static int luaB_ipairs (lua_State *L) {
}
static int load_aux (lua_State *L, int status) {
if (status == LUA_OK)
static int load_aux (lua_State *L, int status, int envidx) {
if (status == LUA_OK) {
if (envidx != 0) { /* 'env' parameter? */
lua_pushvalue(L, envidx); /* environment for loaded function */
if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
lua_pop(L, 1); /* remove 'env' if not used by previous call */
}
return 1;
else {
}
else { /* error (message is on top of the stack) */
lua_pushnil(L);
lua_insert(L, -2); /* put before error message */
return 2; /* return nil plus error message */
@ -256,13 +262,9 @@ static int load_aux (lua_State *L, int status) {
static int luaB_loadfile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
const char *mode = luaL_optstring(L, 2, NULL);
int env = !lua_isnone(L, 3); /* 'env' parameter? */
int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
int status = luaL_loadfilex(L, fname, mode);
if (status == LUA_OK && env) { /* 'env' parameter? */
lua_pushvalue(L, 3);
lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */
}
return load_aux(L, status);
return load_aux(L, status, env);
}
@ -307,9 +309,9 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
static int luaB_load (lua_State *L) {
int status;
size_t l;
int top = lua_gettop(L);
const char *s = lua_tolstring(L, 1, &l);
const char *mode = luaL_optstring(L, 3, "bt");
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
if (s != NULL) { /* loading a string? */
const char *chunkname = luaL_optstring(L, 2, s);
status = luaL_loadbufferx(L, s, l, chunkname, mode);
@ -320,11 +322,7 @@ static int luaB_load (lua_State *L) {
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
status = lua_load(L, generic_reader, NULL, chunkname, mode);
}
if (status == LUA_OK && top >= 4) { /* is there an 'env' argument */
lua_pushvalue(L, 4); /* environment for loaded function */
lua_setupvalue(L, -2, 1); /* set it as 1st upvalue */
}
return load_aux(L, status);
return load_aux(L, status, env);
}
/* }====================================================== */
@ -338,7 +336,8 @@ static int dofilecont (lua_State *L) {
static int luaB_dofile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
lua_settop(L, 1);
if (luaL_loadfile(L, fname) != LUA_OK) lua_error(L);
if (luaL_loadfile(L, fname) != LUA_OK)
return lua_error(L);
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
return dofilecont(L);
}

@ -1,5 +1,5 @@
/*
** $Id: lbitlib.c,v 1.16 2011/06/20 16:35:23 roberto Exp $
** $Id: lbitlib.c,v 1.18.1.2 2013/07/09 18:01:41 roberto Exp $
** Standard library for bitwise operations
** See Copyright Notice in lua.h
*/
@ -129,7 +129,8 @@ static int b_rot (lua_State *L, int i) {
b_uint r = luaL_checkunsigned(L, 1);
i &= (LUA_NBITS - 1); /* i = i % NBITS */
r = trim(r);
r = (r << i) | (r >> (LUA_NBITS - i));
if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */
r = (r << i) | (r >> (LUA_NBITS - i));
lua_pushunsigned(L, trim(r));
return 1;
}
@ -147,7 +148,9 @@ static int b_rrot (lua_State *L) {
/*
** get field and width arguments for field-manipulation functions,
** checking whether they are valid
** checking whether they are valid.
** ('luaL_error' called without 'return' to avoid later warnings about
** 'width' being used uninitialized.)
*/
static int fieldargs (lua_State *L, int farg, int *width) {
int f = luaL_checkint(L, farg);

@ -1,5 +1,5 @@
/*
** $Id: lcode.c,v 2.60 2011/08/30 16:26:41 roberto Exp $
** $Id: lcode.c,v 2.62.1.1 2013/04/12 18:48:47 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@ -330,10 +330,9 @@ int luaK_numberK (FuncState *fs, lua_Number r) {
setnvalue(&o, r);
if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */
/* use raw representation as key to avoid numeric problems */
setsvalue(L, L->top, luaS_newlstr(L, (char *)&r, sizeof(r)));
incr_top(L);
n = addk(fs, L->top - 1, &o);
L->top--;
setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r)));
n = addk(fs, L->top - 1, &o);
L->top--;
}
else
n = addk(fs, &o, &o); /* regular case */
@ -426,7 +425,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
luaK_nil(fs, reg, 1);
break;
}
case VFALSE: case VTRUE: {
case VFALSE: case VTRUE: {
luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
break;
}

@ -1,5 +1,5 @@
/*
** $Id: lcorolib.c,v 1.4 2012/04/27 18:59:04 roberto Exp $
** $Id: lcorolib.c,v 1.5.1.1 2013/04/12 18:48:47 roberto Exp $
** Coroutine Library
** See Copyright Notice in lua.h
*/
@ -73,7 +73,7 @@ static int luaB_auxwrap (lua_State *L) {
lua_insert(L, -2);
lua_concat(L, 2);
}
lua_error(L); /* propagate error */
return lua_error(L); /* propagate error */
}
return r;
}

@ -1,5 +1,5 @@
/*
** $Id: lctype.c,v 1.11 2011/10/03 16:19:23 roberto Exp $
** $Id: lctype.c,v 1.11.1.1 2013/04/12 18:48:47 roberto Exp $
** 'ctype' functions for Lua
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: ldblib.c,v 1.132 2012/01/19 20:14:44 roberto Exp $
** $Id: ldblib.c,v 1.132.1.1 2013/04/12 18:48:47 roberto Exp $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: ldebug.c,v 2.89 2012/01/20 22:05:50 roberto Exp $
** $Id: ldebug.c,v 2.90.1.3 2013/05/16 16:04:15 roberto Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
@ -196,7 +196,7 @@ static void funcinfo (lua_Debug *ar, Closure *cl) {
static void collectvalidlines (lua_State *L, Closure *f) {
if (noLuaClosure(f)) {
setnilvalue(L->top);
incr_top(L);
api_incr_top(L);
}
else {
int i;
@ -204,7 +204,7 @@ static void collectvalidlines (lua_State *L, Closure *f) {
int *lineinfo = f->l.p->lineinfo;
Table *t = luaH_new(L); /* new table to store active lines */
sethvalue(L, L->top, t); /* push it on stack */
incr_top(L);
api_incr_top(L);
setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */
for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */
luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */
@ -285,7 +285,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
status = auxgetinfo(L, what, ar, cl, ci);
if (strchr(what, 'f')) {
setobjs2s(L, L->top, func);
incr_top(L);
api_incr_top(L);
}
if (strchr(what, 'L'))
collectvalidlines(L, cl);
@ -327,12 +327,20 @@ static void kname (Proto *p, int pc, int c, const char **name) {
}
static int filterpc (int pc, int jmptarget) {
if (pc < jmptarget) /* is code conditional (inside a jump)? */
return -1; /* cannot know who sets that register */
else return pc; /* current position sets that register */
}
/*
** try to find last instruction before 'lastpc' that modified register 'reg'
*/
static int findsetreg (Proto *p, int lastpc, int reg) {
int pc;
int setreg = -1; /* keep last instruction that changed 'reg' */
int jmptarget = 0; /* any code before this address is conditional */
for (pc = 0; pc < lastpc; pc++) {
Instruction i = p->code[pc];
OpCode op = GET_OPCODE(i);
@ -341,33 +349,38 @@ static int findsetreg (Proto *p, int lastpc, int reg) {
case OP_LOADNIL: {
int b = GETARG_B(i);
if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */
setreg = pc;
setreg = filterpc(pc, jmptarget);
break;
}
case OP_TFORCALL: {
if (reg >= a + 2) setreg = pc; /* affect all regs above its base */
if (reg >= a + 2) /* affect all regs above its base */
setreg = filterpc(pc, jmptarget);
break;
}
case OP_CALL:
case OP_TAILCALL: {
if (reg >= a) setreg = pc; /* affect all registers above base */
if (reg >= a) /* affect all registers above base */
setreg = filterpc(pc, jmptarget);
break;
}
case OP_JMP: {
int b = GETARG_sBx(i);
int dest = pc + 1 + b;
/* jump is forward and do not skip `lastpc'? */
if (pc < dest && dest <= lastpc)
pc += b; /* do the jump */
if (pc < dest && dest <= lastpc) {
if (dest > jmptarget)
jmptarget = dest; /* update 'jmptarget' */
}
break;
}
case OP_TEST: {
if (reg == a) setreg = pc; /* jumped code can change 'a' */
if (reg == a) /* jumped code can change 'a' */
setreg = filterpc(pc, jmptarget);
break;
}
default:
if (testAMode(op) && reg == a) /* any instruction that set A */
setreg = pc;
setreg = filterpc(pc, jmptarget);
break;
}
}
@ -518,7 +531,7 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
lua_assert(!ttisstring(p1) && !ttisnumber(p2));
lua_assert(!ttisstring(p1) && !ttisnumber(p1));
luaG_typeerror(L, p1, "concatenate");
}
@ -563,7 +576,7 @@ l_noret luaG_errormsg (lua_State *L) {
if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
setobjs2s(L, L->top, L->top - 1); /* move argument */
setobjs2s(L, L->top - 1, errfunc); /* push function */
incr_top(L);
L->top++;
luaD_call(L, L->top - 2, 1, 0); /* call it */
}
luaD_throw(L, LUA_ERRRUN);

@ -1,5 +1,5 @@
/*
** $Id: ldo.c,v 2.105 2012/06/08 15:14:04 roberto Exp $
** $Id: ldo.c,v 2.108.1.3 2013/11/08 18:22:50 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@ -260,6 +260,7 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
StkId base, fixed;
lua_assert(actual >= nfixargs);
/* move fixed parameters to final position */
luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */
fixed = L->top - actual; /* first fixed argument */
base = L->top; /* final position of first argument */
for (i=0; i<nfixargs; i++) {
@ -311,6 +312,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
ci->top = L->top + LUA_MINSTACK;
lua_assert(ci->top <= L->stack_last);
ci->callstatus = 0;
luaC_checkGC(L); /* stack grow uses memory */
if (L->hookmask & LUA_MASKCALL)
luaD_hook(L, LUA_HOOKCALL, -1);
lua_unlock(L);
@ -323,12 +325,18 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
case LUA_TLCL: { /* Lua function: prepare its call */
StkId base;
Proto *p = clLvalue(func)->p;
luaD_checkstack(L, p->maxstacksize);
func = restorestack(L, funcr);
n = cast_int(L->top - func) - 1; /* number of real arguments */
luaD_checkstack(L, p->maxstacksize);
for (; n < p->numparams; n++)
setnilvalue(L->top++); /* complete missing arguments */
base = (!p->is_vararg) ? func + 1 : adjust_varargs(L, p, n);
if (!p->is_vararg) {
func = restorestack(L, funcr);
base = func + 1;
}
else {
base = adjust_varargs(L, p, n);
func = restorestack(L, funcr); /* previous call can change stack */
}
ci = next_ci(L); /* now 'enter' new function */
ci->nresults = nresults;
ci->func = func;
@ -338,6 +346,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
ci->u.l.savedpc = p->code; /* starting point */
ci->callstatus = CIST_LUA;
L->top = ci->top;
luaC_checkGC(L); /* stack grow uses memory */
if (L->hookmask & LUA_MASKCALL)
callhook(L, ci);
return 0;
@ -393,7 +402,6 @@ void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
luaV_execute(L); /* call it */
if (!allowyield) L->nny--;
L->nCcalls--;
luaC_checkGC(L);
}
@ -402,10 +410,11 @@ static void finishCcall (lua_State *L) {
int n;
lua_assert(ci->u.c.k != NULL); /* must have a continuation */
lua_assert(L->nny == 0);
/* finish 'lua_pcallk' */
if (ci->callstatus & CIST_YPCALL)
if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */
ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */
L->errfunc = ci->u.c.old_errfunc;
/* finish 'lua_callk' */
}
/* finish 'lua_callk'/'lua_pcall' */
adjustresults(L, ci->nresults);
/* call continuation function */
if (!(ci->callstatus & CIST_STAT)) /* no call status? */
@ -476,7 +485,7 @@ static int recover (lua_State *L, int status) {
static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
L->top = firstArg; /* remove args from the stack */
setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */
incr_top(L);
api_incr_top(L);
luaD_throw(L, -1); /* jump back to 'lua_resume' */
}
@ -525,6 +534,7 @@ static void resume (lua_State *L, void *ud) {
LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
int status;
int oldnny = L->nny; /* save 'nny' */
lua_lock(L);
luai_userstateresume(L, nargs);
L->nCcalls = (from) ? from->nCcalls + 1 : 1;
@ -546,7 +556,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
}
lua_assert(status == L->status);
}
L->nny = 1; /* do not allow yields */
L->nny = oldnny; /* restore 'nny' */
L->nCcalls--;
lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
lua_unlock(L);
@ -561,7 +571,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) {
api_checknelems(L, nresults);
if (L->nny > 0) {
if (L != G(L)->mainthread)
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
luaG_runerror(L, "attempt to yield across a C-call boundary");
else
luaG_runerror(L, "attempt to yield from outside a coroutine");
}

@ -1,5 +1,5 @@
/*
** $Id: ldump.c,v 2.17 2012/01/23 23:02:10 roberto Exp $
** $Id: ldump.c,v 2.17.1.1 2013/04/12 18:48:47 roberto Exp $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lfunc.c,v 2.29 2012/05/08 13:53:33 roberto Exp $
** $Id: lfunc.c,v 2.30.1.1 2013/04/12 18:48:47 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@ -52,12 +52,12 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
while (*pp != NULL && (p = gco2uv(*pp))->v >= level) {
GCObject *o = obj2gco(p);
lua_assert(p->v != &p->u.value);
lua_assert(!isold(o) || isold(obj2gco(L)));
if (p->v == level) { /* found a corresponding upvalue? */
if (isdead(g, o)) /* is it dead? */
changewhite(o); /* resurrect it */
return p;
}
resetoldbit(o); /* may create a newer upval after this one */
pp = &p->next;
}
/* not found: create a new one */

@ -1,5 +1,5 @@
/*
** $Id: lgc.c,v 2.133 2012/05/31 21:28:59 roberto Exp $
** $Id: lgc.c,v 2.140.1.2 2013/04/26 18:22:05 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@ -43,21 +43,12 @@
*/
#define STEPMULADJ 200
/*
** macro to adjust 'pause': 'pause' is actually used like
** 'pause / PAUSEADJ' (value chosen by tests)
*/
#define PAUSEADJ 200
/*
** standard negative debt for GC; a reasonable "time" to wait before
** starting a new cycle
*/
#define stddebtest(g,e) (-cast(l_mem, (e)/PAUSEADJ) * g->gcpause)
#define stddebt(g) stddebtest(g, gettotalbytes(g))
#define PAUSEADJ 100
/*
@ -144,9 +135,9 @@ static int iscleared (global_State *g, const TValue *o) {
void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
lua_assert(isgenerational(g) || g->gcstate != GCSpause);
lua_assert(g->gcstate != GCSpause);
lua_assert(gch(o)->tt != LUA_TTABLE);
if (keepinvariant(g)) /* must keep invariant? */
if (keepinvariantout(g)) /* must keep invariant? */
reallymarkobject(g, v); /* restore invariant */
else { /* sweep phase */
lua_assert(issweepphase(g));
@ -343,7 +334,7 @@ static void remarkupvals (global_State *g) {
** mark root set and reset all gray lists, to start a new
** incremental (or full) collection
*/
static void markroot (global_State *g) {
static void restartcollection (global_State *g) {
g->gray = g->grayagain = NULL;
g->weak = g->allweak = g->ephemeron = NULL;
markobject(g, g->mainthread);
@ -459,7 +450,7 @@ static lu_mem traversetable (global_State *g, Table *h) {
else /* not weak */
traversestrongtable(g, h);
return sizeof(Table) + sizeof(TValue) * h->sizearray +
sizeof(Node) * sizenode(h);
sizeof(Node) * cast(size_t, sizenode(h));
}
@ -502,17 +493,24 @@ static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
static lu_mem traversestack (global_State *g, lua_State *th) {
int n = 0;
StkId o = th->stack;
if (o == NULL)
return 1; /* stack not completely built yet */
for (; o < th->top; o++)
for (; o < th->top; o++) /* mark live elements in the stack */
markvalue(g, o);
if (g->gcstate == GCSatomic) { /* final traversal? */
StkId lim = th->stack + th->stacksize; /* real end of stack */
for (; o < lim; o++) /* clear not-marked stack slice */
setnilvalue(o);
}
return sizeof(lua_State) + sizeof(TValue) * th->stacksize;
else { /* count call infos to compute size */
CallInfo *ci;
for (ci = &th->base_ci; ci != th->ci; ci = ci->next)
n++;
}
return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
sizeof(CallInfo) * n;
}
@ -796,7 +794,7 @@ static GCObject *udata2finalize (global_State *g) {
g->allgc = o;
resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */
lua_assert(!isold(o)); /* see MOVE OLD rule */
if (!keepinvariant(g)) /* not keeping invariant? */
if (!keepinvariantout(g)) /* not keeping invariant? */
makewhite(g, o); /* "sweep" object */
return o;
}
@ -855,7 +853,7 @@ static void separatetobefnz (lua_State *L, int all) {
while ((curr = *p) != NULL) { /* traverse all finalizable objects */
lua_assert(!isfinalized(curr));
lua_assert(testbit(gch(curr)->marked, SEPARATED));
if (!(all || iswhite(curr))) /* not being collected? */
if (!(iswhite(curr) || all)) /* not being collected? */
p = &gch(curr)->next; /* don't bother with it */
else {
l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */
@ -891,7 +889,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
ho->next = g->finobj; /* link it in list 'finobj' */
g->finobj = o;
l_setbit(ho->marked, SEPARATED); /* mark it as such */
if (!keepinvariant(g)) /* not keeping invariant? */
if (!keepinvariantout(g)) /* not keeping invariant? */
makewhite(g, o); /* "sweep" object */
else
resetoldbit(o); /* see MOVE OLD rule */
@ -908,6 +906,21 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
*/
/*
** set a reasonable "time" to wait before starting a new GC cycle;
** cycle will start when memory use hits threshold
*/
static void setpause (global_State *g, l_mem estimate) {
l_mem debt, threshold;
estimate = estimate / PAUSEADJ; /* adjust 'estimate' */
threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */
? estimate * g->gcpause /* no overflow */
: MAX_LMEM; /* overflow; truncate to maximum */
debt = -cast(l_mem, threshold - gettotalbytes(g));
luaE_setdebt(g, debt);
}
#define sweepphases \
(bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep))
@ -918,7 +931,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
** object inside the list (instead of to the header), so that the real
** sweep do not need to skip objects created between "now" and the start
** of the real sweep.
** Returns how many objects it sweeped.
** Returns how many objects it swept.
*/
static int entersweep (lua_State *L) {
global_State *g = G(L);
@ -985,7 +998,7 @@ void luaC_freeallobjects (lua_State *L) {
static l_mem atomic (lua_State *L) {
global_State *g = G(L);
l_mem work = -g->GCmemtrav; /* start counting work */
l_mem work = -cast(l_mem, g->GCmemtrav); /* start counting work */
GCObject *origweak, *origall;
lua_assert(!iswhite(obj2gco(g->mainthread)));
markobject(g, L); /* mark running thread */
@ -1028,12 +1041,10 @@ static lu_mem singlestep (lua_State *L) {
global_State *g = G(L);
switch (g->gcstate) {
case GCSpause: {
g->GCmemtrav = 0; /* start to count memory traversed */
if (!isgenerational(g))
markroot(g); /* start a new collection */
/* in any case, root must be marked at this point */
lua_assert(!iswhite(obj2gco(g->mainthread))
&& !iswhite(gcvalue(&g->l_registry)));
/* start to count memory traversed */
g->GCmemtrav = g->strt.size * sizeof(GCObject*);
lua_assert(!isgenerational(g));
restartcollection(g);
g->gcstate = GCSpropagate;
return g->GCmemtrav;
}
@ -1105,18 +1116,23 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
static void generationalcollection (lua_State *L) {
global_State *g = G(L);
lua_assert(g->gcstate == GCSpropagate);
if (g->GCestimate == 0) { /* signal for another major collection? */
luaC_fullgc(L, 0); /* perform a full regular collection */
g->GCestimate = gettotalbytes(g); /* update control */
}
else {
lu_mem estimate = g->GCestimate;
luaC_runtilstate(L, ~bitmask(GCSpause)); /* run complete cycle */
luaC_runtilstate(L, bitmask(GCSpause));
luaC_runtilstate(L, bitmask(GCSpause)); /* run complete (minor) cycle */
g->gcstate = GCSpropagate; /* skip restart */
if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc)
g->GCestimate = 0; /* signal for a major collection */
else
g->GCestimate = estimate; /* keep estimate from last major coll. */
}
luaE_setdebt(g, stddebt(g));
setpause(g, gettotalbytes(g));
lua_assert(g->gcstate == GCSpropagate);
}
@ -1124,7 +1140,7 @@ static void incstep (lua_State *L) {
global_State *g = G(L);
l_mem debt = g->GCdebt;
int stepmul = g->gcstepmul;
if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values */
if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values (and 0) */
/* convert debt from Kb to 'work units' (avoid zero debt and overflows) */
debt = (debt / STEPMULADJ) + 1;
debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
@ -1133,10 +1149,11 @@ static void incstep (lua_State *L) {
debt -= work;
} while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
if (g->gcstate == GCSpause)
debt = stddebtest(g, g->GCestimate); /* pause until next cycle */
else
setpause(g, g->GCestimate); /* pause until next cycle */
else {
debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */
luaE_setdebt(g, debt);
luaE_setdebt(g, debt);
}
}
@ -1172,7 +1189,6 @@ void luaC_step (lua_State *L) {
void luaC_fullgc (lua_State *L, int isemergency) {
global_State *g = G(L);
int origkind = g->gckind;
int someblack = keepinvariant(g);
lua_assert(origkind != KGC_EMERGENCY);
if (isemergency) /* do not run finalizers during emergency GC */
g->gckind = KGC_EMERGENCY;
@ -1180,22 +1196,21 @@ void luaC_fullgc (lua_State *L, int isemergency) {
g->gckind = KGC_NORMAL;
callallpendingfinalizers(L, 1);
}
if (someblack) { /* may there be some black objects? */
if (keepinvariant(g)) { /* may there be some black objects? */
/* must sweep all objects to turn them back to white
(as white has not changed, nothing will be collected) */
entersweep(L);
}
/* finish any pending sweep phase to start a new cycle */
luaC_runtilstate(L, bitmask(GCSpause));
/* run entire collector */
luaC_runtilstate(L, ~bitmask(GCSpause));
luaC_runtilstate(L, bitmask(GCSpause));
luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */
luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */
if (origkind == KGC_GEN) { /* generational mode? */
/* generational mode must always start in propagate phase */
/* generational mode must be kept in propagate phase */
luaC_runtilstate(L, bitmask(GCSpropagate));
}
g->gckind = origkind;
luaE_setdebt(g, stddebt(g));
setpause(g, gettotalbytes(g));
if (!isemergency) /* do not run finalizers during emergency GC */
callallpendingfinalizers(L, 1);
}

@ -1,5 +1,5 @@
/*
** $Id: linit.c,v 1.32 2011/04/08 19:17:36 roberto Exp $
** $Id: linit.c,v 1.32.1.1 2013/04/12 18:48:47 roberto Exp $
** Initialization of libraries for lua.c and other clients
** See Copyright Notice in lua.h
*/

@ -1,17 +1,17 @@
/*
** $Id: liolib.c,v 2.108 2011/11/25 12:50:03 roberto Exp $
** $Id: liolib.c,v 2.112.1.1 2013/04/12 18:48:47 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
/*
** POSIX idiosyncrasy!
** This definition must come before the inclusion of 'stdio.h'; it
** should not affect non-POSIX systems
*/
#if !defined(_FILE_OFFSET_BITS)
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE 1
#define _FILE_OFFSET_BITS 64
#endif
@ -29,6 +29,20 @@
#include "lualib.h"
#if !defined(lua_checkmode)
/*
** Check whether 'mode' matches '[rwa]%+?b?'.
** Change this macro to accept other modes for 'fopen' besides
** the standard ones.
*/
#define lua_checkmode(mode) \
(*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \
(*mode != '+' || ++mode) && /* skip if char is '+' */ \
(*mode != 'b' || ++mode) && /* skip if char is 'b' */ \
(*mode == '\0'))
#endif
/*
** {======================================================
@ -66,36 +80,37 @@
/*
** {======================================================
** lua_fseek/lua_ftell: configuration for longer offsets
** lua_fseek: configuration for longer offsets
** =======================================================
*/
#if !defined(lua_fseek) /* { */
#if !defined(lua_fseek) && !defined(LUA_ANSI) /* { */
#if defined(LUA_USE_POSIX)
#if defined(LUA_USE_POSIX) /* { */
#define l_fseek(f,o,w) fseeko(f,o,w)
#define l_ftell(f) ftello(f)
#define l_seeknum off_t
#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \
&& defined(_MSC_VER) && (_MSC_VER >= 1400)
&& defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */
/* Windows (but not DDK) and Visual C++ 2005 or higher */
#define l_fseek(f,o,w) _fseeki64(f,o,w)
#define l_ftell(f) _ftelli64(f)
#define l_seeknum __int64
#else
#endif /* } */
#endif /* } */
#if !defined(l_fseek) /* default definitions */
#define l_fseek(f,o,w) fseek(f,o,w)
#define l_ftell(f) ftell(f)
#define l_seeknum long
#endif
#endif /* } */
/* }====================================================== */
@ -212,14 +227,8 @@ static int io_open (lua_State *L) {
const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r");
LStream *p = newfile(L);
int i = 0;
/* check whether 'mode' matches '[rwa]%+?b?' */
if (!(mode[i] != '\0' && strchr("rwa", mode[i++]) != NULL &&
(mode[i] != '+' || ++i) && /* skip if char is '+' */
(mode[i] != 'b' || ++i) && /* skip if char is 'b' */
(mode[i] == '\0')))
return luaL_error(L, "invalid mode " LUA_QS
" (should match " LUA_QL("[rwa]%%+?b?") ")", mode);
const char *md = mode; /* to traverse/check mode */
luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode");
p->f = fopen(filename, mode);
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
}

@ -1,5 +1,5 @@
/*
** $Id: llex.c,v 2.61 2012/01/23 23:05:51 roberto Exp $
** $Id: llex.c,v 2.63.1.2 2013/08/30 15:49:41 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@ -73,16 +73,16 @@ void luaX_init (lua_State *L) {
const char *luaX_token2str (LexState *ls, int token) {
if (token < FIRST_RESERVED) {
if (token < FIRST_RESERVED) { /* single-byte symbols? */
lua_assert(token == cast(unsigned char, token));
return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) :
luaO_pushfstring(ls->L, "char(%d)", token);
}
else {
const char *s = luaX_tokens[token - FIRST_RESERVED];
if (token < TK_EOS)
if (token < TK_EOS) /* fixed format (symbols and reserved words)? */
return luaO_pushfstring(ls->L, LUA_QS, s);
else
else /* names, strings, and numerals */
return s;
}
}
@ -133,6 +133,9 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
setbvalue(o, 1); /* t[string] = true */
luaC_checkGC(L);
}
else { /* string already present */
ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */
}
L->top--; /* remove string from stack */
return ts;
}
@ -313,7 +316,7 @@ static int readhexaesc (LexState *ls) {
int c[3], i; /* keep input for error message */
int r = 0; /* result accumulator */
c[0] = 'x'; /* for error message */
for (i = 1; i < 3; i++) { /* read two hexa digits */
for (i = 1; i < 3; i++) { /* read two hexadecimal digits */
c[i] = next(ls);
if (!lisxdigit(c[i]))
escerror(ls, c, i + 1, "hexadecimal digit expected");

@ -1,5 +1,5 @@
/*
** $Id: lmathlib.c,v 1.81 2012/05/18 17:47:53 roberto Exp $
** $Id: lmathlib.c,v 1.83.1.1 2013/04/12 18:48:47 roberto Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
@ -17,106 +17,101 @@
#include "lualib.h"
/* macro 'l_tg' allows the addition of an 'l' or 'f' to all math operations */
#if !defined(l_tg)
#define l_tg(x) (x)
#endif
#undef PI
#define PI (l_tg(3.1415926535897932384626433832795))
#define RADIANS_PER_DEGREE (PI/180.0)
#define PI ((lua_Number)(3.1415926535897932384626433832795))
#define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0))
static int math_abs (lua_State *L) {
lua_pushnumber(L, l_tg(fabs)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
return 1;
}
static int math_sin (lua_State *L) {
lua_pushnumber(L, l_tg(sin)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1)));
return 1;
}
static int math_sinh (lua_State *L) {
lua_pushnumber(L, l_tg(sinh)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1)));
return 1;
}
static int math_cos (lua_State *L) {
lua_pushnumber(L, l_tg(cos)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1)));
return 1;
}
static int math_cosh (lua_State *L) {
lua_pushnumber(L, l_tg(cosh)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1)));
return 1;
}
static int math_tan (lua_State *L) {
lua_pushnumber(L, l_tg(tan)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1)));
return 1;
}
static int math_tanh (lua_State *L) {
lua_pushnumber(L, l_tg(tanh)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1)));
return 1;
}
static int math_asin (lua_State *L) {
lua_pushnumber(L, l_tg(asin)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1)));
return 1;
}
static int math_acos (lua_State *L) {
lua_pushnumber(L, l_tg(acos)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1)));
return 1;
}
static int math_atan (lua_State *L) {
lua_pushnumber(L, l_tg(atan)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(atan)(luaL_checknumber(L, 1)));
return 1;
}
static int math_atan2 (lua_State *L) {
lua_pushnumber(L, l_tg(atan2)(luaL_checknumber(L, 1),
lua_pushnumber(L, l_mathop(atan2)(luaL_checknumber(L, 1),
luaL_checknumber(L, 2)));
return 1;
}
static int math_ceil (lua_State *L) {
lua_pushnumber(L, l_tg(ceil)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(ceil)(luaL_checknumber(L, 1)));
return 1;
}
static int math_floor (lua_State *L) {
lua_pushnumber(L, l_tg(floor)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(floor)(luaL_checknumber(L, 1)));
return 1;
}
static int math_fmod (lua_State *L) {
lua_pushnumber(L, l_tg(fmod)(luaL_checknumber(L, 1),
lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1),
luaL_checknumber(L, 2)));
return 1;
}
static int math_modf (lua_State *L) {
lua_Number ip;
lua_Number fp = l_tg(modf)(luaL_checknumber(L, 1), &ip);
lua_Number fp = l_mathop(modf)(luaL_checknumber(L, 1), &ip);
lua_pushnumber(L, ip);
lua_pushnumber(L, fp);
return 2;
}
static int math_sqrt (lua_State *L) {
lua_pushnumber(L, l_tg(sqrt)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1)));
return 1;
}
static int math_pow (lua_State *L) {
lua_pushnumber(L, l_tg(pow)(luaL_checknumber(L, 1),
luaL_checknumber(L, 2)));
lua_Number x = luaL_checknumber(L, 1);
lua_Number y = luaL_checknumber(L, 2);
lua_pushnumber(L, l_mathop(pow)(x, y));
return 1;
}
@ -124,11 +119,11 @@ static int math_log (lua_State *L) {
lua_Number x = luaL_checknumber(L, 1);
lua_Number res;
if (lua_isnoneornil(L, 2))
res = l_tg(log)(x);
res = l_mathop(log)(x);
else {
lua_Number base = luaL_checknumber(L, 2);
if (base == 10.0) res = l_tg(log10)(x);
else res = l_tg(log)(x)/l_tg(log)(base);
if (base == (lua_Number)10.0) res = l_mathop(log10)(x);
else res = l_mathop(log)(x)/l_mathop(log)(base);
}
lua_pushnumber(L, res);
return 1;
@ -136,13 +131,13 @@ static int math_log (lua_State *L) {
#if defined(LUA_COMPAT_LOG10)
static int math_log10 (lua_State *L) {
lua_pushnumber(L, l_tg(log10)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1)));
return 1;
}
#endif
static int math_exp (lua_State *L) {
lua_pushnumber(L, l_tg(exp)(luaL_checknumber(L, 1)));
lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1)));
return 1;
}
@ -158,14 +153,15 @@ static int math_rad (lua_State *L) {
static int math_frexp (lua_State *L) {
int e;
lua_pushnumber(L, l_tg(frexp)(luaL_checknumber(L, 1), &e));
lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e));
lua_pushinteger(L, e);
return 2;
}
static int math_ldexp (lua_State *L) {
lua_pushnumber(L, l_tg(ldexp)(luaL_checknumber(L, 1),
luaL_checkint(L, 2)));
lua_Number x = luaL_checknumber(L, 1);
int ep = luaL_checkint(L, 2);
lua_pushnumber(L, l_mathop(ldexp)(x, ep));
return 1;
}
@ -210,15 +206,15 @@ static int math_random (lua_State *L) {
}
case 1: { /* only upper limit */
lua_Number u = luaL_checknumber(L, 1);
luaL_argcheck(L, 1.0 <= u, 1, "interval is empty");
lua_pushnumber(L, l_tg(floor)(r*u) + 1.0); /* int in [1, u] */
luaL_argcheck(L, (lua_Number)1.0 <= u, 1, "interval is empty");
lua_pushnumber(L, l_mathop(floor)(r*u) + (lua_Number)(1.0)); /* [1, u] */
break;
}
case 2: { /* lower and upper limits */
lua_Number l = luaL_checknumber(L, 1);
lua_Number u = luaL_checknumber(L, 2);
luaL_argcheck(L, l <= u, 2, "interval is empty");
lua_pushnumber(L, l_tg(floor)(r*(u-l+1)) + l); /* int in [l, u] */
lua_pushnumber(L, l_mathop(floor)(r*(u-l+1)) + l); /* [l, u] */
break;
}
default: return luaL_error(L, "wrong number of arguments");

@ -1,5 +1,5 @@
/*
** $Id: lmem.c,v 1.84 2012/05/23 15:41:53 roberto Exp $
** $Id: lmem.c,v 1.84.1.1 2013/04/12 18:48:47 roberto Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: loadlib.c,v 1.111 2012/05/30 12:33:44 roberto Exp $
** $Id: loadlib.c,v 1.111.1.1 2013/04/12 18:48:47 roberto Exp $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
**

@ -1,5 +1,5 @@
/*
** $Id: lobject.c,v 2.55 2011/11/30 19:30:16 roberto Exp $
** $Id: lobject.c,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@ -104,7 +104,7 @@ static int isneg (const char **s) {
static lua_Number readhexa (const char **s, lua_Number r, int *count) {
for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */
r = (r * 16.0) + cast_num(luaO_hexavalue(cast_uchar(**s)));
r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s)));
(*count)++;
}
return r;
@ -149,7 +149,7 @@ static lua_Number lua_strx2number (const char *s, char **endptr) {
*endptr = cast(char *, s); /* valid up to here */
ret:
if (neg) r = -r;
return ldexp(r, e);
return l_mathop(ldexp)(r, e);
}
#endif
@ -171,8 +171,7 @@ int luaO_str2d (const char *s, size_t len, lua_Number *result) {
static void pushstr (lua_State *L, const char *str, size_t l) {
setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
incr_top(L);
setsvalue2s(L, L->top++, luaS_newlstr(L, str, l));
}
@ -182,8 +181,8 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
for (;;) {
const char *e = strchr(fmt, '%');
if (e == NULL) break;
setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));
incr_top(L);
luaD_checkstack(L, 2); /* fmt + item */
pushstr(L, fmt, e - fmt);
switch (*(e+1)) {
case 's': {
const char *s = va_arg(argp, char *);
@ -198,13 +197,11 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
break;
}
case 'd': {
setnvalue(L->top, cast_num(va_arg(argp, int)));
incr_top(L);
setnvalue(L->top++, cast_num(va_arg(argp, int)));
break;
}
case 'f': {
setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
incr_top(L);
setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
break;
}
case 'p': {
@ -226,6 +223,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
n += 2;
fmt = e+2;
}
luaD_checkstack(L, 1);
pushstr(L, fmt, strlen(fmt));
if (n > 0) luaV_concat(L, n + 1);
return svalue(L->top - 1);

@ -1,5 +1,5 @@
/*
** $Id: lopcodes.c,v 1.49 2012/05/14 13:34:18 roberto Exp $
** $Id: lopcodes.c,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: loslib.c,v 1.39 2012/05/23 15:37:09 roberto Exp $
** $Id: loslib.c,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
@ -98,7 +98,7 @@ static int os_remove (lua_State *L) {
static int os_rename (lua_State *L) {
const char *fromname = luaL_checkstring(L, 1);
const char *toname = luaL_checkstring(L, 2);
return luaL_fileresult(L, rename(fromname, toname) == 0, fromname);
return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
}

@ -1,5 +1,5 @@
/*
** $Id: lparser.c,v 2.128 2012/05/20 14:51:23 roberto Exp $
** $Id: lparser.c,v 2.130.1.1 2013/04/12 18:48:47 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@ -245,7 +245,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
static int searchvar (FuncState *fs, TString *n) {
int i;
for (i=fs->nactvar-1; i >= 0; i--) {
for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {
if (luaS_eqstr(n, getlocvar(fs, i)->varname))
return i;
}
@ -512,12 +512,15 @@ static Proto *addprototype (LexState *ls) {
/*
** codes instruction to create new closure in parent function
** codes instruction to create new closure in parent function.
** The OP_CLOSURE instruction must use the last available register,
** so that, if it invokes the GC, the GC knows which registers
** are in use at that time.
*/
static void codeclosure (LexState *ls, expdesc *v) {
FuncState *fs = ls->fs->prev;
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1));
luaK_exp2nextreg(fs, v); /* fix it at stack top (for GC) */
luaK_exp2nextreg(fs, v); /* fix it at the last register */
}

@ -1,5 +1,5 @@
/*
** $Id: lstate.c,v 2.98 2012/05/30 12:33:44 roberto Exp $
** $Id: lstate.c,v 2.99.1.2 2013/11/08 17:45:31 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@ -48,7 +48,7 @@
*/
#if !defined(luai_makeseed)
#include <time.h>
#define luai_makeseed() cast(size_t, time(NULL))
#define luai_makeseed() cast(unsigned int, time(NULL))
#endif
@ -192,6 +192,8 @@ static void f_luaopen (lua_State *L, void *ud) {
g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
luaS_fix(g->memerrmsg); /* it should never be collected */
g->gcrunning = 1; /* allow gc */
g->version = lua_version(NULL);
luai_userstateopen(L);
}
@ -222,6 +224,8 @@ static void close_state (lua_State *L) {
global_State *g = G(L);
luaF_close(L, L->stack); /* close all upvalues for this thread */
luaC_freeallobjects(L); /* collect all objects */
if (g->version) /* closing a fully built state? */
luai_userstateclose(L);
luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
luaZ_freebuffer(L, &g->buff);
freestack(L);
@ -287,7 +291,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
setnilvalue(&g->l_registry);
luaZ_initbuffer(L, &g->buff);
g->panic = NULL;
g->version = lua_version(NULL);
g->version = NULL;
g->gcstate = GCSpause;
g->allgc = NULL;
g->finobj = NULL;
@ -306,8 +310,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
close_state(L);
L = NULL;
}
else
luai_userstateopen(L);
return L;
}
@ -315,7 +317,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
LUA_API void lua_close (lua_State *L) {
L = G(L)->mainthread; /* only the main thread can be closed */
lua_lock(L);
luai_userstateclose(L);
close_state(L);
}

@ -1,5 +1,5 @@
/*
** $Id: lstring.c,v 2.24 2012/05/11 14:14:42 roberto Exp $
** $Id: lstring.c,v 2.26.1.1 2013/04/12 18:48:47 roberto Exp $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@ -49,7 +49,7 @@ int luaS_eqstr (TString *a, TString *b) {
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
unsigned int h = seed ^ l;
unsigned int h = seed ^ cast(unsigned int, l);
size_t l1;
size_t step = (l >> LUAI_HASHLIMIT) + 1;
for (l1 = l; l1 >= step; l1 -= step)
@ -139,7 +139,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
o = gch(o)->next) {
TString *ts = rawgco2ts(o);
if (h == ts->tsv.hash &&
ts->tsv.len == l &&
l == ts->tsv.len &&
(memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */
changewhite(o); /* resurrect it */

@ -1,5 +1,5 @@
/*
** $Id: lstrlib.c,v 1.176 2012/05/23 15:37:09 roberto Exp $
** $Id: lstrlib.c,v 1.178.1.1 2013/04/12 18:48:47 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@ -194,7 +194,9 @@ static int str_dump (lua_State *L) {
#define CAP_UNFINISHED (-1)
#define CAP_POSITION (-2)
typedef struct MatchState {
int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
const char *src_init; /* init of source string */
const char *src_end; /* end ('\0') of source string */
const char *p_end; /* end ('\0') of pattern */
@ -207,6 +209,16 @@ typedef struct MatchState {
} MatchState;
/* recursive function */
static const char *match (MatchState *ms, const char *s, const char *p);
/* maximum recursion depth for 'match' */
#if !defined(MAXCCALLS)
#define MAXCCALLS 200
#endif
#define L_ESC '%'
#define SPECIALS "^$*+?.([%-"
@ -294,19 +306,22 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
}
static int singlematch (int c, const char *p, const char *ep) {
switch (*p) {
case '.': return 1; /* matches any char */
case L_ESC: return match_class(c, uchar(*(p+1)));
case '[': return matchbracketclass(c, p, ep-1);
default: return (uchar(*p) == c);
static int singlematch (MatchState *ms, const char *s, const char *p,
const char *ep) {
if (s >= ms->src_end)
return 0;
else {
int c = uchar(*s);
switch (*p) {
case '.': return 1; /* matches any char */
case L_ESC: return match_class(c, uchar(*(p+1)));
case '[': return matchbracketclass(c, p, ep-1);
default: return (uchar(*p) == c);
}
}
}
static const char *match (MatchState *ms, const char *s, const char *p);
static const char *matchbalance (MatchState *ms, const char *s,
const char *p) {
if (p >= ms->p_end - 1)
@ -331,7 +346,7 @@ static const char *matchbalance (MatchState *ms, const char *s,
static const char *max_expand (MatchState *ms, const char *s,
const char *p, const char *ep) {
ptrdiff_t i = 0; /* counts maximum expand for item */
while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))
while (singlematch(ms, s + i, p, ep))
i++;
/* keeps trying to match with the maximum repetitions */
while (i>=0) {
@ -349,7 +364,7 @@ static const char *min_expand (MatchState *ms, const char *s,
const char *res = match(ms, s, ep+1);
if (res != NULL)
return res;
else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
else if (singlematch(ms, s, p, ep))
s++; /* try with one more repetition */
else return NULL;
}
@ -393,79 +408,105 @@ static const char *match_capture (MatchState *ms, const char *s, int l) {
static const char *match (MatchState *ms, const char *s, const char *p) {
if (ms->matchdepth-- == 0)
luaL_error(ms->L, "pattern too complex");
init: /* using goto's to optimize tail recursion */
if (p == ms->p_end) /* end of pattern? */
return s; /* match succeeded */
switch (*p) {
case '(': { /* start capture */
if (*(p+1) == ')') /* position capture? */
return start_capture(ms, s, p+2, CAP_POSITION);
else
return start_capture(ms, s, p+1, CAP_UNFINISHED);
}
case ')': { /* end capture */
return end_capture(ms, s, p+1);
}
case '$': {
if ((p+1) == ms->p_end) /* is the `$' the last char in pattern? */
return (s == ms->src_end) ? s : NULL; /* check end of string */
else goto dflt;
}
case L_ESC: { /* escaped sequences not in the format class[*+?-]? */
switch (*(p+1)) {
case 'b': { /* balanced string? */
s = matchbalance(ms, s, p+2);
if (s == NULL) return NULL;
p+=4; goto init; /* else return match(ms, s, p+4); */
}
case 'f': { /* frontier? */
const char *ep; char previous;
p += 2;
if (*p != '[')
luaL_error(ms->L, "missing " LUA_QL("[") " after "
LUA_QL("%%f") " in pattern");
ep = classend(ms, p); /* points to what is next */
previous = (s == ms->src_init) ? '\0' : *(s-1);
if (matchbracketclass(uchar(previous), p, ep-1) ||
!matchbracketclass(uchar(*s), p, ep-1)) return NULL;
p=ep; goto init; /* else return match(ms, s, ep); */
}
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
case '8': case '9': { /* capture results (%0-%9)? */
s = match_capture(ms, s, uchar(*(p+1)));
if (s == NULL) return NULL;
p+=2; goto init; /* else return match(ms, s, p+2) */
}
default: goto dflt;
if (p != ms->p_end) { /* end of pattern? */
switch (*p) {
case '(': { /* start capture */
if (*(p + 1) == ')') /* position capture? */
s = start_capture(ms, s, p + 2, CAP_POSITION);
else
s = start_capture(ms, s, p + 1, CAP_UNFINISHED);
break;
}
}
default: dflt: { /* pattern class plus optional suffix */
const char *ep = classend(ms, p); /* points to what is next */
int m = s < ms->src_end && singlematch(uchar(*s), p, ep);
switch (*ep) {
case '?': { /* optional */
const char *res;
if (m && ((res=match(ms, s+1, ep+1)) != NULL))
return res;
p=ep+1; goto init; /* else return match(ms, s, ep+1); */
}
case '*': { /* 0 or more repetitions */
return max_expand(ms, s, p, ep);
}
case '+': { /* 1 or more repetitions */
return (m ? max_expand(ms, s+1, p, ep) : NULL);
case ')': { /* end capture */
s = end_capture(ms, s, p + 1);
break;
}
case '$': {
if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */
goto dflt; /* no; go to default */
s = (s == ms->src_end) ? s : NULL; /* check end of string */
break;
}
case L_ESC: { /* escaped sequences not in the format class[*+?-]? */
switch (*(p + 1)) {
case 'b': { /* balanced string? */
s = matchbalance(ms, s, p + 2);
if (s != NULL) {
p += 4; goto init; /* return match(ms, s, p + 4); */
} /* else fail (s == NULL) */
break;
}
case 'f': { /* frontier? */
const char *ep; char previous;
p += 2;
if (*p != '[')
luaL_error(ms->L, "missing " LUA_QL("[") " after "
LUA_QL("%%f") " in pattern");
ep = classend(ms, p); /* points to what is next */
previous = (s == ms->src_init) ? '\0' : *(s - 1);
if (!matchbracketclass(uchar(previous), p, ep - 1) &&
matchbracketclass(uchar(*s), p, ep - 1)) {
p = ep; goto init; /* return match(ms, s, ep); */
}
s = NULL; /* match failed */
break;
}
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
case '8': case '9': { /* capture results (%0-%9)? */
s = match_capture(ms, s, uchar(*(p + 1)));
if (s != NULL) {
p += 2; goto init; /* return match(ms, s, p + 2) */
}
break;
}
default: goto dflt;
}
case '-': { /* 0 or more repetitions (minimum) */
return min_expand(ms, s, p, ep);
break;
}
default: dflt: { /* pattern class plus optional suffix */
const char *ep = classend(ms, p); /* points to optional suffix */
/* does not match at least once? */
if (!singlematch(ms, s, p, ep)) {
if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */
p = ep + 1; goto init; /* return match(ms, s, ep + 1); */
}
else /* '+' or no suffix */
s = NULL; /* fail */
}
default: {
if (!m) return NULL;
s++; p=ep; goto init; /* else return match(ms, s+1, ep); */
else { /* matched once */
switch (*ep) { /* handle optional suffix */
case '?': { /* optional */
const char *res;
if ((res = match(ms, s + 1, ep + 1)) != NULL)
s = res;
else {
p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */
}
break;
}
case '+': /* 1 or more repetitions */
s++; /* 1 match already done */
/* go through */
case '*': /* 0 or more repetitions */
s = max_expand(ms, s, p, ep);
break;
case '-': /* 0 or more repetitions (minimum) */
s = min_expand(ms, s, p, ep);
break;
default: /* no suffix */
s++; p = ep; goto init; /* return match(ms, s + 1, ep); */
}
}
break;
}
}
}
ms->matchdepth++;
return s;
}
@ -561,12 +602,14 @@ static int str_find_aux (lua_State *L, int find) {
p++; lp--; /* skip anchor character */
}
ms.L = L;
ms.matchdepth = MAXCCALLS;
ms.src_init = s;
ms.src_end = s + ls;
ms.p_end = p + lp;
do {
const char *res;
ms.level = 0;
lua_assert(ms.matchdepth == MAXCCALLS);
if ((res=match(&ms, s1, p)) != NULL) {
if (find) {
lua_pushinteger(L, s1 - s + 1); /* start */
@ -600,6 +643,7 @@ static int gmatch_aux (lua_State *L) {
const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp);
const char *src;
ms.L = L;
ms.matchdepth = MAXCCALLS;
ms.src_init = s;
ms.src_end = s+ls;
ms.p_end = p + lp;
@ -608,6 +652,7 @@ static int gmatch_aux (lua_State *L) {
src++) {
const char *e;
ms.level = 0;
lua_assert(ms.matchdepth == MAXCCALLS);
if ((e = match(&ms, src, p)) != NULL) {
lua_Integer newstart = e-s;
if (e == src) newstart++; /* empty match? go at least one position */
@ -705,12 +750,14 @@ static int str_gsub (lua_State *L) {
p++; lp--; /* skip anchor character */
}
ms.L = L;
ms.matchdepth = MAXCCALLS;
ms.src_init = src;
ms.src_end = src+srcl;
ms.p_end = p + lp;
while (n < max_s) {
const char *e;
ms.level = 0;
lua_assert(ms.matchdepth == MAXCCALLS);
e = match(&ms, src, p);
if (e) {
n++;
@ -867,7 +914,7 @@ static int str_format (lua_State *L) {
nb = sprintf(buff, form, luaL_checkint(L, arg));
break;
}
case 'd': case 'i': {
case 'd': case 'i': {
lua_Number n = luaL_checknumber(L, arg);
LUA_INTFRM_T ni = (LUA_INTFRM_T)n;
lua_Number diff = n - (lua_Number)ni;
@ -877,7 +924,7 @@ static int str_format (lua_State *L) {
nb = sprintf(buff, form, ni);
break;
}
case 'o': case 'u': case 'x': case 'X': {
case 'o': case 'u': case 'x': case 'X': {
lua_Number n = luaL_checknumber(L, arg);
unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n;
lua_Number diff = n - (lua_Number)ni;
@ -887,7 +934,7 @@ static int str_format (lua_State *L) {
nb = sprintf(buff, form, ni);
break;
}
case 'e': case 'E': case 'f':
case 'e': case 'E': case 'f':
#if defined(LUA_USE_AFORMAT)
case 'a': case 'A':
#endif

@ -1,5 +1,5 @@
/*
** $Id: ltable.c,v 2.71 2012/05/23 15:37:09 roberto Exp $
** $Id: ltable.c,v 2.72.1.1 2013/04/12 18:48:47 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@ -480,13 +480,13 @@ const TValue *luaH_getstr (Table *t, TString *key) {
*/
const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) {
case LUA_TNIL: return luaO_nilobject;
case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key));
case LUA_TNIL: return luaO_nilobject;
case LUA_TNUMBER: {
int k;
lua_Number n = nvalue(key);
lua_number2int(k, n);
if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
if (luai_numeq(cast_num(k), n)) /* index is int? */
return luaH_getint(t, k); /* use specialized version */
/* else go through */
}

@ -1,5 +1,5 @@
/*
** $Id: ltablib.c,v 1.63 2011/11/28 17:26:30 roberto Exp $
** $Id: ltablib.c,v 1.65.1.1 2013/04/12 18:48:47 roberto Exp $
** Library for Table Manipulation
** See Copyright Notice in lua.h
*/
@ -16,8 +16,8 @@
#include "lualib.h"
#define aux_getn(L,n) \
(luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n))
#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n))
#if defined(LUA_COMPAT_MAXN)
@ -49,7 +49,7 @@ static int tinsert (lua_State *L) {
case 3: {
int i;
pos = luaL_checkint(L, 2); /* 2nd argument is the position */
if (pos > e) e = pos; /* `grow' array if necessary */
luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
for (i = e; i > pos; i--) { /* move up elements */
lua_rawgeti(L, 1, i-1);
lua_rawseti(L, 1, i); /* t[i] = t[i-1] */
@ -66,17 +66,17 @@ static int tinsert (lua_State *L) {
static int tremove (lua_State *L) {
int e = aux_getn(L, 1);
int pos = luaL_optint(L, 2, e);
if (!(1 <= pos && pos <= e)) /* position is outside bounds? */
return 0; /* nothing to remove */
int size = aux_getn(L, 1);
int pos = luaL_optint(L, 2, size);
if (pos != size) /* validate 'pos' if given */
luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
lua_rawgeti(L, 1, pos); /* result = t[pos] */
for ( ;pos<e; pos++) {
for ( ; pos < size; pos++) {
lua_rawgeti(L, 1, pos+1);
lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */
}
lua_pushnil(L);
lua_rawseti(L, 1, e); /* t[e] = nil */
lua_rawseti(L, 1, pos); /* t[pos] = nil */
return 1;
}

@ -1,5 +1,5 @@
/*
** $Id: ltm.c,v 2.14 2011/06/02 19:31:40 roberto Exp $
** $Id: ltm.c,v 2.14.1.1 2013/04/12 18:48:47 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lua.c,v 1.205 2012/05/23 15:37:09 roberto Exp $
** $Id: lua.c,v 1.206.1.1 2013/04/12 18:48:47 roberto Exp $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@ -237,7 +237,6 @@ static const char *get_prompt (lua_State *L, int firstline) {
lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
p = lua_tostring(L, -1);
if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
lua_pop(L, 1); /* remove global */
return p;
}
@ -263,7 +262,9 @@ static int pushline (lua_State *L, int firstline) {
char *b = buffer;
size_t l;
const char *prmt = get_prompt(L, firstline);
if (lua_readline(L, b, prmt) == 0)
int readstatus = lua_readline(L, b, prmt);
lua_pop(L, 1); /* remove result from 'get_prompt' */
if (readstatus == 0)
return 0; /* no input */
l = strlen(b);
if (l > 0 && b[l-1] == '\n') /* line ends with newline? */

@ -203,7 +203,7 @@ int main(int argc, char* argv[])
}
/*
** $Id: print.c,v 1.68 2011/09/30 10:21:20 lhf Exp $
** $Id: print.c,v 1.69 2013/07/04 01:03:46 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/
@ -251,7 +251,7 @@ static void PrintString(const TString* ts)
static void PrintConstant(const Proto* f, int i)
{
const TValue* o=&f->k[i];
switch (ttype(o))
switch (ttypenv(o))
{
case LUA_TNIL:
printf("nil");

@ -1,5 +1,5 @@
/*
** $Id: lundump.c,v 2.22 2012/05/08 13:53:33 roberto Exp $
** $Id: lundump.c,v 2.22.1.1 2013/04/12 18:48:47 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/

@ -1,5 +1,5 @@
/*
** $Id: lvm.c,v 2.152 2012/06/08 15:14:04 roberto Exp $
** $Id: lvm.c,v 2.155.1.1 2013/04/12 18:48:47 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@ -83,7 +83,7 @@ static void traceexec (lua_State *L) {
if (counthook)
L->hookcount = 1; /* undo decrement to zero */
ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
ci->callstatus |= CIST_HOOKYIELD; /* mark that it yieled */
ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
ci->func = L->top - 1; /* protect stack below results */
luaD_throw(L, LUA_YIELD);
}
@ -98,7 +98,6 @@ static void callTM (lua_State *L, const TValue *f, const TValue *p1,
setobj2s(L, L->top++, p2); /* 2nd argument */
if (!hasres) /* no result? 'p3' is third argument */
setobj2s(L, L->top++, p3); /* 3rd argument */
luaD_checkstack(L, 0);
/* metamethod may yield only when called from Lua code */
luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
if (hasres) { /* if has result, move it to its place */
@ -470,7 +469,7 @@ void luaV_finishOp (lua_State *L) {
L->top = ci->top; /* adjust results */
break;
}
case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:
case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:
break;
default: lua_assert(0);
}

@ -1,5 +1,5 @@
/*
** $Id: lzio.c,v 1.35 2012/05/14 13:34:18 roberto Exp $
** $Id: lzio.c,v 1.35.1.1 2013/04/12 18:48:47 roberto Exp $
** Buffered streams
** See Copyright Notice in lua.h
*/

@ -31,6 +31,9 @@ keybinding add Ctrl-Alt-S@dwarfmode/Default quicksave
keybinding add Ctrl-Shift-N gui/rename
keybinding add Ctrl-Shift-T "gui/rename unit-profession"
# a dfhack prompt in df. Sublime text like.
keybinding add Ctrl-Shift-P command-prompt
##############################
# Generic adv mode bindings #
##############################
@ -90,6 +93,9 @@ keybinding add Alt-A@dwarfmode/QueryBuilding/Some/SiegeEngine gui/siege-engine
# military weapon auto-select
keybinding add Ctrl-W@layer_military/Equip/Customize/View gui/choose-weapons
# military copy uniform
keybinding add Ctrl-C@layer_military/Uniforms gui/clone-uniform
# minecart Guide path
keybinding add Alt-P@dwarfmode/Hauling/DefineStop/Cond/Guide gui/guide-path

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

@ -811,6 +811,15 @@ bool Core::loadScriptFile(color_ostream &out, string fname, bool silent)
}
}
// Load dfhack.init in a dedicated thread (non-interactive console mode)
void fInitthread(void * iodata)
{
IODATA * iod = ((IODATA*) iodata);
Core * core = iod->core;
color_ostream_proxy out(core->getConsole());
core->loadScriptFile(out, "dfhack.init", true);
}
// A thread function... for the interactive console.
void fIOthread(void * iodata)
{
@ -822,7 +831,7 @@ void fIOthread(void * iodata)
main_history.load("dfhack.history");
Console & con = core->getConsole();
if(plug_mgr == 0 || core == 0)
if (plug_mgr == 0)
{
con.printerr("Something horrible happened in Core's constructor...\n");
return;
@ -1008,16 +1017,24 @@ bool Core::Init()
IODATA *temp = new IODATA;
temp->core = this;
temp->plug_mgr = plug_mgr;
HotkeyMutex = new mutex();
HotkeyCond = new condition_variable();
if (!is_text_mode)
{
cerr << "Starting IO thread.\n";
// create IO thread
thread * IO = new thread(fIOthread, (void *) temp);
}
else
{
cerr << "Starting dfhack.init thread.\n";
thread * init = new thread(fInitthread, (void *) temp);
}
cerr << "Starting DF input capture thread.\n";
// set up hotkey capture
HotkeyMutex = new mutex();
HotkeyCond = new condition_variable();
thread * HK = new thread(fHKthread, (void *) temp);
screen_window = new Windows::top_level_window();
screen_window->addChild(new Windows::dfhack_dummy(5,10));

@ -565,7 +565,7 @@ static int dfhack_matinfo_find(lua_State *state)
{
std::vector<std::string> tokens;
for (int i = 1; i < argc; i++)
for (int i = 1; i <= argc; i++)
tokens.push_back(luaL_checkstring(state, i));
info.find(tokens);
@ -1279,6 +1279,9 @@ static std::string getHackPath() { return Core::getInstance().getHackPath(); }
static bool isWorldLoaded() { return Core::getInstance().isWorldLoaded(); }
static bool isMapLoaded() { return Core::getInstance().isMapLoaded(); }
static std::string df2utf(std::string s) { return DF2UTF(s); }
static std::string utf2df(std::string s) { return UTF2DF(s); }
static const LuaWrapper::FunctionReg dfhack_module[] = {
WRAP(getOSType),
WRAP(getDFVersion),
@ -1288,6 +1291,8 @@ static const LuaWrapper::FunctionReg dfhack_module[] = {
WRAP(isWorldLoaded),
WRAP(isMapLoaded),
WRAPM(Translation, TranslateName),
WRAP(df2utf),
WRAP(utf2df),
{ NULL, NULL }
};
@ -1302,6 +1307,10 @@ static const LuaWrapper::FunctionReg dfhack_gui_module[] = {
WRAPM(Gui, getSelectedUnit),
WRAPM(Gui, getSelectedItem),
WRAPM(Gui, getSelectedBuilding),
WRAPM(Gui, writeToGamelog),
WRAPM(Gui, makeAnnouncement),
WRAPM(Gui, addCombatReport),
WRAPM(Gui, addCombatReportAuto),
WRAPM(Gui, showAnnouncement),
WRAPM(Gui, showZoomAnnouncement),
WRAPM(Gui, showPopupAnnouncement),
@ -1322,6 +1331,8 @@ static const LuaWrapper::FunctionReg dfhack_job_module[] = {
WRAPM(Job,getSpecificRef),
WRAPM(Job,getHolder),
WRAPM(Job,getWorker),
WRAPM(Job,setJobCooldown),
WRAPM(Job,removeWorker),
WRAPM(Job,checkBuildingsNow),
WRAPM(Job,checkDesignationsNow),
WRAPM(Job,isSuitableItem),
@ -1363,6 +1374,9 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, getVisibleName),
WRAPM(Units, getIdentity),
WRAPM(Units, getNemesis),
WRAPM(Units, isHidingCurse),
WRAPM(Units, getPhysicalAttrValue),
WRAPM(Units, getMentalAttrValue),
WRAPM(Units, isCrazed),
WRAPM(Units, isOpposedToLife),
WRAPM(Units, hasExtravision),
@ -1379,6 +1393,7 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, getEffectiveSkill),
WRAPM(Units, getExperience),
WRAPM(Units, computeMovementSpeed),
WRAPM(Units, computeSlowdownFactor),
WRAPM(Units, getProfessionName),
WRAPM(Units, getCasteProfessionName),
WRAPM(Units, getProfessionColor),
@ -2194,7 +2209,21 @@ static int internal_diffscan(lua_State *L)
lua_pushnil(L);
return 1;
}
static int internal_getDir(lua_State *L)
{
luaL_checktype(L,1,LUA_TSTRING);
std::string dir=lua_tostring(L,1);
std::vector<std::string> files;
DFHack::getdir(dir,files);
lua_newtable(L);
for(int i=0;i<files.size();i++)
{
lua_pushinteger(L,i+1);
lua_pushstring(L,files[i].c_str());
lua_settable(L,-3);
}
return 1;
}
static const luaL_Reg dfhack_internal_funcs[] = {
{ "getAddress", internal_getAddress },
{ "setAddress", internal_setAddress },
@ -2207,6 +2236,7 @@ static const luaL_Reg dfhack_internal_funcs[] = {
{ "memcmp", internal_memcmp },
{ "memscan", internal_memscan },
{ "diffscan", internal_diffscan },
{ "getDir", internal_getDir },
{ NULL, NULL }
};

@ -246,28 +246,6 @@ static int getdir (string dir, vector<string> &files)
return 0;
}
bool Process::getThreadIDs(vector<uint32_t> & threads )
{
stringstream ss;
vector<string> subdirs;
if(getdir("/proc/self/task/",subdirs) != 0)
{
//FIXME: needs exceptions. this is a fatal error
cerr << "unable to enumerate threads. This is BAD!" << endl;
return false;
}
threads.clear();
for(size_t i = 0; i < subdirs.size();i++)
{
uint32_t tid;
if(sscanf(subdirs[i].c_str(),"%d", &tid))
{
threads.push_back(tid);
}
}
return true;
}
uint32_t Process::getTickCount()
{
struct timeval tp;

@ -181,28 +181,6 @@ static int getdir (string dir, vector<string> &files)
return 0;
}
bool Process::getThreadIDs(vector<uint32_t> & threads )
{
stringstream ss;
vector<string> subdirs;
if(getdir("/proc/self/task/",subdirs) != 0)
{
//FIXME: needs exceptions. this is a fatal error
cerr << "unable to enumerate threads. This is BAD!" << endl;
return false;
}
threads.clear();
for(size_t i = 0; i < subdirs.size();i++)
{
uint32_t tid;
if(sscanf(subdirs[i].c_str(),"%d", &tid))
{
threads.push_back(tid);
}
}
return true;
}
uint32_t Process::getTickCount()
{
struct timeval tp;

@ -24,63 +24,12 @@ distribution.
#include "Internal.h"
#define _WIN32_WINNT 0x0501 // needed for INPUT struct
#define WINVER 0x0501 // OpenThread(), PSAPI, Toolhelp32
#define _WIN32_WINNT 0x0501
#define WINVER 0x0501
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <psapi.h>
#include <tlhelp32.h>
typedef LONG NTSTATUS;
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
// FIXME: it is uncertain how these map to 64bit
typedef struct _DEBUG_BUFFER
{
HANDLE SectionHandle;
PVOID SectionBase;
PVOID RemoteSectionBase;
ULONG SectionBaseDelta;
HANDLE EventPairHandle;
ULONG Unknown[2];
HANDLE RemoteThreadHandle;
ULONG InfoClassMask;
ULONG SizeOfInfo;
ULONG AllocatedSize;
ULONG SectionSize;
PVOID ModuleInformation;
PVOID BackTraceInformation;
PVOID HeapInformation;
PVOID LockInformation;
PVOID Reserved[8];
} DEBUG_BUFFER, *PDEBUG_BUFFER;
typedef struct _DEBUG_HEAP_INFORMATION
{
ULONG Base; // 0×00
ULONG Flags; // 0×04
USHORT Granularity; // 0×08
USHORT Unknown; // 0x0A
ULONG Allocated; // 0x0C
ULONG Committed; // 0×10
ULONG TagCount; // 0×14
ULONG BlockCount; // 0×18
ULONG Reserved[7]; // 0x1C
PVOID Tags; // 0×38
PVOID Blocks; // 0x3C
} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION;
// RtlQueryProcessDebugInformation.DebugInfoClassMask constants
#define PDI_MODULES 0x01
#define PDI_BACKTRACE 0x02
#define PDI_HEAPS 0x04
#define PDI_HEAP_TAGS 0x08
#define PDI_HEAP_BLOCKS 0x10
#define PDI_LOCKS 0x20
extern "C" __declspec(dllimport) NTSTATUS __stdcall RtlQueryProcessDebugInformation( IN ULONG ProcessId, IN ULONG DebugInfoClassMask, IN OUT PDEBUG_BUFFER DebugBuffer);
extern "C" __declspec(dllimport) PDEBUG_BUFFER __stdcall RtlCreateQueryDebugBuffer( IN ULONG Size, IN BOOLEAN EventPair);
extern "C" __declspec(dllimport) NTSTATUS __stdcall RtlDestroyQueryDebugBuffer( IN PDEBUG_BUFFER DebugBuffer);
#include <cstring>
#include <cstdio>
@ -106,8 +55,6 @@ namespace DFHack
sections = 0;
};
HANDLE my_handle;
vector <HANDLE> threads;
vector <HANDLE> stoppedthreads;
uint32_t my_pid;
IMAGE_NT_HEADERS pe_header;
IMAGE_SECTION_HEADER * sections;
@ -138,7 +85,7 @@ Process::Process(VersionInfoFactory * factory)
// read from this process
try
{
uint32_t pe_offset = Process::readDWord(d->base+0x3C);
uint32_t pe_offset = readDWord(d->base+0x3C);
read(d->base + pe_offset, sizeof(d->pe_header), (uint8_t *)&(d->pe_header));
const size_t sectionsSize = sizeof(IMAGE_SECTION_HEADER) * d->pe_header.FileHeader.NumberOfSections;
d->sections = (IMAGE_SECTION_HEADER *) malloc(sectionsSize);
@ -151,24 +98,10 @@ Process::Process(VersionInfoFactory * factory)
VersionInfo* vinfo = factory->getVersionInfoByPETimestamp(d->pe_header.FileHeader.TimeDateStamp);
if(vinfo)
{
vector<uint32_t> threads_ids;
if(!getThreadIDs( threads_ids ))
{
// thread enumeration failed.
return;
}
identified = true;
// give the process a data model and memory layout fixed for the base of first module
my_descriptor = new VersionInfo(*vinfo);
my_descriptor->rebaseTo(getBase());
for(size_t i = 0; i < threads_ids.size();i++)
{
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD) threads_ids[i]);
if(hThread)
d->threads.push_back(hThread);
else
cerr << "Unable to open thread :" << hex << (DWORD) threads_ids[i] << endl;
}
}
}
@ -176,41 +109,10 @@ Process::~Process()
{
// destroy our rebased copy of the memory descriptor
delete my_descriptor;
for(size_t i = 0; i < d->threads.size(); i++)
CloseHandle(d->threads[i]);
if(d->sections != NULL)
free(d->sections);
}
bool Process::getThreadIDs(vector<uint32_t> & threads )
{
HANDLE AllThreads = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
AllThreads = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( AllThreads == INVALID_HANDLE_VALUE )
{
return false;
}
te32.dwSize = sizeof(THREADENTRY32 );
if( !Thread32First( AllThreads, &te32 ) )
{
CloseHandle( AllThreads );
return false;
}
do
{
if( te32.th32OwnerProcessID == d->my_pid )
{
threads.push_back(te32.th32ThreadID);
}
} while( Thread32Next(AllThreads, &te32 ) );
CloseHandle( AllThreads );
return true;
}
/*
typedef struct _MEMORY_BASIC_INFORMATION
{

@ -55,6 +55,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "modules/Units.h"
#include "modules/World.h"
#include "LuaTools.h"
#include "DataDefs.h"
#include "df/ui.h"
#include "df/ui_advmode.h"
@ -656,6 +658,8 @@ CoreService::CoreService() {
addMethod("CoreSuspend", &CoreService::CoreSuspend, SF_DONT_SUSPEND);
addMethod("CoreResume", &CoreService::CoreResume, SF_DONT_SUSPEND);
addMethod("RunLua", &CoreService::RunLua);
// Functions:
addFunction("GetVersion", GetVersion, SF_DONT_SUSPEND);
addFunction("GetDFVersion", GetDFVersion, SF_DONT_SUSPEND);
@ -730,3 +734,85 @@ command_result CoreService::CoreResume(color_ostream &stream, const EmptyMessage
cnt->set_value(--suspend_depth);
return CR_OK;
}
namespace {
struct LuaFunctionData {
command_result rv;
const dfproto::CoreRunLuaRequest *in;
StringListMessage *out;
};
}
command_result CoreService::RunLua(color_ostream &stream,
const dfproto::CoreRunLuaRequest *in,
StringListMessage *out)
{
auto L = Lua::Core::State;
LuaFunctionData data = { CR_FAILURE, in, out };
lua_pushcfunction(L, doRunLuaFunction);
lua_pushlightuserdata(L, &data);
if (!Lua::Core::SafeCall(stream, 1, 0))
return CR_FAILURE;
return data.rv;
}
int CoreService::doRunLuaFunction(lua_State *L)
{
color_ostream &out = *Lua::GetOutput(L);
auto &args = *(LuaFunctionData*)lua_touserdata(L, 1);
// Verify module name
std::string module = args.in->module();
size_t len = module.size();
bool valid = false;
if (len > 4)
{
if (module.substr(0,4) == "rpc.")
valid = true;
else if ((module[len-4] == '.' || module[len-4] == '-') && module.substr(len-3) != "rpc")
valid = true;
}
if (!valid)
{
args.rv = CR_WRONG_USAGE;
out.printerr("Only modules named rpc.* or *.rpc or *-rpc may be called.\n");
return 0;
}
// Prepare function and arguments
lua_settop(L, 0);
if (!Lua::PushModulePublic(out, L, module.c_str(), args.in->function().c_str())
|| lua_isnil(L, 1))
{
args.rv = CR_NOT_FOUND;
return 0;
}
luaL_checkstack(L, args.in->arguments_size(), "too many arguments");
for (int i = 0; i < args.in->arguments_size(); i++)
lua_pushstring(L, args.in->arguments(i).c_str());
// Call
lua_call(L, args.in->arguments_size(), LUA_MULTRET);
// Store results
int nresults = lua_gettop(L);
for (int i = 1; i <= nresults; i++)
{
size_t len;
const char *data = lua_tolstring(L, i, &len);
args.out->add_value(std::string(data, len));
}
args.rv = CR_OK;
return 0;
}

@ -72,20 +72,54 @@ int main (int argc, char *argv[])
if (!client.connect())
return 2;
// Call the command
std::vector<std::string> args;
for (int i = 2; i < argc; i++)
args.push_back(argv[i]);
command_result rv;
command_result rv = client.run_command(argv[1], args);
if (rv != CR_OK) {
if (rv == CR_NOT_IMPLEMENTED)
out.printerr("%s is not a recognized command.\n", argv[1]);
if (strcmp(argv[1], "--lua") == 0)
{
if (argc <= 3)
{
fprintf(stderr, "Usage: dfhack-run --lua <module> <function> [args...]\n");
return 2;
}
RemoteFunction<dfproto::CoreRunLuaRequest,dfproto::StringListMessage> run_call;
if (!run_call.bind(&client, "RunLua"))
{
fprintf(stderr, "No RunLua protocol function found.");
return 3;
}
run_call.in()->set_module(argv[2]);
run_call.in()->set_function(argv[3]);
for (int i = 4; i < argc; i++)
run_call.in()->add_arguments(argv[i]);
rv = run_call();
out.flush();
if (rv == CR_OK)
{
for (int i = 0; i < run_call.out()->value_size(); i++)
printf("%s%s", (i>0?"\t":""), run_call.out()->value(i).c_str());
printf("\n");
}
}
else
{
// Call the command
std::vector<std::string> args;
for (int i = 2; i < argc; i++)
args.push_back(argv[i]);
return 1;
rv = client.run_command(argv[1], args);
}
out.flush();
if (rv != CR_OK)
return 1;
return 0;
}

@ -390,7 +390,7 @@ namespace df
}
virtual bool resize(void *ptr, int size) {
((container*)ptr)->resize(size*8);
((container*)ptr)->resize((size+7)/8);
return true;
}

@ -43,29 +43,6 @@ namespace DFHack
class VersionInfoFactory;
class PlatformSpecific;
/**
* A type for storing an extended OS Process ID (combines PID and the time the process was started for unique identification)
* \ingroup grp_context
*/
struct ProcessID
{
ProcessID(const uint64_t _time, const uint64_t _pid): time(_time), pid(_pid){};
bool operator==(const ProcessID &other) const
{
return (other.time == time && other.pid == pid);
}
bool operator< (const ProcessID& ms) const
{
if (time < ms.time)
return true;
else if(time == ms.time)
return pid < ms.pid ;
return false;
}
uint64_t time;
uint64_t pid;
};
/**
* Structure describing a section of virtual memory inside a process
* \ingroup grp_context
@ -265,8 +242,6 @@ namespace DFHack
{
return identified;
};
/// find the thread IDs of the process
bool getThreadIDs(std::vector<uint32_t> & threads );
/// get virtual memory ranges of the process (what is mapped where)
void getMemRanges(std::vector<t_memrange> & ranges );

@ -48,6 +48,8 @@ namespace DFHack
DFHACK_EXPORT void strVectorToRepeatedField(RepeatedPtrField<std::string> *pf,
const std::vector<std::string> &vec);
using dfproto::StringListMessage;
/**
* Represent bitfield bits as a repeated string field.
*/
@ -131,6 +133,8 @@ namespace DFHack
class CoreService : public RPCService {
int suspend_depth;
static int doRunLuaFunction(lua_State *L);
public:
CoreService();
~CoreService();
@ -144,5 +148,9 @@ namespace DFHack
// For batching
command_result CoreSuspend(color_ostream &stream, const EmptyMessage*, IntMessage *cnt);
command_result CoreResume(color_ostream &stream, const EmptyMessage*, IntMessage *cnt);
command_result RunLua(color_ostream &stream,
const dfproto::CoreRunLuaRequest *in,
StringListMessage *out);
};
}

@ -35,6 +35,8 @@ distribution.
#include "df/init.h"
#include "df/ui.h"
#include "df/announcement_type.h"
#include "df/announcement_flags.h"
#include "df/unit_report_type.h"
namespace df {
struct viewscreen;
@ -97,13 +99,20 @@ namespace DFHack
DFHACK_EXPORT bool any_building_hotkey(df::viewscreen *top);
DFHACK_EXPORT df::building *getSelectedBuilding(color_ostream &out, bool quiet = false);
// Low-level API that gives full control over announcements and reports
DFHACK_EXPORT void writeToGamelog(std::string message);
DFHACK_EXPORT int makeAnnouncement(df::announcement_type type, df::announcement_flags mode, df::coord pos, std::string message, int color = 7, bool bright = true);
DFHACK_EXPORT bool addCombatReport(df::unit *unit, df::unit_report_type slot, int report_index);
DFHACK_EXPORT bool addCombatReportAuto(df::unit *unit, df::announcement_flags mode, int report_index);
// Show a plain announcement, or a titan-style popup message
DFHACK_EXPORT void showAnnouncement(std::string message, int color = 7, bool bright = true);
DFHACK_EXPORT void showZoomAnnouncement(df::announcement_type type, df::coord pos, std::string message, int color = 7, bool bright = true);
DFHACK_EXPORT void showPopupAnnouncement(std::string message, int color = 7, bool bright = true);
// Show an announcement with effects determined by announcements.txt
DFHACK_EXPORT void showAutoAnnouncement(df::announcement_type type, df::coord pos, std::string message, int color = 7, bool bright = true);
DFHACK_EXPORT void showAutoAnnouncement(df::announcement_type type, df::coord pos, std::string message, int color = 7, bool bright = true, df::unit *unit1 = NULL, df::unit *unit2 = NULL);
/*
* Cursor and window coords

@ -63,6 +63,9 @@ namespace DFHack
DFHACK_EXPORT df::building *getHolder(df::job *job);
DFHACK_EXPORT df::unit *getWorker(df::job *job);
DFHACK_EXPORT void setJobCooldown(df::building *workshop, df::unit *worker, int cooldown = 100);
DFHACK_EXPORT bool removeWorker(df::job *job, int cooldown = 100);
// Instruct the game to check and assign workers
DFHACK_EXPORT void checkBuildingsNow();
DFHACK_EXPORT void checkDesignationsNow();

@ -102,8 +102,8 @@ namespace Random
};
#ifndef DFHACK_RANDOM_CPP
extern template void MersenneRNG::unitvector<float>(float *p, int size);
extern template void MersenneRNG::unitvector<double>(double *p, int size);
extern template void DFHACK_IMPORT MersenneRNG::unitvector<float>(float *p, int size);
extern template void DFHACK_IMPORT MersenneRNG::unitvector<double>(double *p, int size);
#endif
/*

@ -241,6 +241,7 @@ DFHACK_EXPORT int getEffectiveSkill(df::unit *unit, df::job_skill skill_id);
DFHACK_EXPORT int getExperience(df::unit *unit, df::job_skill skill_id, bool total = false);
DFHACK_EXPORT int computeMovementSpeed(df::unit *unit);
DFHACK_EXPORT float computeSlowdownFactor(df::unit *unit);
struct NoblePosition {
df::historical_entity *entity;

@ -366,11 +366,28 @@ function dfhack.getSavePath()
end
if dfhack.is_core_context then
local function loadInitFile(path, name)
local env = setmetatable({ SAVE_PATH = path }, { __index = base_env })
local f,perr = loadfile(name, 't', env)
if f == nil then
if not string.match(perr, 'No such file or directory') then
dfhack.printerr(perr)
end
elseif safecall(f) then
if not internal.save_init then
internal.save_init = {}
end
table.insert(internal.save_init, env)
end
end
dfhack.onStateChange.DFHACK_PER_SAVE = function(op)
if op == SC_WORLD_LOADED or op == SC_WORLD_UNLOADED then
if internal.save_init then
if internal.save_init.onUnload then
safecall(internal.save_init.onUnload)
for k,v in ipairs(internal.save_init) do
if v.onUnload then
safecall(v.onUnload)
end
end
internal.save_init = nil
end
@ -378,18 +395,24 @@ if dfhack.is_core_context then
local path = dfhack.getSavePath()
if path and op == SC_WORLD_LOADED then
local env = setmetatable({ SAVE_PATH = path }, { __index = base_env })
local f,perr = loadfile(path..'/raw/init.lua', 't', env)
if f == nil then
if not string.match(perr, 'No such file or directory') then
dfhack.printerr(perr)
loadInitFile(path, path..'/raw/init.lua')
local dirlist = dfhack.internal.getDir(path..'/raw/init.d/')
if dirlist then
table.sort(dirlist)
for i,name in ipairs(dirlist) do
if string.match(name,'%.lua$') then
loadInitFile(path, path..'/raw/init.d/'..name)
end
end
elseif safecall(f) then
internal.save_init = env
end
end
elseif internal.save_init and internal.save_init.onStateChange then
safecall(internal.save_init.onStateChange, op)
elseif internal.save_init then
for k,v in ipairs(internal.save_init) do
if v.onStateChange then
safecall(v.onStateChange, op)
end
end
end
end
end

@ -147,6 +147,21 @@ function make_sort_order(data,ordering)
return index
end
--[[
Iterate a 'list' structure, e.g. df.global.world.job_list
--]]
local function next_df_list(s,link)
link = link.next
if link then
return link, link.item
end
end
function listpairs(list)
return next_df_list, nil, list
end
--[[
Recursively assign data into a table.
--]]
@ -457,6 +472,14 @@ function getBuildingCenter(building)
return xyz2pos(building.centerx, building.centery, building.z)
end
function getItemDescription(item,mode)
return call_with_string(item, 'getItemDescription', mode or 0)
end
function getItemDescriptionPrefix(item,mode)
return call_with_string(item, 'getItemDescriptionPrefix', mode or 0)
end
-- Split the string by the given delimiter
function split_string(self, delimiter)
local result = { }

@ -87,6 +87,8 @@ using namespace DFHack;
#include "df/announcements.h"
#include "df/stop_depart_condition.h"
#include "df/route_stockpile_link.h"
#include "df/game_mode.h"
#include "df/unit.h"
using namespace df::enums;
using df::global::gview;
@ -97,6 +99,7 @@ using df::global::world;
using df::global::selection_rect;
using df::global::ui_menu_width;
using df::global::ui_area_map_width;
using df::global::gamemode;
static df::layer_object_listst *getLayerList(df::viewscreen_layer *layer, int idx)
{
@ -1080,13 +1083,26 @@ df::building *Gui::getSelectedBuilding(color_ostream &out, bool quiet)
//
static void doShowAnnouncement(
df::announcement_type type, df::coord pos, std::string message, int color, bool bright
) {
DFHACK_EXPORT void Gui::writeToGamelog(std::string message)
{
if (message.empty())
return;
std::ofstream fseed("gamelog.txt", std::ios::out | std::ios::app);
if(fseed.is_open())
fseed << message << std::endl;
fseed.close();
}
DFHACK_EXPORT int Gui::makeAnnouncement(df::announcement_type type, df::announcement_flags flags, df::coord pos, std::string message, int color, bool bright)
{
using df::global::world;
using df::global::cur_year;
using df::global::cur_year_tick;
if (message.empty())
return -1;
int year = 0, year_time = 0;
if (cur_year && cur_year_tick)
@ -1102,6 +1118,31 @@ static void doShowAnnouncement(
year_time = last->time;
}
// Apply the requested effects
writeToGamelog(message);
if (flags.bits.DO_MEGA || flags.bits.PAUSE || flags.bits.RECENTER)
{
resetDwarfmodeView(flags.bits.DO_MEGA || flags.bits.PAUSE);
if (flags.bits.RECENTER && pos.isValid())
revealInDwarfmodeMap(pos, true);
if (flags.bits.DO_MEGA)
showPopupAnnouncement(message, color, bright);
}
bool display = false;
if (gamemode == NULL)
display = flags.bits.A_DISPLAY || flags.bits.D_DISPLAY;
else if (*gamemode == game_mode::ADVENTURE)
display = flags.bits.A_DISPLAY;
else
display = flags.bits.D_DISPLAY;
// Generate the report objects
int report_idx = world->status.reports.size();
bool continued = false;
while (!message.empty())
@ -1117,7 +1158,6 @@ static void doShowAnnouncement(
new_rep->time = year_time;
new_rep->flags.bits.continuation = continued;
new_rep->flags.bits.announcement = true;
int size = std::min(message.size(), (size_t)73);
new_rep->text = message.substr(0, size);
@ -1129,20 +1169,114 @@ static void doShowAnnouncement(
new_rep->id = world->status.next_report_id++;
world->status.reports.push_back(new_rep);
world->status.announcements.push_back(new_rep);
world->status.display_timer = 2000;
if (display)
{
new_rep->flags.bits.announcement = true;
world->status.announcements.push_back(new_rep);
world->status.display_timer = 2000;
}
}
return report_idx;
}
bool Gui::addCombatReport(df::unit *unit, df::unit_report_type slot, int report_index)
{
using df::global::world;
CHECK_INVALID_ARGUMENT(is_valid_enum_item(slot));
auto &vec = world->status.reports;
auto report = vector_get(vec, report_index);
if (!unit || !report)
return false;
// Check that it is a new report
auto &rvec = unit->reports.log[slot];
if (!rvec.empty() && rvec.back() >= report->id)
return false;
// Add the report
rvec.push_back(report->id);
unit->reports.last_year[slot] = report->year;
unit->reports.last_year_tick[slot] = report->time;
switch (slot) {
case unit_report_type::Combat:
world->status.flags.bits.combat = true;
break;
case unit_report_type::Hunting:
world->status.flags.bits.hunting = true;
break;
case unit_report_type::Sparring:
world->status.flags.bits.sparring = true;
break;
}
// And all the continuation lines
for (size_t i = report_index+1; i < vec.size() && vec[i]->flags.bits.continuation; i++)
rvec.push_back(vec[i]->id);
return true;
}
bool Gui::addCombatReportAuto(df::unit *unit, df::announcement_flags mode, int report_index)
{
using df::global::world;
auto &vec = world->status.reports;
auto report = vector_get(vec, report_index);
if (!unit || !report)
return false;
bool ok = false;
if (mode.bits.UNIT_COMBAT_REPORT)
{
if (unit->flags2.bits.sparring)
ok |= addCombatReport(unit, unit_report_type::Sparring, report_index);
else if (unit->job.current_job && unit->job.current_job->job_type == job_type::Hunt)
ok |= addCombatReport(unit, unit_report_type::Hunting, report_index);
else
ok |= addCombatReport(unit, unit_report_type::Combat, report_index);
}
if (mode.bits.UNIT_COMBAT_REPORT_ALL_ACTIVE)
{
FOR_ENUM_ITEMS(unit_report_type, slot)
{
if (!unit->reports.log[slot].empty() &&
unit->reports.last_year[slot] == report->year &&
(report->time - unit->reports.last_year_tick[slot]) <= 500)
{
ok |= addCombatReport(unit, slot, report_index);
}
}
}
return ok;
}
void Gui::showAnnouncement(std::string message, int color, bool bright)
{
doShowAnnouncement(df::announcement_type(0), df::coord(), message, color, bright);
df::announcement_flags mode(0);
mode.bits.D_DISPLAY = mode.bits.A_DISPLAY = true;
makeAnnouncement(df::announcement_type(0), mode, df::coord(), message, color, bright);
}
void Gui::showZoomAnnouncement(
df::announcement_type type, df::coord pos, std::string message, int color, bool bright
) {
doShowAnnouncement(type, pos, message, color, bright);
df::announcement_flags mode(0);
mode.bits.D_DISPLAY = mode.bits.A_DISPLAY = true;
makeAnnouncement(type, mode, pos, message, color, bright);
}
void Gui::showPopupAnnouncement(std::string message, int color, bool bright)
@ -1157,26 +1291,21 @@ void Gui::showPopupAnnouncement(std::string message, int color, bool bright)
}
void Gui::showAutoAnnouncement(
df::announcement_type type, df::coord pos, std::string message, int color, bool bright
df::announcement_type type, df::coord pos, std::string message, int color, bool bright,
df::unit *unit1, df::unit *unit2
) {
using df::global::announcements;
df::announcement_flags flags;
df::announcement_flags flags(0);
flags.bits.D_DISPLAY = flags.bits.A_DISPLAY = true;
if (is_valid_enum_item(type) && announcements)
flags = announcements->flags[type];
doShowAnnouncement(type, pos, message, color, bright);
if (flags.bits.DO_MEGA || flags.bits.PAUSE || flags.bits.RECENTER)
{
resetDwarfmodeView(flags.bits.DO_MEGA || flags.bits.PAUSE);
if (flags.bits.RECENTER && pos.isValid())
revealInDwarfmodeMap(pos, true);
}
int id = makeAnnouncement(type, flags, pos, message, color, bright);
if (flags.bits.DO_MEGA)
showPopupAnnouncement(message, color, bright);
addCombatReportAuto(unit1, flags, id);
addCombatReportAuto(unit2, flags, id);
}
df::viewscreen *Gui::getCurViewscreen(bool skip_dismissed)

@ -705,7 +705,7 @@ static void resetUnitInvFlags(df::unit *unit, df::unit_inventory_item *inv_item)
}
else if (inv_item->mode == df::unit_inventory_item::StuckIn)
{
unit->flags3.bits.unk2 = false;
unit->flags3.bits.stuck_weapon_computed = false;
}
}

Some files were not shown because too many files have changed in this diff Show More