Index: resources/styles/default/points
===================================================================
--- resources/styles/default/points	(revision 2795)
+++ resources/styles/default/points	(working copy)
@@ -8,8 +8,6 @@
 # and http://wiki.openstreetmap.org/wiki/Mkgmap/help/Custom_styles
 # for more information.
 
-include 'inc/address';
-
 barrier=bollard | barrier=bus_trap
     { add mkgmap:bicycle='${bicycle|subst:private=>no|def:yes}'; add mkgmap:foot='${foot|subst:private=>no|def:yes}'; addaccess no }
 barrier=block | barrier=cycle_barrier | barrier=stile | barrier=kissing_gate
@@ -273,3 +271,8 @@
 
 include 'inc/water_points';
 include 'inc/landuse_points';
+
+<finalize>
+# The finalizer section is executed for each element when a rule with an element type matches
+
+include 'inc/address';
\ No newline at end of file
Index: resources/styles/default/polygons
===================================================================
--- resources/styles/default/polygons	(revision 2795)
+++ resources/styles/default/polygons	(working copy)
@@ -8,12 +8,6 @@
 # and http://wiki.openstreetmap.org/wiki/Mkgmap/help/Custom_styles
 # for more information.
 
-# polygons do not have address information in the Garmin map format
-# so as long as the address information is not required in a stlye rule
-# it is not required to include the address rules 
-# include 'inc/address';
-
-
 leisure=* & sport=* & name=* { set name='${name} (${sport})' }
 leisure=* & sport=* & name!=* { add name='${sport}' }
 
@@ -80,3 +74,7 @@
 
 include 'inc/water_polygons';
 include 'inc/landuse_polygons';
+
+<finalize>
+# The finalizer section is executed for each element when a rule with an element type matches
+
Index: resources/styles/default/lines
===================================================================
--- resources/styles/default/lines	(revision 2795)
+++ resources/styles/default/lines	(working copy)
@@ -8,7 +8,6 @@
 # and http://wiki.openstreetmap.org/wiki/Mkgmap/help/Custom_styles
 # for more information.
 
-include 'inc/address';
 include 'inc/refs';
 
 aeroway=runway [0x27 resolution 20]
@@ -192,3 +191,8 @@
 
 include 'inc/water_lines';
 include 'inc/contour_lines';
+
+<finalize>
+# The finalizer section is executed for each element when a rule with an element type matches
+
+include 'inc/address';
Index: src/uk/me/parabola/mkgmap/osmstyle/function/TypeFunction.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/function/TypeFunction.java	(revision 0)
+++ src/uk/me/parabola/mkgmap/osmstyle/function/TypeFunction.java	(revision 0)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+package uk.me.parabola.mkgmap.osmstyle.function;
+
+import uk.me.parabola.mkgmap.reader.osm.Element;
+import uk.me.parabola.mkgmap.reader.osm.Node;
+import uk.me.parabola.mkgmap.reader.osm.Relation;
+import uk.me.parabola.mkgmap.reader.osm.Way;
+
+public class TypeFunction extends StyleFunction {
+
+	public TypeFunction() {
+		super(null);
+	}
+
+	public boolean supportsNode() {
+		return true;
+	}
+
+	public boolean supportsWay() {
+		return true;
+	}
+
+	public boolean supportsRelation() {
+		return true;
+	}
+	
+	public String value(Element el) {
+		if (el instanceof Node)
+			return "node";
+		if (el instanceof Way) 
+			return "way";
+		if (el instanceof Relation)
+			return "relation";
+		return null;
+	}
+
+	public String getName() {
+		return "type";
+	}
+
+}
Index: src/uk/me/parabola/mkgmap/osmstyle/function/FunctionFactory.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/function/FunctionFactory.java	(revision 2795)
+++ src/uk/me/parabola/mkgmap/osmstyle/function/FunctionFactory.java	(working copy)
@@ -44,6 +44,8 @@
 			return new MaxSpeedFunction(SpeedUnit.KMH);
 		if ("maxspeedmph".equals(name))
 			return new MaxSpeedFunction(SpeedUnit.MPH);
+		if ("type".equals(name))
+			return new TypeFunction();
 		
 		return null;
 	}
Index: src/uk/me/parabola/mkgmap/osmstyle/eval/ExpressionReader.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/eval/ExpressionReader.java	(revision 2795)
+++ src/uk/me/parabola/mkgmap/osmstyle/eval/ExpressionReader.java	(working copy)
@@ -230,6 +230,9 @@
 		case RELATION:
 			if (function.supportsRelation()) supported = true;
 			break;
+		case ALL:
+			if (function.supportsNode() || function.supportsWay() || function.supportsRelation()) supported = true;
+			break;
 		}
 
 		if (!supported)
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(revision 2795)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(working copy)
@@ -218,19 +218,29 @@
 		else
 			rules = wayRules;
 		
