diff -ru Geo-METAR-1.14-orig/METAR.pm Geo-METAR-1.15-koos/METAR.pm
--- Geo-METAR-1.14-orig/METAR.pm	Sat Nov 25 01:07:51 2000
+++ Geo-METAR-1.15-koos/METAR.pm	Fri Nov 19 18:38:30 2004
@@ -1,5 +1,23 @@
 # $Id: METAR.pm,v 1.8 2000/11/25 00:07:38 jzawodn Exp $
 
+# KH: fix the parser
+# should be a finite state machine
+# - metar has rules what comes after what. but codes can be missing.
+# (measurement not done) or //// (measurement broken at the moment)
+# so given a state counter, it can stay the same or go up one or more states,
+# but it can never go down
+#
+# KNMI slides about METAR codes:
+# http://www.knmi.nl/organis/wa/mo/codeplot/metar/
+#
+# info on the last bit which is actually a forecast: (German)
+# http://www.wetterklima.de/flug/metar/Metarvorhersage.htm
+#
+# more info here (dutch, and txt 707 is not standard metar)
+# http://www.vwkweb.nl/index.html?http://www.vwkweb.nl/weerinfo/weerinfo_teletekst707.html
+# and also (dutch)
+# http://www.gids.nl/weather/eheh/metari.html
+
 # This module is used for decoding NWS METAR code.
 
 # Example METARs
@@ -18,30 +36,53 @@
 # 9/205 51007
 #
 # LA
+#
 # KLAX 251450Z 07004KT 7SM SCT100 BKN200 14/11 A3005 RMK AO2 SLP173
 # T01390111 56005
+#
+# Soesterberg
+#
+# EHSB 181325Z 24009KT 8000 -RA BR FEW011 SCT022 OVC030 07/06 Q1011 WHT WHT TEMPO GRN
 
 # For METAR info, please see
 # http://tgsv5.nws.noaa.gov/oso/oso1/oso12/metar.htm
+# moved
+# http://metar.noaa.gov/
+#
+# in scary detail (metar coding)
+#
+# http://metar.noaa.gov/table_master.jsp?sub_menu=yes&show=fmh1ch12.htm&dir=./handbook/&title=title_handbook
+#
+
 
 # The METAR specification is dictated in the Federal Meteorological Handbook
 # which is available on-line at:
 # http://tgsv5.nws.noaa.gov/oso/oso1/oso12/fmh1.htm
 
 # General Structure is:
-# SITE, DATE/TIME, WIND, VISIBILITY, CLOUDS, TEMPERATURE, PRESSURE, REMARKS
+# TYPE, SITE, DATE/TIME, WIND, VISIBILITY, CLOUDS, TEMPERATURE, PRESSURE, REMARKS
 
 # Specifically:
 
-# SITE
+# TYPE (optional)
+# METAR or SPECI
+# METAR: regular report
+# SPECI: special report
+
+# SITE (required, only once)
 #
 # 4-Char site identifier (KLAX for LA, KHST for Houston)
 
-# DATE/TIME
+# DATE/TIME (required, only once)
 #
 # 6-digit time followed by "Z", indicating UTC
 
-# WIND
+# REPORT MODIFIER (optional)
+# AUTO or COR
+# AUTO = Automatic report (no human intervention)
+# COR = Corrected METAR or SPECI
+
+# WIND (group)
 #
 # Wind direction (\d\d\d) and speed (\d?\d\d) and optionaling gusting
 # information denoted by "G" and speed (\d?\d\d) followed by "KT", for knots.
@@ -50,15 +91,24 @@
 #
 # Calm wind is recorded as 00000KT.
 
-# VISIBILITY
+# VISIBILITY (group)
 #
-# Visibility (\d+) followed by "SM" for statute miles
+# Visibility (\d+) followed by "SM" for statute miles or no 'SM' for meters
+# (european)
 #
 # May be 1/(\d)SM for a fraction.
 #
 # May be M1/\d)SM for less than a given fraction. (M="-")
+#
+# \d\d\d\d according to KNMI
+# lowest horizontal visibility (looking around)
+# round down
+# 0000 - 0500m in steps of 0050m
+# 0500 - 5000m in steps of 0100m
+# 5000 - 9999m in steps of 1000m
+# 10km or more is 9999
 
