
    #define XXX {fprintf(stderr, "@@@ %d\n",__LINE__);};

    #include  <stdio.h>
    #include  <stdlib.h>
    #include  <unistd.h>
    #include  <eggx.h>
    #define ITVL 100  
    #define RSIZ 8    
    #define VSIZ 16   
    #define RMAX 32   
    #define VMAX 32   
    void usage() {
XXX   fprintf(stderr, "usage: virtmem [-vnSL][-s speed][-r rsize][-x vsize] \n");
XXX   fprintf(stderr, "       v : verbose mode.\n");
XXX   fprintf(stderr, "       S : SKIP mode.\n");
XXX   fprintf(stderr, "       L : simple LRU alogorithm.\n");
XXX   fprintf(stderr, "       s : display interval time (default=%dms)\n", ITVL);
XXX   fprintf(stderr, "       r : real memory size (default=%d pages)\n", RSIZ);
XXX   fprintf(stderr, "       x : virtual memory size (default=%d pages)\n", VSIZ);
XXX   return;
    }
    int vmode=1;
    int smode=1; 
    int lmode=1;
    int itvl=ITVL;
    int rsiz=RSIZ;
    int vsiz=VSIZ;
    int rmem[RMAX]; 
    int rtim[RMAX]; 
    int vmem[VMAX]; 
    int vflg[VMAX]; 
    int step=0; 
    int win;    
    #define W 30 
    #define H 40 
    #define WW 800 
    #define HH 400 
    #define XOFF 40 
    #define YOFF 40 
    int col1[7][3]={
    {255, 255, 255} ,   {255,   0,   0} ,   {  0, 255,   0} ,   {  0,   0, 255} ,   {255, 255,   0} ,   {255,   0, 255} ,   {  0, 255, 255} };  
    int col2[7][3]={
    {96, 96, 96} ,  {255, 96, 96} ,   {96, 255, 96} ,   {96, 96, 255} ,   {255, 255, 96} ,   {255, 96, 255} ,   {96, 255, 255} };  
    #define MM 20
    char com[MM][256]; 
    int  comp[MM]; 
    int cp=0; 
    int init_memory() {
      int i;
XXX   for(i=0; i<RMAX; i++) {
XXX     rmem[i]= -1;
XXX     rtim[i]=0;
      };
XXX   for(i=0; i<VMAX; i++) {
XXX     vmem[i]=0;
XXX     vflg[i]=0;
      };
XXX   return 0;
    }
    int pgcolor(int c, int f) {
XXX   if(f == 1) { 
XXX     newrgbcolor(win, col1[c][0], col1[c][1], col1[c][2]);
      } else { 
XXX     newrgbcolor(win, col2[c][0], col2[c][1], col2[c][2]);
      };
XXX   return 0;
    }
    int show_mat() {
      int i;
XXX   gclr(win);
XXX   for(i=1; i<7; i++) {
XXX     pgcolor(i, 1);
XXX     fillrect(win, WW-375, HH-20-i*25, 20, 20);
XXX     newpen(win, 1);
XXX     drawstr(win, WW-350, HH-15-i*25, 16, 0.0, "PROGRAM %d", i);
      };
XXX   for(i=0; i<cp; i++) {
XXX     newpen(win, 1);
XXX     drawstr(win, WW-200, HH-30-i*20, 16, 0.0, "%s", com[i]);
XXX     if(comp[i] != 0) {
XXX       pgcolor(comp[i], 1);
XXX       fillrect(win, WW-220, HH-30-i*20, 13, 13);
        };
      };
XXX   newpen(win, 1);
XXX   drawstr(win, XOFF-30, YOFF+H*3+10, 12, 0.0, "access");
XXX   return 0;
    }
    int show_memory() {
      int i;
XXX   show_mat();
XXX   for(i=0; i<rsiz; i++) {
XXX     if(rmem[i] == -1) { 
XXX       newpen(win, 1); 
XXX       fillrect(win, XOFF+i*W, YOFF+H*2, W-2, H);
        } else {
XXX       pgcolor(vmem[rmem[i]], 1); 
XXX       fillrect(win, XOFF+i*W, YOFF+H*2, W-2, H);
XXX       newpen(win, 1);
XXX       drawstr(win, XOFF+i*W+W/3, YOFF+H*2-16, 16, 0.0, "%2d",rmem[i]+1);
XXX       drawstr(win, XOFF+i*W+W/3, YOFF+H*3+8, 12, 0.0, "%2d",rtim[i]);
        };
      };
XXX   for(i=0; i<vsiz; i++) {
XXX     if(vmem[i] == 0) { 
XXX       newpen(win, 1); 
        } else {
XXX       pgcolor(vmem[i], vflg[i]); 
        };
XXX     fillrect(win, XOFF+i*W, YOFF, W-2, H);
XXX     newpen(win, 1);
XXX     drawstr(win, XOFF+i*W+W/3, YOFF-16, 16, 0.0, "%2d",i+1);
      };
XXX   copylayer(win, 1, 0);
XXX   return 0;
    }
    int vm_load(int v, int m)  {
XXX   vmem[v]=m;
XXX   vflg[v]=1; 
XXX   return 0;
    }
    int anim_run(int x1, int y1, int w, int h, int x2, int y2, int c) {
      int i, ww, s=5;
XXX   newpen(win, 8);
XXX   fillrect(win, x2, y2, w, h);
XXX   copylayer(win, 1, 0);
XXX   for(i=1; i<=s; i++) {
XXX     ww= (float)(w) * (float)(i) / (float)(s);
XXX     newpen(win, 8);
XXX     fillrect(win, x1, y1, ww, h);
XXX     copylayer(win, 1, 0);
XXX     msleep(itvl/5);
      };
XXX   show_memory();
XXX   return 0;
    }
    int anim_move(int x1, int y1, int w, int h, int x2, int y2) {
      int i, x, y, s=10;
XXX   for(i=0; i<=s; i++) { 
XXX     x= x1 + (float)(x2-x1) / (float)(s) * i;
XXX     y= y1 + (float)(y2-y1) / (float)(s) * i;
XXX     newpen(win, 8);
XXX     drawrect(win, x, y, w, h);
XXX     copylayer(win, 1, 0);
XXX     msleep(itvl/5);
      };
XXX   return 0;
    }
    int page_in(int r, int v) {
XXX   anim_move(XOFF+v*W-1, YOFF, W-1, H+1, XOFF+r*W-1, YOFF+H*2-1);
XXX   rmem[r]=v;
XXX   rtim[r]=step++; 
XXX   vflg[v]=0; 
XXX   show_memory();
XXX   return 0;
    }
    int page_out(int r) {
      int v;
XXX   v=rmem[r];
XXX   anim_move(XOFF+r*W-1, YOFF+H*2-1, W-1, H+1, XOFF+v*W-1, YOFF);
XXX   rmem[r]= -1;
XXX   rtim[r]=0;
XXX   vflg[v]=1; 
XXX   show_memory();
XXX   return 0;
    }
    int vm_find_empty() {
      int i;
XXX   for(i=0; i<vsiz; i++) {
XXX     if(vmem[i] == 0) { 
XXX       return i;
        };
      };
XXX   return -1;
    }
    int page_check(int v) {
      int i;
XXX   for(i=0; i<rsiz; i++) {
XXX     if(rmem[i] == v) { 
XXX       return i;
        };
      };
XXX   return -1;
    }
    int page_find_empty() {
      int i;
XXX   for(i=0; i<rsiz; i++) {
XXX     if(rmem[i] == -1) { 
XXX       return i;
        };
      };
XXX   return -1;
    }
    int page_find_out(int c) {
      int i, k, m=2147483647;  
XXX   if( lmode == 1 ) { 
XXX     k= -1;
XXX     for(i=0; i<rsiz; i++) {
XXX       if((rmem[i] == -1)||(vmem[rmem[i]] == c)) {
          } else {
XXX 	if(rtim[i] < m) { 
XXX 	  m=rtim[i];
XXX 	  k=i;
    	};
          };
        };
XXX     if(k != -1) { 
XXX       return k;
        };
      };
XXX   k= -1;
XXX   for(i=0; i<rsiz; i++) {
XXX     if(rmem[i] != -1) { 
XXX       if(rtim[i] < m) { 
XXX 	m=rtim[i];
XXX 	k=i;
          };
        };
      };
XXX   return k;
    }
    int load(int c, int s) {
      int i, v, r;
XXX   for(i=0; i<s; i++) {
XXX     if((v=vm_find_empty()) == -1 ) { 
XXX       if(vmode) fprintf(stderr, "load(%d, %d) = cannot load. ",c,s);
XXX       return -1; 
        } else {
XXX       vm_load(v, c); 
XXX       if((r=page_find_empty()) == -1 ) { 
XXX 	r=page_find_out(c); 
XXX 	page_out(r); 
          };
XXX       page_in(r, v); 
        };
      };
XXX   return 0;
    }
    int run(int c) {
      int r, v;
XXX   for(v=0; v<vsiz; v++) {
XXX     if(vmem[v] == c) { 
XXX       if( (r=page_check(v))== -1) { 
XXX 	if((r=page_find_empty()) == -1 ) { 
XXX 	  r=page_find_out(c); 
XXX 	  page_out(r); 
    	};
XXX 	page_in(r, v); 
          } else {
XXX 	rtim[r]=step++; 
          };
XXX       anim_run(XOFF+r*W, YOFF+H*2, W-2, H, XOFF+v*W, YOFF, c);
        };
      };
XXX   return 0;
    }
    int main(int argc, char *argv[]) {
      int ch;
      extern char *optarg;
      extern int optind;
      char buf[256];
      int p, l;
XXX   while ((ch = getopt(argc, argv, "vnSLs:r:x:")) != EOF) {
XXX     switch((char)ch) {
        case 'v': 
XXX       vmode=1;
XXX       break;
        case 'n': 
XXX       vmode=0;
XXX       break;
        case 'S': 
XXX       smode=0;
XXX       break;
        case 'L': 
XXX       lmode=0;
XXX       break;
        case 's': 
XXX       itvl=atoi(optarg);
XXX       break;
        case 'r': 
XXX       rsiz=atoi(optarg);
XXX       break;
        case 'x': 
XXX       vsiz=atoi(optarg);
XXX       break;
        case '?': 
XXX     default:
XXX       usage();
XXX       fprintf(stderr,"virtmem : unrecognized parameter exist.\n");
XXX       exit(1);
        };
      };
XXX   argc -= optind;
XXX   argv += optind;
XXX   if(argc!=0) {
XXX     usage();
XXX     fprintf(stderr,"virtmem : extra parameter is exist.\n");
XXX     exit(1);
      };
XXX   win=gopen(WW,HH);
XXX   winname(win, "Virtual memory simulation");
XXX   layer(win, 0, 1);
XXX   init_memory();
XXX   show_memory(); 
XXX   newpen(win, 1);
XXX   fillrect(win, WW-145, 20, 20, 20);
XXX   drawstr(win, WW-120, 25, 16, 0.0, "READY to go.");
XXX   copylayer(win, 1, 0);
XXX   ggetch(win);
XXX   show_memory();
XXX   while(! feof(stdin)) {
XXX     fgets(buf, sizeof(buf), stdin);
XXX     if(vmode) printf("%s",buf);
XXX     strcpy(com[cp], buf);
XXX     comp[cp]=0;
XXX     if(strncmp("#", buf, 1)==0) { 
XXX       cp++;
        } else if(strncmp("exit", buf, 4)==0) { 
XXX       cp++;
XXX       break;
        } else if(strncmp("load ", buf, 5)==0) { 
XXX       sscanf(&buf[5], "%d %d", &p, &l);
XXX       comp[cp++]=p;
XXX       show_memory();
XXX       if(smode) ggetch(win);
XXX       load(p, l);
        } else if(strncmp("run ", buf, 4)==0) { 
XXX       sscanf(&buf[4], "%d", &p);
XXX       comp[cp++]=p;
XXX       show_memory();
XXX       if(smode) ggetch(win);
XXX       run(p);
        };
      };
XXX   layer(win, 1, 1);
XXX   show_memory();
XXX   newpen(win, 1);
XXX   fillrect(win, WW-145, 20, 20, 20);
XXX   drawstr(win, WW-120, 25, 16, 0.0, "END of DATA");
XXX   copylayer(win, 1, 0);
XXX   ggetch(win);
XXX   gclose(win); 
XXX   return(0);
    }
