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 <bits/stdc++.h>
using namespace std ;

#define pb(n) push_back(n)
#define fi first
#define se second
#define all(r) (r).begin(),(r).end()
#define gsort(st,en) sort((st),(en),greater<int>())
#define vmax(ary) *max_element(all(ary))
#define vmin(ary) *min_element(all(ary))
#define debug(x) cout<<#x<<": "<<x<<endl
#define fcout(n) cout<<fixed<<setprecision((n))
#define scout(n) cout<<setw(n)
#define vary(type,name,size,init) vector< type> name(size,init)

#define rep(i,n) for(int i = 0; i < (int)(n);++i)
#define REP(i,a,b) for(int i = (a);i < (int)(b);++i)
#define repi(it,array) for(auto it = array.begin(),end = array.end(); it != end;++it)
#define repa(n,array) for(auto &n :(array))

using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using dict = map<string,int>;
using pii = pair<int,int> ;
using pll = pair<ll,ll> ;

const int mod = 1000000007;
constexpr int imax = ((1<<30)-1)*2+1 ;
constexpr int inf = 100000000;
constexpr double PI = acos(-1.0) ;
double eps = 1e-10 ;
const int dy[] = {-1,0,1,0};
const int dx[] = {0,-1,0,1};

inline bool value(int x,int y,int w,int h){
  return (x >= 0 && x < w && y >= 0 && y < h);
}

template<typename T>
void Unique(vector<T> &v){
  sort(all(v));
  v.erase(unique(all(v)),v.end());
}

template<typename T>
T ston(string& str, T n){
  istringstream sin(str) ;
  T num ;
  sin >> num ;
  return num ;
}

void Ans(bool f){
  if(f) cout << "YES"<<endl;
  else cout << "NO"<<endl;
}

ll w,h,ans;
vector<vector<char>> t;
void dfs(ll x, ll y){
  if(value(x,y,w,h)){
    if( t[x][y] != '.' ) return ;
    ++ans;
    t[x][y] = '0';
    rep(i,4){
      dfs(x+dx[i],y+dy[i]);
    }
  }
}
int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  while(cin >> w >> h && w && h){
    ll x,y;
    t = vector<vector<char>>(20,vector<char>(20,' '));
    ans = 0;
    rep(i,h){
      rep(j,w){
        cin >> t[j][i];
        if(t[j][i] == '@'){
          x = j;
          y = i;
        }
      }
    }
    t[x][y] = '.';
    dfs(x,y);
    cout << ans << endl;
  }
  return 0;
}

C++: #include <iostream>
#include <algorithm>
#include <utility>

using namespace std;

char board[23 * 23];
int way[4] = { -1,1,-23,23 };
int gCount;

void solve(int pos) {
	gCount++;
	board[pos] = '#';
	for (int i = 0; i < 4; i++) 
		if (board[pos + way[i]] == '.') 
			solve(pos + way[i]);
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	int H, W;
	while (cin >> W >> H, W) {
		for (int i = 0; i < 23 * 23; i++)
			board[i] = '#';
		gCount = 0;
		int s;
		for (int y = 1; y <= H; y++)
			for (int x = 1; x <= W; x++) {
				cin >> board[y * 23 + x];
				if (board[y * 23 + x] == '@') 
					s = y * 23 + x;
			}
		solve(s);
		cout << gCount << endl;
	}
}

C++: #include <iostream>
#define MAX_W 20
#define MAX_H 20
using namespace std;

int w, h, ax, ay, cnt;
char t[MAX_H][MAX_W + 1];

void PRINT() {
  for(int i = 0; i < h; ++i) {
    for(int j = 0; j < w; ++j) {
      cout << t[i][j];
    }
    cout << endl;
  }
  cout << endl;
}

// 深さ優先探索
// 現在位置(x, y)
void dfs(int x, int y) {
  t[y][x] = 'o';

  for(int dx = -1; dx <= 1; dx++) {
    for(int dy = -1; dy <= 1; dy++) {
      // 4方向に限定
      if(dx * dy == -1 || dx * dy == 1) continue;

      // 現在位置を(nx, ny)に更新
      int nx = x + dx;
      int ny = y + dy;

      // (nx, ny)は部屋の中か？ & t[nx][ny]は黒タイルか？判定
      if(0 <= nx && nx < w && 0 <= ny && ny < h && t[ny][nx] == '.') {
        dfs(nx, ny);
        //PRINT();
        cnt++;
      }
    }
  }
  return;
}

void solve() {
  cnt = 1;
  dfs(ax, ay);
  cout << cnt << endl;
}

int main() {
  while(cin >> w >> h) {
    if(w * h == 0) break;

    for(int i = 0; i < h; ++i) {
      for(int j = 0; j < w; ++j) {
        cin >> t[i][j];
        if(t[i][j] == '@') {
          ax = j;
          ay = i;
        }
      }
    }
    
    solve();
  }
  return 0;
}

C++: //include
//------------------------------------------
#include <bits/stdc++.h>

using namespace std;

//typedef
//------------------------------------------
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<vb> vbb;
typedef pair<int, int> pii;
typedef long long ll;
typedef unsigned long long ull;

//container util
//------------------------------------------
#define all(a)  (a).begin(),(a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define pb push_back
#define mp make_pair
#define iter(i,c) for(auto i=(c).begin(); i!=(c).end(); ++i)

//repetition
//------------------------------------------
#define loop(i,a,b) for(int i=(a);i<(b);++i)
#define rep(i,n)  loop(i,0,n)

//constant
//--------------------------------------------
const double eps = 1e-10;
const double pi  = acos(-1.0);
const double inf = (int)1e8;

// output vector
// ------------------------------------------
namespace std {
    template<typename T> ostream & operator<<(ostream& os, vector<T> const& v){
        for(auto it=v.begin(); it!=v.end(); ++it){
            os << *it << (it+1==v.end() ? "" : ",");
        }
        return os;
    }
}

//clear memory
#define clr(a) memset((a), 0 ,sizeof(a))

int lcm(int a,int b){
   return a*b/__gcd(a,b);
}
 
vb pn((int)1e4+10); 
void prime_number(int n){
   fill(all(pn),true);
   pn[0]=false;pn[1]=false;
   loop(i,2,n/2+1){
      if(!pn[i]) continue;
      for(int j=2;i*j<=n;j++){
         pn[i*j]=false;
      }
   }
}

char m[21][21];
int ans;

void tansaku(int a, int b, int x, int y){
   if(a-1>=0)if(m[a-1][b]=='.'){
      m[a-1][b]='*';
      ans++;
      tansaku(a-1,b,x,y);
   }
   if(b-1>=0)if(m[a][b-1]=='.'){
      m[a][b-1]='*';
      ans++;
      tansaku(a,b-1,x,y);
   }
   if(a+1<x)if(m[a+1][b]=='.'){
      m[a+1][b]='*';
      ans++;
      tansaku(a+1,b,x,y);
   }
   if(b+1<y)if(m[a][b+1]=='.'){
      m[a][b+1]='*';
      ans++;
      tansaku(a,b+1,x,y);
   }
}

int main(){
   int x,y,a,b;
   string tmp;
   while(cin >> x >> y){
      if(x+y==0) break;
      ans=1;
      rep(j,y){
         rep(i,x){
            cin>>m[i][j];
            if(m[i][j]=='@'){
               a=i;b=j;
            }
         }
      }
      tansaku(a,b,x,y);
      cout <<  ans << endl;

   }
}