-# RUNWAY Visual Range Group (I've never seen this, but it's in the spec)
+# RUNWAY Visual Range (Group)
 #
 # R(\d\d\d)(L|C|R)?/((M|P)?\d\d\d\d){1,2}FT
 #
@@ -70,6 +120,16 @@
 #
 #  "M" beginning a value means less than the reportable value of \d\d\d\d.
 #  "P" beginning a value means more than the reportable value of \d\d\d\d.
+#
+#  new
+#
+#  R(\d\d\d[LCR]?)/([MP]?\d\d\d\d)(V[MP]?\d\d\d\d)?FT
+#
+# $1 runway number + Left/Center/Right
+# $2 visibility feet
+# $3 Varying feet
+# M = less than
+# P = more than
 
 # WEATHER (Present Weather Group)
 #
@@ -98,6 +158,8 @@
 # The pressure, or altimeter setting, at the reporting site recorded in
 # inches of mercury (Hg) minus the decimal point. It should always look
 # like (A\d\d\d\d).
+#
+# KNMI: Q\d\d\d\d pressure in hPa calculated for sea level
 
 # REMARKS
 #
@@ -105,6 +167,26 @@
 # informative of special conditions.
 #
 # Remarks begin with the "RMK" keyword and continue to the end of the line.
+#
+# trend group
+#
+# color codes BLU WHT GRN YLO AMB RED
+# BLACK: vliegveld dicht
+# future trend 
+# NOSIG no significant change
+# TEMPO temporary change
+# WHT WHT TEMPO GRN = current white, prediction white temporary green
+# NSW no significant weather
+# AT at a given time
+# PROB30 probability 30%
+# BECMG becoming
+# BECMG (weather) FM \d\d\d\d TL \d\d\d\d = from until utc times
+# BECMG (weather) AT \d\d\d\d = at utc time
+# BECMG (weather) TL \d\d\d\d = change until utc time
+# BECMG 2000 visibility
+# BECMG NSW weather type
+# etc etc
+# FCST CANCEL (2 tokens!) Forecast cancel: no further forecasts for a while
 
 ### Package Definition
 
@@ -117,7 +199,7 @@
 use vars qw($AUTOLOAD $VERSION);
 use Carp 'cluck';
 
-$VERSION = '1.14';
+$VERSION = '1.15';
 
 ##
 ## Lookup tables
@@ -194,13 +276,14 @@
     $self->{TIME}          = undef;             # time it was issued
     $self->{MOD}           = undef;             # modifier (AUTO/COR)
     $self->{WIND_DIR_DEG}  = undef;             # wind dir in degrees
-    $self->{WIND_DIR_ENG}  = undef;             # wind dir in english (NW/SE)
+    $self->{WIND_DIR_ENG}  = undef;             # wind dir in english (Northwest/Southeast)
+    $self->{WIND_DIR_ABB}  = undef;             # wind dir in abbreviated english (NW/SE)
     $self->{WIND_KTS}      = undef;             # wind speed (knots)
     $self->{WIND_GUST_KTS} = undef;             # wind gusts (knots)
     $self->{WIND_MPH}      = undef;             # wind speed (MPH)
     $self->{WIND_GUST_MPH} = undef;             # wind gusts (MPH)
     $self->{VISIBILITY}    = undef;             # visibility info
-    $self->{RUNWAY}        = undef;             # runyway vis.
+    $self->{RUNWAY}        = [ ];             # runyway vis.
     $self->{WEATHER}       = [ ];               # current weather
     $self->{WEATHER_LOG}   = [ ];               # weather log
     $self->{SKY}           = [ ];               # curent sky
@@ -231,6 +314,7 @@
     $self->{sky}           = [ ];               # sky conditions (cloud cover)
     $self->{temp_dew}      = undef;             # temp and dew pt.
     $self->{alt}           = undef;             # altimeter setting
+	$self->{pressure}      = undef;             # pressure (HPa)
     $self->{slp}           = undef;             # sea level pressure
     $self->{remarks}       = [ ];               # remarks
 
@@ -352,7 +436,6 @@
     my @toks = @{$self->{tokens}};      # copy tokens array...
 
     my $tok;
-    my $in_remarks = 0;                 # started processing remarks
 
     ## This is a semi-brute-force way of doing things, but the amount
     ## of data is relatively small, so it shouldn't be a big deal.
@@ -360,6 +443,27 @@
     ## Ideally, I'd have it skip checks for items which have been
     ## found, but that would make this more "linear" and I'd remove
     ## the pretty while loop.
