Standardizing Config Files With Lua

Mike Atamas

hazuzu@aelfgar.com

http://www.aelfgar.com

Standardizing Config Files With Lua

The problem with config files

The solution

Lua

The Problem With Config Files
Programmer's Point of View

Interfacing with the config file is done manually

There is no documented standard for the format of config files.

It is hard to implement dynamic config files, and static config files are limiting.

Handling config files creates more potential errors, and adds to debug time.

The Problem With Config Files
The User's Point of View

Config files are slightly different from program to program

Most config files are static.

Config files require user interaction

They are less portable

They pose problems for servers

The Solution

Config files should be written in a scripting language.

A simple interface should be provided between the scripting language and C/C++.

The scripting language should be very small and fast.

It must be easy to extend and portable.

The language should be very simple to learn.

The Solution
Lua

Lua is very small

Executable 137k

Compiler 96k

liblua.a 129k

liblualib.a 95k

Lua is very fast

Beat python, ruby, perl, and lisp at the great language shootout.

Lua is simple to learn

Lua is easy to embed in C/C++ as well as Java and other languages.

Lua is easy to extend.

Lua is portable ( needs an ANSI C compiler)

Why not Python

Python is very large

Python provides large libraries

It is more difficult to extend

It is not as fast

Meant for larger programs

Python is better for large independent programs.

Ease of Use

The developer should not have to have a deep knowledge of Lua to use it as a scripting engine.

To accomplish this a class, Lua, was created.

It provides a very simple interface to Lua.

The developer no longer has to debug the scripting engine.

Minimal knowledge of Lua is required.

Can be used for things other than config files.

The Product

A small C++ library (156k).

Provides a class Lua.

Allows variables to be retrieved using the GetVar function.

Allows arbitrary Lua programs to be run through it using RunFile.

Allows arbitrary Lua commands to be run using System.

Example

#include “luaconf.hpp”

int main()

{

string foo;

int bar;

Lua lua(“some_config_file”);

lua.GetVar( foo, “foo”);

lua.GetVar( bar, “bar”);

cout << foo << “ “ << bar << endl;

lua.System(“print [[Hello World]]”);

return 0;

}

some_config_file:

foo = “Hello World!”

bar = 5

Output

Hello World! 5

Hello World

Who Uses Lua

Painkiller

Far Cry

World of Warcraft

Angband

Basic Lua

Lua is dynamically typed. No declarations are necessary.

Lua uses the 'nil' value to delete things.

Anything other than false or nil is true.

Lua is garbage collected.

> a = 4; b = "hello"

> print(a,b)

4 hello

> a = b; b = 5.34

> print(a,b)

hello 5.34

> a,b = nil, nil

> print(a,b)

nil nil

Tables

Lua does not have arrays, instead it uses tables.

Tables can be arrays, hashes, or metatables.

Lua tables start their index at 1, not 0.

> foo = { 1, 2, 3, 4, 5, 6 }

> = foo[0]

nil

> return foo[1]

1

> return foo[6]

6

> foo = { a = "bar", b = "bim", c = 47 }

> = foo["a"]

bar

> = foo["c"]

47

Functions and Tables

Functions are treated as variables

function foo ( arg )

print( arg )

end

foo = function( arg )

print( arg )

end

Tables can store functions

> a = function( ) print "hello world!" end

> b = function( ) print "!dlrow olleh" end

> foo = { a, b }

> foo[1]; foo[2]

stdin:1: `=' expected near `;'

> foo[1](); foo[2]();

hello world!

!dlrow olleh

For Loops

Lua provides iterators.

For loops are similar to those in python

for <var-list> in <exp-list> do

<body>

end

for line in io.lines() do

io.write(line, '\n')

end

C style for loops are clunky in Lua and while should be used instead.

Control Structures

while expr

do

code

end

if expr

then

code

elseif expr

code

else

code

end

while x < 10

do

print(x)

x = x + 1

end

if x > 1

then

x = x + 1

elseif x > -1

x = 1

else

print(x)

end

Metatables

Metatables allow the behaviour of tables to be changed.

Regular tables can be assigned a metatable (as can other data)

Metatables work just like regular tables.

To assign a metatable to a table use the setmetatable function

Setmetatable( table, Table.mt )

Metatables Example

Set = {}

Set.mt = {}

function Set.print( )

print( set[1] )

end

function Set.new( a )

local set = { a }

setmetatable( set, Set.mt )

return set

end

Set.mt.__add = function( foo, bar )

end

s1 = Set.new(1); s2 = Set.new(2);

s1 = s1 + s2

s1.print();

Object Oriented Programming

Lua allows for object oriented programming with metatables.

Lua has no classes, only tables with metatables.

Provides three ways of calling

s.print(s) -- minimal syntatic sugar

s:print() -- with syntatic sugar

String.print(s) -- no sugar whatsoever

Embedding Lua

A lua virtual machine is created

lua_State *l = lua_open()

An arbitrary number of these virtual machines can be created.

The stack of the virtual machine is available to C.

Since functions are just variables C can call Lua functions.

Extending Lua

Lua can be built with dynamic library loading.

This is default but not required as it is not specified by ANSI.

Lua can call C functions

They can be loaded into the interpreter through:

Compiling it into the interpreter

Dynamically linking it

Virtual machines can be given acess to certain functions

2004-05-02T10:40:35