Index: /trunk/scripts/BuildProjectionDefinitions.java
===================================================================
--- /trunk/scripts/BuildProjectionDefinitions.java	(revision 13601)
+++ /trunk/scripts/BuildProjectionDefinitions.java	(revision 13602)
@@ -13,4 +13,6 @@
 import java.util.Map;
 import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.openstreetmap.josm.data.projection.CustomProjection;
@@ -81,6 +83,14 @@
         if (list.isEmpty())
             throw new AssertionError("EPSG file seems corrupted");
+        Pattern badDmsPattern = Pattern.compile("(\\d+(?:\\.\\d+)?d\\d+(?:\\.\\d+)?')(N|S|E|W)");
         for (ProjectionDefinition pd : list) {
-            map.put(pd.code, pd);
+            // DMS notation without second causes problems with cs2cs, add 0"
+            Matcher matcher = badDmsPattern.matcher(pd.definition);
+            StringBuffer sb = new StringBuffer();
+            while (matcher.find()) {
+                matcher.appendReplacement(sb, matcher.group(1) + "0\"" + matcher.group(2));
+            }
+            matcher.appendTail(sb);
+            map.put(pd.code, new ProjectionDefinition(pd.code, pd.name, sb.toString()));
         }
     }
@@ -113,5 +123,5 @@
                 }
             }
-            out.write("## ESRI-specific projections (source: proj.4):\n");
+            out.write("## ESRI-specific projections (source: ESRI):\n");
             for (ProjectionDefinition pd : esriProj4.values()) {
                 pd = new ProjectionDefinition(pd.code, "ESRI: " + pd.name, pd.definition);
@@ -194,4 +204,15 @@
             result = false;
             noDeprecated++;
+        }
+
+        // exclude projections failing
+        if (Arrays.asList("EPSG:53025", "EPSG:54025", "EPSG:65062",
+                "EPSG:102061", "EPSG:102062", "EPSG:102121", "EPSG:102212", "EPSG:102366", "EPSG:102445",
+                "EPSG:102491", "EPSG:102591", "EPSG:102631", "EPSG:103232", "EPSG:103235", "EPSG:103238",
+                "EPSG:103241", "EPSG:103371", "EPSG:103471", "EPSG:103474", "EPSG:103475"
+                ).contains(pd.code)) {
+            // 53025/54025: Unsuitable parameters 'lat_1' and 'lat_2' for two point method
+            // Others: cs2cs errors to investigate
+            result = false;
         }
 
Index: /trunk/src/org/openstreetmap/josm/data/Bounds.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/Bounds.java	(revision 13601)
+++ /trunk/src/org/openstreetmap/josm/data/Bounds.java	(revision 13602)
@@ -355,7 +355,7 @@
     public String toShortString(DecimalFormat format) {
         return format.format(minLat) + ' '
-        + format.format(minLon) + " / "
-        + format.format(maxLat) + ' '
-        + format.format(maxLon);
+             + format.format(minLon) + " / "
+             + format.format(maxLat) + ' '
+             + format.format(maxLon);
     }
 
@@ -513,6 +513,5 @@
      */
     public double getArea() {
-        double w = getWidth();
-        return w * (maxLat - minLat);
+        return getWidth() * (maxLat - minLat);
     }
 
@@ -523,9 +522,7 @@
      */
     public String encodeAsString(String separator) {
-        StringBuilder sb = new StringBuilder();
-        sb.append(minLat).append(separator).append(minLon)
-        .append(separator).append(maxLat).append(separator)
-        .append(maxLon);
-        return sb.toString();
+        return new StringBuilder()
+          .append(minLat).append(separator).append(minLon).append(separator)
+          .append(maxLat).append(separator).append(maxLon).toString();
     }
 
@@ -574,7 +571,7 @@
         Bounds bounds = (Bounds) obj;
         return Double.compare(bounds.minLat, minLat) == 0 &&
-                Double.compare(bounds.minLon, minLon) == 0 &&
-                Double.compare(bounds.maxLat, maxLat) == 0 &&
-                Double.compare(bounds.maxLon, maxLon) == 0;
+               Double.compare(bounds.minLon, minLon) == 0 &&
+               Double.compare(bounds.maxLat, maxLat) == 0 &&
+               Double.compare(bounds.maxLon, maxLon) == 0;
     }
 }
Index: /trunk/src/org/openstreetmap/josm/data/coor/conversion/LatLonParser.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/coor/conversion/LatLonParser.java	(revision 13601)
+++ /trunk/src/org/openstreetmap/josm/data/coor/conversion/LatLonParser.java	(revision 13602)
@@ -50,4 +50,14 @@
     private static final Pattern P_XML = Pattern.compile(
             "lat=[\"']([+|-]?\\d+[.,]\\d+)[\"']\\s+lon=[\"']([+|-]?\\d+[.,]\\d+)[\"']");