+	#
+	# KH: modified to maintain state to not get lost in remarks and stuff
+	# and be a lot better at parsing
+	
+	# states
+
+	my $expect_type = 0;
+	my $expect_site = 1;
+	my $expect_datetime = 2;
+	my $expect_modifier = 3;
+	my $expect_wind = 4;
+	my $expect_visibility = 5;
+	my $expect_runwayvisual = 6;
+	my $expect_presentweather = 7;
+	my $expect_clouds = 8;
+	my $expect_temperature = 9;
+	my $expect_pressure = 10;
+	my $expect_remarks = 11;
+	my $expect_usremarks = 12;
+
+	my $parsestate = $expect_type;
 
     ## Assume standard report by default
 
@@ -368,13 +472,13 @@
 
     while (defined($tok = shift(@toks))) ## as long as there are tokens
     {
-        print "trying to match [$tok]\n" if $self->{debug};
+        print "trying to match [$tok] state is $parsestate\n" if $self->{debug};
 
         ##
         ## is it a report type?
         ##
 
-        if (($tok =~ /METAR/i) or ($tok =~ /SPECI/i))
+        if (($parsestate == $expect_type) and ($tok =~ /(METAR|SPECI)/i))
         {
             $self->{type} = $tok;
 
@@ -387,6 +491,7 @@
                 $self->{TYPE} = "Special Weather Report";
             }
             print "[$tok] is a report type.\n" if $self->{debug};
+			$parsestate = $expect_site;
             next;
         }
 
@@ -394,10 +499,11 @@
         ## is is a site ID?
         ##
 
-        elsif ($tok =~ /K[A-Z]{3,3}/)
+        elsif (($parsestate <= $expect_site) and ($tok =~ /[A-Z]{4}/))
         {
             $self->{site} = $tok;
             print "[$tok] is a site ID.\n" if $self->{debug};
+			$parsestate = $expect_datetime;
             next;
         }
 
@@ -405,10 +511,11 @@
         ## is it a date/time?
         ##
 
-        elsif ($tok =~ /\d{6,6}Z/i)
+        elsif (($parsestate == $expect_datetime) and ($tok =~ /\d{6,6}Z/i))
         {
             $self->{date_time} = $tok;
             print "[$tok] is a date/time.\n" if $self->{debug};
+			$parsestate = $expect_modifier;
             next;
 
 
@@ -418,10 +525,11 @@
         ## is it a report modifier?
         ##
 
-        elsif (($tok =~ /AUTO/i) or ($tok =~ /COR/i))
+        elsif (($parsestate == $expect_modifier) and ($tok =~ /AUTO|COR/i))
         {
             $self->{modifier} = $tok;
             print "[$tok] is a report modifier.\n" if $self->{debug};
+			$parsestate = $expect_wind;
             next;
         }
 
@@ -429,21 +537,35 @@
         ## is it wind information?
         ##
 
-        elsif ($tok =~ /.*?KT$/i)
+        elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_visibility) and ($tok =~ /.*?KT$/i))
         {
             $self->{wind} = $tok;
             print "[$tok] is wind information.\n" if $self->{debug};
+			$parsestate = $expect_visibility;
+            next;
+        }
+
+		##
+		## is it visibility information in meters?
+		##
+	
+		elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_runwayvisual) and ($tok =~ /\d\d\d\d/))
+		{
+			$self->{visibility} = $tok;
+            print "[$tok] is visibility information.\n" if $self->{debug};
+			$parsestate = $expect_runwayvisual;
             next;
         }
 
         ##
-        ## is it visibility information?
+        ## is it visibility information in statute miles?
         ##
 
-        elsif ($tok =~ /.*?SM$/i)
+        elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_runwayvisual) and ($tok =~ /.*?SM$/i))
         {
             $self->{visibility} = $tok;
             print "[$tok] is visibility information.\n" if $self->{debug};
+			$parsestate = $expect_runwayvisual;
             next;
         }
 
@@ -451,22 +573,27 @@
         ## is it visibility information with a leading digit?
         ##
 
-        elsif ($tok =~ /^\d$/)
+        elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_runwayvisual) and  ($tok =~ /^\d$/))
         {
             $tok .= " " . shift(@toks);
             $self->{visibility} = $tok;
             print "[$tok is multi-part visibility information.\n" if $self->{debug};
+			$parsestate = $expect_runwayvisual;
             next;
         }
 
         ##
         ## is it runway visibility info?
         ##
