#include <iostream>
#include <complex>
#include <sstream>
#include <string>
#include <algorithm>
#include <deque>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <vector>
#include <set>
#include <limits>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
#define REP(i, j) for(int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for(int i = (int)(j); i < (int)(k); ++i)
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
typedef complex<double> P;
const int INF = 1e9;

int H, W;
bool f;

void check(int y, int x, int py, int px, int total, vector< vector<int> > &v, vector<int> &h, vector<int> &w){
  int sum = 0, ty, tx;
  while(y < H - 1 && x < W - 1){
    if(v[y][x] == INF) { ty = y; tx = x; }
    else sum += v[y][x];
    y += py; x += px;
  }
  v[ty][tx] = total - sum;
  h[ty]--; w[tx]--;
}

vector< vector<int> > solve(vector< vector<int> > v, vector<int> &h, vector<int> &w){
  int cnt = 0;
  REP(i, H) REP(j, W) if(v[i][j] == INF) ++cnt;
  while(cnt != 0){
    bool flg = false;
    REP(i, H) if(h[i] == 1) { check(i, 0, 0, 1, v[i][W - 1], v, h, w); --cnt; flg = true; }
    REP(i, W) if(w[i] == 1) { check(0, i, 1, 0, v[H - 1][i], v, h, w); --cnt; flg = true; }
    if(!flg) { return vector< vector<int> >(); }
  }
  f = true;
  return v;
}

int main() {
  bool t = false;
  while(cin >>H && H){
    cin >>W;
    ++H; ++W;
    f = false;
    vector< vector<int> > v(H, vector<int>(W));
    vector<int> w(W, 0), h(H, 0);
    REP(i, H){
      REP(j, W){
        string s; cin >>s;
        if(s != "?") v[i][j] = atoi(s.c_str());
        else { v[i][j] = INF; h[i]++; w[j]++; }
      }
    }
    if(t) cout <<endl;
    t = true;
    vector< vector<int> > ans = solve(v, h, w);
    if(f) { REP(i, H) REP(j, W) if(v[i][j] == INF) cout <<ans[i][j] <<endl; }
    else cout <<"NO" <<endl;
  }
  return 0;
}