import java.util.concurrent.LinkedBlockingDeque

fun intList() = readLine()?.split(" ")?.map(String::toInt) ?: TODO()
fun main() {
    val (h, w) = intList()
    val matrix = 0.until(h).map {
        readLine() ?: return
    }
    val minimum = Array(h + 1) { Array(w + 1) { 0 } }
    val queue = LinkedBlockingDeque<Pair<Int, Int>>()
    queue.offer(Pair(0, 0))
    while (queue.isNotEmpty()) {
        val (y, x) = queue.poll()
        val s = minimum[y][x]
        if (x - 1 >= 0 && matrix[y][x - 1] == '.') {
            if (minimum[y][x - 1] == 0 || minimum[y][x - 1] > s + 1) {
                minimum[y][x - 1] = s + 1
                queue.offer(Pair(y, x - 1))
            }
        }
        if (x + 1 < w && matrix[y][x + 1] == '.') {
            if (minimum[y][x + 1] == 0 || minimum[y][x + 1] > s + 1) {
                minimum[y][x + 1] = s + 1
                queue.offer(Pair(y, x + 1))
            }
        }
        if (y - 1 >= 0 && matrix[y - 1][x] == '.') {
            if (minimum[y - 1][x] == 0 || minimum[y - 1][x] > s + 1) {
                minimum[y - 1][x] = s + 1
                queue.offer(Pair(y - 1, x))
            }
        }
        if (y + 1 < h && matrix[y + 1][x] == '.') {
            if (minimum[y + 1][x] == 0 || minimum[y + 1][x] > s + 1) {
                minimum[y + 1][x] = s + 1
                queue.offer(Pair(y + 1, x))
            }
        }
    }
    val minimumStep = minimum[h - 1][w - 1]
    if (minimumStep == 0) {
        println("-1")
        return
    }
    val white = matrix.sumBy {
        it.count { it == '.' }
    } - 1
    println((white - minimumStep).toString())
}