Go: package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

var (
	sc = bufio.NewScanner(os.Stdin)
)

type Color int

const (
	ColorBlack Color = iota
	ColorRed
)

type Node struct {
	ID    int
	X, Y  int
	Color Color
	Nexts []*Node
}

func main() {
	for sc.Scan() {
		if sc.Text() == "0 0" {
			break
		}
		chunks := strings.Split(sc.Text(), " ")
		w, _ := strconv.Atoi(chunks[0])
		h, _ := strconv.Atoi(chunks[1])

		// Initialize map
		m := map[int]map[int]*Node{}
		for x := 1; x <= w; x++ {
			m[x] = map[int]*Node{}
			for y := 1; y <= h; y++ {
				m[x][y] = &Node{ID: x + y*w, X: x, Y: y}
			}
		}
		for x := 1; x <= w; x++ {
			for y := 1; y <= h; y++ {
				nexts := []*Node{}
				if n, ok := m[x-1][y]; ok {
					nexts = append(nexts, n)
				}
				if n, ok := m[x][y-1]; ok {
					nexts = append(nexts, n)
				}
				if n, ok := m[x+1][y]; ok {
					nexts = append(nexts, n)
				}
				if n, ok := m[x][y+1]; ok {
					nexts = append(nexts, n)
				}
				m[x][y].Nexts = nexts
			}
		}

		// Set colors
		queue := []*Node{}
		touchedIDs := map[int]struct{}{}
		for y := 1; y <= h; y++ {
			sc.Scan()
			for i, c := range sc.Text() {
				switch c {
				case '.', '@':
					n := m[i+1][y]
					n.Color = ColorBlack
					if c == '@' {
						queue = append(queue, n)
						touchedIDs[n.ID] = struct{}{}
					}
				case '#':
					m[i+1][y].Color = ColorRed
				}
			}
		}

		// Search
		visitedIDs := map[int]struct{}{}
		for {
			if len(queue) == 0 {
				break
			}
			n := queue[0]
			queue = queue[1:]
			visitedIDs[n.ID] = struct{}{}
			for _, next := range n.Nexts {
				if next.Color == ColorRed {
					continue
				}
				if _, ok := touchedIDs[next.ID]; !ok {
					queue = append(queue, next)
					touchedIDs[n.ID] = struct{}{}
				}
			}
		}
		fmt.Println(len(visitedIDs))
	}
}

C++: #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <climits>
#include <algorithm>
#include <string>
#include <sstream>
#include <complex>
#include <vector>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <fstream>

using namespace std;
#define SZ(x) (int)(x).size()
#define REP(i,n) for(int i=0;i<(n);i++)
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define REPR(i,n) for(int i=(n)-1;i>=0;i--)
#define ALL(s) (s).begin(), (s).end()
#define so(V) sort(ALL(V))
#define rev(V) reverse(ALL(V))
#define uni(v) v.erase( unique(ALL(v)) , v.end());

typedef long long unsigned int llu;
typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vll;
typedef vector<bool> vb;
const double EPS = 1e-9;
const int MOD = 1e9 + 7;
const int INF = (1 << 29);
const ll LINF = 1e18;
const double PI = acos(-1);

template<typename T>vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T, typename... Ts>auto make_v(size_t a, Ts... ts) { return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...)); }
template<typename T, typename U, typename... V>
typename enable_if<is_same<T, U>::value != 0>::type
fill_v(U & u, const V... v) { u = U(v...); }
template<typename T, typename U, typename... V>
typename enable_if<is_same<T, U>::value == 0>::type
fill_v(U & u, const V... v) { for (auto& e : u) fill_v<T>(e, v...); }
template<class T> bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> bool chmin(T& a, const T& b) { if (a > b) { a = b; return 1; } return 0; }

int W, H;
bool check(int y, int x) {
	if (y < 0 || y >= H)return false;
	if (x < 0 || x >= W)return false;
	return true;
}

const int BLACK = 1;
const int RED = -1;
vector<vb> Ans;
vvi Map;
int dx[] = { -1,0,0,1 };
int dy[] = { 0,-1,1,0 };