+		# KH: I've seen runway visibility with 'U' units
+		# EHSB 121425Z 22010KT 1200 R27/1600U -DZ BKN003 OVC007 07/07 Q1016 AMB FCST CANCEL
 
-        elsif ($tok =~ /R.*?FT$/i)
+        elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_presentweather) and ($tok =~ /R.*?(FT|U)$/i))
         {
-            $self->{runway} = $tok;
+            push (@{$self->{RUNWAY}},$tok);
             print "[$tok] is runway visual information.\n" if $self->{debug};
+			$parsestate = $expect_runwayvisual;
+			# there can be multiple runways, so stay at this state
             next;
         }
 
@@ -474,7 +601,7 @@
         ## is it current weather info?
         ##
 
-        elsif ($tok =~ /^(-|\+)?(VC)?($_weather_types_pat)+/i)
+        elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_clouds) and ($tok =~ /^(-|\+)?(VC)?($_weather_types_pat)+/i))
         {
             my $engl = "";
             my $qual = $1;
@@ -519,6 +646,8 @@
 
             push(@{$self->{weather}},$tok);
             print "[$tok] is current weather.\n" if $self->{debug};
+			$parsestate = $expect_presentweather;
+			# there can be multiple current weather types, so stay at this state
             next;
         }
 
@@ -526,17 +655,20 @@
         ## is it sky conditions (clear)?
         ##
 
-        elsif ( $tok eq "SKC" || $tok eq "CLR" )
+        elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_temperature) and ( $tok =~ /SKC|CLR/ ))
         {
             push(@{$self->{sky}},$tok);
             push(@{$self->{SKY}}, "Sky Clear");
+            print "[$tok] is a sky condition.\n" if $self->{debug};
+			$parsestate = $expect_clouds;
+			next;
         }
 
         ##
         ## is it sky conditions (clouds)?
         ##
 
-        elsif ( $tok =~ /^(FEW|SCT|BKN|OVC|SKC|CLR)(\d\d\d)?(CB|TCU)?$/i)
+        elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_temperature) and ( $tok =~ /^(FEW|SCT|BKN|OVC)(\d\d\d)?(CB|TCU)?$/i))
         {
             push(@{$self->{sky}},$tok);
             my $engl = "";
@@ -563,6 +695,8 @@
 
             push(@{$self->{SKY}}, $engl);
             print "[$tok] is a sky condition.\n" if $self->{debug};
+			$parsestate = $expect_clouds;
+			# clouds DO repeat. a lot ;)
             next;
         }
 
@@ -570,7 +704,7 @@
         ## is it temperature and dew point info?
         ##
 
-        elsif ($tok =~ /(M?\d\d)\/(M?\d\d)/i)
+        elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_pressure) and ($tok =~ /(M?\d\d)\/(M?\d\d)/i))
         {
             next if $self->{temp_dew};
             $self->{temp_dew} = $tok;
@@ -581,6 +715,7 @@
             $self->{DEW_C} =~ s/^M/-/;
 
             print "[$tok] is temperature/dew point information.\n" if $self->{debug};
+			$parsestate = $expect_pressure;
             next;
         }
 
@@ -588,35 +723,56 @@
         ## is it an altimeter setting?
         ##
 
-        elsif (!$in_remarks && $tok =~ /^A(\d\d)(\d\d)$/i)
+        elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_remarks) and ($tok =~ /^A(\d\d)(\d\d)$/i))
         {
             $self->{alt} = $tok;
             $self->{ALT} = "$1.$2";
+
+			# inches Hg pressure. How imperial can you get
+			# conversion using 'units'
+
+			$self->{pressure} = 33.863886 * $self->{ALT};
+
             print "[$tok] is an altimeter setting.\n" if $self->{debug};
+			$parsestate = $expect_remarks;
             next;
         }
 
+		##
+		## is it a pressure?
+		#$
+
+		elsif (($parsestate >= $expect_modifier) and ($parsestate < $expect_remarks) and ($tok =~ /^Q(\d\d\d\d)$/i))
+		{
+			$self->{pressure} = $1;
+
+			$self->{ALT} = 0.029529983*$self->{pressure};
+			print "[$tok] is an air pressure.\n" if $self->{debug};
+			$parsestate = $expect_remarks;
+			next;
+		}
+
         ##