-		rules.resolveType(way, new TypeResult() {
-			public void add(Element el, GType type) {
-				if (type.isContinueSearch()) {
-					// If not already copied, do so now
-					if (el == way)
-						el = way.copy();
-				}
-				postConvertRules(el, type);
-				addConvertedWay((Way) el, type);
-			}
-		});
+		wayTypeResult.setWay(way);
+		rules.resolveType(way, wayTypeResult);
 	}
 
+	private final WayTypeResult wayTypeResult = new WayTypeResult();
+	private class WayTypeResult implements TypeResult 
+	{
+		private Way way;
+		public void setWay(Way way) {
+			this.way = way;
+		}
+		
+		public void add(Element el, GType type) {
+			if (type.isContinueSearch()) {
+				// If not already copied, do so now
+				if (el == way) 
+					el = way.copy();
+			}
+			postConvertRules(el, type);
+			addConvertedWay((Way) el, type);
+		}
+	}
+	
 	private void addConvertedWay(Way way, GType foundType) {
 		if (foundType.getFeatureKind() == FeatureKind.POLYLINE) {
 		    if(foundType.isRoad() &&
@@ -263,17 +273,27 @@
 
 		housenumberGenerator.addNode(node);
 		
-		nodeRules.resolveType(node, new TypeResult() {
+		nodeTypeResult.setNode(node);
+		nodeRules.resolveType(node, nodeTypeResult);
+	}
+	
+	private NodeTypeResult nodeTypeResult = new NodeTypeResult();
+	private class NodeTypeResult implements TypeResult {
+		private Node node;
+		public void setNode(Node node) {
+			this.node = node;
+		}
+		
 			public void add(Element el, GType type) {
 				if (type.isContinueSearch()) {
 					// If not already copied, do so now
-					if (el == node)
+					if (el == node) 
 						el = node.copy();
 				}
 				postConvertRules(el, type);
 				addPoint((Node) el, type);
 			}
-		});
+		
 	}
 
 	/**
Index: src/uk/me/parabola/mkgmap/osmstyle/ExpressionRule.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/ExpressionRule.java	(revision 2795)
+++ src/uk/me/parabola/mkgmap/osmstyle/ExpressionRule.java	(working copy)
@@ -18,31 +18,50 @@
 
 import uk.me.parabola.mkgmap.osmstyle.eval.Op;
 import uk.me.parabola.mkgmap.reader.osm.Element;
+import uk.me.parabola.mkgmap.reader.osm.FinalizableRule;
 import uk.me.parabola.mkgmap.reader.osm.GType;
 import uk.me.parabola.mkgmap.reader.osm.Rule;
 import uk.me.parabola.mkgmap.reader.osm.TypeResult;
 
 /**
  * A rule that contains a condition.  If the condition is matched by the
- * element then the held gtype is returned.
+ * element then the finalize rule is executed and the held gtype is returned.
  * 
  * @author Steve Ratcliffe
  */
-public class ExpressionRule implements Rule {
+public class ExpressionRule implements FinalizableRule {
 	private final Op expression;
 	private final GType gtype;
+	private Rule finalizeRule;
 
+	/** Finalize rules must not have an element type definition so the add method must never be called. */
+	private final static TypeResult finalizeTypeResult = new TypeResult() {
+		public void add(Element el, GType type) {
+			throw new UnsupportedOperationException("Finalize rules must not contain an action block.");
+		}
+	};
+	
 	public ExpressionRule(Op expression, GType gtype) {
 		this.expression = expression;
 		this.gtype = gtype;
 	}
 
 	public void resolveType(Element el, TypeResult result) {
-		if (expression.eval(el))
+		if (expression.eval(el)) {
+			// expression matches
+			if (finalizeRule != null) {
+				// run the finalize rules
+				finalizeRule.resolveType(el, finalizeTypeResult);
+			}
 			result.add(el, gtype);
+		}
 	}
 
 	public String toString() {
 		return expression.toString() + ' ' + gtype;
 	}
+
+	public void setFinalizeRule(Rule finalizeRule) {
+		this.finalizeRule = finalizeRule;
+	}
 }
Index: src/uk/me/parabola/mkgmap/osmstyle/RuleSet.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/RuleSet.java	(revision 2795)
+++ src/uk/me/parabola/mkgmap/osmstyle/RuleSet.java	(working copy)
@@ -22,7 +22,9 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+
 import uk.me.parabola.mkgmap.reader.osm.Element;
+import uk.me.parabola.mkgmap.reader.osm.FinalizableRule;
 import uk.me.parabola.mkgmap.reader.osm.Rule;
 import uk.me.parabola.mkgmap.reader.osm.TypeResult;
 import uk.me.parabola.mkgmap.reader.osm.WatchableTypeResult;
@@ -34,7 +36,7 @@
  *
  * @author Steve Ratcliffe
  */
-public class RuleSet implements Rule, Iterable<Rule> {
+public class RuleSet implements FinalizableRule, Iterable<Rule> {
 	private Rule[] rules;
 
 	private RuleIndex index = new RuleIndex();
@@ -151,4 +153,17 @@
 	public void addUsedTags(Collection<String> usedTags) {
 		this.usedTags.addAll(usedTags);
 	}
+
+	public void setFinalizeRule(Rule finalizeRule) {
+		if (rules == null) {
+			// this method must be called after prepare() is called so
+			// that we have rules to which the finalize rules can be applied
+			throw new IllegalStateException("First call prepare() before setting the finalize rules");
+		}
+		for (Rule rule : rules) {
+			if (rule instanceof FinalizableRule)
+				((FinalizableRule) rule).setFinalizeRule(finalizeRule);
+		}
+		
+	}
 }
Index: src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java	(revision 2795)
+++ src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java	(working copy)
@@ -61,12 +61,17 @@
 	private final TypeReader typeReader;
 
 	private final RuleSet rules;
+	private final RuleSet finalizeRules;
 	private final boolean performChecks;
 	private final Map<Integer, List<Integer>> overlays;
 
-	public RuleFileReader(FeatureKind kind, LevelInfo[] levels, RuleSet rules, boolean performChecks, Map<Integer, List<Integer>> overlays) {
+	private boolean inFinalizeSection = false;
+	
+	public RuleFileReader(FeatureKind kind, LevelInfo[] levels, RuleSet rules, boolean performChecks, 
+			Map<Integer, List<Integer>> overlays) {
 		this.kind = kind;
 		this.rules = rules;
+		this.finalizeRules = new RuleSet();
 		this.performChecks = performChecks;
 		this.overlays = overlays;
 		typeReader = new TypeReader(kind, levels);
@@ -81,6 +86,8 @@
 	public void load(StyleFileLoader loader, String name) throws FileNotFoundException {
 		loadFile(loader, name);
 		rules.prepare();
+		finalizeRules.prepare();
+		rules.setFinalizeRule(finalizeRules);
 	}
 
 	/**
@@ -193,6 +200,25 @@
 				// Wrong syntax for include statement, so push back token to allow a possible expression to be read
 				scanner.pushToken(token);
 			}
+		} 
+		// check if it is the start label of the <finalize> section
+		else if (inFinalizeSection == false && scanner.checkToken("<")) {
+			Token token = scanner.nextToken();
+			if (scanner.checkToken("finalize")) {
+				Token finalizeToken = scanner.nextToken();
+				if (scanner.checkToken(">")) {
+					// consume the > token
+					scanner.nextToken();
+					// mark start of the finalize block
+					inFinalizeSection = true;
+					return true;
+				} else {
+					scanner.pushToken(finalizeToken);
+					scanner.pushToken(token);
+				}
+			} else {
+				scanner.pushToken(token);
+			}
 		}
 		scanner.skipSpace();
 		return false;
@@ -212,6 +238,10 @@
 	private void saveRule(TokenScanner scanner, Op op, ActionList actions, GType gt) {
 		log.info("EXP", op, ", type=", gt);
 
+		// check if the type definition is allowed
+		if (inFinalizeSection && gt != null)
+			throw new SyntaxException(scanner, "Element type definition is not allowed in <finalize> section");
+		
 		//System.out.println("From: " + op);
 		Op op2 = rearrangeExpression(op);
 		//System.out.println("TO  : " + op2);
@@ -486,7 +516,10 @@
 		else
 			rule = new ActionRule(expr, actions.getList(), gt);
 
-		rules.add(keystring, rule, actions.getChangeableTags());
+		if (inFinalizeSection)
+			finalizeRules.add(keystring, rule, actions.getChangeableTags());
+		else
+			rules.add(keystring, rule, actions.getChangeableTags());
 	}
 
 	public static void main(String[] args) throws FileNotFoundException {
Index: src/uk/me/parabola/mkgmap/reader/osm/FinalizableRule.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/FinalizableRule.java	(revision 0)
+++ src/uk/me/parabola/mkgmap/reader/osm/FinalizableRule.java	(revision 0)
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013
+ * 
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ * 
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ * 
+ */
+package uk.me.parabola.mkgmap.reader.osm;
+
+/**
+ * This interface is implemented by all rules that
+ * support finalize rules.
+ * 
+ * @author WanMil
+ */
+public interface FinalizableRule extends Rule {
+	
+	/**
+	 * Sets the finalize rules that are executed when 
+	 * an element type definition matches.
+	 * 
+	 * @param finalizeRule finalize rule(s)
+	 */
+	public void setFinalizeRule(Rule finalizeRule);
+}
Index: src/uk/me/parabola/mkgmap/reader/osm/FeatureKind.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/FeatureKind.java	(revision 2795)
+++ src/uk/me/parabola/mkgmap/reader/osm/FeatureKind.java	(working copy)
@@ -23,6 +23,7 @@
 	POLYLINE,
 	POLYGON,
 
-	// This is not really a feature kind, as there is no corresponding Garmin object.
+	// These are not really feature kinds, as there is no corresponding Garmin object.
 	RELATION,
+	ALL,
 }
