{-# LANGUAGE ScopedTypeVariables #-}

import Data.Array.IO
import Data.Array
import Control.Monad
import Control.Applicative

bfs :: IOUArray (Int, Int) Char -> IOUArray (Int, Int) Int -> (Int, Int) -> [(Int, Int)] -> IO Int
bfs grid distance goal [] = return (-1)
bfs grid distance goal (p@(y,x):queue) = do
  ((miny,minx),(maxy,maxx)) <- getBounds grid
  d <- readArray distance p
  if p == goal then
    return d
  else do
    next <- filterM (\(ny,nx) ->
              if (ny < miny || nx < minx || ny > maxy || nx > maxx) then
                return False
              else do
                ng <- readArray grid (ny,nx)
                nd <- readArray distance (ny,nx)
                return (nd == -1 && ng /= '#')
            ) [(y+1,x),(y-1,x),(y,x+1),(y,x-1)]
    forM_ next $ \n -> writeArray distance n (d+1)
    bfs grid distance goal (queue ++ next)

main = do
  [h,w] <- map read . words <$> getLine :: IO [Int]
  strs <- replicateM h getLine :: IO [String]
  (grid :: IOUArray (Int, Int) Char) <- thaw $ listArray ((1,1),(h,w)) $ concat strs
  (distance :: IOUArray (Int, Int) Int) <- newArray ((1,1),(h,w)) (-1)
  (grid' :: Array (Int, Int) Char) <- freeze grid
  let white = (h*w) - 2 - (length [() | (_,e) <- assocs grid', e == '#'])
  b <- bfs grid distance (h,w) [(1,1)]
  print $ if b == -1 then b else white - b