void dfs(int x,int y){
	REP(i, 4) {
		int X = x + dx[i];
		int Y = y + dy[i];
		if (check(Y, X)) {
			if (Map[Y][X] == BLACK && (!Ans[Y][X])) {
				Ans[Y][X] = true;
				dfs(X,Y);
			}
		}
	}
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	cin >> W >> H;
	while (W != 0) {
		Ans = vector<vb>(H, vb(W, false));
		Map = vvi(H, vi(W, 0));
		int x = 0, y = 0;
		REP(i, H) {
			string S;
			cin >> S;
			REP(j, W) {
				if (S[j] == '.') {
					Map[i][j] = BLACK;
				}
				else if (S[j] == '#') {
					Map[i][j] = RED;
				}
				else {
					Map[i][j] = BLACK;
					x = j;
					y = i;
					Ans[i][j] = true;
				}
			}
		}
		dfs(x, y);
		int ans = 0;
		REP(i, H) {
			REP(j, W) {
				if (Ans[i][j])ans++;
			}
		}
		cout << ans << endl;
		cin >> W >> H;
	}
	return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;

#define REP(i, n) for(int i = 0;i < (n);i++)
#define FOR(i, a, b) for(int i = (a);i < (b);i++)
#define all(v) v.begin(),v.end()

using int64 = long long;

int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};

int main(void){
	int H, W;
	while(cin >> H >> W && H && W){
		vector<string> f(H+2, string(W+2, '#'));
		int sy, sx;
		REP(i, H){
			cin >> f[i+1];
			REP(j, W+2)
				if(f[i+1][j] == '@'){
					sy = i+1;
					sx = j;
				}
			f[i+1][0] = f[i+1][W+1] = '#';
		}
		bool visited[30][30] = {};
		int cnt = 0;
		
		function<void(int, int)> dfs = [&](int y, int x){
			visited[y][x] = 1;
			cnt++;
			REP(i, 4){
				int yy = y+dy[i], xx = x+dx[i];
				if(f[yy][xx] != '#' && !visited[yy][xx]){
					dfs(yy, xx);
				}
			}
		};
		dfs(sy, sx);
		cout << cnt << endl;
	}
}

C++: #include <bits/stdc++.h>
const int INF = 1e9;
const int MOD = 1e9+7;
using LL = long long;
const LL LINF = 1e18;
const double EPS = 1e-10;
using namespace std;
class Edge{
public:
    int from,to,value;
    Edge(LL a,LL b,LL c){
        from = a;
        to = b;
        value = c;
    }
    Edge(LL a,LL b){
        from = a;
        to = b;
    }
};

class UnionFind {
public:
    vector<int> data;
    UnionFind(int size) : data(size, -1) { }
    bool connect(int x, int y) {
        x = root(x); y = root(y);
        if (x != y) {
            if (data[y] < data[x]) swap(x, y);
            data[x] += data[y]; data[y] = x;
        }
        return x != y;
    }
    bool same(int x, int y) {
        return root(x) == root(y);
    }
    int root(int x) {
        return data[x] < 0 ? x : data[x] = root(data[x]);
    }
    int size(int x) {
        return -data[root(x)];
    }
};


int main(){
   int h,w;
   while(cin >> w >> h){
       if(h == 0 && w == 0)return 0;
       UnionFind Uni(h*w);
       vector<string> field;
       for(int i = 0;i < h;i++){
           string s;cin >> s;
           field.push_back(s);
       }
       pair<int,int> at;
       for(int i = 0;i < h;i++){
           for(int j = 0;j < w;j++){
      //         cout<<i<<" "<<j<<endl;
               if(field.at(i).at(j) == '#')continue;
               if(field.at(i).at(j) == '@'){
                   at = make_pair(i, j);
                   field.at(i).at(j) = '.';
               }
               if(i != 0){
                   if(field.at(i-1).at(j) == '.')Uni.connect(i*w+j,(i-1)*w+j);
               }
               if(j != 0){
                   if(field.at(i).at(j-1) == '.')Uni.connect(i*w+j,i*w+j-1);
               }
           }
       }
       cout<<Uni.size(at.first*w+at.second)<<endl;
   }
}