Index: resources/styles/default/finalizer
===================================================================
--- resources/styles/default/finalizer	(revision 0)
+++ resources/styles/default/finalizer	(revision 0)
@@ -0,0 +1,4 @@
+# The finalize file contains actions that are performed on each
+# element when a rule matches with an element type definition. 
+
+# highway=* { echo "Next highway"; set test=yes }
\ No newline at end of file
Index: src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java	(revision 2788)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java	(working copy)
@@ -107,6 +107,7 @@
 	private final RuleSet polygons = new RuleSet();
 	private final RuleSet nodes = new RuleSet();
 	private final RuleSet relations = new RuleSet();
+	private final RuleSet finalizer = new RuleSet();
 
 	private OverlayReader overlays;
 	private final boolean performChecks;
@@ -203,6 +204,11 @@
 		relations.prepare();
 		return relations;
 	}
+	
+	public Rule getFinalizerRules() {
+		finalizer.prepare();
+		return finalizer;
+	}
 
 	public LineAdder getOverlays(final LineAdder lineAdder) {
 		LineAdder adder = null;
@@ -223,6 +229,7 @@
 		set.addAll(lines.getUsedTags());
 		set.addAll(polygons.getUsedTags());
 		set.addAll(nodes.getUsedTags());
+		set.addAll(finalizer.getUsedTags());
 
 		// this is to allow style authors to say that tags are really used even
 		// if they are not found in the style file.  This is mostly to work
@@ -290,7 +297,7 @@
 		}
 
 		try {
-			RuleFileReader reader = new RuleFileReader(FeatureKind.RELATION, levels, relations, performChecks, getOverlaidTypeMap());
+			RuleFileReader reader = new RuleFileReader(FeatureKind.RELATION, levels, relations, performChecks, getOverlaidTypeMap(), false);
 			reader.load(fileLoader, "relations");
 		} catch (FileNotFoundException e) {
 			// it is ok for this file to not exist.
@@ -298,7 +305,7 @@
 		}
 
 		try {
-			RuleFileReader reader = new RuleFileReader(FeatureKind.POINT, levels, nodes, performChecks, getOverlaidTypeMap());
+			RuleFileReader reader = new RuleFileReader(FeatureKind.POINT, levels, nodes, performChecks, getOverlaidTypeMap(), false);
 			reader.load(fileLoader, "points");
 		} catch (FileNotFoundException e) {
 			// it is ok for this file to not exist.
@@ -306,18 +313,25 @@
 		}
 
 		try {
-			RuleFileReader reader = new RuleFileReader(FeatureKind.POLYLINE, levels, lines, performChecks, getOverlaidTypeMap());
+			RuleFileReader reader = new RuleFileReader(FeatureKind.POLYLINE, levels, lines, performChecks, getOverlaidTypeMap(), false);
 			reader.load(fileLoader, "lines");
 		} catch (FileNotFoundException e) {
 			log.debug("no lines file");
 		}
 
 		try {
-			RuleFileReader reader = new RuleFileReader(FeatureKind.POLYGON, levels, polygons, performChecks, getOverlaidTypeMap());
+			RuleFileReader reader = new RuleFileReader(FeatureKind.POLYGON, levels, polygons, performChecks, getOverlaidTypeMap(), false);
 			reader.load(fileLoader, "polygons");
 		} catch (FileNotFoundException e) {
 			log.debug("no polygons file");
 		}
