1
0
Fork 0

- add more "var" keywords, fix indentation, drop some parentheses,

fix comments, consistency fixes, ...
- aircraft.nas: angular_lowpass -> minor speedup
This commit is contained in:
mfranz 2007-10-07 15:12:05 +00:00
parent ef22d3f5a3
commit dfd21c722d
7 changed files with 187 additions and 193 deletions

View file

@ -330,18 +330,19 @@ var lowpass = {
# angular lowpass # angular lowpass
# ============================================================================== # ==============================================================================
# same as above, but for angles. Filters sin/cos separately and calculates the # same as above, but for angles. Filters sin/cos separately and calculates the
# angle again from them. This avoids unexpected jumps from 180 to -179.99 degree. # angle again from them. This avoids unexpected jumps from 179.99 to -180 degree.
# #
var angular_lowpass = { var angular_lowpass = {
new : func(coeff) { new : func(coeff) {
var m = { parents : [angular_lowpass] }; var m = { parents : [angular_lowpass] };
m.sin = lowpass.new(coeff); m.sin = lowpass.new(coeff);
m.cos = lowpass.new(coeff); m.cos = lowpass.new(coeff);
m.buf = nil;
return m; return m;
}, },
filter : func(v) { filter : func(v) {
v *= D2R; v *= D2R;
math.atan2(me.sin.filter(math.sin(v)), me.cos.filter(math.cos(v))) * R2D; me.buf = math.atan2(me.sin.filter(math.sin(v)), me.cos.filter(math.cos(v))) * R2D;
}, },
set : func(v) { set : func(v) {
v *= D2R; v *= D2R;
@ -349,7 +350,7 @@ var angular_lowpass = {
me.cos.set(math.cos(v)); me.cos.set(math.cos(v));
}, },
get : func { get : func {
math.atan2(me.sin.get(), me.cos.get()) * R2D; me.buf;
}, },
}; };

View file

@ -1,8 +1,8 @@
startEngine = func { var startEngine = func {
sel = props.globals.getNode("/sim/input/selected"); var sel = props.globals.getNode("/sim/input/selected");
engs = props.globals.getNode("/controls/engines").getChildren("engine"); var engs = props.globals.getNode("/controls/engines").getChildren("engine");
for(i=0; i<size(engs); i=i+1) { for(var i=0; i<size(engs); i+=1) {
select = sel.getChild("engine", i); var select = sel.getChild("engine", i);
if(select != nil and select.getValue() != 0) { if(select != nil and select.getValue() != 0) {
engs[i].getNode("starter").setBoolValue(1); engs[i].getNode("starter").setBoolValue(1);
} }
@ -13,18 +13,18 @@ startEngine = func {
# make sure that the number of engine properties in the selection tree # make sure that the number of engine properties in the selection tree
# match the actual number of engines. This should probably be fixed in a # match the actual number of engines. This should probably be fixed in a
# more elegant way... # more elegant way...
initSelectProps = func { var initSelectProps = func {
engs = props.globals.getNode("/controls/engines").getChildren("engine"); var engs = props.globals.getNode("/controls/engines").getChildren("engine");
sel = props.globals.getNode("/sim/input/selected"); var sel = props.globals.getNode("/sim/input/selected");
for(i=0; i<size(engs); i=i+1) { for(var i=0; i<size(engs); i+=1) {
if(sel.getChild("engine", i) == nil) { if(sel.getChild("engine", i) == nil) {
sel.getNode("engine[" ~ i ~ "]", 1); }} sel.getNode("engine[" ~ i ~ "]", 1); }}
} }
settimer(initSelectProps, 0); settimer(initSelectProps, 0);
selectEngine = func { var selectEngine = func {
sel = props.globals.getNode("/sim/input/selected").getChildren("engine"); var sel = props.globals.getNode("/sim/input/selected").getChildren("engine");
foreach(node; sel) { node.setBoolValue(node.getIndex() == arg[0]); } foreach(var node; sel) { node.setBoolValue(node.getIndex() == arg[0]); }
} }
# Selects (state=1) or deselects (state=0) a list of engines, or all # Selects (state=1) or deselects (state=0) a list of engines, or all
@ -41,25 +41,25 @@ var selectEngines = func (state, engines...) {
} }
} }
selectAllEngines = func { var selectAllEngines = func {
sel = props.globals.getNode("/sim/input/selected").getChildren("engine"); var sel = props.globals.getNode("/sim/input/selected").getChildren("engine");
foreach(node; sel) { node.setBoolValue(1); } foreach(var node; sel) { node.setBoolValue(1); }
} }
stepMagnetos = func { var stepMagnetos = func {
change = arg[0]; var change = arg[0];
engs = props.globals.getNode("/controls/engines").getChildren("engine"); var engs = props.globals.getNode("/controls/engines").getChildren("engine");
sel = props.globals.getNode("/sim/input/selected"); var sel = props.globals.getNode("/sim/input/selected");
for(i=0; i<size(engs); i=i+1) { for(var i=0; i<size(engs); i+=1) {
select = sel.getChild("engine", i); var select = sel.getChild("engine", i);
if(select != nil and select.getValue() != 0) { if(select != nil and select.getValue() != 0) {
mag = engs[i].getNode("magnetos", 1); var mag = engs[i].getNode("magnetos", 1);
mag.setIntValue(mag.getValue() + change); mag.setIntValue(mag.getValue() + change);
} }
} }
} }
centerFlightControls = func { var centerFlightControls = func {
setprop("/controls/flight/elevator", 0); setprop("/controls/flight/elevator", 0);
setprop("/controls/flight/aileron", 0); setprop("/controls/flight/aileron", 0);
setprop("/controls/flight/rudder", 0); setprop("/controls/flight/rudder", 0);
@ -89,18 +89,18 @@ var throttleAxis = func {
setprop("/controls/engines/engine[" ~ n.getIndex() ~ "]/throttle", setprop("/controls/engines/engine[" ~ n.getIndex() ~ "]/throttle",
(1 - val)/2); (1 - val)/2);
} }
mixtureAxis = func { var mixtureAxis = func {
val = cmdarg().getNode("setting").getValue(); var val = cmdarg().getNode("setting").getValue();
if(size(arg) > 0) { val = -val; } if(size(arg) > 0) { val = -val; }
props.setAll("/controls/engines/engine", "mixture", (1 - val)/2); props.setAll("/controls/engines/engine", "mixture", (1 - val)/2);
} }
propellerAxis = func { var propellerAxis = func {
val = cmdarg().getNode("setting").getValue(); var val = cmdarg().getNode("setting").getValue();
if(size(arg) > 0) { val = -val; } if(size(arg) > 0) { val = -val; }
props.setAll("/controls/engines/engine", "propeller-pitch", (1 - val)/2); props.setAll("/controls/engines/engine", "propeller-pitch", (1 - val)/2);
} }
carbHeatAxis = func { var carbHeatAxis = func {
val = cmdarg().getNode("setting").getValue(); var val = cmdarg().getNode("setting").getValue();
if(size(arg) > 0) { val = -val; } if(size(arg) > 0) { val = -val; }
props.setAll("/controls/anti-ice/engine", "carb-heat", (1 - val)/2); props.setAll("/controls/anti-ice/engine", "carb-heat", (1 - val)/2);
} }
@ -110,36 +110,36 @@ carbHeatAxis = func {
# Wrapper around stepProps() which emulates the "old" flap behavior for # Wrapper around stepProps() which emulates the "old" flap behavior for
# configurations that aren't using the new mechanism. # configurations that aren't using the new mechanism.
# #
flapsDown = func { var flapsDown = func {
if(arg[0] == 0) { return; } if(arg[0] == 0) { return; }
if(props.globals.getNode("/sim/flaps") != nil) { if(props.globals.getNode("/sim/flaps") != nil) {
stepProps("/controls/flight/flaps", "/sim/flaps", arg[0]); stepProps("/controls/flight/flaps", "/sim/flaps", arg[0]);
return; return;
} }
# Hard-coded flaps movement in 3 equal steps: # Hard-coded flaps movement in 3 equal steps:
val = 0.3333334 * arg[0] + getprop("/controls/flight/flaps"); var val = 0.3333334 * arg[0] + getprop("/controls/flight/flaps");
if(val > 1) { val = 1 } elsif(val < 0) { val = 0 } if(val > 1) { val = 1 } elsif(val < 0) { val = 0 }
setprop("/controls/flight/flaps", val); setprop("/controls/flight/flaps", val);
} }
stepSpoilers = func { var stepSpoilers = func {
if(props.globals.getNode("/sim/spoilers") != nil) { if(props.globals.getNode("/sim/spoilers") != nil) {
stepProps("/controls/flight/spoilers", "/sim/spoilers", arg[0]); stepProps("/controls/flight/spoilers", "/sim/spoilers", arg[0]);
return; return;
} }
# Hard-coded spoilers movement in 4 equal steps: # Hard-coded spoilers movement in 4 equal steps:
val = 0.25 * arg[0] + getprop("/controls/flight/spoilers"); var val = 0.25 * arg[0] + getprop("/controls/flight/spoilers");
if(val > 1) { val = 1 } elsif(val < 0) { val = 0 } if(val > 1) { val = 1 } elsif(val < 0) { val = 0 }
setprop("/controls/flight/spoilers", val); setprop("/controls/flight/spoilers", val);
} }
stepSlats = func { var stepSlats = func {
if(props.globals.getNode("/sim/slats") != nil) { if(props.globals.getNode("/sim/slats") != nil) {
stepProps("/controls/flight/slats", "/sim/slats", arg[0]); stepProps("/controls/flight/slats", "/sim/slats", arg[0]);
return; return;
} }
# Hard-coded slats movement in 4 equal steps: # Hard-coded slats movement in 4 equal steps:
val = 0.25 * arg[0] + getprop("/controls/flight/slats"); var val = 0.25 * arg[0] + getprop("/controls/flight/slats");
if(val > 1) { val = 1 } elsif(val < 0) { val = 0 } if(val > 1) { val = 1 } elsif(val < 0) { val = 0 }
setprop("/controls/flight/slats", val); setprop("/controls/flight/slats", val);
} }
@ -164,15 +164,15 @@ stepSlats = func {
# magnetos, for instance), work similarly but not compatibly, and # magnetos, for instance), work similarly but not compatibly, and
# could be integrated. # could be integrated.
# #
stepProps = func { var stepProps = func {
dst = props.globals.getNode(arg[0]); var dst = props.globals.getNode(arg[0]);
array = props.globals.getNode(arg[1]); var array = props.globals.getNode(arg[1]);
delta = arg[2]; var delta = arg[2];
if(dst == nil or array == nil) { return; } if(dst == nil or array == nil) { return; }
sets = array.getChildren("setting"); var sets = array.getChildren("setting");
curr = array.getNode("current-setting", 1).getValue(); var curr = array.getNode("current-setting", 1).getValue();
if(curr == nil) { curr = 0; } if(curr == nil) { curr = 0; }
curr = curr + delta; curr = curr + delta;
if (curr < 0) { curr = 0; } if (curr < 0) { curr = 0; }
@ -190,47 +190,46 @@ stepProps = func {
# which repeat each frame. If you want to cause motion over time, see # which repeat each frame. If you want to cause motion over time, see
# interpolate(). # interpolate().
# #
slewProp = func { var slewProp = func(prop, delta) {
prop = arg[0]; delta *= getprop("/sim/time/delta-realtime-sec");
delta = arg[1] * getprop("/sim/time/delta-realtime-sec");
setprop(prop, getprop(prop) + delta); setprop(prop, getprop(prop) + delta);
} }
# Standard trim rate, in units per second. Remember that the full # Standard trim rate, in units per second. Remember that the full
# range of a trim axis is 2.0. Should probably read this out of a # range of a trim axis is 2.0. Should probably read this out of a
# property... # property...
TRIM_RATE = 0.045; var TRIM_RATE = 0.045;
## ##
# Handlers. These are suitable for binding to repeatable button press # Handlers. These are suitable for binding to repeatable button press
# events. They are *not* good for binding to the keyboard, since (at # events. They are *not* good for binding to the keyboard, since (at
# least) X11 synthesizes its own key repeats. # least) X11 synthesizes its own key repeats.
# #
elevatorTrim = func { var elevatorTrim = func {
slewProp("/controls/flight/elevator-trim", arg[0] * TRIM_RATE); } slewProp("/controls/flight/elevator-trim", arg[0] * TRIM_RATE); }
aileronTrim = func { var aileronTrim = func {
slewProp("/controls/flight/aileron-trim", arg[0] * TRIM_RATE); } slewProp("/controls/flight/aileron-trim", arg[0] * TRIM_RATE); }
rudderTrim = func { var rudderTrim = func {
slewProp("/controls/flight/rudder-trim", arg[0] * TRIM_RATE); } slewProp("/controls/flight/rudder-trim", arg[0] * TRIM_RATE); }
THROTTLE_RATE = 0.33; var THROTTLE_RATE = 0.33;
adjThrottle = func { var adjThrottle = func {
adjEngControl("throttle", arg[0]); } adjEngControl("throttle", arg[0]); }
adjMixture = func { var adjMixture = func {
adjEngControl("mixture", arg[0]); } adjEngControl("mixture", arg[0]); }
adjCondition = func { var adjCondition = func {
adjEngControl("condition", arg[0]); } adjEngControl("condition", arg[0]); }
adjPropeller = func { var adjPropeller = func {
adjEngControl("propeller-pitch", arg[0]); } adjEngControl("propeller-pitch", arg[0]); }
adjEngControl = func { var adjEngControl = func {
engs = props.globals.getNode("/controls/engines").getChildren("engine"); var engs = props.globals.getNode("/controls/engines").getChildren("engine");
selected = props.globals.getNode("/sim/input/selected"); var selected = props.globals.getNode("/sim/input/selected");
delta = arg[1] * THROTTLE_RATE * getprop("/sim/time/delta-realtime-sec"); var delta = arg[1] * THROTTLE_RATE * getprop("/sim/time/delta-realtime-sec");
foreach(e; engs) { foreach(var e; engs) {
if(selected.getChild("engine", e.getIndex(), 1).getBoolValue()) { if(selected.getChild("engine", e.getIndex(), 1).getBoolValue()) {
node = e.getNode(arg[0], 1); var node = e.getNode(arg[0], 1);
node.setValue(node.getValue() + delta); node.setValue(node.getValue() + delta);
} }
} }
@ -252,7 +251,7 @@ var incThrottle = func {
} }
} }
} else { } else {
node = props.globals.getNode("/autopilot/settings/target-speed-kt", 1); var node = props.globals.getNode("/autopilot/settings/target-speed-kt", 1);
if (node.getValue() == nil) { if (node.getValue() == nil) {
node.setValue(0.0); node.setValue(0.0);
} }
@ -266,10 +265,10 @@ var incThrottle = func {
## ##
# arg[0] is the aileron increment # arg[0] is the aileron increment
# arg[1] is the autopilot target heading increment # arg[1] is the autopilot target heading increment
incAileron = func { var incAileron = func {
auto = props.globals.getNode("/autopilot/locks/heading", 1); var auto = props.globals.getNode("/autopilot/locks/heading", 1);
if (!auto.getValue()) { if (!auto.getValue()) {
aileron = props.globals.getNode("/controls/flight/aileron"); var aileron = props.globals.getNode("/controls/flight/aileron");
if (aileron.getValue() == nil) { if (aileron.getValue() == nil) {
aileron.setValue(0.0); aileron.setValue(0.0);
} }
@ -282,7 +281,7 @@ incAileron = func {
} }
} }
if (auto.getValue() == "dg-heading-hold") { if (auto.getValue() == "dg-heading-hold") {
node = props.globals.getNode("/autopilot/settings/heading-bug-deg", 1); var node = props.globals.getNode("/autopilot/settings/heading-bug-deg", 1);
if (node.getValue() == nil) { if (node.getValue() == nil) {
node.setValue(0.0); node.setValue(0.0);
} }
@ -295,7 +294,7 @@ incAileron = func {
} }
} }
if (auto.getValue() == "true-heading-hold") { if (auto.getValue() == "true-heading-hold") {
node = props.globals.getNode("/autopilot/settings/true-heading-deg", 1); var node = props.globals.getNode("/autopilot/settings/true-heading-deg", 1);
if (node.getValue() == nil) { if (node.getValue() == nil) {
node.setValue(0.0); node.setValue(0.0);
} }
@ -312,10 +311,10 @@ incAileron = func {
## ##
# arg[0] is the elevator increment # arg[0] is the elevator increment
# arg[1] is the autopilot target altitude increment # arg[1] is the autopilot target altitude increment
incElevator = func { var incElevator = func {
auto = props.globals.getNode("/autopilot/locks/altitude", 1); var auto = props.globals.getNode("/autopilot/locks/altitude", 1);
if (!auto.getValue() or auto.getValue() == 0) { if (!auto.getValue() or auto.getValue() == 0) {
elevator = props.globals.getNode("/controls/flight/elevator"); var elevator = props.globals.getNode("/controls/flight/elevator");
if (elevator.getValue() == nil) { if (elevator.getValue() == nil) {
elevator.setValue(0.0); elevator.setValue(0.0);
} }
@ -327,7 +326,7 @@ incElevator = func {
elevator.setValue(1.0); elevator.setValue(1.0);
} }
} elsif (auto.getValue() == "altitude-hold") { } elsif (auto.getValue() == "altitude-hold") {
node = props.globals.getNode("/autopilot/settings/target-altitude-ft", 1); var node = props.globals.getNode("/autopilot/settings/target-altitude-ft", 1);
if (node.getValue() == nil) { if (node.getValue() == nil) {
node.setValue(0.0); node.setValue(0.0);
} }
@ -341,17 +340,17 @@ incElevator = func {
## ##
# Joystick axis handlers. Don't call from other contexts. # Joystick axis handlers. Don't call from other contexts.
# #
elevatorTrimAxis = func { elevatorTrim(cmdarg().getNode("value").getValue()); } var elevatorTrimAxis = func { elevatorTrim(cmdarg().getNode("value").getValue()); }
aileronTrimAxis = func { aileronTrim(cmdarg().getNode("value").getValue()); } var aileronTrimAxis = func { aileronTrim(cmdarg().getNode("value").getValue()); }
rudderTrimAxis = func { rudderTrim(cmdarg().getNode("value").getValue()); } var rudderTrimAxis = func { rudderTrim(cmdarg().getNode("value").getValue()); }
## ##
# Gear handling. # Gear handling.
# #
var gearDown = func { var gearDown = func(v) {
if (arg[0] < 0) { if (v < 0) {
setprop("/controls/gear/gear-down", 0); setprop("/controls/gear/gear-down", 0);
} elsif (arg[0] > 0) { } elsif (v > 0) {
setprop("/controls/gear/gear-down", 1); setprop("/controls/gear/gear-down", 1);
} }
} }

View file

@ -13,10 +13,9 @@
var UPDATE_PERIOD = 0.3; var UPDATE_PERIOD = 0.3;
update = func { var update = func {
if (fuel_freeze) { if (fuel_freeze)
return; return;
}
var consumed_fuel = 0; var consumed_fuel = 0;
foreach (var e; engines) { foreach (var e; engines) {
@ -25,17 +24,15 @@ update = func {
fuel.setDoubleValue(0); fuel.setDoubleValue(0);
} }
if (!consumed_fuel) { if (!consumed_fuel)
return; return;
}
var selected_tanks = []; var selected_tanks = [];
foreach (var t; tanks) { foreach (var t; tanks) {
var cap = t.getNode("capacity-gal_us").getValue(); var cap = t.getNode("capacity-gal_us").getValue();
if (cap > 0.01 and t.getNode("selected").getBoolValue()) { if (cap > 0.01 and t.getNode("selected").getBoolValue())
append(selected_tanks, t); append(selected_tanks, t);
} }
}
# Subtract fuel from tanks, set auxilliary properties. Set out-of-fuel # Subtract fuel from tanks, set auxilliary properties. Set out-of-fuel
# when any one tank is dry. # when any one tank is dry.
@ -52,12 +49,11 @@ update = func {
lbs = 0; lbs = 0;
# Kill the engines if we're told to, otherwise simply # Kill the engines if we're told to, otherwise simply
# deselect the tank. # deselect the tank.
if (t.getNode("kill-when-empty", 1).getBoolValue()) { if (t.getNode("kill-when-empty", 1).getBoolValue())
out_of_fuel = 1; out_of_fuel = 1;
} else { else
t.getNode("selected").setBoolValue(0); t.getNode("selected").setBoolValue(0);
} }
}
var gals = lbs / ppg; var gals = lbs / ppg;
t.getNode("level-gal_us").setDoubleValue(gals); t.getNode("level-gal_us").setDoubleValue(gals);
t.getNode("level-lbs").setDoubleValue(lbs); t.getNode("level-lbs").setDoubleValue(lbs);
@ -79,22 +75,21 @@ update = func {
total_gals.setDoubleValue(gals); total_gals.setDoubleValue(gals);
total_norm.setDoubleValue(gals / cap); total_norm.setDoubleValue(gals / cap);
foreach (var e; engines) { foreach (var e; engines)
e.getNode("out-of-fuel").setBoolValue(out_of_fuel); e.getNode("out-of-fuel").setBoolValue(out_of_fuel);
} }
}
loop = func { var loop = func {
update(); update();
settimer(loop, UPDATE_PERIOD); settimer(loop, UPDATE_PERIOD);
} }
init_double_prop = func(node, prop, val) { var init_double_prop = func(node, prop, val) {
if (node.getNode(prop) != nil) { if (node.getNode(prop) != nil)
val = num(node.getNode(prop).getValue()); val = num(node.getNode(prop).getValue());
}
node.getNode(prop, 1).setDoubleValue(val); node.getNode(prop, 1).setDoubleValue(val);
} }
@ -108,9 +103,7 @@ var total_lbs = nil;
var total_norm = nil; var total_norm = nil;
var L = _setlistener("/sim/signals/fdm-initialized", func { _setlistener("/sim/signals/fdm-initialized", func {
removelistener(L);
setlistener("/sim/freeze/fuel", func { fuel_freeze = cmdarg().getBoolValue() }, 1); setlistener("/sim/freeze/fuel", func { fuel_freeze = cmdarg().getBoolValue() }, 1);
total_gals = props.globals.getNode("/consumables/fuel/total-fuel-gals", 1); total_gals = props.globals.getNode("/consumables/fuel/total-fuel-gals", 1);
@ -124,19 +117,18 @@ var L = _setlistener("/sim/signals/fdm-initialized", func {
} }
foreach (var t; props.globals.getNode("/consumables/fuel", 1).getChildren("tank")) { foreach (var t; props.globals.getNode("/consumables/fuel", 1).getChildren("tank")) {
if (!size(t.getChildren())) { if (!size(t.getChildren()))
continue; # skip native_fdm.cxx generated zombie tanks continue; # skip native_fdm.cxx generated zombie tanks
}
append(tanks, t); append(tanks, t);
init_double_prop(t, "level-gal_us", 0.0); init_double_prop(t, "level-gal_us", 0.0);
init_double_prop(t, "level-lbs", 0.0); init_double_prop(t, "level-lbs", 0.0);
init_double_prop(t, "capacity-gal_us", 0.01); # not zero (div/zero issue) init_double_prop(t, "capacity-gal_us", 0.01); # not zero (div/zero issue)
init_double_prop(t, "density-ppg", 6.0); # gasoline init_double_prop(t, "density-ppg", 6.0); # gasoline
if (t.getNode("selected") == nil) { if (t.getNode("selected") == nil)
t.getNode("selected", 1).setBoolValue(1); t.getNode("selected", 1).setBoolValue(1);
} }
}
loop(); loop();
}); });

View file

@ -296,7 +296,7 @@ var _put_model = func(path, lat, lon, elev_m = nil, hdg = 0, pitch = 0, roll = 0
if (elev_m == nil) if (elev_m == nil)
elev_m = elevation(lat, lon); elev_m = elevation(lat, lon);
if (elev_m == nil) if (elev_m == nil)
die("can't get elevation for " ~ lat ~ "/" ~ lon); die("geo.put_model(): can't get elevation for " ~ lat ~ "/" ~ lon);
var n = props.globals.getNode("/models"); var n = props.globals.getNode("/models");
for (var i = 0; 1; i += 1) for (var i = 0; 1; i += 1)
if (n.getChild("model", i, 0) == nil) if (n.getChild("model", i, 0) == nil)

View file

@ -43,7 +43,7 @@ foreach(fmt; keys(ifmts))
# prefix prepended to the name. If the prefix is nil, then attributes # prefix prepended to the name. If the prefix is nil, then attributes
# are ignored. Returns nil on error. # are ignored. Returns nil on error.
# #
var readxml = func(file, prefix = "___") { var readxml = func(path, prefix = "___") {
var stack = [[{}, ""]]; var stack = [[{}, ""]];
var node = props.Node.new(); var node = props.Node.new();
var tree = node; # prevent GC var tree = node; # prevent GC
@ -69,7 +69,7 @@ var readxml = func(file, prefix = "___") {
var data = func(d) { var data = func(d) {
stack[-1][1] ~= d; stack[-1][1] ~= d;
} }
return parsexml(file, start, end, data) == nil ? nil : tree; return parsexml(path, start, end, data) == nil ? nil : tree;
} }
# Writes a property tree as returned by readxml() to a file. Children # Writes a property tree as returned by readxml() to a file. Children
@ -77,39 +77,38 @@ var readxml = func(file, prefix = "___") {
# their parent. <node> must contain exactly one child, which will # their parent. <node> must contain exactly one child, which will
# become the XML file's outermost element. # become the XML file's outermost element.
# #
var writexml = func(file, node, indent = "\t", prefix = "___") { var writexml = func(path, node, indent = "\t", prefix = "___") {
var root = node.getChildren(); var root = node.getChildren();
if(!size(root)) if(!size(root))
die("writexml(): tree doesn't have a root node"); die("writexml(): tree doesn't have a root node");
if(substr(file, -4) != ".xml") if(substr(path, -4) != ".xml")
file ~= ".xml"; path ~= ".xml";
var fh = open(file, "w"); var file = open(path, "w");
var pre = size(prefix); write(file, "<?xml version=\"1.0\"?>\n\n");
write(fh, "<?xml version=\"1.0\"?>\n\n");
var writenode = func(n, ind = "") { var writenode = func(n, ind = "") {
var name = n.getName(); var name = n.getName();
var name_attr = name; var name_attr = name;
var children = []; var children = [];
foreach(var c; n.getChildren()) { foreach(var c; n.getChildren()) {
var aname = c.getName(); var a = c.getName();
if(substr(aname, 0, pre) == prefix) if(substr(a, 0, size(prefix)) == prefix)
name_attr ~= " " ~ substr(aname, pre) ~ '="' ~ c.getValue() ~ '"'; name_attr ~= " " ~ substr(a, size(prefix)) ~ '="' ~ c.getValue() ~ '"';
else else
append(children, c); append(children, c);
} }
if(size(children)) { if(size(children)) {
write(fh, ind ~ "<" ~ name_attr ~ ">\n"); write(file, ind ~ "<" ~ name_attr ~ ">\n");
foreach(var c; children) foreach(var c; children)
writenode(c, ind ~ indent); writenode(c, ind ~ indent);
write(fh, ind ~ "</" ~ name ~ ">\n"); write(file, ind ~ "</" ~ name ~ ">\n");
} elsif((var value = n.getValue()) != nil) { } elsif((var value = n.getValue()) != nil) {
write(fh, ind ~ "<" ~ name_attr ~ ">" ~ value ~ "</" ~ name ~ ">\n"); write(file, ind ~ "<" ~ name_attr ~ ">" ~ value ~ "</" ~ name ~ ">\n");
} else { } else {
write(fh, ind ~ "<" ~ name_attr ~ "/>\n"); write(file, ind ~ "<" ~ name_attr ~ "/>\n");
} }
} }
writenode(root[0]); writenode(root[0]);
close(fh); close(file);
if(size(root) != 1) if(size(root) != 1)
die("writexml(): tree has more than one root node"); die("writexml(): tree has more than one root node");
} }

View file

@ -68,7 +68,7 @@ var imatch = func(a, b) match(lc(a), lc(b));
# \? stands for a question mark (not the "any single character" placeholder) # \? stands for a question mark (not the "any single character" placeholder)
# [] stands for a group of characters: # [] stands for a group of characters:
# [abc] stands for letters a, b or c # [abc] stands for letters a, b or c
# [^abc] stands for any character but a, b, and c # [^abc] stands for any character but a, b, and c (^ as first character -> inversion)
# [1-4] stands for digits 1 to 4 (1, 2, 3, 4) # [1-4] stands for digits 1 to 4 (1, 2, 3, 4)
# [1-4-] stands for digits 1 to 4, and the minus # [1-4-] stands for digits 1 to 4, and the minus
# [-1-4] same as above # [-1-4] same as above
@ -76,8 +76,11 @@ var imatch = func(a, b) match(lc(a), lc(b));
# [1-3-6-9] stands for digits 1 to 3, minus, and 6 to 9 # [1-3-6-9] stands for digits 1 to 3, minus, and 6 to 9
# [][] stands for the closing and the opening bracket (']' must be first!) # [][] stands for the closing and the opening bracket (']' must be first!)
# [^^] stands for all characters but the caret symbol # [^^] stands for all characters but the caret symbol
# [\/] stands for a backslash or a slash (the backslash isn't an
# escape character in a [] character group)
# #
# Note that a minus can't be a range delimiter, as in [a--b] # Note that a minus can't be a range delimiter, as in [a--e],
# which would be interpreted as any of a, e, or minus.
# #
# Example: # Example:
# string.match(name, "*[0-9].xml"); ... true if 'name' ends with digit followed by ".xml" # string.match(name, "*[0-9].xml"); ... true if 'name' ends with digit followed by ".xml"