extensions.html 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  2. <html>
  3. <head>
  4. <title>Extensions</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  6. <meta name="Author" content="Mike Pall">
  7. <meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
  8. <meta name="Language" content="en">
  9. <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
  10. <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
  11. <style type="text/css">
  12. table.exc {
  13. line-height: 1.2;
  14. }
  15. tr.exchead td {
  16. font-weight: bold;
  17. }
  18. td.excplatform {
  19. width: 48%;
  20. }
  21. td.exccompiler {
  22. width: 29%;
  23. }
  24. td.excinterop {
  25. width: 23%;
  26. }
  27. </style>
  28. </head>
  29. <body>
  30. <div id="site">
  31. <a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
  32. </div>
  33. <div id="head">
  34. <h1>Extensions</h1>
  35. </div>
  36. <div id="nav">
  37. <ul><li>
  38. <a href="luajit.html">LuaJIT</a>
  39. <ul><li>
  40. <a href="http://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
  41. </li><li>
  42. <a href="install.html">Installation</a>
  43. </li><li>
  44. <a href="running.html">Running</a>
  45. </li></ul>
  46. </li><li>
  47. <a class="current" href="extensions.html">Extensions</a>
  48. <ul><li>
  49. <a href="ext_ffi.html">FFI Library</a>
  50. <ul><li>
  51. <a href="ext_ffi_tutorial.html">FFI Tutorial</a>
  52. </li><li>
  53. <a href="ext_ffi_api.html">ffi.* API</a>
  54. </li><li>
  55. <a href="ext_ffi_semantics.html">FFI Semantics</a>
  56. </li></ul>
  57. </li><li>
  58. <a href="ext_jit.html">jit.* Library</a>
  59. </li><li>
  60. <a href="ext_c_api.html">Lua/C API</a>
  61. </li><li>
  62. <a href="ext_profiler.html">Profiler</a>
  63. </li></ul>
  64. </li><li>
  65. <a href="status.html">Status</a>
  66. <ul><li>
  67. <a href="changes.html">Changes</a>
  68. </li></ul>
  69. </li><li>
  70. <a href="faq.html">FAQ</a>
  71. </li><li>
  72. <a href="http://luajit.org/performance.html">Performance <span class="ext">&raquo;</span></a>
  73. </li><li>
  74. <a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
  75. </li><li>
  76. <a href="http://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
  77. </li></ul>
  78. </div>
  79. <div id="main">
  80. <p>
  81. LuaJIT is fully upwards-compatible with Lua 5.1. It supports all
  82. <a href="http://www.lua.org/manual/5.1/manual.html#5"><span class="ext">&raquo;</span>&nbsp;standard Lua
  83. library functions</a> and the full set of
  84. <a href="http://www.lua.org/manual/5.1/manual.html#3"><span class="ext">&raquo;</span>&nbsp;Lua/C API
  85. functions</a>.
  86. </p>
  87. <p>
  88. LuaJIT is also fully ABI-compatible to Lua 5.1 at the linker/dynamic
  89. loader level. This means you can compile a C&nbsp;module against the
  90. standard Lua headers and load the same shared library from either Lua
  91. or LuaJIT.
  92. </p>
  93. <p>
  94. LuaJIT extends the standard Lua VM with new functionality and adds
  95. several extension modules. Please note this page is only about
  96. <em>functional</em> enhancements and not about performance enhancements,
  97. such as the optimized VM, the faster interpreter or the JIT compiler.
  98. </p>
  99. <h2 id="modules">Extensions Modules</h2>
  100. <p>
  101. LuaJIT comes with several built-in extension modules:
  102. </p>
  103. <h3 id="bit"><tt>bit.*</tt> &mdash; Bitwise operations</h3>
  104. <p>
  105. LuaJIT supports all bitwise operations as defined by
  106. <a href="http://bitop.luajit.org"><span class="ext">&raquo;</span>&nbsp;Lua BitOp</a>:
  107. </p>
  108. <pre class="code">
  109. bit.tobit bit.tohex bit.bnot bit.band bit.bor bit.bxor
  110. bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap
  111. </pre>
  112. <p>
  113. This module is a LuaJIT built-in &mdash; you don't need to download or
  114. install Lua BitOp. The Lua BitOp site has full documentation for all
  115. <a href="http://bitop.luajit.org/api.html"><span class="ext">&raquo;</span>&nbsp;Lua BitOp API functions</a>.
  116. The FFI adds support for
  117. <a href="ext_ffi_semantics.html#cdata_arith">64&nbsp;bit bitwise operations</a>,
  118. using the same API functions.
  119. </p>
  120. <p>
  121. Please make sure to <tt>require</tt> the module before using any of
  122. its functions:
  123. </p>
  124. <pre class="code">
  125. local bit = require("bit")
  126. </pre>
  127. <p>
  128. An already installed Lua BitOp module is ignored by LuaJIT.
  129. This way you can use bit operations from both Lua and LuaJIT on a
  130. shared installation.
  131. </p>
  132. <h3 id="ffi"><tt>ffi.*</tt> &mdash; FFI library</h3>
  133. <p>
  134. The <a href="ext_ffi.html">FFI library</a> allows calling external
  135. C&nbsp;functions and the use of C&nbsp;data structures from pure Lua
  136. code.
  137. </p>
  138. <h3 id="jit"><tt>jit.*</tt> &mdash; JIT compiler control</h3>
  139. <p>
  140. The functions in this module
  141. <a href="ext_jit.html">control the behavior of the JIT compiler engine</a>.
  142. </p>
  143. <h3 id="c_api">C API extensions</h3>
  144. <p>
  145. LuaJIT adds some
  146. <a href="ext_c_api.html">extra functions to the Lua/C API</a>.
  147. </p>
  148. <h3 id="profiler">Profiler</h3>
  149. <p>
  150. LuaJIT has an <a href="ext_profiler.html">integrated profiler</a>.
  151. </p>
  152. <h2 id="library">Enhanced Standard Library Functions</h2>
  153. <h3 id="xpcall"><tt>xpcall(f, err [,args...])</tt> passes arguments</h3>
  154. <p>
  155. Unlike the standard implementation in Lua 5.1, <tt>xpcall()</tt>
  156. passes any arguments after the error function to the function
  157. which is called in a protected context.
  158. </p>
  159. <h3 id="load"><tt>loadfile()</tt> etc. handle UTF-8 source code</h3>
  160. <p>
  161. Non-ASCII characters are handled transparently by the Lua source code parser.
  162. This allows the use of UTF-8 characters in identifiers and strings.
  163. A UTF-8 BOM is skipped at the start of the source code.
  164. </p>
  165. <h3 id="tostring"><tt>tostring()</tt> etc. canonicalize NaN and &plusmn;Inf</h3>
  166. <p>
  167. All number-to-string conversions consistently convert non-finite numbers
  168. to the same strings on all platforms. NaN results in <tt>"nan"</tt>,
  169. positive infinity results in <tt>"inf"</tt> and negative infinity results
  170. in <tt>"-inf"</tt>.
  171. </p>
  172. <h3 id="tonumber"><tt>tonumber()</tt> etc. use builtin string to number conversion</h3>
  173. <p>
  174. All string-to-number conversions consistently convert integer and
  175. floating-point inputs in decimal, hexadecimal and binary on all platforms.
  176. <tt>strtod()</tt> is <em>not</em> used anymore, which avoids numerous
  177. problems with poor C library implementations. The builtin conversion
  178. function provides full precision according to the IEEE-754 standard, it
  179. works independently of the current locale and it supports hex floating-point
  180. numbers (e.g. <tt>0x1.5p-3</tt>).
  181. </p>
  182. <h3 id="string_dump"><tt>string.dump(f [,strip])</tt> generates portable bytecode</h3>
  183. <p>
  184. An extra argument has been added to <tt>string.dump()</tt>. If set to
  185. <tt>true</tt>, 'stripped' bytecode without debug information is
  186. generated. This speeds up later bytecode loading and reduces memory
  187. usage. See also the
  188. <a href="running.html#opt_b"><tt>-b</tt> command line option</a>.
  189. </p>
  190. <p>
  191. The generated bytecode is portable and can be loaded on any architecture
  192. that LuaJIT supports, independent of word size or endianess. However the
  193. bytecode compatibility versions must match. Bytecode stays compatible
  194. for dot releases (x.y.0 &rarr; x.y.1), but may change with major or
  195. minor releases (2.0 &rarr; 2.1) or between any beta release. Foreign
  196. bytecode (e.g. from Lua 5.1) is incompatible and cannot be loaded.
  197. </p>
  198. <p>
  199. Note: <tt>LJ_GC64</tt> mode requires a different frame layout, which implies
  200. a different, incompatible bytecode format for ports that use this mode (e.g.
  201. ARM64 or MIPS64) or when explicitly enabled for x64. This may be rectified
  202. in the future.
  203. </p>
  204. <h3 id="table_new"><tt>table.new(narray, nhash)</tt> allocates a pre-sized table</h3>
  205. <p>
  206. An extra library function <tt>table.new()</tt> can be made available via
  207. <tt>require("table.new")</tt>. This creates a pre-sized table, just like
  208. the C API equivalent <tt>lua_createtable()</tt>. This is useful for big
  209. tables if the final table size is known and automatic table resizing is
  210. too expensive.
  211. </p>
  212. <h3 id="table_clear"><tt>table.clear(tab)</tt> clears a table</h3>
  213. <p>
  214. An extra library function <tt>table.clear()</tt> can be made available
  215. via <tt>require("table.clear")</tt>. This clears all keys and values
  216. from a table, but preserves the allocated array/hash sizes. This is
  217. useful when a table, which is linked from multiple places, needs to be
  218. cleared and/or when recycling a table for use by the same context. This
  219. avoids managing backlinks, saves an allocation and the overhead of
  220. incremental array/hash part growth.
  221. </p>
  222. <p>
  223. Please note this function is meant for very specific situations. In most
  224. cases it's better to replace the (usually single) link with a new table
  225. and let the GC do its work.
  226. </p>
  227. <h3 id="math_random">Enhanced PRNG for <tt>math.random()</tt></h3>
  228. <p>
  229. LuaJIT uses a Tausworthe PRNG with period 2^223 to implement
  230. <tt>math.random()</tt> and <tt>math.randomseed()</tt>. The quality of
  231. the PRNG results is much superior compared to the standard Lua
  232. implementation which uses the platform-specific ANSI rand().
  233. </p>
  234. <p>
  235. The PRNG generates the same sequences from the same seeds on all
  236. platforms and makes use of all bits in the seed argument.
  237. <tt>math.random()</tt> without arguments generates 52 pseudo-random bits
  238. for every call. The result is uniformly distributed between 0.0 and 1.0.
  239. It's correctly scaled up and rounded for <tt>math.random(n&nbsp;[,m])</tt> to
  240. preserve uniformity.
  241. </p>
  242. <h3 id="io"><tt>io.*</tt> functions handle 64&nbsp;bit file offsets</h3>
  243. <p>
  244. The file I/O functions in the standard <tt>io.*</tt> library handle
  245. 64&nbsp;bit file offsets. In particular this means it's possible
  246. to open files larger than 2&nbsp;Gigabytes and to reposition or obtain
  247. the current file position for offsets beyond 2&nbsp;GB
  248. (<tt>fp:seek()</tt> method).
  249. </p>
  250. <h3 id="debug_meta"><tt>debug.*</tt> functions identify metamethods</h3>
  251. <p>
  252. <tt>debug.getinfo()</tt> and <tt>lua_getinfo()</tt> also return information
  253. about invoked metamethods. The <tt>namewhat</tt> field is set to
  254. <tt>"metamethod"</tt> and the <tt>name</tt> field has the name of
  255. the corresponding metamethod (e.g. <tt>"__index"</tt>).
  256. </p>
  257. <h2 id="resumable">Fully Resumable VM</h2>
  258. <p>
  259. The LuaJIT VM is fully resumable. This means you can yield from a
  260. coroutine even across contexts, where this would not possible with
  261. the standard Lua&nbsp;5.1 VM: e.g. you can yield across <tt>pcall()</tt>
  262. and <tt>xpcall()</tt>, across iterators and across metamethods.
  263. </p>
  264. <h2 id="lua52">Extensions from Lua 5.2</h2>
  265. <p>
  266. LuaJIT supports some language and library extensions from Lua&nbsp;5.2.
  267. Features that are unlikely to break existing code are unconditionally
  268. enabled:
  269. </p>
  270. <ul>
  271. <li><tt>goto</tt> and <tt>::labels::</tt>.</li>
  272. <li>Hex escapes <tt>'\x3F'</tt> and <tt>'\*'</tt> escape in strings.</li>
  273. <li><tt>load(string|reader [, chunkname [,mode [,env]]])</tt>.</li>
  274. <li><tt>loadstring()</tt> is an alias for <tt>load()</tt>.</li>
  275. <li><tt>loadfile(filename [,mode [,env]])</tt>.</li>
  276. <li><tt>math.log(x [,base])</tt>.</li>
  277. <li><tt>string.rep(s, n [,sep])</tt>.</li>
  278. <li><tt>string.format()</tt>: <tt>%q</tt> reversible.
  279. <tt>%s</tt> checks <tt>__tostring</tt>.
  280. <tt>%a</tt> and <tt>"%A</tt> added.</li>
  281. <li>String matching pattern <tt>%g</tt> added.</li>
  282. <li><tt>io.read("*L")</tt>.</li>
  283. <li><tt>io.lines()</tt> and <tt>file:lines()</tt> process
  284. <tt>io.read()</tt> options.</li>
  285. <li><tt>os.exit(status|true|false [,close])</tt>.</li>
  286. <li><tt>package.searchpath(name, path [, sep [, rep]])</tt>.</li>
  287. <li><tt>package.loadlib(name, "*")</tt>.</li>
  288. <li><tt>debug.getinfo()</tt> returns <tt>nparams</tt> and <tt>isvararg</tt>
  289. for option <tt>"u"</tt>.</li>
  290. <li><tt>debug.getlocal()</tt> accepts function instead of level.</li>
  291. <li><tt>debug.getlocal()</tt> and <tt>debug.setlocal()</tt> accept negative
  292. indexes for varargs.</li>
  293. <li><tt>debug.getupvalue()</tt> and <tt>debug.setupvalue()</tt> handle
  294. C&nbsp;functions.</li>
  295. <li><tt>debug.upvalueid()</tt> and <tt>debug.upvaluejoin()</tt>.</li>
  296. <li>Lua/C API extensions:
  297. <tt>lua_version()</tt>
  298. <tt>lua_upvalueid()</tt>
  299. <tt>lua_upvaluejoin()</tt>
  300. <tt>lua_loadx()</tt>
  301. <tt>lua_copy()</tt>
  302. <tt>lua_tonumberx()</tt>
  303. <tt>lua_tointegerx()</tt>
  304. <tt>luaL_fileresult()</tt>
  305. <tt>luaL_execresult()</tt>
  306. <tt>luaL_loadfilex()</tt>
  307. <tt>luaL_loadbufferx()</tt>
  308. <tt>luaL_traceback()</tt>
  309. <tt>luaL_setfuncs()</tt>
  310. <tt>luaL_pushmodule()</tt>
  311. <tt>luaL_newlibtable()</tt>
  312. <tt>luaL_newlib()</tt>
  313. <tt>luaL_testudata()</tt>
  314. <tt>luaL_setmetatable()</tt>
  315. </li>
  316. <li>Command line option <tt>-E</tt>.</li>
  317. <li>Command line checks <tt>__tostring</tt> for errors.</li>
  318. </ul>
  319. <p>
  320. Other features are only enabled, if LuaJIT is built with
  321. <tt>-DLUAJIT_ENABLE_LUA52COMPAT</tt>:
  322. </p>
  323. <ul>
  324. <li><tt>goto</tt> is a keyword and not a valid variable name anymore.</li>
  325. <li><tt>break</tt> can be placed anywhere. Empty statements (<tt>;;</tt>)
  326. are allowed.</li>
  327. <li><tt>__lt</tt>, <tt>__le</tt> are invoked for mixed types.</li>
  328. <li><tt>__len</tt> for tables. <tt>rawlen()</tt> library function.</li>
  329. <li><tt>pairs()</tt> and <tt>ipairs()</tt> check for <tt>__pairs</tt> and
  330. <tt>__ipairs</tt>.</li>
  331. <li><tt>coroutine.running()</tt> returns two results.</li>
  332. <li><tt>table.pack()</tt> and <tt>table.unpack()</tt>
  333. (same as <tt>unpack()</tt>).</li>
  334. <li><tt>io.write()</tt> and <tt>file:write()</tt> return file handle
  335. instead of <tt>true</tt>.</li>
  336. <li><tt>os.execute()</tt> and <tt>pipe:close()</tt> return detailed
  337. exit status.</li>
  338. <li><tt>debug.setmetatable()</tt> returns object.</li>
  339. <li><tt>debug.getuservalue()</tt> and <tt>debug.setuservalue()</tt>.</li>
  340. <li>Remove <tt>math.mod()</tt>, <tt>string.gfind()</tt>.</li>
  341. <li><tt>package.searchers</tt>.</li>
  342. <li><tt>module()</tt> returns the module table.</li>
  343. </ul>
  344. <p>
  345. Note: this provides only partial compatibility with Lua 5.2 at the
  346. language and Lua library level. LuaJIT is API+ABI-compatible with
  347. Lua&nbsp;5.1, which prevents implementing features that would otherwise
  348. break the Lua/C API and ABI (e.g. <tt>_ENV</tt>).
  349. </p>
  350. <h2 id="lua53">Extensions from Lua 5.3</h2>
  351. <p>
  352. LuaJIT supports some extensions from Lua&nbsp;5.3:
  353. <ul>
  354. <li>Unicode escape <tt>'\u{XX...}'</tt> embeds the UTF-8 encoding in string literals.</li>
  355. <li>The argument table <tt>arg</tt> can be read (and modified) by <tt>LUA_INIT</tt> and <tt>-e</tt> chunks.</li>
  356. <li><tt>io.read()</tt> and <tt>file:read()</tt> accept formats with or without a leading <tt>*</tt>.</li>
  357. <li><tt>table.move(a1, f, e, t [,a2])</tt>.</li>
  358. <li><tt>coroutine.isyieldable()</tt>.</li>
  359. <li>Lua/C API extensions:
  360. <tt>lua_isyieldable()</tt>
  361. </li>
  362. </ul>
  363. <h2 id="exceptions">C++ Exception Interoperability</h2>
  364. <p>
  365. LuaJIT has built-in support for interoperating with C++&nbsp;exceptions.
  366. The available range of features depends on the target platform and
  367. the toolchain used to compile LuaJIT:
  368. </p>
  369. <table class="exc">
  370. <tr class="exchead">
  371. <td class="excplatform">Platform</td>
  372. <td class="exccompiler">Compiler</td>
  373. <td class="excinterop">Interoperability</td>
  374. </tr>
  375. <tr class="odd separate">
  376. <td class="excplatform">POSIX/x64, DWARF2 unwinding</td>
  377. <td class="exccompiler">GCC 4.3+, Clang</td>
  378. <td class="excinterop"><b style="color: #00a000;">Full</b></td>
  379. </tr>
  380. <tr class="even">
  381. <td class="excplatform">ARM <tt>-DLUAJIT_UNWIND_EXTERNAL</tt></td>
  382. <td class="exccompiler">GCC, Clang</td>
  383. <td class="excinterop"><b style="color: #00a000;">Full</b></td>
  384. </tr>
  385. <tr class="odd">
  386. <td class="excplatform">Other platforms, DWARF2 unwinding</td>
  387. <td class="exccompiler">GCC, Clang</td>
  388. <td class="excinterop"><b style="color: #c06000;">Limited</b></td>
  389. </tr>
  390. <tr class="even">
  391. <td class="excplatform">Windows/x64</td>
  392. <td class="exccompiler">MSVC or WinSDK</td>
  393. <td class="excinterop"><b style="color: #00a000;">Full</b></td>
  394. </tr>
  395. <tr class="odd">
  396. <td class="excplatform">Windows/x86</td>
  397. <td class="exccompiler">Any</td>
  398. <td class="excinterop"><b style="color: #00a000;">Full</b></td>
  399. </tr>
  400. <tr class="even">
  401. <td class="excplatform">Other platforms</td>
  402. <td class="exccompiler">Other compilers</td>
  403. <td class="excinterop"><b style="color: #a00000;">No</b></td>
  404. </tr>
  405. </table>
  406. <p>
  407. <b style="color: #00a000;">Full interoperability</b> means:
  408. </p>
  409. <ul>
  410. <li>C++&nbsp;exceptions can be caught on the Lua side with <tt>pcall()</tt>,
  411. <tt>lua_pcall()</tt> etc.</li>
  412. <li>C++&nbsp;exceptions will be converted to the generic Lua error
  413. <tt>"C++&nbsp;exception"</tt>, unless you use the
  414. <a href="ext_c_api.html#mode_wrapcfunc">C&nbsp;call wrapper</a> feature.</li>
  415. <li>It's safe to throw C++&nbsp;exceptions across non-protected Lua frames
  416. on the C&nbsp;stack. The contents of the C++&nbsp;exception object
  417. pass through unmodified.</li>
  418. <li>Lua errors can be caught on the C++ side with <tt>catch(...)</tt>.
  419. The corresponding Lua error message can be retrieved from the Lua stack.</li>
  420. <li>Throwing Lua errors across C++ frames is safe. C++ destructors
  421. will be called.</li>
  422. </ul>
  423. <p>
  424. <b style="color: #c06000;">Limited interoperability</b> means:
  425. </p>
  426. <ul>
  427. <li>C++&nbsp;exceptions can be caught on the Lua side with <tt>pcall()</tt>,
  428. <tt>lua_pcall()</tt> etc.</li>
  429. <li>C++&nbsp;exceptions will be converted to the generic Lua error
  430. <tt>"C++&nbsp;exception"</tt>, unless you use the
  431. <a href="ext_c_api.html#mode_wrapcfunc">C&nbsp;call wrapper</a> feature.</li>
  432. <li>C++&nbsp;exceptions will be caught by non-protected Lua frames and
  433. are rethrown as a generic Lua error. The C++&nbsp;exception object will
  434. be destroyed.</li>
  435. <li>Lua errors <b>cannot</b> be caught on the C++ side.</li>
  436. <li>Throwing Lua errors across C++ frames will <b>not</b> call
  437. C++ destructors.</li>
  438. </ul>
  439. <p>
  440. <b style="color: #a00000;">No interoperability</b> means:
  441. </p>
  442. <ul>
  443. <li>It's <b>not</b> safe to throw C++&nbsp;exceptions across Lua frames.</li>
  444. <li>C++&nbsp;exceptions <b>cannot</b> be caught on the Lua side.</li>
  445. <li>Lua errors <b>cannot</b> be caught on the C++ side.</li>
  446. <li>Throwing Lua errors across C++ frames will <b>not</b> call
  447. C++ destructors.</li>
  448. </ul>
  449. <br class="flush">
  450. </div>
  451. <div id="foot">
  452. <hr class="hide">
  453. Copyright &copy; 2005-2017 Mike Pall
  454. <span class="noprint">
  455. &middot;
  456. <a href="contact.html">Contact</a>
  457. </span>
  458. </div>
  459. </body>
  460. </html>