-        ## automatic station type?
+        ## us type remarks?
         ##
 
-        elsif ($in_remarks && $tok =~ /^A(O\d)$/i)
+        elsif (($parsestate == $expect_remarks) and ($tok =~ /^RMK$/i))
         {
-            $self->{autostationtype} = $tok;
-            $self->{AUTO_STATIONTYPE} = $1;
-            print "[$tok] is an automatic station type remark.\n" if $self->{debug};
+            push(@{$self->{remarks}},$tok);
+            print "[$tok] is a (US type) remark.\n" if $self->{debug};
+			$parsestate  = $expect_usremarks;
             next;
         }
 
         ##
-        ## remarks?
+        ## automatic station type?
         ##
 
-        elsif ($tok =~ /^RMK$/i)
+        elsif (($parsestate == $expect_usremarks) and ($tok =~ /^A(O\d)$/i))
         {
-            push(@{$self->{remarks}},$tok);
-            $in_remarks = 1;
-            print "[$tok] is a remark.\n" if $self->{debug};
+            $self->{autostationtype} = $tok;
+            $self->{AUTO_STATIONTYPE} = $1;
+            print "[$tok] is an automatic station type remark.\n" if $self->{debug};
             next;
         }
 
@@ -624,7 +780,7 @@
         ## sea level pressure
         ##
 
