home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / cellsim / v2_5 / cm2 / cm_cell.c next >
Encoding:
C/C++ Source or Header  |  1990-02-26  |  42.4 KB  |  1,957 lines

  1. /*****
  2.  *
  3.  * File: cm_cell.c
  4.  *   By: Dave Hiebeler
  5.  *       June 1989
  6.  *
  7.  * Basic routines for the CM side of Cellsim...
  8.  */
  9.  
  10. #include "cm_cell.h"
  11. #include <sys/time.h>
  12.  
  13.  
  14. /*
  15.  *
  16.  * Cellsim copyright 1989, 1990 by Chris Langton and Dave Hiebeler
  17.  * (cgl@lanl.gov, hiebeler@heretic.lanl.gov)
  18.  *
  19.  * This package may be freely distributed, as long as you don't:
  20.  * - remove this notice
  21.  * - try to make money by doing so
  22.  * - prevent others from copying it freely
  23.  * - distribute modified versions without clearly documenting your changes
  24.  *   and notifying us
  25.  *
  26.  * Please contact either of the authors listed above if you have questions
  27.  * or feel an exception to any of the above restrictions is in order.
  28.  *
  29.  * If you make changes to the code, or have suggestions for changes,
  30.  * let us know!  If we use your suggestion, you will receive full credit
  31.  * of course.
  32.  */
  33.  
  34. /*****
  35.  * Cellsim history:
  36.  *
  37.  * Cellsim was originally written on Apollo workstations by Chris Langton.
  38.  *
  39.  * Sun versions:
  40.  *
  41.  * - version 1.0
  42.  *   by C. Ferenbaugh and C. Langton
  43.  *   released 09/02/88
  44.  *
  45.  * - version 1.5
  46.  *   by Dave Hiebeler and C. Langton  May - June 1989
  47.  *   released 07/03/89
  48.  *
  49.  * - version 2.0
  50.  *   by Dave Hiebeler and C. Langton  July - August 1989
  51.  *   never officially released (unofficially released 09/08/89)
  52.  *
  53.  * - version 2.5
  54.  *   by Dave Hiebeler and C. Langton  September '89 - February 1990
  55.  *   released 02/26/90
  56.  *****/
  57.  
  58.  
  59. #define CELLSIM_PORT 12700
  60.  
  61.  
  62. /* Functions callable by Sun-side of Cellsim */
  63. void
  64.     send_LT(), send_image(), run(), display_image(), change_stuff(),
  65.     set_displays(), get_LT(), cm_probe(), enable_socket(), disable_socket(),
  66.     send_cmap(), change_delay(), run_forever(), set_disp_interval(),
  67.     load_image(), quick_random(), general_random(),
  68.     CM_clear_array(), CM_get_image(), CM_set_image_dir(), CM_set_fcn_dir(),
  69.     CM_set_LT_dir(), load_rule(), set_zoom(), set_pan(), change_image_size(),
  70.     CM_get_image_dir(), CM_get_fcn_dir(), CM_get_LT_dir();
  71.  
  72. /* Dummy routine to hold a place in the array of routines */
  73. void null_proc();
  74.  
  75. /* Various internal functions */
  76. void
  77.     set_params(), init_cmfb(), set_states(), load_fcn(), load_LT(),
  78.     CM_init_stuff(), get_client(), CM_uninit_stuff(), load_function_file(),
  79.     CMFB_display_image(), load_image_compressed(), load_LT_compressed();
  80. int
  81.      read_image_from_fp(), read_LT_from_fp();
  82.  
  83. static struct stat statbuf;
  84.  
  85. /* struct holding function callable by Cellsim */
  86. typedef struct {
  87.     void_func_ptr fcn;    /* ptr to function */
  88.     char *fcn_name;    /* name or description of fcn */
  89.     int debug_lvl;    /* debug-level at which to print out fcn-call */
  90. } CM_cellsim_func;
  91.  
  92.  
  93. /* Array of functions */
  94. CM_cellsim_func CM_cellsim_func_array[] = {
  95.     {null_proc, "zero-entry", 0},
  96.     {null_proc, "quit", 0}, {send_LT, "send_LT", 1},
  97.     {send_image, "send_image", 1}, {run, "run", 1},
  98.     {display_image, "display_image", 1}, {change_stuff, "change_stuff", 1},
  99.     {set_displays, "set_displays", 1}, {get_LT, "get_LT", 1},
  100.     {cm_probe, "probe", 1}, {enable_socket, "enable_socket", 1},
  101.     {disable_socket, "disable_socket", 1}, {send_cmap, "send_cmap", 1},
  102.     {change_delay, "change_delay", 1}, {run_forever, "run_forever", 1},
  103.     {null_proc, "stop_run", 1}, {null_proc, "run2", 1},
  104.     {set_disp_interval, "set_disp_interval", 1}, {null_proc, "done", 1},
  105.     {null_proc, "error", 1}, {load_image, "load_image", 1},
  106.     {quick_random, "quick_random", 1}, {general_random, "general_random", 1},
  107.     {CM_clear_array, "clear", 1}, {CM_get_image, "get_image", 1},
  108.     {CM_set_image_dir, "set image_dir", 1}, {CM_set_fcn_dir, "set_fcn_dir", 1},
  109.     {CM_set_LT_dir, "set_LT_DIR", 1}, {load_rule, "load_rule", 1},
  110.     {set_zoom, "set_zoom", 1}, {set_pan, "set_pan", 1},
  111.     {change_image_size, "change_image_size", 1},
  112.     {CM_get_image_dir, "get image-dir", 1}, {CM_get_fcn_dir, "get fcn-dir", 1},
  113.     {CM_get_LT_dir, "get LT-dir", 1}
  114. };
  115. CM_cellsim_func_max = 34;    /* max possible index into array */
  116.  
  117.  
  118. extern char *getenv();
  119. void which();
  120.  
  121. char argv0[256];
  122. unsigned char buf[256];
  123. unsigned int
  124.     start_vector[2], end_vector[2], axis_vector[2],
  125.     dimension_vector[2];
  126. int offset_vector[2];
  127. unsigned int saved_x=0, saved_y=0, state_count[16];
  128. char CM_image_dir[128], CM_fcn_dir[128], CM_LT_dir[128], saved_fcn_name[256];
  129. int zoom_fac, pan_x, pan_y;
  130.  
  131. int port_num, sock_fd, daemon;
  132.  
  133.  
  134. void
  135. printusage(s)
  136. char *s;
  137. {
  138.     fprintf(stderr, "Usage: %s [-p port#] [-d debug-level]\n",s);
  139.     exit(1);
  140. }
  141.  
  142.  
  143. void
  144. quit(s)
  145. char *s;
  146. {
  147.     fprintf(stderr,"%s\n",s);
  148.     exit(1);
  149. }
  150.  
  151.  
  152.  
  153. void
  154. pquit(s)
  155. char *s;
  156. {
  157.     fprintf(stderr,"%s\n",s);
  158.     perror("cm_cell");
  159.     exit(1);
  160. }
  161.  
  162.  
  163. void
  164. quit2(s1,s2)
  165. char *s1,*s2;
  166. {
  167.     fprintf(stderr,s1,s2);
  168.     fprintf(stderr,"\n");
  169.     exit(1);
  170. }
  171.  
  172.  
  173. void
  174. Log(s,d)
  175. char *s;
  176. int d;
  177. {
  178.     fprintf(logfile, "%s\n",s);
  179.     if (debug >= d)
  180.     fprintf(stderr, "%s\n",s);
  181.     fflush(logfile);
  182. }
  183.  
  184. void
  185. Log2(s1,s2,d)
  186. char *s1, *s2;
  187. int d;
  188. {
  189.     fprintf(logfile, s1, s2);
  190.     fprintf(logfile, "\n");
  191.     if (debug >= d) {
  192.     fprintf(stderr, s1, s2);
  193.     fprintf(stderr, "\n");
  194.     }
  195.     fflush(logfile);
  196. }
  197.  
  198.  
  199.  
  200. void
  201. Logd(s,n,d)
  202. char *s;
  203. int n, d;
  204. {
  205.     fprintf(logfile, s, n);
  206.     fprintf(logfile, "\n");
  207.     if (debug >= d) {
  208.     fprintf(stderr, s, n);
  209.     fprintf(stderr, "\n");
  210.     }
  211.     fflush(logfile);
  212. }
  213.  
  214.     
  215.  
  216. /* Main control loop to read commands from the socket and execute them */
  217. void
  218. main(argc,argv)
  219. int argc;
  220. char **argv;
  221. {
  222.     u_short port;
  223.     int addrs;
  224.     int done, logfd, ret_val, err, tmp, i;
  225.     char tmp_str[80];
  226.  
  227.     printf("Please wait.. initializing...\n");
  228.     /* strcpy(argv0, argv[0]); */
  229.     which(argv[0], argv0);
  230.     daemon = 0;
  231.     if (argc == 1)    /* user, not the daemon, is invoking the program.
  232.              * that means we have to act as a daemon & wait for
  233.              * a client */
  234.     daemon = 1;
  235.     else {    /* check to see if user or daemon is invoking us */
  236.     err = sscanf(argv[1], "%d", &tmp);
  237.     if ((err != 1) || (tmp == 0))
  238.         daemon = 1;
  239.     }
  240.     /* set up some variables & stuff */
  241.     debug = 0;
  242.     debug2 = 0;
  243.     exit_function = NULL;
  244.     strcpy(CM_image_dir, CM_IMAGE_DIR);
  245.     strcpy(CM_fcn_dir, CM_FCN_DIR);
  246.     strcpy(CM_LT_dir, CM_LT_DIR);
  247.     unlink("/tmp/cm_cell.log");    /* remove logfile */
  248.     if ((logfile = fopen("/tmp/cm_cell.log", "w"))==NULL) {
  249.     logfile = stderr;
  250.     fprintf("Logging to stderr, couldn't open /tmp/cm_cell.log\n");
  251.     }
  252.     setbuf(logfile, NULL);    /* turn off buffering in case someone is
  253.                  * watching (e.g. "tail -f") the logfile */
  254.     CM_init();
  255.     if (daemon) {
  256.     port_num = CELLSIM_PORT;
  257.     for (i=1; i<argc; i++) {
  258.         if (strcmp(argv[i], "-p") && strncmp(argv[i], "-d", 2)) {
  259.         printf("bad arg is '%s'\n",argv[i]);
  260.         printusage(argv[0]);
  261.         }
  262.         switch (argv[i][1]) {
  263.           case 'p':        /* port number */
  264.         if (i == (argc-1))
  265.             quit("No port # given");
  266.         sscanf(argv[++i], "%d", &port_num);
  267.         printf("port # is %d\n",port_num);
  268.         break;
  269.           case 'd':
  270.         if ((argv[i][2] > '0') && (argv[i][2] <= '9'))
  271.             debug = argv[i][2] - '0';
  272.         else {
  273.             if (i == (argc-1))
  274.             quit("No debug-value given");
  275.             err = sscanf(argv[++i], "%d", &debug);
  276.             if (err == 0)
  277.             quit("No debug-value given");
  278.         }
  279.         break;
  280.         }
  281.     }
  282.     port = htons(port_num);
  283.     if ((sock_fd = open_host_socket(&addrs, &port, debug2)) == -1)
  284.         pquit("Couldn't open socket");
  285.     }
  286.     else {    /* if running under daemon, it's opened socket for us */
  287.         sscanf(argv[1], "%d", &ns);
  288.     sscanf(argv[2], "%d", &logfd); /* not used (leftover from old code) */
  289.     set_params(argv[3]);
  290.     }
  291.     Log("***entering command loop***",0);
  292.     Logd("debug = %d", debug, 0);
  293.     forever_flag = 0;
  294.     while (1) {
  295.     if (daemon)
  296.         get_client();
  297.     while (!done) {
  298.         Log("***waiting for command***",1);
  299.         if ((ret_val = read_from_sock(ns, buf, 1, OFF, debug2)) == -1) {
  300.         Log("read_from_sock returned -1 looking for cmd",0);
  301.         quit("read_from_sock error");
  302.         }
  303.         if (!ret_val) {
  304.         Log("Socket closed by client", 0);
  305.         Log("Waiting for new client", 0);
  306.         done = 1;
  307.         break;
  308.         }
  309.         if (buf[0] == QUIT) {
  310.         if (!daemon)
  311.             exit(0);
  312.         else {
  313.             Log("Got quit command from client...", 0);
  314.             done = 1;
  315.             break;
  316.         }
  317.         }
  318.         else if (buf[0] > CM_cellsim_func_max) {
  319.         Logd("Got bogus command from Cellsim! (%d)", buf[0], 0);
  320.         Log("Shutting down... waiting for new client", 0);
  321.         done = 1;
  322.         break;
  323.         }
  324.         else {    /* call the function requested by Sun-Cellsim */
  325.         Log2("Got %s request",CM_cellsim_func_array[buf[0]].fcn_name,
  326.              CM_cellsim_func_array[buf[0]].debug_lvl);
  327.         (CM_cellsim_func_array[buf[0]].fcn)();
  328.         Log2("Done with %s", CM_cellsim_func_array[buf[0]].fcn_name,
  329.              CM_cellsim_func_array[buf[0]].debug_lvl);
  330.         }
  331.     }
  332.     close(ns);
  333.     CM_uninit_stuff();
  334.     done = 0;
  335.     strcpy(CM_image_dir, CM_IMAGE_DIR);
  336.     strcpy(CM_fcn_dir, CM_FCN_DIR);
  337.     strcpy(CM_LT_dir, CM_LT_DIR);
  338.     }
  339. }
  340.  
  341.  
  342. /*
  343.  * Send acknowledgement to client; this is used to synchronize the CMFE
  344.  * with the client
  345.  */
  346. void
  347. CM_send_ack()
  348. {
  349.     unsigned char buf[1];
  350.  
  351.     buf[0] = DONE;
  352.     write_to_sock(ns, buf, 1, OFF, debug2);
  353. }
  354.  
  355.  
  356. /*
  357.  * Read an integer from client.  Since the byte-order of an integer on a
  358.  * Vax is reverse from that on a Sun, we need this portable way to
  359.  * transfer integers between CMFE and client.
  360.  */
  361. int
  362. CM_read_int()
  363. {
  364.     unsigned char buf[4];
  365.     int n;
  366.  
  367.     read_from_sock(ns, buf, 4, OFF, 0);
  368.     n = buf[0] + buf[1]*256;
  369.     n += buf[2]*256*256 + buf[3]*256*256*256;
  370.     return n;
  371. }
  372.  
  373.  
  374. /*
  375.  * Send an integer to client
  376.  */
  377. void
  378. CM_send_int(n)
  379. int n;
  380. {
  381.     unsigned char buf[4];
  382.  
  383.     buf[0] = n%256;
  384.     buf[1] = n/256;
  385.     buf[2] = n/(256*256);
  386.     buf[3] = n/(256*256*256);
  387.     write_to_sock(ns, buf, 4, OFF, 0);
  388. }
  389.  
  390.  
  391. /*
  392.  * If some kind of error occurs, tell client about it and send a brief
  393.  * error message.
  394.  */
  395. void
  396. CM_send_error(str)
  397. char str[80];
  398. {
  399.     unsigned char buf[1];
  400.     char local_copy[80];
  401.  
  402.     strcpy(local_copy, str);
  403.     Log(str, 0);
  404.     buf[0] = ERROR;
  405.     write_to_sock(ns, buf, 1, OFF, debug2);
  406.     write_to_sock(ns, local_copy, 80, OFF, debug2);
  407. }
  408.  
  409.  
  410. /*
  411.  * Send the lookup-table (LT) to shared-array on CM
  412.  */
  413. void
  414. send_table_to_CM()
  415. {
  416.     unsigned int *iptr, i, j;
  417.     unsigned char word[4];
  418.  
  419.     j = 0;
  420.     iptr = (unsigned int *)word;
  421.     for (i=0; i<TSIZE/4; i++) {
  422.     if (!SUN) {    /* have to worry about Sun vs. Vax byte-order again */
  423.         word[0] = table[j++];
  424.         word[1] = table[j++];
  425.         word[2] = table[j++];
  426.         word[3] = table[j++];
  427.     }
  428.     else {
  429.         word[3] = table[j++];
  430.         word[2] = table[j++];
  431.         word[1] = table[j++];
  432.         word[0] = table[j++];
  433.     }
  434.     CM_u_move_constant_1L(temp_value, *iptr, 32);
  435.     CM_u_move_constant_1L(table_index, i, 13);
  436.     CM_aset32_shared_2L(temp_value, trans, table_index, 32, 13, max_index);
  437.     }
  438. }
  439.  
  440.  
  441. /*
  442.  * Set up neighborhood & array-size characteristics, based on arguments
  443.  */
  444. void
  445. set_params(args)
  446. char *args;
  447. {
  448.     int i, err, n, tmp;
  449.     char arg[80];
  450.     double f1, f2, f3;
  451.  
  452.     B = 256;
  453.     S = 8;
  454.     L = 3;
  455.     R = 1;
  456.     function = 0;
  457.     nhood = NH_VONN;
  458.     while (sscanf(args, "%s", arg) == 1) {
  459.     args += strlen(arg);
  460.     while (*args == ' ')
  461.         args++;
  462.     switch (arg[0]) {
  463.       case 'd':    /* debug mode */
  464.         debug = arg[1]-'0';
  465.         break;
  466.       case 'b':    /* array size */
  467.         err = sscanf(&arg[1],"%d",&n);
  468.         if ((err != 1) || ((n != 128) && (n != 256) && (n != 512)))
  469.         quit2("Illegal value %s for B",&arg[1]);
  470.         B = n;
  471.         break;
  472.       case 'm':
  473.         nhood = NH_MOORE;
  474.         set_states(&arg[1]);
  475.         break;
  476.       case 'M':
  477.         nhood = NH_MARG;
  478.         set_states(&arg[1]);
  479.         break;
  480.       case 'v':
  481.         nhood = NH_VONN;
  482.         set_states(&arg[1]);
  483.         break;
  484.       case 'l':
  485.         nhood = NH_LIN;
  486.         set_states(&arg[1]);
  487.         break;
  488.       case 'r':
  489.         err = sscanf(&arg[1], "%d", &R);
  490.         if ((err != 1) || (R <= 0) || (R >3))
  491.         quit("Illegal value for R");
  492.         break;
  493.       default:
  494.         Log2("bad argument '%s'", arg, 0);
  495.         quit("Bad arguments");
  496.         break;
  497.     }
  498.     }
  499.     if ((grid = (unsigned char *)malloc(B*B)) == NULL)
  500.     quit("Could not allocate grid");
  501.     if (S == 256)
  502.     function = 1;
  503.     L = 0;
  504.     tmp = S;
  505.     while (!(tmp & 0x01)) {
  506.     tmp >>= 1;
  507.     L++;
  508.     }
  509.     
  510.     switch (nhood) {
  511.       case NH_VONN:
  512.     set_params_v();
  513.     break;
  514.       case NH_MOORE:
  515.     set_params_m();
  516.     break;
  517.       case NH_MARG:
  518.     set_params_marg();
  519.     break;
  520.       case NH_LIN:
  521.     set_params_l();
  522.     break;
  523.     }
  524.     Logd("L = %d", L, 1);
  525.     Logd("N = %d", N, 1);
  526.     Logd("S = %d", S, 1);
  527.     if (nhood == NH_LIN)
  528.     Logd("R = %d", R, 1);
  529.     AMASK = S - 1;
  530.     if (!function) {
  531.     TSIZE = 1 << (L * N);
  532.     Logd("tsize = %d\n",TSIZE, 1);
  533.     if ((table = (unsigned char *)malloc(TSIZE)) == NULL)
  534.         quit("Could not allocate table");
  535.     max_index = TSIZE/4;
  536.     }
  537.  
  538.  
  539.     CM_init_stuff();
  540.  
  541.     init_cmfb();
  542. }
  543.  
  544.  
  545.  
  546. /*
  547.  * Initialize the frame-buffer, if there is one
  548.  */
  549. void
  550. init_cmfb()
  551. {
  552.     if (CMFB_EXISTS) {
  553.     FB_attach_ret_val = CMFB_attach_display(NULL, &disp_id);
  554.     if (FB_attach_ret_val)
  555.         Logd("CMFB_attach_display returned %d (successfully attached)", FB_attach_ret_val, 0);
  556.     if (FB_attach_ret_val) {
  557.         CMFB_initialize_display(&disp_id, 8, 1);
  558.         CMFB_initialize_color_table(&disp_id);
  559.         CMFB_switch_buffer(&disp_id, CMFB_green);
  560.     }
  561.     else {
  562.         Log("\n\n=======Could not attach to the CM frame-buffer!======", 0);
  563.         Log("=======Execution will continue, but you won't see anything on the CM FB====\n\n", 0);
  564.     }
  565.     }
  566.     else
  567.     FB_attach_ret_val = 0;
  568. }
  569.  
  570.  
  571. /*
  572.  * Set # of states
  573.  */
  574. void
  575. set_states(str)
  576. char *str;
  577. {
  578.     int n, err;
  579.     if (str[0] == 0)
  580.     return;
  581.     err = sscanf(str,"%d",&n);
  582.     if ((err != 1) || ((n != 2) && (n != 4) && (n != 8) && (n != 16) &&
  583.                (n != 256)))
  584.     quit2("Illegal value %s for S",str);
  585.     else
  586.     S = n;
  587. }
  588.  
  589.  
  590. /*
  591.  * Send lookup table to CM, after reading it from client
  592.  */
  593. void
  594. send_LT()
  595. {
  596.     unsigned int *iptr, i, j, k, t1, t2, comsize, newlen;
  597.     unsigned char word[4], buf[8], *table2;
  598.     FILE *dumpfile;
  599.  
  600.     read_from_sock(ns, buf, 1, OFF, debug2);
  601.     if (buf[0] == COMPRESSED) {
  602.     Log("compressed\n", 1);
  603.     }
  604.     else {
  605.     Log("uncompressed\n", 1);
  606.     read_from_sock(ns, table, TSIZE, OFF, debug2);
  607.     send_table_to_CM();
  608.     CM_send_ack();
  609.     }
  610. }
  611.  
  612.  
  613. /*
  614.  * This is left over from debugging the code, it should never be called.
  615.  */
  616. void
  617. get_LT()
  618. {
  619. }
  620.  
  621.  
  622. /*
  623.  * Client is sending us an image; transfer it to the CM
  624.  */
  625. void
  626. send_image()
  627. {
  628.     unsigned char buf[8], *grid2;
  629.     unsigned int t1, t2, comsize, newlen, ret_val;
  630.     
  631.     read_from_sock(ns, buf, 1, OFF, debug2);
  632.     if (buf[0] == COMPRESSED) {
  633.     Log("compressed\n", 1);
  634.     }
  635.     else {
  636.     Log("uncompressed\n", 1);
  637.     read_from_sock(ns, grid, B*B, OFF, debug2);
  638.     }
  639.     CM_u_write_to_news_array_1L(grid,
  640.                 offset_vector,
  641.                 start_vector,
  642.                 end_vector,
  643.                 axis_vector,
  644.                 cell,
  645.                 L,
  646.                 2,
  647.                 dimension_vector,
  648.                 1);
  649.     if (use_FB && FB_attach_ret_val)
  650.     CMFB_display_image();
  651.     CM_send_ack();
  652. }
  653.  
  654.  
  655. /*
  656.  * Probe the lookup table to find the result of the transition from
  657.  * the neighborhood the client is sending us.
  658.  */
  659. void
  660. cm_probe()
  661. {
  662.     int x;
  663.     unsigned char buf2[4];
  664.  
  665.     saved_x = CM_read_int();
  666.     saved_y = CM_read_int();
  667.     read_from_sock(ns, buf, 4, OFF, debug2);
  668.     bcopy(buf, &x, 4);
  669.     if (nhood == NH_MARG) {
  670.     phase = CM_read_int();
  671.     phase = phase%S;
  672.     }
  673.     probe_func(buf);
  674.     Logd("probing nhood #%d\n", x, 1);
  675.     Logd("probe returning %d\n", buf[0], 1);
  676.     write_to_sock(ns, buf, 1, OFF, debug2
  677. );
  678. }
  679.  
  680.  
  681. /*
  682.  * Run for a given number of steps (read the interval from client)
  683.  */
  684. void
  685. run()
  686. {
  687.     int num_steps, nthframes, i;
  688.     unsigned char parm[4];
  689.     struct timeval tp;
  690.     struct timezone *tzp;
  691.     long usec, sec;
  692.     CM_timeval_t *cmtime;
  693.  
  694.     tzp = NULL;
  695.     num_steps = CM_read_int();
  696.     CM_disp_interval = CM_read_int();
  697.     if (function) {
  698.     parm1 = CM_read_int();
  699.     parm2 = CM_read_int();
  700.     }
  701.     Logd("running for %d steps",num_steps, 1);
  702.     if (nhood == NH_MARG) {
  703.     phase = CM_read_int();
  704.     phase = phase%S;
  705.     }
  706.     /* start timer */
  707.     /*
  708.     gettimeofday(&tp, tzp);
  709.     sec = tp.tv_sec;
  710.     usec = tp.tv_usec;
  711.     */
  712.     
  713.     CM_set_context();
  714.     /*
  715.     CM_reset_timer();
  716.     CM_start_timer();
  717.     */
  718.     auto_step(num_steps);
  719.     /*
  720.     cmtime = (CM_timeval_t *) CM_stop_timer();
  721.     printf("timings:\n real = %f, cm = %f\n",
  722.        cmtime->cmtv_real, cmtime->cmtv_cm);
  723.     */   
  724.     CM_set_context();
  725.  
  726.     /* stop timer */
  727.     /*
  728.     gettimeofday(&tp, tzp);
  729.     printf("%d seconds, %d useconds\n", tp.tv_sec-sec, tp.tv_usec-usec);
  730.     */
  731.  
  732.     if (FB_attach_ret_val && use_FB)
  733.     CMFB_display_image();
  734.     CM_send_ack();
  735. }
  736.  
  737.  
  738.  
  739. /*
  740.  * Run until the client tells us to stop
  741.  */
  742. void
  743. run_forever()
  744. {
  745.     unsigned char buf[4];
  746.     int num_steps;
  747.     struct timeval tp;
  748.     struct timezone *tzp;
  749.     long usec, sec;
  750.  
  751.     tzp = NULL;
  752.     if (function) {
  753.     parm1 = CM_read_int();
  754.     parm2 = CM_read_int();
  755.     }
  756.     if (nhood == NH_MARG) {
  757.     phase = CM_read_int();
  758.     phase = phase%S;
  759.     Log("done reading phase from Sun\n",1);
  760.     }
  761.     CM_disp_interval = CM_read_int();
  762.     Logd("display interval is %d", CM_disp_interval, 1);
  763.     forever_flag = 1;
  764.     CM_set_context();
  765.     /* start timer */
  766.     /*
  767.     gettimeofday(&tp, tzp);
  768.     sec = tp.tv_sec;
  769.     usec = tp.tv_usec;
  770.     */
  771.     
  772.     num_steps = auto_step(-1);
  773.  
  774.     /* stop timer */
  775.     /*
  776.     gettimeofday(&tp, tzp);
  777.     printf("%d seconds, %d useconds\n", tp.tv_sec-sec, tp.tv_usec-usec);
  778.     */
  779.        
  780.     CM_set_context();
  781.     if (use_FB && FB_attach_ret_val)
  782.     CMFB_display_image();
  783.     Logd("num_steps = %d\n",num_steps, 1);
  784.     forever_flag = 0;
  785.     CM_send_int(num_steps);    /* tell client how long we ran */
  786. }
  787.  
  788.  
  789. /*
  790.  * Display the current image, on the CM frame-buffer (CMFB) and/or the
  791.  * client's display (by sending the image through the socket to the client)
  792.  */
  793. void
  794. display_image()
  795. {
  796.     unsigned int newlen, se;
  797.     unsigned char *grid2, buf[8];
  798.     int ret_val;
  799.     
  800.     if (use_FB) {
  801.     if (FB_attach_ret_val)
  802.         CMFB_display_image();
  803.     else
  804.         Log("Remember, CMFB could not be initialized...", 0);
  805.     }
  806.     if (use_Sun_disp) {
  807.     Log("sending image to sun...", 1);
  808.     CM_u_read_from_news_array_1L(grid,
  809.                 offset_vector,
  810.                 start_vector,
  811.                 end_vector,
  812.                 axis_vector,
  813.                 cell,
  814.                 L,
  815.                 2,
  816.                 dimension_vector,
  817.                 1);
  818.     read_from_sock(ns, buf, 1, OFF, debug2);
  819.     if (buf[0] == COMPRESSED) {
  820.     }
  821.     else {
  822.         write_to_sock(ns, grid, B*B, OFF, debug2);
  823.         Logd("%d bytes written", B*B, 1);
  824.     }
  825.     Log("Done.", 1);
  826.     }
  827. }
  828.  
  829.  
  830. /*
  831.  * Change the current neighborhood configuration
  832.  */
  833. void
  834. change_stuff()
  835. {
  836.     char buf[80], arg[80];
  837.     int i, j, tmp, oldnhood, oldS, oldL, oldN, oldR, oldfunction, err;
  838.  
  839.     read_from_sock(ns, buf, 80, OFF, debug2);
  840.     Log2("Change-string is '%s'\n",buf, 1);
  841.     i = 0;
  842.     oldnhood = nhood;
  843.     oldL = L;
  844.     oldS = S;
  845.     oldN = N;
  846.     oldR = R;
  847.     oldfunction = function;
  848.     while (sscanf(&buf[i], "%s", arg) == 1) {
  849.     i += strlen(arg);
  850.     while (buf[i] == ' ')
  851.         i++;
  852.     switch (arg[0]) {
  853.       case 'm':
  854.         nhood = NH_MOORE;
  855.         set_states(&arg[1]);
  856.         break;
  857.       case 'M':
  858.         nhood = NH_MARG;
  859.         set_states(&arg[1]);
  860.         break;
  861.       case 'v':
  862.         nhood = NH_VONN;
  863.         set_states(&arg[1]);
  864.         break;
  865.       case 'l':
  866.         nhood = NH_LIN;
  867.         set_states(&arg[1]);
  868.         for (j=2; j<strlen(arg); j++) {
  869.         if (arg[j] == 'r') {
  870.             err = sscanf(&arg[j+1], "%d", &R);
  871.             if ((err != 1) || (R <= 0) || (R > 3))
  872.             quit("Illegal value for R");
  873.             j = strlen(arg);
  874.         }
  875.         }
  876.         break;
  877.       case 'r':
  878.         err = sscanf(&arg[1], "%d", &R);
  879.         if ((err != 1) || (R <= 0) || (R > 3)) {
  880.         R = 1;
  881.         Logd("Illegal value for R (%d)", R, 0);
  882.         }
  883.         break;
  884.       default:
  885.         quit("Bad arguments to change_stuff() routine");
  886.         break;
  887.     }
  888.     switch (nhood) {
  889.       case NH_VONN:
  890.         set_params_v();
  891.         break;
  892.       case NH_MOORE:
  893.         set_params_m();
  894.         break;
  895.       case NH_MARG:
  896.         set_params_marg();
  897.         break;
  898.       case NH_LIN:
  899.         set_params_l();
  900.         break;
  901.     }
  902.     tmp = S;
  903.     L = 0;
  904.     while (!(tmp & 0x01)) {
  905.         tmp >>= 1;
  906.         L++;
  907.     }
  908.     Logd("L = %d", L, 1);
  909.     Logd("N = %d", N, 1);
  910.     Logd("S = %d", S, 1);
  911.     if (S == 256)
  912.         function = 1;
  913.     else
  914.         function = 0;
  915.     if ((nhood == oldnhood) && (S == oldS) && (R == oldR)) {
  916.         Log("nhood didn't change", 0);
  917.         CM_send_ack();
  918.         return;
  919.     }
  920.     if (!oldfunction) {
  921.         free(table);
  922.         CM_deallocate_heap_field(trans);
  923.     }
  924.     else {
  925.         if (exit_function) {
  926.         exit_function();
  927.         exit_function = NULL;
  928.         initialization_function = NULL;
  929.         }
  930.     }
  931.     if (!function) {
  932.         TSIZE = 1 << (L * N);
  933.         Logd("tsize = %d\n",TSIZE, 1);
  934.         if ((table = (unsigned char *)malloc(TSIZE)) == NULL)
  935.         quit("Could not allocate table");
  936.         max_index = TSIZE/4;
  937.         array_size = (TSIZE/CM_geometry_total_vp_ratio(geo))/4;
  938.         trans = CM_allocate_heap_field(array_size);
  939.     }
  940.     CM_deallocate_heap_field(nbor_values);
  941.     CM_logand_constant_2_1L(cell, S-1, 8);
  942.     if (use_FB && FB_attach_ret_val)
  943.         CMFB_display_image();
  944.     nbor_values = CM_allocate_heap_field(L * N);
  945.     VNorth = nbor_values + L * V_N_OFF;
  946.     VSouth = nbor_values + L * V_S_OFF;
  947.     VEast = nbor_values + L * V_E_OFF;
  948.     VWest = nbor_values + L * V_W_OFF;
  949.     VCenter = nbor_values + L * V_C_OFF;
  950.     MNorth = nbor_values + L * M_N_OFF;
  951.     MSouth = nbor_values + L * M_S_OFF;
  952.     MEast = nbor_values + L * M_E_OFF;
  953.     MWest = nbor_values + L * M_W_OFF;
  954.     MNW = nbor_values + L * M_NW_OFF;
  955.     MSW = nbor_values + L * M_SW_OFF;
  956.     MNE = nbor_values + L * M_NE_OFF;
  957.     MSE = nbor_values + L * M_SE_OFF;
  958.     MCenter = nbor_values + L * M_C_OFF;
  959.     MargCenter = nbor_values + L * MARG_C_OFF;
  960.     MargCcw = nbor_values + L * MARG_CCW_OFF;
  961.     MargOpp = nbor_values + L * MARG_OPP_OFF;
  962.     MargCw = nbor_values + L * MARG_CW_OFF;
  963.     MargPhase = nbor_values + L * MARG_PHASE_OFF;
  964.     if (nhood == NH_LIN) {
  965.         switch (R) {
  966.           case 1:
  967.         LR1_L = nbor_values + L * LR1_L_OFF;
  968.         LR1_C = nbor_values + L * LR1_C_OFF;
  969.         LR1_R = nbor_values + L * LR1_R_OFF;
  970.         break;
  971.           case 2:
  972.         LR2_LL = nbor_values + L * LR2_LL_OFF;
  973.         LR2_L = nbor_values + L * LR2_L_OFF;
  974.         LR2_C = nbor_values + L * LR2_C_OFF;
  975.         LR2_R = nbor_values + L * LR2_R_OFF;
  976.         LR2_RR = nbor_values + L * LR2_RR_OFF;
  977.         break;
  978.           case 3:
  979.         LR3_LLL = nbor_values + L * LR3_LLL_OFF;
  980.         LR3_LL = nbor_values + L * LR3_LL_OFF;
  981.         LR3_L = nbor_values + L * LR3_L_OFF;
  982.         LR3_C = nbor_values + L * LR3_C_OFF;
  983.         LR3_R = nbor_values + L * LR3_R_OFF;
  984.         LR3_RR = nbor_values + L * LR3_RR_OFF;
  985.         LR3_RRR = nbor_values + L * LR3_RRR_OFF;
  986.         break;
  987.         }
  988.     }
  989.     CM_set_context();
  990.     CM_logand_constant_2_1L(cell, AMASK, 8);
  991.     }
  992.     CM_send_ack();
  993. }
  994.  
  995.  
  996.  
  997. /*
  998.  * Change image-size.  This means we have to deallocate the current
  999.  * VP-set and geometry (after deallocating all the fields), and recreate
  1000.  * a new one with the new geometry.
  1001.  */
  1002. void
  1003. change_image_size()
  1004. {
  1005.     char buf[80], arg[80];
  1006.     int i, tmp, oldB, saved_parm1, saved_parm2;
  1007.  
  1008.     oldB = B;
  1009.     B = CM_read_int();
  1010.     if (B == oldB)
  1011.     return;
  1012.     CM_set_context();
  1013.     if (!function)
  1014.     CM_deallocate_heap_field(trans);
  1015.     CM_u_move_zero_1L(cell, 8);
  1016.     if (use_FB && FB_attach_ret_val)
  1017.     CMFB_display_image();
  1018.     CM_deallocate_heap_field(cell);
  1019.     CM_deallocate_heap_field(temp_value);
  1020.     CM_deallocate_heap_field(one);
  1021.     CM_deallocate_heap_field(table_index);
  1022.     CM_deallocate_heap_field(bottom);
  1023.     CM_deallocate_heap_field(not_bottom);
  1024.     CM_deallocate_heap_field(nbor_values);
  1025.     CM_deallocate_heap_field(UL);
  1026.     CM_deallocate_heap_field(UR);
  1027.     CM_deallocate_heap_field(LL);
  1028.     CM_deallocate_heap_field(LR);
  1029.     if (function) {
  1030.     if (exit_function)    /* deallocate user-function stuff */
  1031.         exit_function();
  1032.     }
  1033.     CM_deallocate_vp_set(vp_set);
  1034.     CM_deallocate_geometry(geo);
  1035.     free(grid);
  1036.     if ((grid = (unsigned char *)malloc(B*B))==NULL)
  1037.     quit("Couldn't allocate memory for array on CMFE");
  1038.  
  1039.     CM_init_stuff();
  1040.     if (!function)
  1041.     send_table_to_CM();
  1042.     else {
  1043.     saved_parm1 = parm1;
  1044.     saved_parm2 = parm2;
  1045.     if (initialization_function)    /* re-invoke user-fcn init-fcn, so it
  1046.                      * can re-create any fields it needs */
  1047.         initialization_function();
  1048.     parm1 = saved_parm1;
  1049.     parm2 = saved_parm2;
  1050.     }
  1051.     CM_send_ack();
  1052. }
  1053.  
  1054.  
  1055. /*
  1056.  * Clear out the fields on the CM
  1057.  */
  1058. void
  1059. CM_uninit_stuff()
  1060. {
  1061.     if (!function) {
  1062.     CM_deallocate_heap_field(trans);
  1063.     free(table);
  1064.     }
  1065.     CM_deallocate_heap_field(cell);
  1066.     CM_deallocate_heap_field(temp_value);
  1067.     CM_deallocate_heap_field(one);
  1068.     CM_deallocate_heap_field(table_index);
  1069.     CM_deallocate_heap_field(bottom);
  1070.     CM_deallocate_heap_field(not_bottom);
  1071.     CM_deallocate_heap_field(nbor_values);
  1072.     CM_deallocate_heap_field(UL);
  1073.     CM_deallocate_heap_field(UR);
  1074.     CM_deallocate_heap_field(LL);
  1075.     CM_deallocate_heap_field(LR);
  1076.     CM_deallocate_vp_set(vp_set);
  1077.     CM_deallocate_geometry(geo);
  1078.     free(grid);
  1079. }
  1080.  
  1081.  
  1082. /*
  1083.  * Allocate fields and stuff for the CM
  1084.  */
  1085. void
  1086. CM_init_stuff()
  1087. {
  1088.     offset_vector[0] = 0;
  1089.     offset_vector[1] = 0;
  1090.     start_vector[0] = 0;
  1091.     start_vector[1] = 0;
  1092.     end_vector[0] = B;
  1093.     end_vector[1] = B;
  1094.     dimension_vector[0] = B;
  1095.     dimension_vector[1] = B;
  1096.     axis_vector[0] = 1;
  1097.     axis_vector[1] = 0;
  1098.     CM_set_context();
  1099.     geo_array[0] = B;
  1100.     geo_array[1] = B;
  1101.     geo = CM_create_geometry(geo_array, 2);
  1102.     vp_set = CM_allocate_vp_set(geo);
  1103.     CM_set_vp_set(vp_set);
  1104.     
  1105.     cell = CM_allocate_heap_field(8);
  1106.     temp_value = CM_allocate_heap_field(32);
  1107.     one = CM_allocate_heap_field(1);
  1108.     table_index = CM_allocate_heap_field(13);
  1109.     /* bottom & not_bottom used for 1-D rules */
  1110.     bottom = CM_allocate_heap_field(1);
  1111.     not_bottom = CM_allocate_heap_field(1);
  1112.     /* the next 4 are used to implement margolus neighborhood */
  1113.     UL = CM_allocate_heap_field(1);
  1114.     UR = CM_allocate_heap_field(1);
  1115.     LR = CM_allocate_heap_field(1);
  1116.     LL = CM_allocate_heap_field(1);
  1117.     if (!function) {
  1118.     array_size = (TSIZE/CM_geometry_total_vp_ratio(geo))/4;
  1119.     trans = CM_allocate_heap_field(array_size);
  1120.     }
  1121.     nbor_values = CM_allocate_heap_field(L * N);
  1122.     CM_set_context();
  1123.     CM_u_move_zero_1L(cell, 8);
  1124.     CM_u_move_zero_1L(bottom, 1);
  1125.     CM_my_news_coordinate_1L(temp_value, VERTICAL, 9);
  1126.     CM_u_eq_constant_1L(temp_value, B-1, 9);
  1127.     CM_logand_context_with_test();
  1128.     CM_u_move_constant_1L(bottom, 1, 1);
  1129.     CM_set_context();
  1130.     CM_lognot_2_1L(not_bottom, bottom, 1);
  1131.     CM_u_move_zero_1L(UL, 1);
  1132.     CM_u_move_zero_1L(UR, 1);
  1133.     CM_u_move_zero_1L(LR, 1);
  1134.     CM_u_move_zero_1L(LL, 1);
  1135.     CM_my_news_coordinate_1L(temp_value, HORIZONTAL, 9);
  1136.     CM_my_news_coordinate_1L(temp_value+1, VERTICAL, 9);
  1137.     CM_lognot_2_1L(temp_value+2, temp_value, 1);
  1138.     CM_lognot_2_1L(temp_value+3, temp_value+1, 1);
  1139.     CM_load_context(temp_value+2);
  1140.     CM_logand_context(temp_value+3);
  1141.     CM_u_move_constant_1L(UL, 1, 1);
  1142.     CM_load_context(temp_value+2);
  1143.     CM_logand_context(temp_value+1);
  1144.     CM_u_move_constant_1L(LL, 1, 1);
  1145.     CM_load_context(temp_value);
  1146.     CM_logand_context(temp_value+3);
  1147.     CM_u_move_constant_1L(UR, 1, 1);
  1148.     CM_load_context(temp_value);
  1149.     CM_logand_context(temp_value+1);
  1150.     CM_u_move_constant_1L(LR, 1, 1);
  1151.     CM_set_context();
  1152.     CM_u_move_constant_1L(one, 1, 1);
  1153.     VNorth = nbor_values + L * V_N_OFF;
  1154.     VSouth = nbor_values + L * V_S_OFF;
  1155.     VEast = nbor_values + L * V_E_OFF;
  1156.     VWest = nbor_values + L * V_W_OFF;
  1157.     VCenter = nbor_values + L * V_C_OFF;
  1158.     MNorth = nbor_values + L * M_N_OFF;
  1159.     MSouth = nbor_values + L * M_S_OFF;
  1160.     MEast = nbor_values + L * M_E_OFF;
  1161.     MWest = nbor_values + L * M_W_OFF;
  1162.     MNW = nbor_values + L * M_NW_OFF;
  1163.     MSW = nbor_values + L * M_SW_OFF;
  1164.     MNE = nbor_values + L * M_NE_OFF;
  1165.     MSE = nbor_values + L * M_SE_OFF;
  1166.     MCenter = nbor_values + L * M_C_OFF;
  1167.     MargCenter = nbor_values + L * MARG_C_OFF;
  1168.     MargCcw = nbor_values + L * MARG_CCW_OFF;
  1169.     MargOpp = nbor_values + L * MARG_OPP_OFF;
  1170.     MargCw = nbor_values + L * MARG_CW_OFF;
  1171.     MargPhase = nbor_values + L * MARG_PHASE_OFF;
  1172.     if (nhood == NH_LIN) {
  1173.     switch (R) {
  1174.       case 1:
  1175.         LR1_L = nbor_values + L * LR1_L_OFF;
  1176.         LR1_C = nbor_values + L * LR1_C_OFF;
  1177.         LR1_R = nbor_values + L * LR1_R_OFF;
  1178.         break;
  1179.       case 2:
  1180.         LR2_LL = nbor_values + L * LR2_LL_OFF;
  1181.         LR2_L = nbor_values + L * LR2_L_OFF;
  1182.         LR2_C = nbor_values + L * LR2_C_OFF;
  1183.         LR2_R = nbor_values + L * LR2_R_OFF;
  1184.         LR2_RR = nbor_values + L * LR2_RR_OFF;
  1185.         break;
  1186.       case 3:
  1187.         LR3_LLL = nbor_values + L * LR3_LLL_OFF;
  1188.         LR3_LL = nbor_values + L * LR3_LL_OFF;
  1189.         LR3_L = nbor_values + L * LR3_L_OFF;
  1190.         LR3_C = nbor_values + L * LR3_C_OFF;
  1191.         LR3_R = nbor_values + L * LR3_R_OFF;
  1192.         LR3_RR = nbor_values + L * LR3_RR_OFF;
  1193.         LR3_RRR = nbor_values + L * LR3_RRR_OFF;
  1194.         break;
  1195.     }
  1196.     }
  1197. }
  1198.  
  1199.  
  1200. /*
  1201.  * Read colormap from client, and send to FB
  1202.  */
  1203. void
  1204. send_cmap()
  1205. {
  1206.     unsigned char buf[256];
  1207.     int i, clen;
  1208.  
  1209.     clen = 256;
  1210.     read_from_sock(ns, red, clen, OFF, debug2);
  1211.     read_from_sock(ns, green, clen, OFF, debug2);
  1212.     read_from_sock(ns, blue, clen, OFF, debug2);
  1213.     if (FB_attach_ret_val) {
  1214.     CMFB_write_color_table(&disp_id, CMFB_red, red);
  1215.     CMFB_write_color_table(&disp_id, CMFB_green, green);
  1216.     CMFB_write_color_table(&disp_id, CMFB_blue, blue);
  1217.     }
  1218.     CM_send_ack();
  1219. }
  1220.  
  1221.  
  1222. /*
  1223.  * Change the delay we pause between updates (sometimes necessary in order
  1224.  * to slow down the CM enough to watch stuff on the FB :-)
  1225.  */
  1226. void
  1227. change_delay()
  1228. {
  1229.     unsigned char buf[4];
  1230.  
  1231.     CM_delay = CM_read_int();
  1232.     CM_send_ack();
  1233. }
  1234.  
  1235.  
  1236. /*
  1237.  * Client is telling us which display(s) to use, CMFB and/or client display
  1238.  */
  1239. void
  1240. set_displays()
  1241. {
  1242.     unsigned char buf[4];
  1243.  
  1244.     read_from_sock(ns, buf, 1, OFF, debug2);
  1245.     Logd("set_displays parm = %d", buf[0], 1);
  1246.     use_FB = (buf[0] & 0x01);
  1247.     use_Sun_disp = (buf[0] & 0x02) >> 1;
  1248.     CM_send_ack();
  1249. }
  1250.  
  1251.  
  1252. /*
  1253.  * How often to display an image, when running
  1254.  */
  1255. void
  1256. set_disp_interval()
  1257. {
  1258.     unsigned char buf[4];
  1259.  
  1260.     CM_disp_interval = CM_read_int();
  1261.     Logd("set disp interval to %d", CM_disp_interval, 1);
  1262.     CM_send_ack();
  1263. }
  1264.  
  1265.  
  1266. /*
  1267.  * Load an image from the CMFE disk
  1268.  */
  1269. void
  1270. load_image()
  1271. {
  1272.     char fname[128], fname2[256];
  1273.     FILE *fp;
  1274.     
  1275.     read_from_sock(ns, fname, 128, OFF, debug2);
  1276.     if (expand_fname(fname,fname)) {
  1277.     CM_send_error(fname);
  1278.     return;
  1279.     }
  1280.     if (!strcmp(&fname[strlen(fname)-2], ".Z")) {
  1281.     load_image_compressed(fname);
  1282.     return;
  1283.     }
  1284.     Log2("fname is '%s'",fname, 1);
  1285.     if ((fp=fopen(fname, "r"))==NULL) {
  1286.     sprintf(fname2, "%s/%s", CM_image_dir, fname);
  1287.     if ((fp=fopen(fname, "r"))==NULL) {
  1288.         load_image_compressed(fname);
  1289.         return;
  1290.     }
  1291.     }
  1292.     if (read_image_from_fp(fp)) {
  1293.     fclose(fp);
  1294.     return;
  1295.     }
  1296.     fclose(fp);
  1297.     CM_send_ack();
  1298. }
  1299.  
  1300.  
  1301. /*
  1302.  * Load a compressed image from the CMFE disk
  1303.  */
  1304. void
  1305. load_image_compressed(fname)
  1306. char *fname;
  1307. {
  1308.     char fname2[256], cmdstr[256];
  1309.     FILE *fp;
  1310.     int err;
  1311.     
  1312.     if (strcmp(&fname[strlen(fname)-2], ".Z"))
  1313.     strcat(fname, ".Z");
  1314.     if (!stat(fname, &statbuf)) {
  1315.     sprintf(cmdstr, "uncompress -c %s", fname);
  1316.     if (!(fp = popen(cmdstr, "r"))) {
  1317.         Log("Error trying to open pipe to uncompress image", 0);
  1318.         CM_send_error("Error opening pipe");
  1319.         return;
  1320.     }
  1321.     }
  1322.     else {
  1323.     sprintf(fname2, "%s/%s", CM_image_dir, fname);
  1324.     if (stat(fname2, &statbuf)) {
  1325.         Log("No such image file", 0);
  1326.         CM_send_error("No such image file");
  1327.         return;
  1328.     }
  1329.     sprintf(cmdstr, "uncompress -c %s/%s", CM_image_dir, fname);
  1330.     if (!(fp = popen(cmdstr, "r"))) {
  1331.         Log("Error trying to open pipe to uncompress image", 0);
  1332.         CM_send_error("Error opening pipe");
  1333.         return;
  1334.     }
  1335.     }
  1336.     if (read_image_from_fp(fp)) {
  1337.     pclose(fp);
  1338.     return;
  1339.     }
  1340.     err = pclose(fp);
  1341.     if (err) {
  1342.     Logd("pclose returned %d", err, 0);
  1343.     CM_send_error("pclose() failed");
  1344.     return;
  1345.     }
  1346.     CM_send_ack();
  1347. }
  1348.  
  1349.  
  1350. int
  1351. read_image_from_fp(fp)
  1352. FILE *fp;
  1353. {
  1354.     int bytes_left, count, ret_val;
  1355.     
  1356.     if (nhood == NH_LIN) {
  1357.     bytes_left = B;
  1358.     count = B*B-B;
  1359.     CM_u_read_from_news_array_1L(grid,
  1360.                      offset_vector,
  1361.                      start_vector,
  1362.                      end_vector,
  1363.                      axis_vector,
  1364.                      cell,
  1365.                      L,
  1366.                      2,
  1367.                      dimension_vector,
  1368.                      1);
  1369.     }
  1370.     else {
  1371.     bytes_left = B*B;
  1372.     count = 0;
  1373.     }
  1374.     while (bytes_left) {
  1375.     if (!(ret_val = fread(grid+count, 1, bytes_left, fp))) {
  1376.         CM_send_error("Error reading file");
  1377.         return 1;
  1378.     }
  1379.     bytes_left -= ret_val;
  1380.     count += ret_val;
  1381.     }
  1382.     Log("done reading file... sending to CM", 1);
  1383.     CM_u_write_to_news_array_1L(grid,
  1384.                 offset_vector,
  1385.                 start_vector,
  1386.                 end_vector,
  1387.                 axis_vector,
  1388.                 cell,
  1389.                 L,
  1390.                 2,
  1391.                 dimension_vector,
  1392.                 1);
  1393.     if (use_FB && FB_attach_ret_val)
  1394.     CMFB_display_image();
  1395.     return 0;
  1396. }
  1397.  
  1398.  
  1399.  
  1400. /*
  1401.  * Count the number of cells in each possible state, and tell client
  1402.  */
  1403. void
  1404. count_states()
  1405. {
  1406.     int i;
  1407.     unsigned int x;
  1408.     
  1409.     /* count all the states, put into the state_count[] array,
  1410.      * then send to Sun */
  1411.     for (i=0; i < S; i++) {
  1412.     if (nhood == NH_LIN)
  1413.         CM_load_context(bottom);
  1414.     else
  1415.         CM_set_context();
  1416.     CM_u_eq_constant_1L(cell, i, L);
  1417.     CM_logand_context_with_test();
  1418.     x = CM_global_u_add_1L(one, 1);
  1419.     buf[i*4] = x%256;
  1420.     buf[i*4+1] = x/256;
  1421.     buf[i*4+2] = x/(256*256);
  1422.     buf[i*4+3] = x/(256*256*256);
  1423.     }
  1424.     write_to_sock(ns, buf, S*4, OFF, debug2);
  1425. }
  1426.  
  1427.  
  1428. /*
  1429.  * Generate quick (distributed evenly across all values, including 0)
  1430.  * random image
  1431.  */
  1432. void
  1433. quick_random()
  1434. {
  1435.     CM_set_context();
  1436.     CM_u_random_1L(cell, 8, S);
  1437.     if (use_FB && FB_attach_ret_val)
  1438.     CMFB_display_image();
  1439.     CM_send_ack();
  1440. }
  1441.  
  1442.  
  1443. /*
  1444.  * More general random image routine
  1445.  */
  1446. void
  1447. general_random()
  1448. {
  1449.     int ox, oy, sx, sy, density, min_val, max_val;
  1450.     
  1451.     CM_set_context();
  1452.     ox = CM_read_int();
  1453.     oy = CM_read_int();
  1454.     sx = CM_read_int();
  1455.     sy = CM_read_int();
  1456.     density = CM_read_int();
  1457.     min_val = CM_read_int();
  1458.     max_val = CM_read_int();
  1459.     CM_my_news_coordinate_1L(temp_value, HORIZONTAL, 10);
  1460.     CM_my_news_coordinate_1L(temp_value+10, VERTICAL, 10);
  1461.     /* make sure x-coord is > ox but < (ox+sx)  (or ">=" and "<="?)
  1462.      * and similarly for oy
  1463.      * use that to set context-flag, then have active processors
  1464.      * generate a number in the appropriate range
  1465.      */
  1466.     CM_u_ge_constant_1L(temp_value, ox, 10);
  1467.     CM_logand_context_with_test();
  1468.     CM_u_lt_constant_1L(temp_value, ox+sx, 10);
  1469.     CM_logand_context_with_test();
  1470.     CM_u_ge_constant_1L(temp_value+10, oy, 10);
  1471.     CM_logand_context_with_test();
  1472.     CM_u_lt_constant_1L(temp_value+10, oy+sy, 10);
  1473.     CM_logand_context_with_test();
  1474.     CM_u_random_1L(temp_value, 7, 100);
  1475.     CM_u_lt_constant_1L(temp_value, density, 7);
  1476.     CM_logand_context_with_test();
  1477.     CM_u_random_1L(cell, 8, max_val - min_val + 1);
  1478.     CM_u_add_constant_2_1L(cell, min_val, 8);
  1479.     if (use_FB && FB_attach_ret_val)
  1480.     CMFB_display_image();
  1481.     CM_send_ack();
  1482.     CM_set_context();
  1483. }
  1484.  
  1485.  
  1486. /*
  1487.  * Clear out the current array on the CM
  1488.  */
  1489. void
  1490. CM_clear_array()
  1491. {
  1492.     CM_u_move_zero_1L(cell,8);
  1493.     if (use_FB && FB_attach_ret_val)
  1494.     CMFB_display_image();
  1495.     CM_send_ack();
  1496. }
  1497.  
  1498.  
  1499. /*
  1500.  * Client wants to get image, so we send it
  1501.  */
  1502. void
  1503. CM_get_image()
  1504. {
  1505.     Log("sending image to sun...", 1);
  1506.     CM_u_read_from_news_array_1L(grid,
  1507.                  offset_vector,
  1508.                  start_vector,
  1509.                  end_vector,
  1510.                  axis_vector,
  1511.                  cell,
  1512.                  L,
  1513.                  2,
  1514.                  dimension_vector,
  1515.                  1);
  1516.     write_to_sock(ns, grid, B*B, OFF, debug2);
  1517.     Logd("%d bytes written", B*B, 1);
  1518.     Log("Done.", 1);
  1519. }
  1520.  
  1521.  
  1522.  
  1523. /*
  1524.  * Load a rule (LT or computed-fcn) from CMFE disk
  1525.  */
  1526. void
  1527. load_rule()
  1528. {
  1529.     if (function)
  1530.     load_fcn();
  1531.     else
  1532.     load_LT();
  1533. }
  1534.  
  1535.  
  1536. /*
  1537.  * Load a computed-function rule (written in Paris)
  1538.  */
  1539. void
  1540. load_fcn()
  1541. {
  1542.     char fname[128], fname2[256];
  1543.     struct stat statbuf;
  1544.  
  1545.     read_from_sock(ns, fname, 128, OFF, debug2);
  1546.     if (expand_fname(fname,fname)) {
  1547.     CM_send_error(fname);
  1548.     return;
  1549.     }
  1550.     strcpy(fname2, fname);
  1551.     Log2("fname is '%s'", fname, 1);
  1552.     if (stat(fname, &statbuf)) {
  1553.     sprintf(fname2, "%s/%s", CM_fcn_dir, fname);
  1554.     if (stat(fname2, &statbuf)) {
  1555.         CM_send_error("No such file");
  1556.         return;
  1557.     }
  1558.     }
  1559.     Log2("full filename is '%s'", fname2, 1);
  1560.     strcpy(saved_fcn_name, fname2);
  1561.     /* call previous function's exit-function, if it has one, to deallocate
  1562.      * any extra CM fields the rule was using */
  1563.     if (exit_function)
  1564.     exit_function();
  1565.     load_function_file(fname2);
  1566.     CM_send_ack();
  1567.     CM_send_int(parm1);
  1568.     CM_send_int(parm2);
  1569. }
  1570.  
  1571. /*
  1572.  * Actually load in the computed-function
  1573.  */
  1574. void
  1575. load_function_file(fname)
  1576. char *fname;
  1577. {
  1578.     Log("linking file...", 1);
  1579.     update_function = NULL;
  1580.     exit_function = NULL;
  1581.     initialization_function = (void_func_ptr) dynamic_load(argv0, fname);
  1582.     Logd("done linking, init_fcn = %d.", initialization_function, 1);
  1583.     initialization_function();
  1584.     Log("done initializing", 1);
  1585. }
  1586.  
  1587.  
  1588. /*
  1589.  * Load lookup table (LT) from CMFE disk
  1590.  */
  1591. void
  1592. load_LT()
  1593. {
  1594.     char fname[128], fname2[256];
  1595.     FILE *fp;
  1596.     unsigned char word[4], buf[8];
  1597.     unsigned int *iptr, j, i;
  1598.  
  1599.     read_from_sock(ns, fname, 128, OFF, debug2);
  1600.     if (expand_fname(fname,fname)) {
  1601.     CM_send_error(fname);
  1602.     return;
  1603.     }
  1604.     if (!strcmp(&fname[strlen(fname)-2], ".Z")) {
  1605.     load_LT_compressed(fname);
  1606.     return;
  1607.     }
  1608.     Log2("fname is '%s'", fname, 1);
  1609.     if ((fp = fopen(fname, "r")) == NULL) {
  1610.     sprintf(fname2, "%s/%s", CM_LT_dir, fname);
  1611.     if ((fp=fopen(fname2, "r")) == NULL) {
  1612.         load_LT_compressed(fname);
  1613.         return;
  1614.     }
  1615.     }
  1616.     if (read_LT_from_fp(fp)) {
  1617.     fclose(fp);
  1618.     return;
  1619.     }
  1620.     fclose(fp);
  1621.     CM_send_ack();
  1622. }
  1623.  
  1624.  
  1625. void
  1626. load_LT_compressed(fname)
  1627. char *fname;
  1628. {
  1629.     char fname2[256], cmdstr[256];
  1630.     FILE *fp;
  1631.     int err;
  1632.  
  1633.     if (strcmp(&fname[strlen(fname)-2], ".Z"))
  1634.     strcat(fname, ".Z");
  1635.     if (!stat(fname, &statbuf)) {
  1636.     sprintf(cmdstr, "uncompress -c %s", fname);
  1637.     if (!(fp = popen(cmdstr, "r"))) {
  1638.         Log("Error trying to open pipe to uncompress LT", 0);
  1639.         CM_send_error("Error opening pipe");
  1640.         return;
  1641.     }
  1642.     }
  1643.     else {
  1644.     sprintf(fname2, "%s/%s", CM_LT_dir, fname);
  1645.     if (stat(fname2, &statbuf)) {
  1646.         Log("No such LT file", 0);
  1647.         CM_send_error("No such LT file");
  1648.         return;
  1649.     }
  1650.     sprintf(cmdstr, "uncompress -c %s/%s", CM_LT_dir, fname);
  1651.     if (!(fp = popen(cmdstr, "r"))) {
  1652.         Log("Error trying to open pipe to uncompress LT", 0);
  1653.         CM_send_error("Error opening pipe");
  1654.         return;
  1655.     }
  1656.     }
  1657.     if (read_LT_from_fp(fp)) {
  1658.     pclose(fp);
  1659.     return;
  1660.     }
  1661.     err = pclose(fp);
  1662.     if (err) {
  1663.     Logd("pclose returned %d", err, 0);
  1664.     CM_send_error("pclose() failed");
  1665.     return;
  1666.     }
  1667.     CM_send_ack();
  1668. }
  1669.  
  1670.  
  1671.  
  1672. int
  1673. read_LT_from_fp(fp)
  1674. FILE *fp;
  1675. {
  1676.     int bytes_left, count, ret_val;
  1677.  
  1678.     bytes_left = TSIZE;
  1679.     count = 0;
  1680.     while (bytes_left) {
  1681.     if (!(ret_val = fread(table+count, 1, bytes_left, fp))) {
  1682.         CM_send_error("Error reading file");
  1683.         return 1;
  1684.     }
  1685.     bytes_left -= ret_val;
  1686.     count += ret_val;
  1687.     }
  1688.     send_table_to_CM();
  1689.     return 0;
  1690. }
  1691.     
  1692.     
  1693. /*
  1694.  * Set directory to look for images in, when they can't be found in
  1695.  * current directory
  1696.  */
  1697. void
  1698. CM_set_image_dir()
  1699. {
  1700.     read_from_sock(ns, CM_image_dir, 128, OFF, debug2);
  1701. }
  1702.  
  1703.  
  1704. /*
  1705.  * Get image-dir from CMFE to Sun
  1706.  */
  1707. void
  1708. CM_get_image_dir()
  1709. {
  1710.     write_to_sock(ns, CM_image_dir, 128, OFF, debug2);
  1711. }
  1712.  
  1713.  
  1714.  
  1715. /*
  1716.  * Set default function dir
  1717.  */
  1718. void
  1719. CM_set_fcn_dir()
  1720. {
  1721.     read_from_sock(ns, CM_fcn_dir, 128, OFF, debug2);
  1722. }
  1723.  
  1724.  
  1725. /*
  1726.  * Get fcn-dir from CMFE to Sun
  1727.  */
  1728. void
  1729. CM_get_fcn_dir()
  1730. {
  1731.     write_to_sock(ns, CM_fcn_dir, 128, OFF, debug2);
  1732. }    
  1733.  
  1734.  
  1735.  
  1736. /*
  1737.  * Set lookup-table dir
  1738.  */
  1739. void
  1740. CM_set_LT_dir()
  1741. {
  1742.     read_from_sock(ns, CM_LT_dir, 128, OFF, debug2);
  1743. }
  1744.  
  1745.  
  1746. /*
  1747.  * Get LT dir from CMFE to Sun
  1748.  */
  1749. void
  1750. CM_get_LT_dir()
  1751. {
  1752.     write_to_sock(ns, CM_LT_dir, 128, OFF, debug2);
  1753. }
  1754.  
  1755.     
  1756. /*
  1757.  * Find the full pathname of the program that is being executed,
  1758.  * so we can do dynamic linking if we need to.
  1759.  */
  1760. void
  1761. which(a0, result)
  1762. char *a0, *result;
  1763. {
  1764.     char *path, directory[256];
  1765.     int i, j;
  1766.     struct stat statbuf;
  1767.  
  1768.     if ((!strncmp(a0, "./", 2)) || (!strncmp(a0, "../", 3)) ||
  1769.     (a0[0] == '/')) {
  1770.     strcpy(result, a0);
  1771.     return;
  1772.     }
  1773.     if ((path = getenv("PATH")) == NULL)
  1774.      quit("Couldn't look up PATH from the environment!");
  1775.     i = 0;
  1776.     while (i < strlen(path)) {
  1777.     j = 0;
  1778.     while ((path[i] != ':') && (path[i] != '\0'))
  1779.         directory[j++] = path[i++];
  1780.     i++;
  1781.     directory[j++] = '/';
  1782.     directory[j++] = '\0';
  1783.     strcat(directory, a0);
  1784.     /* Now "directory" contains the next try */
  1785.     if (!stat(directory, &statbuf)) {
  1786.         strcpy(result, directory);
  1787.         return;
  1788.     }
  1789.     }
  1790. }
  1791.  
  1792.  
  1793. /*
  1794.  * Set zoom-factor (magnification level) for the CMFB
  1795.  */
  1796. void
  1797. set_zoom()
  1798. {
  1799.     zoom_fac = CM_read_int();
  1800.     if (FB_attach_ret_val)
  1801.     /* CMFB_set_pan_and_zoom(&disp_id, pan_x, pan_y, zoom_fac, zoom_fac, 1); */
  1802.     CMFB_set_zoom(&disp_id, zoom_fac, zoom_fac, 0);
  1803.     /* CM_send_ack(); */
  1804. }
  1805.  
  1806.  
  1807. /*
  1808.  * Set pan (translational offsets) for CMFB
  1809.  */
  1810. void
  1811. set_pan()
  1812. {
  1813.     pan_x = CM_read_int()-B/2;
  1814.     pan_y = CM_read_int()-B/2;
  1815.     if (FB_attach_ret_val)
  1816.     /* CMFB_set_pan_and_zoom(&disp_id, pan_x, pan_y, zoom_fac, zoom_fac,1); */
  1817.     CMFB_set_pan(&disp_id, pan_x, pan_y);
  1818.     /* CM_send_ack(); */
  1819. }
  1820.  
  1821.  
  1822. /*
  1823.  * Client wants state-count info when running
  1824.  */
  1825. void
  1826. enable_socket()
  1827. {
  1828.     SOCKET_INUSE = 1;
  1829. }
  1830.  
  1831.  
  1832. /*
  1833.  * Client doesn't want state-count info when running
  1834.  */
  1835. void
  1836. disable_socket()
  1837. {
  1838.     SOCKET_INUSE = 0;
  1839. }
  1840.  
  1841.  
  1842. /*
  1843.  * If cm_cell wasn't invoked by the cm_celld daemon, then we have to
  1844.  * wait for a client ourselves..
  1845.  */
  1846. void
  1847. get_client()
  1848. {
  1849.     int addrlen;
  1850.     struct sockaddr addr;
  1851.     unsigned char buf[80];
  1852.  
  1853.     Log("waiting to accept client...", 0);
  1854.     addrlen = sizeof(struct sockaddr);
  1855.     if ((ns=wait_to_accept_socket(sock_fd, &addr, &addrlen, OFF, debug2))==-1)
  1856.     pquit("Couldn't wait for client");
  1857.     write_to_sock(ns, buf, 1, OFF, 0);
  1858.     Log("client accepted", 0);
  1859.     read_from_sock(ns, buf, 80, OFF, debug2);
  1860.     set_params(buf);
  1861. }
  1862.  
  1863.  
  1864. /*
  1865.  * Display image, using double-buffering
  1866.  */
  1867. void
  1868. CMFB_display_image()
  1869. {
  1870.     static CMFB_buffer_id_t cmfb_buf=CMFB_green;
  1871.  
  1872.     if (cmfb_buf == CMFB_green) {
  1873.     CMFB_write_always(&disp_id, CMFB_blue, cell, 0, 0);
  1874.     CMFB_switch_buffer(&disp_id, CMFB_blue);
  1875.     }
  1876.     else {
  1877.     CMFB_write_always(&disp_id, CMFB_green, cell, 0, 0);
  1878.     CMFB_switch_buffer(&disp_id, CMFB_green);
  1879.     }
  1880. }
  1881.  
  1882.  
  1883.  
  1884. /*
  1885.  * Expand a "tilde" filename or filename with wildcards in it.
  1886.  */
  1887. int
  1888. expand_fname(src, dest)
  1889. char *src, *dest;
  1890. {
  1891.     FILE *fp;
  1892.     char command_str[256];
  1893.     int err, i;
  1894.  
  1895.     if (!strlen(src))
  1896.     return;
  1897.     sprintf(command_str, "/bin/sh -c \"/bin/csh -f -c '/bin/echo %s' 2>&1\"",src);
  1898.     if ((fp = popen(command_str, "r")) == NULL) {
  1899.     Log("Error trying to expand filename", 0);
  1900.     return 1;
  1901.     }
  1902.     fgets(dest, 128, fp);
  1903.     if ((dest[strlen(dest)-1] == '\n') || (dest[strlen(dest)-1] == '\r'))
  1904.     dest[strlen(dest)-1] = '\0';
  1905.     if ((!strncmp(dest,"Unknown user",12))||(!strncmp(dest,"No match.",9))) {
  1906.     Log(dest, 0);
  1907.     pclose(fp);
  1908.     return 1;
  1909.     }
  1910.     for (i=0; i<strlen(dest); i++)
  1911.     if (dest[i] == ' ') {    /* multiple matches */
  1912.         Log("Multiple filenames matched.", 0);
  1913.         return 1;
  1914.     }
  1915.     if (strlen(dest) == 0) {
  1916.     Log("error trying to expand filename", 0);
  1917.     return 1;
  1918.     }
  1919.     err = pclose(fp);
  1920.     if (err) {
  1921.     Log("Error trying to expand filename", 0);
  1922.     return 1;
  1923.     }
  1924.     return 0;
  1925. }
  1926.     
  1927.  
  1928.  
  1929.  
  1930. /*
  1931.  * Null procedure, to hold a place in the array of routines
  1932.  */
  1933. void
  1934. null_proc()
  1935. {
  1936. }
  1937.  
  1938.  
  1939.     
  1940. /*
  1941.  * There doesn't seem to be a usleep (microsecond sleep) routine in
  1942.  * the Vax C library, so we have to define one.
  1943.  * Yes, I know, this isn't really microseconds, it's just a counter;
  1944.  * I'll make this do real microseconds one of these days.
  1945.  */
  1946. #if (SUN==0)
  1947. usleep(delay)
  1948. int delay;
  1949. {
  1950.     int i, j;
  1951.  
  1952.     for (i=0; i<delay; i++)
  1953.     j = i;    /* make sure the compiler doesn't optimize out this loop */
  1954. }
  1955. #endif
  1956.  
  1957.