using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
class abc089_d {
    static int __cnt = 0;
    static string __mark = "@@@";
    static void Main(string[] args) {
#if LOCAL_ENVIRONMENT
        StreamReader __sr = new StreamReader("stdin.txt");
        string __str = __sr.ReadToEnd();
        __sr.Close();
        int __index = __str.IndexOf(__mark, 0);
        while (__index != -1) {
            __index = __str.IndexOf(__mark, __index + __mark.Length);
            __cnt++;
        }
        if (__cnt > 0) {
            Console.Write("Eenter test data no(1-{0})? ", __cnt);
            Console.Out.Flush();
            if (!int.TryParse(Console.ReadLine(), out __cnt)) __cnt = 1;
            Console.WriteLine("Select/Default test data: {0}", __cnt);
        }
        var stdin = new System.IO.StreamReader("stdin.txt");
        Console.SetIn(stdin);
#endif
        SimpleScanner sc = new SimpleScanner(__cnt);
        int H = sc.NextInt(), W = sc.NextInt();
        var S = new char[H, W];
        int whiteCnt = 0;
        const char white = '.', black = '#', white2 = '@';
        for (var h = 0; h < H; h++) {
            var s = sc.NextString();
            for (var w = 0; w < W; w++) {
                char c = s[w];
                S[h,w] = c;
                if (c == white) whiteCnt++;
            }
        }
        var que = new Queue<Tuple<int, int, int>>();
        int ng = 0;
        bool goal = false;
        que.Enqueue(Tuple.Create(0, 0, 1));
        Func<int, int, bool> check = (h, w) => ((h < 0 || w < 0 || w > W-1 || h > H-1) ? false : (S[h,w] == white));
        while (que.Count > 0) {
            Tuple<int, int, int> p = que.Dequeue();
            int h = p.Item1, w = p.Item2, c = p.Item3;
#if LOCAL_ENVIRONMENT
        Console.Error.WriteLine($"h:{h}, w:{w}, c:{c}");
#endif
            if (S[h, w] != white) continue;
            if (h == H-1 && w == W-1) { goal=true; ng = c; break; }
            c++;
            var f = false;
            if (check(h, w+1)) {que.Enqueue(Tuple.Create(h, w+1, c)); f=true;}
            if (check(h+1, w)) {que.Enqueue(Tuple.Create(h+1, w, c)); f=true;}
            if (check(h, w-1)) {que.Enqueue(Tuple.Create(h, w-1, c)); f=true;}
            if (check(h-1, w)) {que.Enqueue(Tuple.Create(h-1, w, c)); f=true;}
            if (f) S[h,w] = white2;
        }
#if LOCAL_ENVIRONMENT
        for (var h = 0; h < H; h++) {
            for (var w = 0; w < W; w++) Console.Error.Write($"{S[h,w]} ");
            Console.Error.WriteLine();
        }
#endif
        if (!goal)  { Console.WriteLine(-1); return; }
        Console.WriteLine(whiteCnt - ng);
    } //Main

    public class SimpleScanner {
        private int cnt;
        private string[] items;
        public SimpleScanner(int cnt = 0) {
            this.cnt = 0;
            var sb = new StringBuilder();
            var s = Console.ReadLine();
            while (s != null) {
                sb.Append(s + " ");
                s = Console.ReadLine();
            }
            this.items = sb.ToString().Split(' ');
#if LOCAL_ENVIRONMENT
            if (cnt > 0) {
                int index = Array.IndexOf(this.items, __mark + cnt.ToString());
                this.cnt = index + 1;
            }
            Console.Error.WriteLine("SimpleScanner.cnt: {0}", this.cnt);
            Console.Error.WriteLine("SimpleScanner.items: {0}" , this.items.ToStringA());
#endif
        }
        public void SetCnt(int n) { this.cnt = n; }
        public int NextInt() {
            return int.Parse(this.items[this.cnt++]);
        }
        public long NextLong() {
            return long.Parse(this.items[this.cnt++]);
        }
        public string NextString() {
            return this.items[this.cnt++];
        }
        public int[] NextIntArray(int n) {
            if (n < 1) throw new IndexOutOfRangeException("引数は1以上であること！");
            var result = new int[n];
            for (var i = 0; i < n; i++) result[i] = this.NextInt();
#if LOCAL_ENVIRONMENT
            Console.Error.WriteLine("{0}", result.ToStringA());
#endif
            return result;
        }
        public long[] NextLongArray(int n) {
            if (n < 1) throw new IndexOutOfRangeException("引数は1以上であること！");
            var result = new long[n];
            for (var i = 0; i < n; i++) result[i] = this.NextLong();
#if LOCAL_ENVIRONMENT
            Console.Error.WriteLine("{0}", result.ToStringA());
#endif
            return result;
        }
        public string[] NextStringArray(int n) {
            if (n < 1) throw new IndexOutOfRangeException("引数は1以上であること！");
            var result = new string[n];
            for (var i = 0; i < n; i++) result[i] = this.NextString();
#if LOCAL_ENVIRONMENT
            Console.Error.WriteLine("{0}", result.ToStringA());
#endif
            return result;
        }
        public int[][] NextInt2Col(int n) {
            const int M = 2;
            if (n < 1) throw new IndexOutOfRangeException("引数は1以上であること！");
            int[][] result = new int[M][] {
                new int[n],
                new int[n],
            };
            for (var i = 0; i < n; i++) {
                result[0][i] = this.NextInt();
                result[1][i] = this.NextInt();
            }
#if LOCAL_ENVIRONMENT
            Console.Error.WriteLine("NextInt2Col: [");
            for (var i = 0; i < M; i++)
                Console.Error.WriteLine("  {0},", result[i].ToStringA());
            Console.Error.WriteLine("]");
#endif
            return result;
        }
    }
}
static class Extensions {
    public static string ToStringA<T>(this T[] array, string separator = ", ", string braces = "[]") {
        string bL = braces.Length > 0 ? braces[0].ToString() : "";
        string bR = braces.Length > 1 ? braces[1].ToString() : "";
        return bL + String.Join(separator, array) + bR;
    }
    public static T[] SortDesc<T>(this T[] array) {
        Array.Sort(array);
        Array.Reverse(array);
        return array;
    }

}


Measured memory_bytes: 13396