#include <bits/stdc++.h>
using namespace std;
const int INF = 1000000000;
const long long LINF = 1e17;
const double PI = 3.141592653589793238;
const int mod = 1000000007;
#pragma unused(INF, PI, LINF, mod)
template <typename T, typename TT>
ostream &operator<<(ostream &s, pair<T, TT> t) {
  return s << "(" << t.first << "," << t.second << ")";
}
template <typename T>
ostream &operator<<(ostream &s, vector<T> t) {
  for (int i = 0; i < (t).size(); i++)
    s << t[i] << ((i < (t).size() - 1) ? " " : "");
  return s;
}
template <typename T>
ostream &operator<<(ostream &s, set<T> t) {
  for (T x : t) s << x << " ";
  return s;
}
template <typename T>
istream &operator>>(istream &s, vector<T> &t) {
  for (int _i = 0; _i < t.size(); _i++) s >> t[_i];
  return s;
}
struct op {
  int type;
  int r;
  int c;
  int x;
};
int mat[110][110];
void rot_col(int n, int m, int c) {
  int temp = mat[n - 1][c];
  for (int i = n - 1; i > 0; i--) mat[i][c] = mat[i - 1][c];
  mat[0][c] = temp;
}
void rot_row(int n, int m, int c) {
  int temp = mat[c][m - 1];
  for (int i = m - 1; i > 0; i--) mat[c][i] = mat[c][i - 1];
  mat[c][0] = temp;
}
int main(int argc, const char *argv[]) {
  int n, m, q;
  cin >> n >> m >> q;
  vector<op> a(q);
  for (int i = (0); i < (q); i++) {
    cin >> a[i].type;
    if (a[i].type == 1)
      cin >> a[i].r;
    else if (a[i].type == 2)
      cin >> a[i].c;
    else
      cin >> a[i].r >> a[i].c >> a[i].x;
  }
  for (int i = (0); i < (n); i++)
    for (int j = (0); j < (m); j++) mat[i][j] = 0;
  reverse(a.begin(), a.end());
  for (op o : a) {
    if (o.type == 1) {
      rot_row(n, m, o.r - 1);
    } else if (o.type == 2) {
      rot_col(n, m, o.c - 1);
    } else {
      mat[o.r - 1][o.c - 1] = o.x;
    }
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) cout << mat[i][j] << " ";
    cout << "\n";
  }
}