+		
+		try {
+			RuleFileReader reader = new RuleFileReader(FeatureKind.ALL, levels, finalizer, performChecks, getOverlaidTypeMap(), true);
+			reader.load(fileLoader, "finalizer");
+		} catch (FileNotFoundException e) {
+			log.debug("no finalizer file");
+		}
 	}
 
 	/**
@@ -466,6 +480,7 @@
 		polygons.merge(other.polygons);
 		nodes.merge(other.nodes);
 		relations.merge(other.relations);
+		finalizer.merge(other.finalizer);
 	}
 
 	private void checkVersion() throws FileNotFoundException {
@@ -498,6 +513,7 @@
 		stylePrinter.setLines(lines);
 		stylePrinter.setNodes(nodes);
 		stylePrinter.setPolygons(polygons);
+		stylePrinter.setFinalizer(finalizer);
 		stylePrinter.dumpToFile(out);
 	}
 
Index: src/uk/me/parabola/mkgmap/osmstyle/eval/ExpressionReader.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/eval/ExpressionReader.java	(revision 2788)
+++ 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/function/FunctionFactory.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/function/FunctionFactory.java	(revision 2788)
+++ 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/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/StylePrinter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StylePrinter.java	(revision 2788)
+++ src/uk/me/parabola/mkgmap/osmstyle/StylePrinter.java	(working copy)
@@ -22,6 +22,7 @@
 	private RuleSet lines;
 	private RuleSet polygons;
 	private RuleSet relations;
+	private RuleSet finalizer;
 
 	public StylePrinter(Style style) {
 		this.style = style;
@@ -51,6 +52,9 @@
 		if (polygons != null)
 			dumpRuleSet(fmt, "polygons", polygons);
 
+		if (finalizer != null)
+			dumpRuleSet(fmt, "finalizer", finalizer);
+
 		fmt.flush();
 	}
 
@@ -112,4 +116,8 @@
 	public void setRelations(RuleSet relations) {
 		this.relations = relations;
 	}
+
+	public void setFinalizer(RuleSet finalizer) {
+		this.finalizer = finalizer;
+	}
 }
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(revision 2791)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(working copy)
@@ -133,6 +133,7 @@
 	private final Rule nodeRules;
 	private final Rule lineRules;
 	private final Rule polygonRules;
+	private final Rule finalizerRules;
 
 	private boolean driveOnLeft;
 	private boolean driveOnRight;
@@ -159,6 +160,7 @@
 		nodeRules = style.getNodeRules();
 		lineRules = style.getLineRules();
 		polygonRules = style.getPolygonRules();
+		finalizerRules = style.getFinalizerRules();
 		
 		housenumberGenerator = new HousenumberGenerator(props);
 
@@ -296,6 +298,15 @@
 	 * Built in rules to run after converting the element.
 	 */
 	private void postConvertRules(Element el, GType type) {
+		
+		// run the finalizer
+		finalizerRules.resolveType(el, new TypeResult() {
+			public void add(Element el, GType type) {
+				log.error("finalizer rules contains an element type definition "+type+" which is not allowed. It is ignored.");
+				assert false;
+			}
+		});
+		
 		// Set the name from the 'name' tag or failing that from
 		// the default_name.
 		el.setName(el.getTag("name"));
Index: src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java	(revision 2788)
+++ src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java	(working copy)
@@ -63,12 +63,16 @@
 	private final RuleSet rules;
 	private final boolean performChecks;
 	private final Map<Integer, List<Integer>> overlays;
+	/** Flag that is set to {@true} if a type definition is forbidden. This is the case for the finalizer rules. */
+	private final boolean noTypeDef;
 
-	public RuleFileReader(FeatureKind kind, LevelInfo[] levels, RuleSet rules, boolean performChecks, Map<Integer, List<Integer>> overlays) {
+	public RuleFileReader(FeatureKind kind, LevelInfo[] levels, RuleSet rules, boolean performChecks, 
+			Map<Integer, List<Integer>> overlays, boolean noTypeDef) {
 		this.kind = kind;
 		this.rules = rules;
 		this.performChecks = performChecks;
 		this.overlays = overlays;
+		this.noTypeDef = noTypeDef;
 		typeReader = new TypeReader(kind, levels);
 	}
 
@@ -212,6 +216,11 @@
 	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 (noTypeDef && gt != null)
+			// TODO: better hint where the problem is
+			throw new SyntaxException(scanner, "Element type definition not allowed");
+		
 		//System.out.println("From: " + op);
 		Op op2 = rearrangeExpression(op);
 		//System.out.println("TO  : " + op2);
@@ -494,7 +503,7 @@
 			RuleSet rs = new RuleSet();
 			RuleFileReader rr = new RuleFileReader(FeatureKind.POLYLINE,
 					LevelInfo.createFromString("0:24 1:20 2:18 3:16 4:14"), rs, false,
-					Collections.<Integer, List <Integer>>emptyMap());
+					Collections.<Integer, List <Integer>>emptyMap(), false);
 
 			StyleFileLoader loader = new DirectoryFileLoader(
 					new File(args[0]).getAbsoluteFile().getParentFile());
Index: src/uk/me/parabola/mkgmap/reader/osm/FeatureKind.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/FeatureKind.java	(revision 2788)
+++ 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,
 }
Index: src/uk/me/parabola/mkgmap/reader/osm/Style.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Style.java	(revision 2788)
+++ src/uk/me/parabola/mkgmap/reader/osm/Style.java	(working copy)
@@ -66,6 +66,11 @@
 	public Rule getRelationRules();
 
 	/**
+	 * Get the finalizer rules.
+	 */
+	public Rule getFinalizerRules();
+	
+	/**
 	 * Get the overlay definitions.  Most styles will not use this.
 	 */
 	public LineAdder getOverlays(LineAdder lineAdder);