+
+    private static final String FLOAT = "(\\d+(\\.\\d*)?)";
+    /** Degree-Minute-Second pattern **/
+    private static final String DMS = "(?<neg1>-)?"
+            + "(?=\\d)(?:(?<single>" + FLOAT + ")|"
+            + "((?<degree>" + FLOAT + ")d)?"
+            + "((?<minutes>" + FLOAT + ")\')?"
+            + "((?<seconds>" + FLOAT + ")\")?)"
+            + "(?:[NE]|(?<neg2>[SW]))?";
+    private static final Pattern P_DMS = Pattern.compile("^" + DMS + "$");
 
     private static class LatLonHolder {
@@ -199,12 +209,6 @@
      */
     public static double parseCoordinate(String angleStr) {
-        final String floatPattern = "(\\d+(\\.\\d*)?)";
         // pattern does all error handling.
-        Matcher in = Pattern.compile("^(?<neg1>-)?"
-                + "(?=\\d)(?:(?<single>" + floatPattern + ")|"
-                + "((?<degree>" + floatPattern + ")d)?"
-                + "((?<minutes>" + floatPattern + ")\')?"
-                + "((?<seconds>" + floatPattern + ")\")?)"
-                + "(?:[NE]|(?<neg2>[SW]))?$").matcher(angleStr);
+        Matcher in = P_DMS.matcher(angleStr);
 
         if (!in.find()) {
Index: /trunk/src/org/openstreetmap/josm/data/projection/Projections.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/projection/Projections.java	(revision 13601)
+++ /trunk/src/org/openstreetmap/josm/data/projection/Projections.java	(revision 13602)
@@ -315,9 +315,12 @@
         List<ProjectionDefinition> result = new ArrayList<>();
         Pattern epsgPattern = Pattern.compile("<(\\d+)>(.*)<>");
+        String coor = "(-?\\d+\\.\\d+)";
+        Pattern areaPattern = Pattern.compile("# area: \\(lat: "+coor+", "+coor+"\\) - \\(lon: "+coor+", "+coor+"\\).*");
         StringBuilder sb = new StringBuilder();
+        String bounds = null;
         String line;
         while ((line = r.readLine()) != null) {
             line = line.trim();
-            if (!line.isEmpty()) {
+            if (!line.isEmpty() && !line.startsWith("##")) {
                 if (!line.startsWith("#")) {
                     Matcher m = epsgPattern.matcher(line);
@@ -325,4 +328,7 @@
                         String code = "EPSG:" + m.group(1);
                         String definition = m.group(2).trim();
+                        if (!definition.contains("+bounds=") && bounds != null) {
+                            definition += bounds;
+                        }
                         result.add(new ProjectionDefinition(code, sb.toString(), definition));
                     } else {
@@ -330,9 +336,16 @@
                     }
                     sb.setLength(0);
-                } else if (!line.startsWith("# area: ")) {
+                    bounds = null;
+                } else if (line.startsWith("# area: ")) {
+                    Matcher m = areaPattern.matcher(line);
+                    if (m.matches()) {
+                        bounds = " +bounds=" + String.join(",", m.group(3), m.group(1), m.group(4), m.group(2));
+                    }
+                } else {
+                    String s = line.substring(1).trim();
                     if (sb.length() == 0) {
-                        sb.append(line.substring(1).trim());
+                        sb.append(s);
                     } else {
-                        sb.append('(').append(line.substring(1).trim()).append(')');
+                        sb.append('(').append(s).append(')');
                     }
                 }
Index: /trunk/test/unit/org/openstreetmap/josm/data/projection/CustomProjectionTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/projection/CustomProjectionTest.java	(revision 13601)
+++ /trunk/test/unit/org/openstreetmap/josm/data/projection/CustomProjectionTest.java	(revision 13602)
@@ -61,4 +61,12 @@
         assertEquals(1.1 + 3 / 60.0 + 5.2 / 3600.0, CustomProjection.parseAngle("1.1d3'5.2\"", "xxx"), 1e-10);
 
+        assertEquals(1.1, CustomProjection.parseAngle("1.1dN", "xxx"), 1e-10);
+        assertEquals(-1.1, CustomProjection.parseAngle("1.1dS", "xxx"), 1e-10);
+        assertEquals(1.1, CustomProjection.parseAngle("1.1dE", "xxx"), 1e-10);
+        assertEquals(-1.1, CustomProjection.parseAngle("1.1dW", "xxx"), 1e-10);
+
+        assertEquals(49.5, CustomProjection.parseAngle("49d30'N", "xxx"), 1e-10);
+        assertEquals(-120.8333333333, CustomProjection.parseAngle("120.0d50'W", "xxx"), 1e-10);
+
         // fail
         Stream.of("", "-", "-N", "N", "1.1 ", "x", "1.1d1.1d", "1.1e", "1.1.1", ".1", "1.1d3\"5.2'").forEach(
