{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}

import Control.Applicative
import Debug.Trace
import Control.Monad
import Control.Monad.ST
import Data.Array.ST
import Data.List
import Data.Maybe


bfs :: forall s. [[Char]] -> Int -> Int -> (Int, Int) -> (Int, Int) -> ST s (Maybe Int)
bfs field w h (x0,y0) (x1,y1) = do
  check <- newArray ((1,1),(w,h)) (-1) :: ST s (STArray s (Int,Int) Int)

  let
    bfs' :: [[Char]] -> (Int,Int) -> [(Int,Int)] -> ST s ()
    bfs' _ _ [] = return ()
    bfs' field (x1,y1) ((x0,y0):queue)
      | (x0,y0) == (x1,y1) = return ()
      | otherwise = do
          
          next <- forM [(x0+1,y0), (x0-1,y0), (x0,y0+1), (x0,y0-1)] $ \(x,y) -> do
            if x>=1 && y>=1 && x<=w && y<=h then do
              c <- readArray check (x,y)
              if (field!!(y-1))!!(x-1) == '.' && c<0 then do
                readArray check (x0,y0) >>= \v -> writeArray check (x,y) (v+1)
                return $ Just (x,y)
                else
                return Nothing
              else
              return Nothing
                
          bfs' field (x1,y1) (queue ++ (catMaybes next))

  writeArray check (1,1) 0 
  bfs' field (x1,y1) [(x0,y0)]
  
  readArray check (w,h) >>= return . (\x -> if x == -1 then Nothing else Just x)



main = do
  (h:w:_) <- getLine >>= return . map read . words :: IO [Int]
  s <- getContents >>= return . lines :: IO [[Char]]

  let countWhite = sum $ map (length . filter (=='.')) s
              
  print $ case runST $ bfs s w h (1,1) (w,h) of
            Nothing -> -1
            Just x -> countWhite - x - 1