-        elsif ($tok =~ /^SLP(\d+)/i)
+        elsif (($parsestate == $expect_usremarks) and ($tok =~ /^SLP(\d+)/i))
         {
             $self->{slp} = $tok;
             $self->{SLP} = "$1 mb";
@@ -636,7 +792,7 @@
         ## sea level pressure not available
         ##
 
-        elsif ($tok eq "SLPNO")
+        elsif (($parsestate == $expect_usremarks) and ($tok eq "SLPNO"))
         {
             $self->{slp} = "SLPNO";
             $self->{SLP} = "not available";
@@ -648,7 +804,7 @@
         ## hourly precipitation
         ##
 
-        elsif ($tok =~ /^P(\d\d\d\d)$/i)
+        elsif (($parsestate == $expect_usremarks) and ($tok =~ /^P(\d\d\d\d)$/i))
         {
             $self->{hourlyprecip} = $tok;
 
@@ -663,7 +819,7 @@
         ## weather begin/end times
         ##
 
-        elsif ($tok =~ /^($_weather_types_pat)([BE\d]+)$/i)
+        elsif (($parsestate == $expect_usremarks) and ($tok =~ /^($_weather_types_pat)([BE\d]+)$/i))
         {
             my $engl = "";
             my $times = $2;
@@ -690,7 +846,7 @@
         ## remarks for significant cloud types
         ##
 
-        elsif ($in_remarks && ($tok eq "CB" || $tok eq "TCU"))
+        elsif (($parsestate == $expect_usremarks) and ($tok eq "CB" || $tok eq "TCU"))
         {
             push(@{$self->{sigclouds}}, $tok);
 
@@ -705,7 +861,7 @@
         ## hourly temp/dewpoint
         ##
 
-        elsif ($tok =~ /^T(\d)(\d\d)(\d)(\d)(\d\d)(\d)$/i)
+        elsif (($parsestate == $expect_usremarks) and ($tok =~ /^T(\d)(\d\d)(\d)(\d)(\d\d)(\d)$/i))
         {
             $self->{hourlytempdew} = $tok;
             if ( $1 == 1 ) {
@@ -727,11 +883,11 @@
         ## unknown, not in remarks yet
         ##
 
-        elsif (!$in_remarks)
+        elsif ($parsestate < $expect_remarks)
         {
             push(@{$self->{unknown}},$tok);
             push(@{$self->{UNKNOWN}},$tok);
-            print "[$tok] is unknown.\n" if $self->{debug};
+            print "[$tok] is unexpected at this state.\n" if $self->{debug};
             next;
         }
 
@@ -768,6 +924,7 @@
         my $wind = $self->{wind};
         my $dir_deg  = substr($wind,0,3);
         my $dir_eng = "";
+		my $dir_abb = "";
 
         # Check for wind direction
         if ($dir_deg =~ /VRB/i) {
@@ -775,38 +932,55 @@
         } else {
             if      ($dir_deg < 15) {
                 $dir_eng = "North";
+				$dir_abb = "N";
             } elsif ($dir_deg < 30) {
                 $dir_eng = "North/Northeast";
+				$dir_abb = "NNE";
             } elsif ($dir_deg < 60) {
                 $dir_eng = "Northeast";
+				$dir_abb = "NE";
             } elsif ($dir_deg < 75) {
                 $dir_eng = "East/Northeast";
+				$dir_abb = "ENE";
             } elsif ($dir_deg < 105) {
                 $dir_eng = "East";
+				$dir_abb = "E";
             } elsif ($dir_deg < 120) {
                 $dir_eng = "East/Southeast";
+				$dir_abb = "ESE";
             } elsif ($dir_deg < 150) {
                 $dir_eng = "Southeast";
+				$dir_abb = "SE";
             } elsif ($dir_deg < 165) {
                 $dir_eng = "South/Southeast";
+				$dir_abb = "SSE";
             } elsif ($dir_deg < 195) {
                 $dir_eng = "South";
+				$dir_abb = "S";
             } elsif ($dir_deg < 210) {
                 $dir_eng = "South/Southwest";
+				$dir_abb = "SSW";
             } elsif ($dir_deg < 240) {
                 $dir_eng = "Southwest";
+				$dir_abb = "SW";
             } elsif ($dir_deg < 265) {
                 $dir_eng = "West/Southwest";
+				$dir_abb = "WSW";
             } elsif ($dir_deg < 285) {
                 $dir_eng = "West";
+				$dir_abb = "W";
             } elsif ($dir_deg < 300) {
                 $dir_eng = "West/Northwest";
+				$dir_abb = "WNW";
             } elsif ($dir_deg < 330) {
                 $dir_eng = "Northwest";
+				$dir_abb = "NW";
             } elsif ($dir_deg < 345) {
                 $dir_eng = "North/Northwest";
+				$dir_abb = "NNW";
             } else {
                 $dir_eng = "North";
+				$dir_abb = "N";
             }
         }
 
@@ -829,6 +1003,7 @@
 
         $self->{WIND_DIR_DEG} = $dir_deg;
         $self->{WIND_DIR_ENG} = $dir_eng;
+        $self->{WIND_DIR_ABB} = $dir_abb;
 
     }
 
@@ -838,12 +1013,16 @@
 
     {
         my $vis = $self->{visibility};
-        $vis =~ s/SM$//oi;                              # nuke the "SM"
-        if ($vis =~ /M(\d\/\d)/o) {
-            $self->{VISIBILITY} = "Less than $1 statute miles";
-        } else {
-            $self->{VISIBILITY} = $vis . " Statute Miles";
-        } # end if
+		if ($vis =~ /SM$/){
+			$vis =~ s/SM$//oi;                              # nuke the "SM"
+			if ($vis =~ /M(\d\/\d)/o) {
+				$self->{VISIBILITY} = "Less than $1 statute miles";
+			} else {
+				$self->{VISIBILITY} = $vis . " Statute Miles";
+			} # end if
+		} else {
+			$self->{VISIBILITY} = $vis . " meters";
+		}
     }
 
     ##
@@ -861,6 +1040,11 @@
             $self->{$fkey} = sprintf("%.1f", (($self->{$key} * (9/5)) + 32));
         }
     }
+
+	# join the runway group
+	
+	$self->{runway} = join(', ' , @{$self->{RUNWAY}});
+	
 }
 
 ##
@@ -903,7 +1087,7 @@
 {
     my $self = shift;
 
-    print "METAR dump follows.\n\n";
+    print "Modified METAR dump follows.\n\n";
 
     print "type: $self->{type}\n";
     print "site: $self->{site}\n";
@@ -915,7 +1099,7 @@
     print "weather: " . join(', ', @{$self->{weather}}) . "\n";
     print "sky: " . join(', ', @{$self->{sky}}) . "\n";
     print "temp_dew: $self->{temp_dew}\n";
-    print "alt: $self->{alt}\n";
+    print "alt: $self->{ALT}\n";
     print "slp: $self->{slp}\n";
     print "remarks: " . join (', ', @{$self->{remarks}}) . "\n";
     print "\n";
@@ -1087,6 +1271,10 @@
 =item WIND_DIR_ENG
 
 The current wind direction in english (Southwest, East, North, etc.)
+
+=item WIND_DIR_ABB
+
+The current wind direction in abbreviated english (S, E, N, etc.)
 
 =item WIND_DIR_DEG
 
