On 04/09/13 08:13, Steve Brophy wrote:
I tested this, and it fixed the problem of including from the wrong
place. Also I saw no repeat of the other errors reported.
Thanks for testing, that is all good news.
For completeness I am attaching a revised version of the patch which
removes all the code from the original way of doing this that is no
longer used.
There is also a patch removing base-style from the "noname" style which
I could not do before because of this very bug ;)
Prebuilt: http://files.mkgmap.org.uk/download/151/mkgmap.jar
..Steve
Index: resources/styles/noname/points
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- resources/styles/noname/points (revision )
+++ resources/styles/noname/points (revision )
@@ -0,0 +1,2 @@
+
+include points from default;
Index: resources/styles/noname/lines
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- resources/styles/noname/lines (revision 2687)
+++ resources/styles/noname/lines (revision )
@@ -27,3 +27,4 @@
{name '${name} (${ref})' | '${ref}' }
[0x7 resolution 22]
+include lines from default;
Index: resources/styles/noname/info
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- resources/styles/noname/info (revision 2687)
+++ resources/styles/noname/info (revision )
@@ -8,9 +8,6 @@
summary: Special map to highlight roads with no name
-# This uses the default style as a base
-base-style: default
-
description {
This style is to help find roads that don't yet have a name in OSM
by highlighting those roads. Roads that have a name or a ref
Index: resources/styles/noname/polygons
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- resources/styles/noname/polygons (revision )
+++ resources/styles/noname/polygons (revision )
@@ -0,0 +1,2 @@
+
+include polygons from default;
Index: src/uk/me/parabola/mkgmap/osmstyle/StyleFileLoader.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyleFileLoader.java (revision 2687)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyleFileLoader.java (revision )
@@ -16,6 +16,7 @@
*/
package uk.me.parabola.mkgmap.osmstyle;
+import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.Reader;
@@ -29,7 +30,7 @@
*
* @author Steve Ratcliffe
*/
-public abstract class StyleFileLoader {
+public abstract class StyleFileLoader implements Closeable {
private static final Logger log = Logger.getLogger(StyleFileLoader.class);
/**
Index: src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java (revision 2687)
+++ src/uk/me/parabola/mkgmap/osmstyle/RuleFileReader.java (revision )
@@ -16,11 +16,14 @@
*/
package uk.me.parabola.mkgmap.osmstyle;
+import java.io.File;
import java.io.FileNotFoundException;
-import java.io.FileReader;
import java.io.Reader;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
+
+import uk.me.parabola.imgfmt.Utils;
import uk.me.parabola.log.Logger;
import uk.me.parabola.mkgmap.general.LevelInfo;
import uk.me.parabola.mkgmap.osmstyle.actions.ActionList;
@@ -58,12 +61,14 @@
private final TypeReader typeReader;
private final RuleSet rules;
- private TokenScanner scanner;
- private StyleFileLoader loader;
+ private final boolean performChecks;
+ private final Map<Integer, List<Integer>> overlays;
- public RuleFileReader(FeatureKind kind, LevelInfo[] levels, RuleSet rules) {
+ public RuleFileReader(FeatureKind kind, LevelInfo[] levels, RuleSet rules, boolean performChecks, Map<Integer, List<Integer>> overlays) {
this.kind = kind;
this.rules = rules;
+ this.performChecks = performChecks;
+ this.overlays = overlays;
typeReader = new TypeReader(kind, levels);
}
@@ -74,27 +79,17 @@
* @throws FileNotFoundException If the given file does not exist.
*/
public void load(StyleFileLoader loader, String name) throws FileNotFoundException {
- this.loader = loader;
- load(loader.open(name), name, false, null);
+ loadFile(loader, name);
+ rules.prepare();
}
-
/**
- * Read a rules file.
- * @param loader A file loader.
- * @param name The name of the file to open.
- * @param performChecks if true, report potential errors
- * @param overlays a map with overlays or null
- * @throws FileNotFoundException If the given file does not exist.
+ * Load a rules file. This should be used when calling recursively when including
+ * files.
*/
- public void load(StyleFileLoader loader, String name, boolean performChecks, Map<Integer, List<Integer>> overlays) throws FileNotFoundException {
- this.loader = loader;
- load(loader.open(name), name, performChecks, overlays);
- }
-
-
- private void load(Reader r, String name, boolean performChecks, Map<Integer, List<Integer>> overlays) {
- scanner = new TokenScanner(name, r);
+ private void loadFile(StyleFileLoader loader, String name) throws FileNotFoundException {
+ Reader r = loader.open(name);
+ TokenScanner scanner = new TokenScanner(name, r);
scanner.setExtraWordChars("-:.");
ExpressionReader expressionReader = new ExpressionReader(scanner, kind);
@@ -103,7 +98,7 @@
// Read all the rules in the file.
scanner.skipSpace();
while (!scanner.isEndOfFile()) {
- if (checkCommand())
+ if (checkCommand(loader, scanner))
continue;
if (scanner.isEndOfFile())
@@ -120,13 +115,12 @@
else if (actionList == null)
throw new SyntaxException(scanner, "No type definition given");
- saveRule(expr, actionList, type);
+ saveRule(scanner, expr, actionList, type);
scanner.skipSpace();
}
rules.addUsedTags(expressionReader.getUsedTags());
rules.addUsedTags(actionReader.getUsedTags());
- rules.prepare();
}
/**
@@ -145,8 +139,11 @@
* Called before reading an expression, must put back any token (apart from whitespace) if there is
* not a command.
* @return true if a command was found. The caller should check again for a command.
+ * @param currentLoader The current style loader. Any included files are loaded from here, if no other
+ * style is specified.
+ * @param scanner The current token scanner.
*/
- private boolean checkCommand() {
+ private boolean checkCommand(StyleFileLoader currentLoader, TokenScanner scanner) {
scanner.skipSpace();
if (scanner.isEndOfFile())
return false;
@@ -162,9 +159,8 @@
|| (next.getType() == TokType.SYMBOL && (next.isValue("'") || next.isValue("\""))))
{
String filename = scanner.nextWord();
- String displayName = filename;
- StyleFileLoader styleLoader = loader;
+ StyleFileLoader loader = currentLoader;
scanner.skipSpace();
// The include can be followed by an optional 'from' clause. The file is read from the given
@@ -176,11 +172,7 @@
throw new SyntaxException(scanner, "No style name after 'from'");
try {
- // Note: this style loader is never explicitly closed and so if the style loader opens
- // a file it will not be explicitly closed either. The only loader where this happens has
- // a finalise() method that closes its underlying file.
- styleLoader = StyleFileLoader.createStyleLoader(null, styleName);
- displayName = String.format("%s/%s", styleName, filename);
+ loader = StyleFileLoader.createStyleLoader(null, styleName);
} catch (FileNotFoundException e) {
throw new SyntaxException(scanner, "Cannot find style: " + styleName);
}
@@ -189,10 +181,13 @@
scanner.validateNext(";");
try {
- scanner.includeFile(displayName, styleLoader.open(filename));
+ loadFile(loader, filename);
return true;
} catch (FileNotFoundException e) {
throw new SyntaxException(scanner, "Cannot open included file: " + filename);
+ } finally {
+ if (loader != currentLoader)
+ Utils.closeFile(loader);
}
} else {
// Wrong syntax for include statement, so push back token to allow a possible expression to be read
@@ -214,7 +209,7 @@
* in a basket we know that the first term is true so we can drop that
* from the expression.
*/
- private void saveRule(Op op, ActionList actions, GType gt) {
+ private void saveRule(TokenScanner scanner, Op op, ActionList actions, GType gt) {
log.info("EXP", op, ", type=", gt);
//System.out.println("From: " + op);
@@ -222,9 +217,9 @@
//System.out.println("TO : " + op2);
if (op2 instanceof BinaryOp) {
- optimiseAndSaveBinaryOp((BinaryOp) op2, actions, gt);
+ optimiseAndSaveBinaryOp(scanner, (BinaryOp) op2, actions, gt);
} else {
- optimiseAndSaveOtherOp(op2, actions, gt);
+ optimiseAndSaveOtherOp(scanner, op2, actions, gt);
}
}
@@ -399,7 +394,7 @@
}
}
- private void optimiseAndSaveOtherOp(Op op, ActionList actions, GType gt) {
+ private void optimiseAndSaveOtherOp(TokenScanner scanner, Op op, ActionList actions, GType gt) {
if (op.isType(EXISTS)) {
// The lookup key for the exists operation is 'tag=*'
createAndSaveRule(op.getFirst().getKeyValue() + "=*", op, actions, gt);
@@ -411,11 +406,12 @@
/**
* Optimise the expression tree, extract the primary key and
* save it as a rule.
+ * @param scanner The token scanner, used for error message file/line numbers.
* @param op a binary expression
* @param actions list of actions to execute on match
* @param gt the Garmin type of the element
*/
- private void optimiseAndSaveBinaryOp(BinaryOp op, ActionList actions, GType gt) {
+ private void optimiseAndSaveBinaryOp(TokenScanner scanner, BinaryOp op, ActionList actions, GType gt) {
Op first = op.getFirst();
Op second = op.getSecond();
@@ -446,9 +442,9 @@
}
} else if (op.isType(OR)) {
LinkedOp op1 = LinkedOp.create(first, true);
- saveRule(op1, actions, gt);
+ saveRule(scanner, op1, actions, gt);
- saveRestOfOr(actions, gt, second, op1);
+ saveRestOfOr(scanner, actions, gt, second, op1);
return;
} else {
if (!first.isType(FUNCTION) || !((StyleFunction) first).isIndexable())
@@ -462,23 +458,23 @@
AndOp andOp = new AndOp();
andOp.setFirst(existsOp);
andOp.setSecond(op);
- optimiseAndSaveBinaryOp(andOp, actions, gt);
+ optimiseAndSaveBinaryOp(scanner, andOp, actions, gt);
return;
}
createAndSaveRule(keystring, op, actions, gt);
}
- private void saveRestOfOr(ActionList actions, GType gt, Op second, LinkedOp op1) {
+ private void saveRestOfOr(TokenScanner scanner, ActionList actions, GType gt, Op second, LinkedOp op1) {
if (second.isType(OR)) {
LinkedOp nl = LinkedOp.create(second.getFirst(), false);
op1.setLink(nl);
- saveRule(nl, actions, gt);
- saveRestOfOr(actions, gt, second.getSecond(), op1);
+ saveRule(scanner, nl, actions, gt);
+ saveRestOfOr(scanner, actions, gt, second.getSecond(), op1);
} else {
LinkedOp op2 = LinkedOp.create(second, false);
op1.setLink(op2);
- saveRule(op2, actions, gt);
+ saveRule(scanner, op2, actions, gt);
}
}
@@ -495,11 +491,15 @@
public static void main(String[] args) throws FileNotFoundException {
if (args.length > 0) {
- Reader r = new FileReader(args[0]);
RuleSet rs = new RuleSet();
RuleFileReader rr = new RuleFileReader(FeatureKind.POLYLINE,
- LevelInfo.createFromString("0:24 1:20 2:18 3:16 4:14"), rs);
- rr.load(r, "string", true,null);
+ LevelInfo.createFromString("0:24 1:20 2:18 3:16 4:14"), rs, false,
+ Collections.<Integer, List <Integer>>emptyMap());
+
+ StyleFileLoader loader = new DirectoryFileLoader(
+ new File(args[0]).getAbsoluteFile().getParentFile());
+ rr.load(loader, args[0]);
+
System.out.println("Result: " + rs);
} else {
System.err.println("Usage: RuleFileReader <file>");
Index: test/func/lib/TestUtils.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- test/func/lib/TestUtils.java (revision 2687)
+++ test/func/lib/TestUtils.java (revision )
@@ -153,7 +153,7 @@
public static RuleSet makeRuleSet(StyleFileLoader loader) {
RuleSet rs = new RuleSet();
RuleFileReader rr = new RuleFileReader(FeatureKind.POLYLINE, LevelInfo.createFromString("0:24 1:20 2:18 3:16 4:14"),
- rs);
+ rs, false, null);
try {
rr.load(loader, "lines");
} catch (FileNotFoundException e) {
Index: src/uk/me/parabola/mkgmap/scan/TokenScanner.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/uk/me/parabola/mkgmap/scan/TokenScanner.java (revision 2687)
+++ src/uk/me/parabola/mkgmap/scan/TokenScanner.java (revision )
@@ -19,11 +19,8 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
-import java.util.Deque;
import java.util.LinkedList;
-import uk.me.parabola.imgfmt.Utils;
-
/**
* Read a file in terms of word and symbol tokens.
*
@@ -33,20 +30,17 @@
private static final int NO_PUSHBACK = 0;
// Reading state
- private Reader reader;
+ private final Reader reader;
private int pushback = NO_PUSHBACK;
private boolean isEOF;
- private String fileName;
+ private final String fileName;
private int linenumber;
- private LinkedList<Token> tokens = new LinkedList<Token>();
+ private final LinkedList<Token> tokens = new LinkedList<Token>();
private boolean bol = true;
- // Included file state
- private final Deque<ScanState> states = new LinkedList<ScanState>();
-
// Extra word characters.
private String extraWordChars = "";
private String commentChar = "#";
@@ -234,41 +228,16 @@
return c;
}
- do {
- try {
- c = reader.read();
- } catch (IOException e) {
+ try {
+ c = reader.read();
+ } catch (IOException e) {
+ isEOF = true;
- c = -1;
- }
+ c = -1;
+ }
- // Finished a file, return to the including file if there was one.
- if (c == -1)
- popState();
- } while (!isEOF && c == -1);
-
return c;
}
- /**
- * Finish the currently included file and return the state to start reading from the parent
- * file.
- *
- * This is called when at the end of the current input file.
- * If there are no more parent files then the end of file flag is set.
- */
- private void popState() {
- // Close the current reader that is finished.
- Utils.closeFile(reader);
-
- if (states.isEmpty()) {
- isEOF = true;
- return;
- }
-
- ScanState state = states.removeFirst();
- state.copyTo(this);
- }
-
private boolean isSpace(int nextch) {
return Character.isWhitespace(nextch) || nextch == '\uFEFF';
}
@@ -440,67 +409,5 @@
this.commentChar = "";
else
this.commentChar = commentChar;
- }
-
- /**
- * Include a new file in the token stream.
- *
- * Stop reading from the current file and save all the details about the file. Sets up to read from
- * the included file.
- *
- * @param filename The name of the file that is being read. This is only used for messages and so doesn't
- * have to be a name that can be directly opened for example.
- * @param r The input reader for the file.
- */
- public void includeFile(String filename, Reader r) {
- ScanState state = new ScanState(this);
- states.addFirst(state);
-
- reader = r;
- pushback = NO_PUSHBACK;
- isEOF = false;
- fileName = filename;
- linenumber = 1;
- tokens = new LinkedList<Token>();
- bol = true;
- }
-
- /**
- * Saved state of scanning and individual file. Used when including files.
- */
- private class ScanState {
- private final Reader reader;
- private final int pushback;
-
- private final String fileName;
- private final int linenumber;
-
- private final LinkedList<Token> tokens;
-
- private final boolean bol;
-
- /**
- * Create this state with the state of the token scanner.
- */
- public ScanState(TokenScanner ts) {
- reader = ts.reader;
- pushback = ts.pushback;
- fileName = ts.fileName;
- linenumber = ts.linenumber;
- tokens = ts.tokens;
- bol = ts.bol;
- }
-
- /**
- * Copy this state to the given token scanner.
- */
- public void copyTo(TokenScanner ts) {
- ts.reader = reader;
- ts.pushback = pushback;
- ts.fileName = fileName;
- ts.linenumber = linenumber;
- ts.tokens = tokens;
- ts.bol = bol;
- }
}
}
Index: src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java (revision 2687)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyleImpl.java (revision )
@@ -290,31 +290,31 @@
}
try {
- RuleFileReader reader = new RuleFileReader(FeatureKind.RELATION, levels, relations);
- reader.load(fileLoader, "relations", performChecks, getOverlaidTypeMap());
+ RuleFileReader reader = new RuleFileReader(FeatureKind.RELATION, levels, relations, performChecks, getOverlaidTypeMap());
+ reader.load(fileLoader, "relations");
} catch (FileNotFoundException e) {
// it is ok for this file to not exist.
log.debug("no relations file");
}
try {
- RuleFileReader reader = new RuleFileReader(FeatureKind.POINT, levels, nodes);
- reader.load(fileLoader, "points", performChecks, getOverlaidTypeMap());
+ RuleFileReader reader = new RuleFileReader(FeatureKind.POINT, levels, nodes, performChecks, getOverlaidTypeMap());
+ reader.load(fileLoader, "points");
} catch (FileNotFoundException e) {
// it is ok for this file to not exist.
log.debug("no points file");
}
try {
- RuleFileReader reader = new RuleFileReader(FeatureKind.POLYLINE, levels, lines);
- reader.load(fileLoader, "lines", performChecks, getOverlaidTypeMap());
+ RuleFileReader reader = new RuleFileReader(FeatureKind.POLYLINE, levels, lines, performChecks, getOverlaidTypeMap());
+ reader.load(fileLoader, "lines");
} catch (FileNotFoundException e) {
log.debug("no lines file");
}
try {
- RuleFileReader reader = new RuleFileReader(FeatureKind.POLYGON, levels, polygons);
- reader.load(fileLoader, "polygons", performChecks, getOverlaidTypeMap());
+ RuleFileReader reader = new RuleFileReader(FeatureKind.POLYGON, levels, polygons, performChecks, getOverlaidTypeMap());
+ reader.load(fileLoader, "polygons");
} catch (FileNotFoundException e) {
log.debug("no polygons file");
}
@@ -536,7 +536,7 @@
name = "default";
if (name == null){
- StyleFileLoader loader;
+ StyleFileLoader loader = null;
try {
loader = StyleFileLoader.createStyleLoader(loc, null);
int numEntries = loader.list().length;
@@ -544,9 +544,12 @@
throw new ExitException("Style file " + loc + " contains multiple styles, use option --style to select one.");
} catch (FileNotFoundException e) {
throw new ExitException("Could not open style file " + loc);
+ } finally {
+ Utils.closeFile(loader);
}
}
- Style style = null;
+
+ Style style;
try {
style = new StyleImpl(loc, name, props, WITHOUT_CHECKS);
} catch (SyntaxException e) {
Index: test/uk/me/parabola/mkgmap/osmstyle/RuleFileReaderTest.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- test/uk/me/parabola/mkgmap/osmstyle/RuleFileReaderTest.java (revision 2687)
+++ test/uk/me/parabola/mkgmap/osmstyle/RuleFileReaderTest.java (revision )
@@ -804,6 +804,21 @@
}
@Test
+ public void testIncludeFrom() {
+ // NOTE: this test uses the default style, which could change.
+ StyleFileLoader loader = new StringStyleFileLoader(new String[][] {
+ {"lines", "include 'lines' from default;\n"},
+ });
+ RuleSet rs = makeRuleSet(loader);
+
+ Way way = new Way(1);
+ way.addTag("highway", "motorway");
+ GType type = getFirstType(rs, way);
+ assertNotNull("Check type not null", type);
+ assertEquals(1, type.getType());
+ }
+
+ @Test
public void testLengthFunction() {
// Its less than 92m
RuleSet rs = makeRuleSet("A=B & length() < 92 [0x5]");
@@ -914,7 +929,8 @@
RuleSet rs = new RuleSet();
RuleFileReader rr = new RuleFileReader(FeatureKind.POINT,
- LevelInfo.createFromString("0:24 1:20 2:18 3:16 4:14"), rs);
+ LevelInfo.createFromString("0:24 1:20 2:18 3:16 4:14"),
+ rs, false, null);
try {
rr.load(loader, "points");
} catch (FileNotFoundException e) {
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://lists.mkgmap.org.uk/mailman/listinfo/mkgmap-dev