home *** CD-ROM | disk | FTP | other *** search
/ Windoware / WINDOWARE_1_6.iso / miscprog / atre20 / atree.c next >
Encoding:
C/C++ Source or Header  |  1991-08-08  |  83.9 KB  |  2,764 lines

  1. /*****************************************************************************
  2.  ****                                                                     ****
  3.  **** atree.c                                                             ****
  4.  ****                                                                     ****
  5.  **** atree release 2.0 for PC, Windows                                   ****
  6.  **** Adaptive Logic Network (ALN) simulation program.                    ****
  7.  **** Copyright (C) A. Dwelly, R. Manderscheid, W.W. Armstrong,           ****
  8.  **** M. Thomas, 1991                                                     ****
  9.  **** License:                                                            ****
  10.  **** A royalty-free license is granted for the use of this software for  ****
  11.  **** NON_COMMERCIAL PURPOSES ONLY. The software may be copied and/or     ****
  12.  **** modified provided this notice appears in its entirety and unchanged ****
  13.  **** in all derived source programs.  Persons modifying the code are     ****
  14.  **** requested to state the date, the changes made and who made them     ****
  15.  **** in the modification history.                                        ****
  16.  ****                                                                     ****
  17.  **** Patent License:                                                     ****
  18.  **** The use of a digital circuit which transmits a signal indicating    ****
  19.  **** heuristic responsibility is protected by U. S. Patent 3,934,231     ****
  20.  **** and others assigned to Dendronic Decisions Limited of Edmonton,     ****
  21.  **** W. W. Armstrong, President.  A royalty-free license is granted      ****
  22.  **** by the company to use this patent for NON_COMMERCIAL PURPOSES to    ****
  23.  **** adapt logic trees using this program and its modifications.         ****
  24.  ****                                                                     ****
  25.  **** Limited Warranty:                                                   ****
  26.  **** This software is provided "as is" without warranty of any kind,     ****
  27.  **** either expressed or implied, including, but not limited to, the     ****
  28.  **** implied warrantees of merchantability and fitness for a particular  ****
  29.  **** purpose.  The entire risk as to the quality and performance of the  ****
  30.  **** program is with the user.  Neither the authors, nor the             ****
  31.  **** University of Alberta, its officers, agents, servants or employees  ****
  32.  **** shall be liable or responsible in any way for any damage to         ****
  33.  **** property or direct personal or consequential injury of any nature   ****
  34.  **** whatsoever that may be suffered or sustained by any licensee, user  ****
  35.  **** or any other party as a consequence of the use or disposition of    ****
  36.  **** this software.                                                      ****
  37.  ****                                                                     ****
  38.  **** Modification history:                                               ****
  39.  ****                                                                     ****
  40.  **** 90.09.05 Initial implementation, A.Dwelly                           ****
  41.  **** 91.04.15 Port to PC and minor bug fixes, R. Manderscheid            ****
  42.  **** 91.05.31 Port to Windows & Windows Extensions, M. Thomas            ****
  43.  **** 91.07.17 atree v2.0 for Windows, M. Thomas                          ****
  44.  ****                                                                     ****
  45.  *****************************************************************************/
  46.  
  47. #pragma inline
  48.  
  49. /*****************************************************************************
  50.  ****                                                                     ****
  51.  **** Include Files                                                       ****
  52.  ****                                                                     ****
  53.  *****************************************************************************/
  54.  
  55. #include <windows.h>
  56. #include <stdio.h>
  57. #include <stdlib.h>
  58. #include <math.h>
  59. #include "..\atree.h"
  60.  
  61. #define assert(exp)\
  62.     {\
  63.     if (!(exp))\
  64.         {\
  65.         char szBuffer[80]; \
  66.         wsprintf(szBuffer, "%s, Line %d",\
  67.             (LPSTR)__FILE__, __LINE__);\
  68.         MessageBox (NULL, szBuffer, "Assertion Failed",\
  69.                 MB_OK | MB_ICONSTOP);\
  70.         }\
  71.     }
  72.  
  73. /*****************************************************************************
  74.  ****                                                                     ****
  75.  **** Constants                                                           ****
  76.  ****                                                                     ****
  77.  *****************************************************************************/
  78.  
  79. #define AND 0
  80. #define RIGHT 1
  81. #define LEFT 2
  82. #define OR 3
  83. #define LEAF 4
  84.  
  85. #define LEFT_CHILD 0
  86. #define RIGHT_CHILD 1
  87.  
  88. #define FALSE 0             /* As usual */
  89. #define TRUE 1
  90. #define UNEVALUATED 2       /* We complete the lattice of boolean functions */
  91. #define ATREE_ERROR 3       /* Don't want conflict with Windows.h ERROR */
  92.  
  93. #define MAX_RETRY 50        /* No. of retrys before an error in atree_rand_walk */
  94.  
  95.  
  96. /* Number of nodes/leaves to allocate in each call to malloc in get_node() */
  97.  
  98. #define NEWMALLOC   1024
  99.  
  100. #define BYTE 8     /*length of a byte in bits*/
  101.  
  102. /* Initialisation values */
  103.  
  104. #define MAXSET 63
  105. #define ABOVEMID 32
  106. #define BELOWMID 31
  107. #define MINSET 0
  108.  
  109. #define STACKSIZE 100       /*stack used in load_tree */
  110. #define LEAF_TOKEN 256
  111.  
  112. #define CODING_HEADER_FORMAT "vectors=%d, width=%d, range=%g,%g\n"
  113. #define CODING_HEADER_ITEMS 4
  114.  
  115.  
  116. /* memory manager constants */
  117.  
  118. #define SEGLENGTH 65536L   /* 64K */
  119. #define NUMSEGS 256         /* can manage up to 16384K (16Megs) */
  120.  
  121. /*
  122.  *  Macros
  123.  */
  124.  
  125. #define Printf(str,fmt) {\
  126.                         char string[] = str; \
  127.                         sprintf(szBuffer,string,fmt);\
  128.                         }
  129.  
  130. /* Public and private procedures */
  131.  
  132. #define public
  133. #define private static
  134.  
  135. /* Infinite loops - for EVER */
  136.  
  137. #define EVER (;;)
  138.  
  139. /* Printing out the boolean lattice */
  140.  
  141. #define PRINTBOOL(b) if (b == TRUE) {Printf("1",0);} else if (b == FALSE)\
  142.     {Printf("0",0);} else if (b == UNEVALUATED) {Printf("U",0);} else \
  143.     if (b == ATREE_ERROR) {Printf("E",0);} else {Printf("?",0);}
  144.  
  145. /* Verbosity */
  146.  
  147. #define VERBOSE(level,s) if (verbosity >= level) {s ;}
  148.  
  149.  
  150. /*
  151.  * Types
  152.  */
  153.  
  154. typedef int bool_t;       /*
  155.                            * Only TRUE, FALSE, UNEVALUATED or ATREE_ERROR
  156.                            * are used in these variables
  157.                            */
  158.  
  159. typedef struct token_struct
  160. {
  161.     int token;
  162.     int bit_no;
  163.     int complemented;
  164. } token_t;
  165.  
  166. /*
  167.  * some static variables needed by the atree memory manager
  168.  */
  169.  
  170. /* HANDLE to each segment */
  171. static HANDLE seg[NUMSEGS];
  172.  
  173. /* memory free in each segment */
  174. static WORD freemem[NUMSEGS];
  175.  
  176.  
  177. /*
  178.  * Preliminary Private Procedure Declarations
  179.  */
  180.  
  181. private void NEAR PASCAL        WinMem_Init();
  182. private LPATREE NEAR PASCAL     get_node(int);
  183. private void NEAR PASCAL        reclaim_node(LPATREE);
  184. private LPATREE NEAR PASCAL     build_tree(LPINT, bool_t far *,int,int);
  185. private void NEAR PASCAL        print_tree(LPATREE, int, int, int);
  186. private bool_t NEAR PASCAL      train(LPATREE, LPBIT_VEC, bool_t);
  187. private void NEAR PASCAL        adapt(LPATREE, LPBIT_VEC, bool_t);
  188. private char NEAR PASCAL        node_function(LPATREE);
  189. private void NEAR PASCAL        compress_tree(LPATREE,LPFAST_TREE,LPFAST_TREE,LPFAST_TREE,LPINT);
  190. private int NEAR PASCAL         count_leaves(LPATREE, int);
  191. private int NEAR PASCAL         store_tree(LPATREE, FILE *);
  192. private int NEAR PASCAL         get_token(FILE *, token_t far *);
  193.  
  194. #pragma argsused
  195.  
  196. HANDLE hVerbInstance;
  197. HWND hwnd;
  198. char szVerbLine1[60];
  199. char szVerbLine2[60];
  200. char szVerbLine3[60];
  201. short cyChar;
  202.  
  203. BOOL atree_quit_flag = FALSE;
  204.  
  205.  
  206. long FAR PASCAL VerbosityWndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
  207.     {
  208.     static short cxChar, cxCaps;
  209.     char szBuffer[10];
  210.     HDC hdc;
  211.     short i;
  212.     PAINTSTRUCT ps;
  213.     TEXTMETRIC tm;
  214.  
  215.     switch (message)
  216.         {
  217.         case WM_CREATE:
  218.             hdc = GetDC(hwnd);
  219.  
  220.             GetTextMetrics(hdc, &tm);
  221.             cxChar = tm.tmAveCharWidth;
  222.             cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
  223.             cyChar = tm.tmHeight + tm.tmExternalLeading ;
  224.  
  225.             ReleaseDC(hwnd,hdc);
  226.             return 0;
  227.  
  228.         case WM_PAINT:
  229.  
  230.             hdc = BeginPaint(hwnd, &ps);
  231.  
  232.             TextOut (hdc, 5 * cxChar, cyChar * 6, szVerbLine1, lstrlen(szVerbLine1));
  233.             TextOut (hdc, 5 * cxChar, cyChar * 7, szVerbLine2, lstrlen(szVerbLine2));
  234.             TextOut (hdc, 5 * cxChar, cyChar * 8, szVerbLine3, lstrlen(szVerbLine3));
  235.  
  236.             EndPaint(hwnd, &ps);
  237.  
  238.             return 0;
  239.  
  240.         case WM_DESTROY:
  241.             PostQuitMessage(0);
  242.             return 0;
  243.         }
  244.  
  245.     return DefWindowProc(hwnd,message, wParam, lParam);
  246.     }
  247.  
  248. /*****************************************************************************
  249.  *****************************************************************************
  250.  ****                                                                     ****
  251.  ****                        Public Routines                              ****
  252.  ****                                                                     ****
  253.  *****************************************************************************
  254.  *****************************************************************************/
  255.  
  256.  
  257. /*****************************************************************************
  258.  ****                                                                     ****
  259.  **** void FAR PASCAL atree_init()                                        ****
  260.  ****                                                                     ****
  261.  **** Synopsis:                                                           ****
  262.  ****                                                                     ****
  263.  **** Initialises various global variables, and makes an initial call to  ****
  264.  **** the random number seed routine.  Checks to make sure Windows is in  ****
  265.  **** protect mode.                                                       ****
  266.  ****                                                                     ****
  267.  *****************************************************************************/
  268.  
  269. public void FAR PASCAL
  270. atree_init(hInstance)
  271.  
  272. HANDLE hInstance;
  273.  
  274. {
  275.     DWORD   c;
  276.     static BOOL first = TRUE;
  277.     WNDCLASS wndclass;
  278.     static char cInstance[40];
  279.  
  280.     if (first)
  281.     {
  282.         first = FALSE;
  283.  
  284.         itoa(hInstance, cInstance, 10);
  285.  
  286.         hVerbInstance = hInstance;
  287.  
  288.         wndclass.style          = CS_NOCLOSE;
  289.         wndclass.lpfnWndProc    = VerbosityWndProc;
  290.         wndclass.cbClsExtra     = 0;
  291.         wndclass.cbWndExtra     = 0;
  292.         wndclass.hInstance      = hInstance;
  293.         wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
  294.         wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  295.         wndclass.hbrBackground  = GetStockObject(WHITE_BRUSH);
  296.         wndclass.lpszMenuName   = NULL;
  297.         wndclass.lpszClassName  = (LPSTR) cInstance;
  298.  
  299.         RegisterClass(&wndclass);
  300.  
  301.         c = GetTickCount();
  302.         (void) srand((int) c);
  303.  
  304.         c = GetWinFlags();
  305.         if (!(c & WF_PMODE))
  306.             {
  307.             MessageBox(NULL, "Atree software cannot run\nin Windows Real Mode!",
  308.                        "Not in Protected Mode!", MB_OK | MB_ICONSTOP);
  309.             exit(0);
  310.             }
  311.  
  312.         hwnd = CreateWindow((LPSTR)cInstance, "atree Status",
  313.                                         WS_OVERLAPPEDWINDOW,
  314.                                         CW_USEDEFAULT, CW_USEDEFAULT,
  315.                                         300, 180,
  316.                                         NULL, NULL, hVerbInstance, NULL);
  317.         }
  318.         return;
  319. }
  320.  
  321.  
  322. /*****************************************************************************
  323.  ****                                                                     ****
  324.  **** void atree_quit()                                                   ****
  325.  ****                                                                     ****
  326.  **** sets the quit flag for use by other atree routines when an exit     ****
  327.  **** is desired                                                          ****
  328.  *****************************************************************************/
  329.  
  330. void FAR PASCAL
  331. atree_quit(void)
  332.  
  333. {
  334.     atree_quit_flag = TRUE;
  335. //    DestroyWindow(hwnd);
  336. }
  337.  
  338.  
  339. /*****************************************************************************
  340.  ****                                                                     ****
  341.  **** LPBIT_VEC atree_rand_walk(num,width,p)                              ****
  342.  ****                                                                     ****
  343.  **** int num;                                                            ****
  344.  **** int width;                                                          ****
  345.  **** int p;                                                              ****
  346.  ****                                                                     ****
  347.  **** Synopsis:                                                           ****
  348.  ****                                                                     ****
  349.  **** Creates an array of _num_ binary vectors, of _width_ bits where     ****
  350.  **** each is _p_ bits away from its neighbours in Hamming space. Each    ****
  351.  **** vector is unique.                                                   ****
  352.  **** This routine returns NULL if it's unable to find enough vectors.    ****
  353.  *****************************************************************************/
  354.  
  355. #pragma warn -pia
  356.  
  357. public LPBIT_VEC FAR PASCAL
  358. atree_rand_walk(num,width,p)
  359.  
  360. int num;
  361. int width;
  362. int p;
  363.  
  364. {
  365.     /*
  366.      * An initial vector is produced with random bits, and each subsequent
  367.      * vector in the random walk just has _p_ bits flipped. In order to
  368.      * guarantee that each vector is unique, it is checked against
  369.      * a chained list of vectors of the same bit sum. If it is not already
  370.      * in the chain it is appended to the end, or else the vector is discarded
  371.      * and the process repeats itself.
  372.      */
  373.  
  374.     LPBIT_VEC   walk;            /* An array of bit vectors */
  375.     LPBIT_VEC   pckd_vec;          /* The packed unique ? vector */
  376.     bool_t      unique;            /* Uniqueness flag set during testing */
  377.     LPINT       bit_sum_chain;     /* Pointers to vectors of equivalent bit sums */
  378.     LPINT       next_vec;          /* Chain array */
  379.     LPSTR       unpckd_vec;        /* An unpacked vector */
  380.     LPSTR       this_vec;          /* An unpacked vector */
  381.     LPSTR       mark_vec;          /* TRUE where a bit has been flipped */
  382.     int         i;
  383.     int         j;
  384.     int         old_bit_sum;       /* Last number of TRUE bits in vector */
  385.     int         bit_sum;           /* Current number of TRUE bits in vector */
  386.     int         retrys;            /* Number of attempts to find a unique vec */
  387.     int         victim;            /* The bit just twiddled */
  388.     int         current_vec;       /* Part of the chain */
  389.  
  390.     assert(num > 0);
  391.     assert(width > 0);
  392.     assert((p > 0) && (p <= width));
  393.  
  394.     /* Assign space in memory */
  395.  
  396.     walk = (LPBIT_VEC) Malloc((unsigned) num * sizeof(bit_vec));
  397.     MEMCHECK(walk);
  398.  
  399.     bit_sum_chain = (LPINT) Malloc((unsigned) (width+1) * sizeof(int));
  400.     MEMCHECK(bit_sum_chain);
  401.  
  402.     next_vec = (LPINT) Malloc((unsigned) num * sizeof(int));
  403.     MEMCHECK(next_vec);
  404.  
  405.     unpckd_vec = (LPSTR) Malloc((unsigned) width * sizeof(char));
  406.     MEMCHECK(unpckd_vec);
  407.  
  408.     this_vec = (LPSTR) Malloc((unsigned) width * sizeof(char));
  409.     MEMCHECK(this_vec);
  410.  
  411.     mark_vec = (LPSTR) Malloc((unsigned) width * sizeof(char));
  412.     MEMCHECK(mark_vec);
  413.  
  414.     /* Clear bit_sum_chain */
  415.  
  416.     for (i = 0; i <= width; i++)
  417.     {
  418.         bit_sum_chain[i] = -1;
  419.     }
  420.  
  421.     /* Clear next_vec */
  422.  
  423.     for (i = 0; i < num; i++)
  424.     {
  425.         next_vec[i] = -1;
  426.     }
  427.  
  428.     /* Create initial vector and bit sum */
  429.  
  430.     old_bit_sum = 0;
  431.     for (i = 0; i < width; i++)
  432.     {
  433.         if (unpckd_vec[i] = RANDOM(2))
  434.         {
  435.            old_bit_sum++;
  436.         }
  437.     }
  438.  
  439.     walk[0] = *(bv_pack(unpckd_vec,width));
  440.     bit_sum_chain[old_bit_sum] = 0;
  441.  
  442.     /* Random walk */
  443.  
  444.     for (i = 1; i < num; i++)
  445.     {
  446.  
  447.         /* allow multitasking */
  448.         Windows_Interrupt(1000);
  449.  
  450.         retrys = 0;
  451.         unique = FALSE;
  452.         while ((!unique) && (retrys < MAX_RETRY))
  453.         {
  454.             retrys++;
  455.  
  456.             /* Make a new vector */
  457.  
  458.             bit_sum = old_bit_sum;
  459.             for (j = 0; j < width; j++)
  460.             {
  461.                 this_vec[j] = unpckd_vec[j];
  462.                 mark_vec[j] = FALSE;
  463.             }
  464.  
  465.             for (j = 0; j < p; j++)
  466.             {
  467.                 do
  468.                 {
  469.                     victim = RANDOM(width);
  470.                 }
  471.                 while (mark_vec[victim]);
  472.  
  473.                 mark_vec[victim] = TRUE;
  474.                 this_vec[victim] = !this_vec[victim];
  475.                 if (this_vec[victim] == FALSE)
  476.                 {
  477.                     bit_sum--;
  478.                 }
  479.                 else
  480.                 {
  481.                     bit_sum++;
  482.                 }
  483.             }
  484.  
  485.             pckd_vec = bv_pack(this_vec,width);
  486.  
  487.             /* Compare it with the existing ones of equal bit length */
  488.  
  489.             if (bit_sum_chain[bit_sum] == -1)
  490.             {
  491.                 /* There are no other vectors with this bit sum, so ... */
  492.  
  493.                 unique = TRUE;
  494.                 walk[i] = *pckd_vec;
  495.                 bit_sum_chain[bit_sum] = i;     
  496.                 next_vec[i] = -1;
  497.             }
  498.             else
  499.             {
  500.                 current_vec = bit_sum_chain[bit_sum];
  501.                 for EVER /* We break out of here inside the loop */ 
  502.                 { 
  503.                     if (bv_equal(&(walk[current_vec]),pckd_vec))
  504.                     {
  505.                         /* This vector already exists,  unique = FALSE; */
  506.                         break;
  507.                     }
  508.                     else
  509.                     {
  510.                         if (next_vec[current_vec] == -1)
  511.                         {
  512.                             unique = TRUE;
  513.                             walk[i] = *pckd_vec;
  514.                             next_vec[current_vec] = i;
  515.                             next_vec[i] = -1;
  516.                             break;
  517.                         }
  518.                         else
  519.                         {
  520.                             current_vec = next_vec[current_vec];
  521.                         }
  522.                     }
  523.                 } /* for EVER */
  524.             } /* if (bit_sum_chain...) */
  525.         } /* while ((!unique... ))*/
  526.  
  527.         /*
  528.          * If Unique is TRUE at this point, we have a unique
  529.          * vector stored, we have to set up old_bit sum and unpckd_vec
  530.          * for the next vector.
  531.          * If unique is FALSE, we have tried to create a unique vector
  532.          * MAX_RETRY times, and failed. We therefore signal an error.
  533.          */
  534.  
  535.         if (unique)
  536.         {
  537.             for (j = 0; j < width; j++)
  538.             {
  539.                 unpckd_vec[j] = this_vec[j];
  540.             }
  541.             old_bit_sum = bit_sum;
  542.         }
  543.         else
  544.         {
  545.             (void) Free(walk);
  546.             walk = NULL;
  547.             break;
  548.         }
  549.     } /* for */
  550.  
  551.  
  552.     /* Free space in memory */
  553.  
  554.     Free(bit_sum_chain);
  555.     Free(next_vec);
  556.     Free(unpckd_vec);
  557.     Free(this_vec);
  558.     Free(mark_vec);
  559.  
  560.     /* Return final vector */
  561.  
  562.     return(walk);
  563. }
  564.  
  565. #pragma warn .pia
  566.  
  567. /*****************************************************************************
  568.  ****                                                                     ****
  569.  **** LPATREE atree_create(numvars,leaves)                                ****
  570.  ****                                                                     ****
  571.  **** int numvars;                                                        ****
  572.  **** int leaves;                                                         ****
  573.  ****                                                                     ****
  574.  **** Synopsis:                                                           ****
  575.  ****                                                                     ****
  576.  **** Creates an adaptive tree with _leaves_ number of leaves connected   ****
  577.  **** to _numvars_  variables and their complements.  The number of       ****
  578.  **** leaves should probably be at least twice _numvars_.                 ****
  579.  **** The node functions and the connections are picked at random.        ****
  580.  ****                                                                     ****
  581.  *****************************************************************************/
  582.  
  583. public LPATREE FAR PASCAL
  584. atree_create(numvars,leaves)
  585.  
  586. int numvars;
  587. int leaves;
  588.  
  589. {
  590.     LPATREE     tree;
  591.     LPINT       connection;
  592.     bool_t far  *complemented;
  593.     bool_t      comp;
  594.     int         i;
  595.  
  596.     assert(leaves > 0);
  597.     assert(numvars > 0);
  598.  
  599.     /*
  600.      * Create a list of bit inputs and shuffle, complemented inputs
  601.      * are marked with a TRUE in the complemented array.
  602.      */
  603.  
  604.     connection = (LPINT) Malloc((unsigned) sizeof(int) * leaves);
  605.     MEMCHECK(connection);
  606.     complemented = (bool_t far *) Malloc((unsigned) sizeof(int) * leaves);
  607.     MEMCHECK(complemented);
  608.  
  609.     comp = FALSE;
  610.     for (i = 0; i < leaves; i++)
  611.     {
  612.         int numvarscount = i % numvars;
  613.         if (numvarscount == 0)
  614.         {
  615.             comp = !comp;
  616.         }
  617.         connection[i] = numvarscount;
  618.         complemented[i] = comp;
  619.     }
  620.  
  621.     /* Shuffle */
  622.  
  623.     for (i = 0; i < leaves; i++)
  624.     {
  625.         int a;
  626.         int b;
  627.         int tmp;
  628.  
  629.         a = RANDOM(leaves);
  630.         b = RANDOM(leaves);
  631.         tmp = connection[a];
  632.         connection[a] = connection[b];
  633.         connection[b] = tmp;
  634.         tmp = complemented[a];
  635.         complemented[a] = complemented[b];
  636.         complemented[b] = tmp;
  637.     }
  638.  
  639.     tree = build_tree(connection, complemented, 0, leaves - 1);
  640.  
  641.     (void) Free(connection);
  642.     (void) Free(complemented);
  643.  
  644.     return(tree);
  645. }
  646.  
  647.  
  648. /*****************************************************************************
  649.  ****                                                                     ****
  650.  **** BOOL atree_eval(tree,vec)                                           ****
  651.  ****                                                                     ****
  652.  **** LPATREE tree;                                                       ****
  653.  **** LPBIT_VEC vec;                                                      ****
  654.  ****                                                                     ****
  655.  **** Synopsis:                                                           ****
  656.  ****                                                                     ****
  657.  **** Applies the _tree_ to the bit vector _vec_ and returns the result,  ****
  658.  **** 1 for true, and 0 for false.                                        ****
  659.  *****************************************************************************/
  660.  
  661. #pragma warn -pia
  662.  
  663. public BOOL FAR PASCAL
  664. atree_eval(tree,vec)
  665.  
  666. LPATREE tree;
  667. LPBIT_VEC vec;
  668.  
  669. {
  670.     register bool_t result;
  671.  
  672.     switch (tree -> c_tag)
  673.     {
  674.     case AND:
  675.         tree -> n_sig_right = UNEVALUATED;
  676.         result = (tree -> n_sig_left =
  677.                      atree_eval(tree -> n_child[LEFT_CHILD], vec))
  678.               && (tree -> n_sig_right =
  679.                      atree_eval(tree -> n_child[RIGHT_CHILD], vec));
  680.         break;
  681.  
  682.     case RIGHT:
  683.         tree -> n_sig_left = UNEVALUATED;
  684.         result = (tree -> n_sig_right =
  685.                      atree_eval(tree -> n_child[RIGHT_CHILD], vec));
  686.         break;
  687.  
  688.     case LEFT:
  689.         tree -> n_sig_right = UNEVALUATED;
  690.         result = (tree -> n_sig_left =
  691.                      atree_eval(tree -> n_child[LEFT_CHILD], vec));
  692.         break;
  693.  
  694.     case OR:
  695.         tree -> n_sig_right = UNEVALUATED;
  696.         result = (tree -> n_sig_left =
  697.                      atree_eval(tree -> n_child[LEFT_CHILD], vec))
  698.               || (tree -> n_sig_right =
  699.                      atree_eval(tree -> n_child[RIGHT_CHILD], vec));
  700.         break;
  701.  
  702.     case LEAF:
  703.         result = bv_extract((int) tree -> l_bit_no, vec) != tree -> l_comp;
  704.         break;
  705.  
  706.     }
  707.  
  708.     return(result);
  709. }
  710.  
  711. #pragma warn .pia
  712.  
  713. /*****************************************************************************
  714.  ****                                                                     ****
  715.  **** BOOL atree_train(tree,tset,correct_result,bit_col,tset_size,        ****
  716.  ****                  no_correct,epochs,verbosity)                       ****
  717.  ****                                                                     ****
  718.  **** LPATREE tree;                                                       ****
  719.  **** LPBIT_VEC tset;                                                     ****
  720.  **** LPBIT_VEC correct_result;                                           ****
  721.  **** int bit_col;                                                        ****
  722.  **** int tset_size;                                                      ****
  723.  **** int no_correct;                                                     ****
  724.  **** int epochs;                                                         ****
  725.  **** int verbosity;                                                      ****
  726.  ****                                                                     ****
  727.  **** Synopsis:                                                           ****
  728.  ****                                                                     ****
  729.  **** This routine is the heart of the library. It takes an atree _tree_  ****
  730.  **** to be trained, an array of input vectors _tset_, an array of        ****
  731.  **** vectors, _correct_result_ where each bit column holds a correct bit ****
  732.  **** result for each vector in _tset_. [Note: Only a single vector is    ****
  733.  **** actually required here, but doing it this way make life convenient  ****
  734.  **** for training collections of trees for real numbers] An integer      ****
  735.  **** _bit_col_ denoting the column to be trained on. Another integer     ****
  736.  **** _test_size gives the size of both the _tset_ and _correct_result_   ****
  737.  **** arrays.                                                             ****
  738.  ****                                                                     ****
  739.  **** The _tree_ is trained until the number of vectors presented in      ****
  740.  **** _tset_ equals _epoch_ epochs, or the last presentation of the number****
  741.  **** in an epoch had at least _no_correct_ presentations.                ****
  742.  **** The _verbosity_ is currently 0 or 1.                                ****
  743.  **** The routine returns TRUE if it stopped because it succeeded         ****
  744.  **** _no_correct_ times.                                                 ****
  745.  ****                                                                     ****
  746.  *****************************************************************************/
  747.  
  748. public BOOL FAR PASCAL
  749. atree_train(tree,tset,correct_result,bit_col,tset_size,no_correct,
  750.             epochs,verbosity)
  751.  
  752. LPATREE tree;
  753. LPBIT_VEC tset;
  754. LPBIT_VEC correct_result;
  755. int bit_col;
  756. int tset_size;
  757. int no_correct;
  758. int epochs;
  759. int verbosity;
  760.  
  761. {
  762.     bool_t      no_correct_flag = FALSE;
  763.     LPINT       vec_list;
  764.     int         i;
  765.     int         j;
  766.     int         cor_this_epoch;
  767.     int         vec_num;
  768.     LPBIT_VEC   vec;
  769.     char        szBuff1[60];
  770.     char        szBuff2[60];
  771.  
  772.     /* For the specified number of epochs */
  773.     VERBOSE(1,  lstrcpy(szVerbLine1,  "Beginning Training...");
  774.                 lstrcpy(szVerbLine2, " ");
  775.                 lstrcpy(szVerbLine3, " ");
  776.                 ShowWindow(hwnd, SW_SHOW);
  777.                 UpdateWindow(hwnd)
  778.            );
  779.  
  780.     vec_list = (LPINT) Malloc((unsigned) sizeof(int) * tset_size);
  781.     MEMCHECK(vec_list);
  782.  
  783.     for (i = 0; i < tset_size; i++)
  784.     {
  785.         vec_list[i] = i;
  786.     }
  787.  
  788.     for (i = 0; i < epochs; i++)
  789.     {
  790.         cor_this_epoch = 0;
  791.  
  792.         VERBOSE(1,wsprintf(szBuff1,"Epoch : %d                    ",i));
  793.  
  794.         /* Shuffle */
  795.  
  796.         for (j = 0; j < tset_size; j++)
  797.         {
  798.             int a;
  799.             int b;
  800.             int tmp;
  801.  
  802.             a = RANDOM(tset_size);
  803.  
  804.             do
  805.             {
  806.                 b = RANDOM(tset_size);
  807.             }
  808.             while (a == b);
  809.  
  810.             tmp = vec_list[a];
  811.             vec_list[a] = vec_list[b];
  812.             vec_list[b] = tmp;
  813.         }
  814.  
  815.  
  816.         /* For the elements of the test set */
  817.  
  818.         for (j = 0; j < tset_size; j++)
  819.         {
  820.             if (atree_quit_flag) return(FALSE);  /* check if exit requested */
  821.  
  822.             /* Pick a random vector */
  823.  
  824.             vec_num = vec_list[j];
  825.             vec = tset + vec_num;
  826.  
  827.             /* allow for multitasking */
  828.             Windows_Interrupt(1000);
  829.  
  830.             /* Train the tree */
  831.  
  832.             if (train(tree,vec,(bool_t)bv_extract(bit_col,correct_result + vec_num)))
  833.             {
  834.                 /* The tree succeeded */
  835.  
  836.                 cor_this_epoch++;
  837.                 if (cor_this_epoch == no_correct)
  838.                 {
  839.                     no_correct_flag = TRUE;
  840.                     break; /* out of this epoch */
  841.  
  842.                 } /* if (cor_this...) */
  843.             } /* if (train..) */
  844.         } /* for (j = ..) */
  845.  
  846.         VERBOSE(1,wsprintf(szBuff2,"Estimated number correct was %d   ",cor_this_epoch));
  847.  
  848.         /* If no_correct_flag is TRUE here, its time to stop */
  849.  
  850.         if (no_correct_flag || (i == epochs - 1))
  851.         {
  852.             int correct = 0;
  853.  
  854.             for (j = 0; j < tset_size; j++)
  855.             {
  856.                 if (atree_eval(tree, tset + j)
  857.                     == bv_extract(bit_col, correct_result + j))
  858.                 {
  859.                         correct++;
  860.                 }
  861.             }
  862.  
  863.             VERBOSE(1,wsprintf(szVerbLine3,"Actual number correct was %d   ",correct);
  864.                   lstrcpy(szVerbLine1, szBuff1);
  865.                   lstrcpy(szVerbLine2, szBuff2);
  866.                   ScrollWindow(hwnd, 0, -3 * cyChar, NULL, NULL);
  867.                   InvalidateRect(hwnd, NULL, FALSE);
  868.                   UpdateWindow(hwnd));
  869.  
  870.             if (correct >= no_correct)
  871.             {
  872.                 break; /* out of the epoch loop */
  873.             }
  874.  
  875.         }
  876.         else
  877.         {
  878.             VERBOSE(1,lstrcpy(szVerbLine3,"                                   ");
  879.                   lstrcpy(szVerbLine1, szBuff1);
  880.                   lstrcpy(szVerbLine2, szBuff2);
  881.                   ScrollWindow(hwnd, 0, -3 * cyChar, NULL, NULL);
  882.                   InvalidateRect(hwnd, NULL, FALSE);
  883.                   UpdateWindow(hwnd));
  884.         }
  885.  
  886.     } /* for (i = ...) */
  887.  
  888.     Free(vec_list);
  889.     VERBOSE(1, ShowWindow(hwnd,SW_HIDE));
  890.     return(no_correct_flag);
  891. }
  892.  
  893. /*****************************************************************************
  894.  ****                                                                     ****
  895.  **** (void) atree_print(tree,verbosity)                                  ****
  896.  ****                                                                     ****
  897.  **** LPATREE tree;                                                       ****
  898.  ****                                                                     ****
  899.  **** Synopsis:                                                           ****
  900.  ****                                                                     ****
  901.  **** Prints out a tree for diagnostic and explanation purposes, the      ****
  902.  **** verbosity levels are 0 or above.  Currently, the Windows            ****
  903.  **** implementation outputs to a file called atree.out in the current    ****
  904.  **** directory.                                                          ****
  905.  *****************************************************************************/
  906.  
  907. public void FAR PASCAL
  908. atree_print(tree,verbosity)
  909.  
  910. LPATREE tree;
  911. int verbosity;
  912.  
  913. {
  914.     /*
  915.      * This routine makes an call to the private
  916.      * print tree routine that takes an extra paramater
  917.      * controlling the indentation
  918.      */
  919.  
  920.     int hOut;           /* File Handle */
  921.  
  922.     if((hOut = _lcreat("atree.out", 0)) == -1)
  923.         {
  924.         MessageBox(NULL, "Cannot open ATREE.OUT", "atree_print", MB_OK);
  925.         return;
  926.         }
  927.  
  928.     print_tree(tree,0,verbosity, hOut);
  929.     _lclose(hOut);
  930. }
  931.  
  932.  
  933. /*****************************************************************************
  934.  ****                                                                     ****
  935.  **** void atree_free(tree)                                               ****
  936.  ****                                                                     ****
  937.  **** LPATREE tree;                                                       ****
  938.  ****                                                                     ****
  939.  **** Synopsis:                                                           ****
  940.  ****                                                                     ****
  941.  **** returns the memory used by _tree_ to the freelists                  ****
  942.  *****************************************************************************/
  943.  
  944. public void FAR PASCAL
  945. atree_free(tree)
  946.  
  947. LPATREE tree;
  948.  
  949. {
  950.     if (tree -> c_tag != LEAF)
  951.     {
  952.         atree_free(tree -> n_child[LEFT_CHILD]);
  953.         atree_free(tree -> n_child[RIGHT_CHILD]);
  954.     }
  955.     reclaim_node(tree);
  956. }
  957.  
  958. /*****************************************************************************
  959.  * function: atree_fold
  960.  *
  961.  * This function removes all LEFT and RIGHT nodes from _tree_
  962.  * and returns a pointer to the resulting tree.
  963. ******************************************************************************/
  964.  
  965. public LPATREE FAR PASCAL
  966. atree_fold(tree)
  967.  
  968. LPATREE tree;
  969.  
  970. {
  971.     LPATREE folded_tree;
  972.     int keep;
  973.  
  974.     switch (tree -> c_tag)
  975.     {
  976.     case LEAF:
  977.         folded_tree = tree;
  978.         break;
  979.     case OR:
  980.     case AND:
  981.         tree -> n_child[LEFT_CHILD] = atree_fold(tree -> n_child[LEFT_CHILD]);
  982.         tree -> n_child[RIGHT_CHILD] = atree_fold(tree -> n_child[RIGHT_CHILD]);
  983.         folded_tree = tree;
  984.         break;
  985.     case LEFT:
  986.     case RIGHT:
  987.         keep = (tree -> c_tag == LEFT) ? LEFT_CHILD : RIGHT_CHILD;
  988.         folded_tree = atree_fold(tree -> n_child[keep]);
  989.         atree_free(tree -> n_child[!keep]);
  990.         reclaim_node(tree);
  991.         break;
  992.     default:
  993.         assert(0);
  994.     }
  995.  
  996.     return(folded_tree);
  997. }
  998.  
  999. /******************************************************************************
  1000.  * function: atree_compress
  1001.  *
  1002.  * This function converts an atree to a fast_tree.
  1003.  * See the commentary for the private function
  1004.  * compress_tree for more information.
  1005. ******************************************************************************/
  1006. public LPFAST_TREE FAR PASCAL
  1007. atree_compress(tree)
  1008.  
  1009. LPATREE tree;
  1010. {
  1011.     LPFAST_TREE ftree;
  1012.     int leaf_num;
  1013.     int leaf_count = count_leaves(tree, TRUE);
  1014.  
  1015.     ftree = (LPFAST_TREE) Malloc((unsigned) (leaf_count + 1) * sizeof(fast_tree));
  1016.     MEMCHECK(ftree);
  1017.     ftree[leaf_count].bit_no = -1;  /* mark end */
  1018.     leaf_num = leaf_count - 1;
  1019.     compress_tree(tree, NULL, NULL, ftree, (LPINT) &leaf_num);
  1020.     return(ftree);
  1021. }
  1022.  
  1023. /******************************************************************************
  1024.  * function: atree_fast_eval
  1025.  *
  1026.  * This function is the fast_tree equivalent of atree_eval.
  1027. ******************************************************************************/
  1028. public int FAR PASCAL
  1029. atree_fast_eval(tree, vec)
  1030.  
  1031. LPFAST_TREE tree;
  1032. LPBIT_VEC vec;
  1033.  
  1034. {
  1035.     register int result;
  1036.  
  1037.     do
  1038.     {
  1039.         result = bv_extract(tree -> bit_no, vec) != tree -> comp;
  1040.     } while ((tree = tree -> next[result]) != NULL);
  1041.  
  1042.     return(result);
  1043. }
  1044.  
  1045. /******************************************************************************
  1046. * function atree_fast_print : outputs to file called fasttree.out
  1047. ******************************************************************************/
  1048. public void FAR PASCAL
  1049. atree_fast_print(ftree)
  1050.  
  1051. LPFAST_TREE ftree;
  1052.  
  1053. {
  1054.     int i;
  1055.     int hOut;           /* File Handle */
  1056.     char szBuffer[80];
  1057.  
  1058.     if((hOut = _lcreat("fasttree.out", 0)) == -1)
  1059.         {
  1060.         MessageBox(NULL, "Cannot open FASTTREE.OUT", "atree_fast_print", MB_OK);
  1061.         return;
  1062.         }
  1063.  
  1064.     for (i = 0; ftree[i].bit_no >= 0; i++)
  1065.     {
  1066.         wsprintf((LPSTR)szBuffer,"[%3d] bit=%c%d, next[0]=%d, next[1]=%d\r\n",
  1067.                i, ftree[i].comp ? '!' : '\0', ftree[i].bit_no,
  1068.                ftree[i].next[0] ? ftree[i].next[0] - ftree : -1,
  1069.                ftree[i].next[1] ? ftree[i].next[1] - ftree : -1);
  1070.  
  1071.         _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
  1072.  
  1073.     }
  1074.  
  1075.     _lclose(hOut);
  1076. }
  1077.  
  1078. /******************************************************************************
  1079.  * function: atree_set_code
  1080.  *
  1081.  * This is the constructor for type code_t.
  1082.  * Returns non-zero on failure.
  1083. ******************************************************************************/
  1084. public int FAR PASCAL
  1085. atree_set_code(code, low, high, count, width, dist)
  1086.  
  1087. LPCODE_T code;
  1088. double low;
  1089. double high;
  1090. int count;
  1091. int width;
  1092. int dist;
  1093.  
  1094. {
  1095.     int error = FALSE;
  1096.  
  1097.     static LPBIT_VEC zero_vec = NULL;
  1098.     static LPBIT_VEC one_vec = NULL;
  1099.  
  1100.     assert(low < high);
  1101.     assert(count > 1);
  1102.     assert(width > 0);
  1103.     assert(dist > 0);
  1104.  
  1105.     code -> width = width;
  1106.     code -> low = low;
  1107.     code -> high = high;
  1108.  
  1109.     if (width == 1)         /* boolean */
  1110.     {
  1111.         code -> vector = (LPBIT_VEC) Malloc((unsigned) sizeof(bit_vec) * 2);
  1112.         MEMCHECK(code -> vector);
  1113.         if (zero_vec == NULL)
  1114.         {
  1115.             zero_vec = bv_create(1);
  1116.             one_vec = bv_create(1);
  1117.             bv_set(0, zero_vec, 0);
  1118.             bv_set(0, one_vec, 1);
  1119.         }
  1120.         code -> vector[0] = *zero_vec;
  1121.         code -> vector[1] = *one_vec;
  1122.         code -> vector_count = 2;
  1123.         code -> step = high - low;
  1124.     }
  1125.     else
  1126.     {
  1127.         if ((code -> vector = atree_rand_walk(count, width, dist)) == NULL)
  1128.         {
  1129.             error = TRUE;
  1130.         }
  1131.         code -> vector_count = count;
  1132.         code -> step = (high - low) / (count -1);
  1133.     }
  1134.     return(error);
  1135. }
  1136.  
  1137. /******************************************************************************
  1138.  * atree_encode:
  1139.  *
  1140.  * returns the quantization level corresponding to the floating point
  1141.  * value _x_.  To get the bit vector, use the expression:
  1142.  *
  1143.  *   code -> vector + atree_encode(x, code)
  1144. ******************************************************************************/
  1145.  
  1146. public int FAR PASCAL
  1147. atree_encode(x, code)
  1148.  
  1149. double x;
  1150. LPCODE_T code;
  1151.  
  1152. {
  1153.     int index;
  1154.     char szBuffer[80];
  1155.  
  1156.     if (code -> width == 1)
  1157.     {
  1158.         index = x > (code -> low + code -> high) / 2;
  1159.     }
  1160.     else if (x < code -> low)
  1161.     {
  1162.         Printf("warning: argument out of range: %g\n", x);
  1163.         MessageBox(NULL,szBuffer,"atree_encode",MB_OK | MB_ICONEXCLAMATION);
  1164.         index = 0;
  1165.     }
  1166.     else if (x > code -> high)
  1167.     {
  1168.         Printf("warning: argument out of range: %g\n", x);
  1169.         MessageBox(NULL,szBuffer,"atree_encode",MB_OK | MB_ICONEXCLAMATION);
  1170.         index = code -> vector_count - 1;
  1171.     }
  1172.     else if (x == code -> high)
  1173.     {
  1174.         index = code -> vector_count - 1;
  1175.     }
  1176.     else
  1177.     {
  1178.         double temp = (x - code->low) / code->step;
  1179.         index = (int)(temp);
  1180.     }
  1181.  
  1182.     return(index);
  1183. }
  1184.  
  1185. /******************************************************************************
  1186.  * atree_decode:
  1187.  *
  1188.  * returns the quantization level corresponding to the bit vector
  1189.  * _vec_.  To get the corresponding floating point value, use the
  1190.  * expression:
  1191.  *
  1192.  *   code -> low + code -> step * atree_decode(vec, code)
  1193. ******************************************************************************/
  1194.  
  1195. public int FAR PASCAL
  1196. atree_decode(vec, code)
  1197.  
  1198. LPBIT_VEC vec;
  1199. LPCODE_T code;
  1200.  
  1201. {
  1202.     int closest = 0;
  1203.  
  1204.     if (code->width == 1)               /*boolean*/
  1205.     {
  1206.         closest = bv_extract(0, vec);
  1207.     }
  1208.     else
  1209.     {
  1210.         int i;
  1211.         int diff;
  1212.         int closest_bit_diff = code -> width;
  1213.  
  1214.         for (i = 0; i < code -> vector_count; i++)
  1215.         {
  1216.             if ((diff = bv_diff(vec, code -> vector + i)) < closest_bit_diff)
  1217.             {
  1218.                 closest_bit_diff = diff;
  1219.                 closest = i;
  1220.             }
  1221.         }
  1222.     }
  1223.     return(closest);
  1224. }
  1225.  
  1226.  
  1227. /******************************************************************************
  1228.  * atree I/O routines.
  1229. ******************************************************************************/
  1230.  
  1231. public int FAR PASCAL
  1232. atree_store(tree, filename)
  1233.  
  1234. LPATREE tree;
  1235. LPSTR filename;
  1236. {
  1237.     FILE *fp;
  1238.     PSTR fname;
  1239.     char szBuffer[60];
  1240.  
  1241.     lstrcpy((LPSTR)fname, filename);
  1242.  
  1243.     if ((fp = (FILE *) fopen(fname, "w")) == NULL)
  1244.     {
  1245.         Printf("Unable to open %s", fname);
  1246.         MessageBox(NULL,szBuffer,"atree_store",MB_OK | MB_ICONEXCLAMATION);
  1247.         return(-1);
  1248.     }
  1249.     atree_write(fp, tree);
  1250.     fclose(fp);
  1251.     return(0);
  1252. }
  1253.  
  1254. public LPATREE FAR PASCAL
  1255. atree_load(filename)
  1256.  
  1257. LPSTR filename;
  1258.  
  1259. {
  1260.     FILE *fp;
  1261.     LPATREE tree;
  1262.     PSTR fname;
  1263.     char szBuffer[60];
  1264.  
  1265.     lstrcpy((LPSTR)fname, filename);
  1266.  
  1267.     if ((fp = (FILE *) fopen(fname, "r")) == NULL)
  1268.     {
  1269.         Printf("Unable to open %s", fname);
  1270.         MessageBox(NULL,szBuffer,"atree_store",MB_OK | MB_ICONEXCLAMATION);
  1271.         return(NULL);
  1272.     }
  1273.     tree = atree_read(fp);
  1274.     fclose(fp);
  1275.     return(tree);
  1276. }
  1277.  
  1278. /******************************************************************************
  1279.  * function: atree_write
  1280.  *
  1281.  * Stores a single _tree_ onto _stream_.
  1282.  * returns 0 for success, 1 on failure.
  1283. ******************************************************************************/
  1284. public int FAR PASCAL
  1285. atree_write(stream, tree)
  1286.  
  1287. FILE *stream;
  1288. LPATREE tree;
  1289.  
  1290. {
  1291.     return store_tree(tree, stream) || fprintf(stream, ";\n") == EOF;
  1292. }
  1293.  
  1294. /******************************************************************************
  1295.  * function: atree_read
  1296.  *
  1297.  * Reads tree stored in postfix notation.  Valid symbols are:
  1298.  * '&', '|', 'L', 'R' (AND, OR, LEFT, and RIGHT respectively),
  1299.  * and numerals (representing bit numbers) optionally preceded
  1300.  * by a '!' for negation.  Returns NULL if any error or EOF is
  1301.  * encountered.  A file may store multiple trees, each tree is
  1302.  * separated by a ';'.
  1303. ******************************************************************************/
  1304. public LPATREE FAR PASCAL
  1305. atree_read(stream)
  1306.  
  1307. FILE *stream;
  1308.  
  1309. {
  1310.     token_t t;
  1311.     LPATREE node = NULL;
  1312.     int error = 0;
  1313.     char szBuffer[80];
  1314.  
  1315.     LPATREE stack[STACKSIZE];
  1316.     int top = 0;
  1317. #define ITEMS       top
  1318. #define PUSH(node)  stack[top++] = (node)
  1319. #define POP         stack[--top]
  1320.  
  1321.     while ((error = get_token(stream, (token_t far *)&t)) == 0)
  1322.     {
  1323.         if (t.token == EOF || t.token == ';')
  1324.         {
  1325.             break;
  1326.         }
  1327.  
  1328.         if (t.token == LEAF_TOKEN)
  1329.         {
  1330.             node = get_node(LEAF);
  1331.             node -> l_bit_no = t.bit_no;
  1332.             node -> l_comp = t.complemented;
  1333.         }
  1334.         else if (ITEMS < 2)
  1335.         {
  1336.             wsprintf(szBuffer,"too few arguments for %c, offset %ld\n",
  1337.                            t.token, ftell(stream));
  1338.             MessageBox(NULL,szBuffer,"atree_read",MB_OK | MB_ICONEXCLAMATION);
  1339.             error++;
  1340.             break;
  1341.         }
  1342.         else
  1343.         {
  1344.             node = get_node(!LEAF);
  1345.             node -> n_cnt_left = (t.token == '|' || t.token == 'L')
  1346.                                  ? MAXSET : MINSET;
  1347.             node -> n_cnt_right = (t.token == '|' || t.token == 'R')
  1348.                                  ? MAXSET : MINSET;
  1349.             node -> c_tag = node_function(node);
  1350.             node -> n_sig_left = UNEVALUATED;
  1351.             node -> n_sig_right = UNEVALUATED;
  1352.             node -> n_child[RIGHT_CHILD] = POP;
  1353.             node -> n_child[LEFT_CHILD] = POP;
  1354.         }
  1355.  
  1356.         if (ITEMS >= STACKSIZE)
  1357.         {
  1358.             wsprintf(szBuffer, "atree_read: stack overflow\n");
  1359.             MessageBox(NULL,szBuffer,"atree_read",MB_OK | MB_ICONEXCLAMATION);
  1360.             error++;
  1361.             break;
  1362.         }
  1363.         else
  1364.         {
  1365.             PUSH(node);
  1366.         }
  1367.  
  1368.     } /* while */
  1369.  
  1370.     if (!error && ITEMS != 1)
  1371.     {
  1372.         if (t.token == EOF)
  1373.         {
  1374.             wsprintf(szBuffer, "unexpected EOF\n");
  1375.         }
  1376.         else
  1377.         {
  1378.             wsprintf(szBuffer, "unexpected ';', offset %ld\n", ftell(stream));
  1379.         }
  1380.         MessageBox(NULL,szBuffer,"atree_read",MB_OK | MB_ICONEXCLAMATION);
  1381.         error++;
  1382.     }
  1383.  
  1384.     return(error ? NULL : node);
  1385.  
  1386. #undef ITEMS
  1387. #undef PUSH
  1388. #undef POP
  1389. }
  1390.  
  1391. /*
  1392.  * code I/O routines
  1393.  */
  1394.  
  1395. /******************************************************************************
  1396.  * function: atree_write_code
  1397.  *
  1398.  * writes _code_ onto _stream_.
  1399.  * returns 0 for success, 1 on failure.
  1400. ******************************************************************************/
  1401. public int FAR PASCAL
  1402. atree_write_code(stream, code)
  1403.  
  1404. FILE *stream;
  1405. LPCODE_T code;
  1406.  
  1407. {
  1408.     int i;
  1409.     int error;
  1410.  
  1411.     error = fprintf(stream, CODING_HEADER_FORMAT,
  1412.                     code -> vector_count, code -> width,
  1413.                     code -> low, code -> high) == EOF;
  1414.  
  1415.     if (!error && code -> width > 1)
  1416.     {
  1417.         for (i = 0; i < code -> vector_count; i++)
  1418.         {
  1419.             if ((bv_print(stream, code -> vector + i))
  1420.                 || (fprintf(stream, "\n") == 0))
  1421.             {
  1422.                 error = TRUE;
  1423.                 break;
  1424.             }
  1425.         }
  1426.     }
  1427.     return(error);
  1428. }
  1429.  
  1430. public LPCODE_T FAR PASCAL
  1431. atree_read_code(stream, code)
  1432.  
  1433. FILE *stream;
  1434. LPCODE_T code;
  1435. {
  1436.     char *buf;
  1437.     char *p;
  1438.     int i;
  1439.     int error = 0;
  1440.     char szBuffer[80];
  1441.  
  1442.     int count, width;
  1443.     float high, low;
  1444.  
  1445.     if (fscanf(stream, CODING_HEADER_FORMAT,
  1446.                &count, &width,
  1447.                &low, &high) != CODING_HEADER_ITEMS)
  1448.     {
  1449.         wsprintf(szBuffer, "bad header, offset %ld\n", ftell(stream));
  1450.         MessageBox(NULL, szBuffer, "atree_read_code", MB_OK | MB_ICONEXCLAMATION);
  1451.         return(NULL);
  1452.     }
  1453.     else if (count < 2)
  1454.     {
  1455.         wsprintf(szBuffer, "vector count too low, offset %ld\n", ftell(stream));
  1456.         MessageBox(NULL, szBuffer, "atree_read_code", MB_OK | MB_ICONEXCLAMATION);
  1457.         return(NULL);
  1458.     }
  1459.     else if (high <= low)
  1460.     {
  1461.         wsprintf(szBuffer, "bad range, offset %ld\n", ftell(stream));
  1462.         MessageBox(NULL, szBuffer, "atree_read_code", MB_OK | MB_ICONEXCLAMATION);
  1463.         return(NULL);
  1464.     }
  1465.     else if (width < 1)
  1466.     {
  1467.         wsprintf(szBuffer, "width must be at least 1, offset %ld\n", ftell(stream));
  1468.         MessageBox(NULL, szBuffer, "atree_read_code", MB_OK | MB_ICONEXCLAMATION);
  1469.         return(NULL);
  1470.     }
  1471.  
  1472.     code -> vector_count = count;
  1473.     code -> width = width;
  1474.     code -> low = low;
  1475.     code -> high = high;
  1476.  
  1477.     if (code -> width == 1)         /* boolean */
  1478.     {
  1479.         atree_set_code(code, 0.0,   /* low */
  1480.                              1.0,   /* high */
  1481.                              2,     /* count */
  1482.                              1,     /* width */
  1483.                              1);    /* distance */
  1484.     }
  1485.     else
  1486.     {
  1487.         code -> step = (code->high - code->low ) / (code -> vector_count - 1);
  1488.         code -> vector = (LPBIT_VEC) Malloc((unsigned) sizeof(bit_vec) * code -> vector_count);
  1489.         MEMCHECK(code -> vector);
  1490.  
  1491.         buf = (char *) malloc((unsigned) code -> width + 2); /* room for \n and \0 */
  1492.         MEMCHECK(buf);
  1493.  
  1494.         for (i = 0; i < code -> vector_count; i++)
  1495.         {
  1496.             if (fgets(buf, code -> width + 2, stream) == NULL)
  1497.             {
  1498.                 wsprintf(szBuffer,"read error on offset %ld\n", ftell(stream));
  1499.                 MessageBox(NULL, szBuffer, "atree_read_code", MB_OK | MB_ICONEXCLAMATION);
  1500.                 error++;
  1501.                 break;
  1502.             }
  1503.  
  1504.             if (strlen(buf) != code -> width + 1
  1505.             || buf[code -> width] != '\n')
  1506.             {
  1507.                 wsprintf(szBuffer,"inconsistent vector length, offset %ld\n",
  1508.                           ftell(stream));
  1509.                 MessageBox(NULL, szBuffer, "atree_read_code", MB_OK | MB_ICONEXCLAMATION);
  1510.                 error++;
  1511.                 break;
  1512.             }
  1513.             else
  1514.             {
  1515.                 buf[code -> width] = '\0'; /* remove \n */
  1516.             }
  1517.  
  1518.             if (strspn(buf, "01") != code -> width)
  1519.             {
  1520.                 wsprintf(szBuffer,"garbage at offset %ld\n",ftell(stream));
  1521.                 MessageBox(NULL, szBuffer, "atree_read_code", MB_OK | MB_ICONEXCLAMATION);
  1522.                 error++;
  1523.                 break;
  1524.             }
  1525.  
  1526.             /*
  1527.              * prepare the vector for packing
  1528.              */
  1529.             for (p = buf; *p; p++)
  1530.             {
  1531.                 *p -= '0';
  1532.             }
  1533.             code -> vector[i] = *(bv_pack(buf, code -> width));
  1534.         }
  1535.  
  1536.         (void) free(buf);
  1537.         if (error)
  1538.         {
  1539.             (void) Free(code -> vector);
  1540.             code = NULL;
  1541.         }
  1542.     }
  1543.  
  1544.     return(code);
  1545. }
  1546.  
  1547.  
  1548. /*****************************************************************************
  1549.  ****                                                                     ****
  1550.  **** LPBIT_VEC bv_create(length)                                         ****
  1551.  ****                                                                     ****
  1552.  **** int length;                                                         ****
  1553.  ****                                                                     ****
  1554.  **** Synopsis:                                                           ****
  1555.  ****                                                                     ****
  1556.  **** Produces a vector of _length_ bits, each one of which has been set  ****
  1557.  **** to 0                                                                ****
  1558.  *****************************************************************************/
  1559.  
  1560.  
  1561. public LPBIT_VEC FAR PASCAL
  1562. bv_create(length)
  1563.  
  1564. int length;
  1565.  
  1566. {
  1567.     int i;
  1568.     LPBIT_VEC out_vec;
  1569.  
  1570.     assert(length > 0);
  1571.  
  1572.     out_vec = (LPBIT_VEC) Malloc((unsigned)sizeof(bit_vec));
  1573.     MEMCHECK(out_vec);
  1574.  
  1575.     out_vec -> len = length;
  1576.     out_vec -> bv = Malloc((unsigned) (length + BYTE - 1) / BYTE);
  1577.     MEMCHECK(out_vec -> bv);
  1578.  
  1579.     for (i = 0; i < (length + BYTE - 1) / BYTE; i++)
  1580.     {
  1581.         *((out_vec -> bv) + i) = (char) 0;
  1582.     }
  1583.  
  1584.     return(out_vec);
  1585. }
  1586.  
  1587. /*****************************************************************************
  1588.  ****                                                                     ****
  1589.  **** LPBIT_VEC bv_pack(unpacked,length)                                  ****
  1590.  ****                                                                     ****
  1591.  **** LPSTR unpacked;                                                     ****
  1592.  **** int length;                                                         ****
  1593.  ****                                                                     ****
  1594.  **** This routine takes an array _arr_ of zero and one characters        ****
  1595.  **** and returns a packed bit vector suitable for use with the other     ****
  1596.  **** routines in this library.                                           ****
  1597.  *****************************************************************************/
  1598.  
  1599. public LPBIT_VEC FAR PASCAL
  1600. bv_pack(unpacked,length)
  1601.  
  1602. LPSTR unpacked;
  1603. int length;
  1604.  
  1605. {
  1606.     LPBIT_VEC out_vec;
  1607.     LPSTR out_ptr;
  1608.     int i;
  1609.     int j;
  1610.     int bitptr;
  1611.  
  1612.     /* Create the structure */
  1613.  
  1614.     out_vec = (LPBIT_VEC) Malloc((unsigned)sizeof(bit_vec));
  1615.     MEMCHECK(out_vec);
  1616.  
  1617.     out_vec -> len = length;
  1618.     out_vec -> bv = Malloc((unsigned) (length + BYTE - 1) / BYTE);
  1619.     MEMCHECK(out_vec -> bv);
  1620.  
  1621.     /* Pack the vector */
  1622.  
  1623.     out_ptr = out_vec -> bv;
  1624.  
  1625.     bitptr = 0;
  1626.     for (i = 0; i < (length + BYTE - 1) / BYTE; i++)
  1627.     {
  1628.         *out_ptr = 0;
  1629.  
  1630.         for (j = 0; j < BYTE; j++)
  1631.         {
  1632.             if (bitptr < length)
  1633.             {
  1634.                *out_ptr |= (unpacked[bitptr] << j);
  1635.                bitptr++;
  1636.             }
  1637.             else
  1638.             {
  1639.                 break;
  1640.             }
  1641.         }
  1642.         out_ptr++;
  1643.     }
  1644.  
  1645.     /* Return the vector */
  1646.  
  1647.     return(out_vec);
  1648. }
  1649.  
  1650. /*****************************************************************************
  1651.  ****                                                                     ****
  1652.  **** int bv_diff(v1,v2)                                                  ****
  1653.  ****                                                                     ****
  1654.  **** LPBIT_VEC v1;                                                       ****
  1655.  **** LPBIT_VEC v2;                                                       ****
  1656.  ****                                                                     ****
  1657.  **** This function returns the number of bits that are unequal in the    ****
  1658.  **** two vectors. They must be the same number of bits in each vector    ****
  1659.  *****************************************************************************/
  1660.  
  1661. public int FAR PASCAL
  1662. bv_diff(v1,v2)
  1663.  
  1664. LPBIT_VEC v1;
  1665. LPBIT_VEC v2;
  1666. {
  1667.     int diff = 0;
  1668.     int i;
  1669.  
  1670.     assert (v1 -> len == v2 -> len);
  1671.     for (i = 0; i < v1 -> len; i++)
  1672.     {
  1673.         if (bv_extract(i,v1) != bv_extract(i,v2))
  1674.         {
  1675.             diff++;
  1676.         }
  1677.     }
  1678.  
  1679.     return(diff);
  1680. }
  1681.  
  1682. /*****************************************************************************
  1683.  ****                                                                     ****
  1684.  **** LPBIT_VEC bv_concat(n,vectors)                                      ****
  1685.  ****                                                                     ****
  1686.  **** int n;                                                              ****
  1687.  **** LPBIT_VEC *vectors;                                                 ****
  1688.  ****                                                                     ****
  1689.  **** Synopsis:                                                           ****
  1690.  ****                                                                     ****
  1691.  **** Returns the bit vector which is the string concatenation of each    ****
  1692.  **** bit vector in _vector_; _n_ is the number of elements in _vector_.  ****
  1693.  *****************************************************************************/
  1694.  
  1695. public LPBIT_VEC FAR PASCAL
  1696. bv_concat(n,vector)
  1697.  
  1698. int n;
  1699. LPBIT_VEC FAR *vector;
  1700.  
  1701. {
  1702.     int size;
  1703.     LPBIT_VEC out_vec;
  1704.     LPSTR str;
  1705.     int i;
  1706.     int j;
  1707.     int count;
  1708.  
  1709.     /* Work out how big the new vector will be */
  1710.  
  1711.     size = 0;
  1712.     for (i = 0; i < n; i++)
  1713.     {
  1714.         size += vector[i] -> len;
  1715.     }
  1716.  
  1717.     /* Unpack the input vectors */
  1718.  
  1719.     str = Malloc((unsigned) size);
  1720.     MEMCHECK(str);
  1721.  
  1722.     count = 0;
  1723.     for (i = 0; i < n; i++)
  1724.     {
  1725.         for (j = 0; j < vector[i] -> len; j++)
  1726.         {
  1727.             str[count] = bv_extract(j,vector[i]);
  1728.             count++;
  1729.         }
  1730.     }
  1731.  
  1732.     out_vec = bv_pack(str,size);
  1733.  
  1734.     Free(str);
  1735.  
  1736.     return(out_vec);
  1737. }
  1738.  
  1739.  
  1740. /*****************************************************************************
  1741.  ****                                                                     ****
  1742.  **** LPBIT_VEC bv_copy(vector)                                           ****
  1743.  ****                                                                     ****
  1744.  **** LPBIT_VEC vector;                                                   ****
  1745.  ****                                                                     ****
  1746.  **** Synopsis:                                                           ****
  1747.  ****                                                                     ****
  1748.  **** Returns a copy of the bit vector _vector_.                          ****
  1749.  *****************************************************************************/
  1750.  
  1751. public LPBIT_VEC FAR PASCAL
  1752. bv_copy(vector)
  1753.  
  1754. LPBIT_VEC vector;
  1755. {
  1756.     LPBIT_VEC out_vec;
  1757.     int i;
  1758.  
  1759.     /* Work out how big the new vector will be */
  1760.  
  1761.     out_vec = (LPBIT_VEC) Malloc((unsigned) sizeof(bit_vec));
  1762.     MEMCHECK(out_vec);
  1763.  
  1764.     out_vec -> len = vector -> len;
  1765.     out_vec -> bv = Malloc((unsigned) (vector -> len + BYTE - 1) / BYTE);
  1766.     MEMCHECK(out_vec -> bv);
  1767.  
  1768.     for (i = 0; i < (vector -> len + BYTE - 1) / BYTE; i++)
  1769.     {
  1770.         out_vec -> bv[i] = vector -> bv[i];
  1771.     }
  1772.  
  1773.     return(out_vec);
  1774. }
  1775.  
  1776. /*****************************************************************************
  1777.  ****                                                                     ****
  1778.  **** void bv_set(n,vec,bit)                                              ****
  1779.  ****                                                                     ****
  1780.  **** int n;                                                              ****
  1781.  **** LPBIT_VEC vec;                                                      ****
  1782.  **** BOOL bit;                                                           ****
  1783.  ****                                                                     ****
  1784.  **** Synopsis:                                                           ****
  1785.  ****                                                                     ****
  1786.  **** Sets bit _n_ in _vec_ to have the value in _bit_.                   ****
  1787.  *****************************************************************************/
  1788.  
  1789. public void FAR PASCAL
  1790. bv_set(n,vec,bit)
  1791.  
  1792. int n;
  1793. LPBIT_VEC vec;
  1794. BOOL bit;
  1795.  
  1796. {
  1797.     char mask;
  1798.     LPSTR b;
  1799.     assert(n < vec -> len);
  1800.  
  1801.     mask = 0x1;
  1802.     b = (vec -> bv) + ((int) (n / BYTE));
  1803.  
  1804.     if (bit)
  1805.     {
  1806.         *b |= (mask << (n % BYTE));
  1807.     }
  1808.     else
  1809.     {
  1810.         *b &= ~(mask << (n % BYTE));
  1811.     }
  1812. }
  1813.  
  1814. /*****************************************************************************
  1815.  ****                                                                     ****
  1816.  **** BOOL bv_extract(n,vec)                                              ****
  1817.  ****                                                                     ****
  1818.  **** int n;                                                              ****
  1819.  **** LPBIT_VEC vec;                                                      ****
  1820.  ****                                                                     ****
  1821.  **** Synopsis:                                                           ****
  1822.  ****                                                                     ****
  1823.  **** Returns the _n_th bit of _vec_.                                     ****
  1824.  *****************************************************************************/
  1825.  
  1826. public BOOL FAR PASCAL
  1827. bv_extract(n,vec)
  1828.  
  1829. int n;
  1830. LPBIT_VEC vec;
  1831.  
  1832. {
  1833.     register int mask = 0x1;
  1834.  
  1835.     assert(n < vec -> len);
  1836.     return(((*((vec -> bv) + ((int) (n / BYTE)))) & (mask << (n % BYTE))) != 0);
  1837. }
  1838.  
  1839. /*****************************************************************************
  1840.  ****                                                                     ****
  1841.  **** int bv_print(stream, vector)                                        ****
  1842.  ****                                                                     ****
  1843.  **** FILE *stream;                                                   ****
  1844.  **** LPBIT_VEC vector;                                                   ****
  1845.  ****                                                                     ****
  1846.  **** Synopsis:                                                           ****
  1847.  ****                                                                     ****
  1848.  **** Prints out _vector_ in binary, MSB is the rightmost.                ****
  1849.  *****************************************************************************/
  1850.  
  1851. public int FAR PASCAL
  1852. bv_print(stream, vector)
  1853.  
  1854. FILE *stream;
  1855. LPBIT_VEC vector;
  1856.  
  1857. {
  1858.     LPSTR ptr; /* Points to the current char */
  1859.     char mask;
  1860.     int bits; /* Counts the number of bits output */
  1861.     int  i;
  1862.  
  1863.     bits = 0;
  1864.     for (ptr = (vector -> bv); bits < vector -> len; ptr++)
  1865.  
  1866.     {
  1867.         mask = 0x1;
  1868.         for (i = 0; i < BYTE; i++)
  1869.         {
  1870.             if (fprintf(stream, (*ptr & mask) ? "1" : "0") == EOF)
  1871.             {
  1872.                 return (1);
  1873.             }
  1874.             bits++;
  1875.             if (bits == vector -> len)
  1876.             {
  1877.                 break;
  1878.             }
  1879.             mask <<= 1;
  1880.         }
  1881.     }
  1882.     return(0);
  1883. }
  1884.  
  1885. /*****************************************************************************
  1886.  ****                                                                     ****
  1887.  **** void bv_free(vector)                                                ****
  1888.  ****                                                                     ****
  1889.  **** LPBIT_VEC vector;                                                   ****
  1890.  ****                                                                     ****
  1891.  **** Synopsis:                                                           ****
  1892.  ****                                                                     ****
  1893.  **** Frees the memory used by _vector_                                   ****
  1894.  *****************************************************************************/
  1895.  
  1896. public void FAR PASCAL
  1897. bv_free(vector)
  1898.  
  1899. LPBIT_VEC vector;
  1900.  
  1901. {
  1902.     Free(vector -> bv);
  1903.     Free(vector);
  1904. }
  1905.  
  1906. /*****************************************************************************
  1907.  ****                                                                     ****
  1908.  **** BOOL bv_equal(v1,v2)                                                ****
  1909.  ****                                                                     ****
  1910.  **** LPBIT_VEC v1;                                                       ****
  1911.  **** LPBIT_VEC v2;                                                       ****
  1912.  ****                                                                     ****
  1913.  **** Synopsis:                                                           ****
  1914.  ****                                                                     ****
  1915.  **** Returns TRUE if each bit in v1 and v2 have the same value in the    ****
  1916.  **** same position. It returns FALSE otherwise.                          ****
  1917.  *****************************************************************************/
  1918.  
  1919. public BOOL FAR PASCAL
  1920. bv_equal(v1,v2)
  1921.  
  1922. LPBIT_VEC v1;
  1923. LPBIT_VEC v2;
  1924.  
  1925. {
  1926.     bool_t eq;
  1927.     int i;
  1928.  
  1929.     eq = TRUE;
  1930.  
  1931.     if (v1 -> len != v2 -> len)
  1932.     {
  1933.         eq = FALSE;
  1934.     }
  1935.     else
  1936.     {
  1937.         for (i = 0; i < (v1 -> len + BYTE - 1) / BYTE; i++)
  1938.         {
  1939.             if (v1 -> bv[i] != v2 -> bv[i])
  1940.             {
  1941.                 eq = FALSE;
  1942.                 break;
  1943.             }
  1944.         }
  1945.     }
  1946.  
  1947.     return(eq);
  1948. }
  1949.  
  1950. /*****************************************************************************
  1951.  ****                                                                     ****
  1952.  **** void FAR PASCAL Windows_Interrupt(cElapsed)                         ****
  1953.  ****                                                                     ****
  1954.  **** DWORD cElapsed                                                      ****
  1955.  ****                                                                     ****
  1956.  **** Synopsis:                                                           ****
  1957.  ****                                                                     ****
  1958.  **** Allows Windows to access other applications that may be running     ****
  1959.  **** A call to PeekMessage accomplishes this, and we process all calling ****
  1960.  **** window messages. Will only call PeekMessage if _cElapsed_ time      ****
  1961.  **** has passed since the last call to Windows_Interrupt.                ****
  1962.  ****                                                                     ****
  1963.  *****************************************************************************/
  1964.  
  1965. public void FAR PASCAL
  1966. Windows_Interrupt(cElapsed)
  1967.  
  1968. DWORD cElapsed;
  1969.  
  1970. {
  1971.     static  cTick = 0;      /* number of ticks since first called */
  1972.     MSG     msg;            /* Windows message structure */
  1973.  
  1974.     if ((GetTickCount() - cTick) > cElapsed)
  1975.         {
  1976.         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  1977.             {
  1978.             TranslateMessage(&msg);
  1979.             DispatchMessage(&msg);
  1980.             }
  1981.         cTick = GetTickCount();
  1982.         }
  1983. }
  1984.  
  1985. /*****************************************************************************
  1986.  ****                                                                     ****
  1987.  **** LPSTR FAR PASCAL  WinMem_Malloc(wFlags, wBytes)                     ****
  1988.  ****                                                                     ****
  1989.  **** WORD wFlags                                                         ****
  1990.  **** WORD wBytes                                                         ****
  1991.  ****                                                                     ****
  1992.  **** Synopsis:                                                           ****
  1993.  ****                                                                     ****
  1994.  **** Allocates _wBytes_ bytes of memory in a dynamically allocated       ****
  1995.  **** segment. _wBytes_ cannot be greater than SEGLENGTH. wFlags can be   ****
  1996.  **** any of the local memory allocation flags defined in the Windows     ****
  1997.  **** Programmer's Reference, usually LMEM_MOVEABLE.                      ****
  1998.  **** Returns a valid pointer if successful, NULL if not.                 ****
  1999.  ****                                                                     ****
  2000.  ****                                                                     ****
  2001.  *****************************************************************************/
  2002.  
  2003. public LPSTR FAR PASCAL  WinMem_Malloc(WORD wFlags, WORD wBytes)
  2004.     {
  2005.     int offset;
  2006.     int i,j;
  2007.     BOOL found;
  2008.     HANDLE hmem;
  2009.     LPSTR lp;
  2010.     PSTR p;
  2011.     LONG lSize;
  2012.     WORD wSeg;
  2013.     static BOOL bFirst = TRUE;
  2014.  
  2015.     if (bFirst) 
  2016.         {
  2017.         bFirst = FALSE;
  2018.         WinMem_Init();
  2019.         }
  2020.  
  2021.     if ((long)wBytes > (SEGLENGTH - 16)) return(NULL);
  2022.  
  2023.     for (i = 0; i < NUMSEGS; i++)
  2024.         {
  2025.         if (seg[i] == NULL)
  2026.             {
  2027.  
  2028.             /**** Get global segment, initialize local heap ****/
  2029.  
  2030.             hmem = GlobalAlloc(GMEM_MOVEABLE, SEGLENGTH);
  2031.             if (!hmem) return(NULL);
  2032.             lp = GlobalWire(hmem);
  2033.             wSeg = HIWORD(lp);
  2034.             seg[i] = hmem;
  2035.             lSize = GlobalSize(hmem) - 16;    /*
  2036.                                                * reserve 16 bytes for local
  2037.                                                * heap initialization
  2038.                                                */
  2039.             if (lSize > (SEGLENGTH - 16)) lSize = SEGLENGTH - 16;
  2040.             if (!LocalInit(wSeg,0,lSize)) return(NULL);
  2041.             freemem[i] = (WORD) lSize;
  2042.             GlobalUnlock(hmem);   /* from LocalInit */
  2043.             GlobalUnWire(hmem);
  2044.             }
  2045.         if (freemem[i] > wBytes)
  2046.             {
  2047.             lp = GlobalWire(seg[i]);
  2048.             if (!lp) return(NULL);
  2049.             wSeg = HIWORD(lp);
  2050.  
  2051.             asm { push      ds
  2052.                   mov       ax, wSeg
  2053.                   mov       ds, ax
  2054.                 }
  2055.  
  2056.             hmem = LocalAlloc(wFlags, wBytes);
  2057.  
  2058.             asm { pop       ds
  2059.                 }
  2060.  
  2061.             GlobalUnWire(seg[i]);
  2062.  
  2063.             if (hmem)
  2064.                 {
  2065.                 j = i;
  2066.                 break;
  2067.                 }
  2068.             }
  2069.         }            
  2070.  
  2071.     if (!hmem) return(NULL);
  2072.  
  2073.     lp = GlobalWire (seg[j]);       /*
  2074.                                      * move to low memory, will be
  2075.                                      * unwired in WinMem_Free
  2076.                                      */
  2077.     if (!lp) return(NULL);
  2078.     wSeg = HIWORD(lp);
  2079.  
  2080.     asm { push  ds
  2081.           mov   ax, wSeg
  2082.           mov   ds, ax
  2083.         }
  2084.  
  2085.     i = LocalSize(hmem);
  2086.     p = LocalLock (hmem);
  2087.  
  2088.     asm { pop  ds
  2089.         }
  2090.  
  2091.     freemem[j] -= i;
  2092.  
  2093.     if (!p) return(NULL);
  2094.     else    return (LPSTR)MAKELONG (p, wSeg);
  2095.     }
  2096.  
  2097. /*****************************************************************************
  2098.  ****                                                                     ****
  2099.  **** LPSTR FAR PASCAL  WinMem_Free(lpfree)                               ****
  2100.  ****                                                                     ****
  2101.  **** LPSTR lpfree                                                        ****
  2102.  ****                                                                     ****
  2103.  **** Synopsis:                                                           ****
  2104.  ****                                                                     ****
  2105.  **** Frees the block of memory in a dynamically allocated segment        ****
  2106.  **** pointed to by _lpFree_.                                             ****
  2107.  **** Returns NULL if successful, lpfree if not                           ****
  2108.  ****                                                                     ****
  2109.  ****                                                                     ****
  2110.  *****************************************************************************/
  2111.  
  2112. public LPSTR FAR PASCAL  WinMem_Free(LPSTR lpfree)
  2113.     {
  2114.     HANDLE hmem, hseg;
  2115.     LPSTR lp;
  2116.     WORD wSeg;
  2117.     int i,j;
  2118.  
  2119.     wSeg = HIWORD(lpfree);
  2120.     hseg = GlobalHandle(wSeg);
  2121.  
  2122.     j = -1;
  2123.     for (i = 0; i < NUMSEGS; i++)
  2124.         {
  2125.         if (seg[i] == hseg)
  2126.             {
  2127.             j = i;
  2128.             break;
  2129.             }
  2130.         }
  2131.     if (j == -1) return(lpfree);
  2132.  
  2133.     lp = GlobalWire(hseg);
  2134.     if (!lp) goto FAIL;
  2135.  
  2136.     asm { push  ds
  2137.           mov   ax, wSeg
  2138.           mov   ds, ax
  2139.         }
  2140.  
  2141.     hmem = LocalHandle(LOWORD(lpfree));
  2142.     if (!hmem)
  2143.         {
  2144.         asm { pop ds
  2145.             }
  2146.         goto FAIL;
  2147.         }
  2148.     
  2149.     i = LocalSize(hmem);
  2150.         
  2151.     if (!LocalUnlock (hmem))  
  2152.         {
  2153.         hmem = LocalFree(hmem);    /*returns NULL if successful*/
  2154.         if (hmem)
  2155.             {
  2156.             asm { pop ds
  2157.                 }
  2158.             goto FAIL;
  2159.             }
  2160.         }
  2161.     else
  2162.         {
  2163.         asm { pop ds
  2164.             }
  2165.         goto FAIL;
  2166.         }
  2167.  
  2168.     asm { pop   ds
  2169.         }
  2170.  
  2171.     freemem[j] += i;
  2172.  
  2173.     GlobalUnWire(hseg);
  2174.     if ((GlobalUnWire(hseg)) && (freemem[j] == (SEGLENGTH - 16))) /* TRUE if lock count at 0 */
  2175.         {
  2176.         GlobalFree(hseg);
  2177.         seg[j] = NULL;
  2178.         freemem[j] = 0;
  2179.         }
  2180.  
  2181.     return(NULL);
  2182. FAIL:
  2183.     return(lpfree);
  2184.     }
  2185.  
  2186. /*****************************************************************************
  2187.  *****************************************************************************
  2188.  ****                                                                     ****
  2189.  ****                        Private Routines                             ****
  2190.  ****                                                                     ****
  2191.  *****************************************************************************
  2192.  *****************************************************************************/
  2193.  
  2194. /*
  2195.  * void FAR PASCAL WinMem_Init()
  2196.  *
  2197.  * internal routine to initialize memory manager
  2198.  * called automatically as needed
  2199.  */
  2200.  
  2201. private void NEAR PASCAL WinMem_Init()
  2202.     {
  2203.     int i;
  2204.  
  2205.     for (i = 0; i < NUMSEGS; i++)
  2206.         {
  2207.         seg[i] = NULL;
  2208.         freemem[i] = 0;
  2209.         }
  2210.     }
  2211.  
  2212. /*
  2213.  * Free list management routines.
  2214.  */
  2215.  
  2216. static LPATREE_LEAF free_leaf_list = NULL;
  2217. static LPATREE_NODE free_node_list = NULL;
  2218.  
  2219. #define get_free_list(type, free_list) { \
  2220.   int i; \
  2221.   type far *ptr = (type far *) Malloc(sizeof(type) * NEWMALLOC); \
  2222.   MEMCHECK(ptr); \
  2223.   for (i = 0; i < NEWMALLOC - 1; i++) \
  2224.     ptr[i].next = &ptr[i + 1]; \
  2225.   ptr[NEWMALLOC - 1].next = free_list; \
  2226.   free_list = ptr; \
  2227. }
  2228.  
  2229. private LPATREE NEAR PASCAL
  2230. get_node(tag)
  2231.  
  2232. int tag;
  2233.  
  2234. {
  2235.     LPATREE node;
  2236.  
  2237.     if (tag == LEAF)
  2238.     {
  2239.  
  2240.         /*
  2241.          * add to free_leaf_list if necessary.
  2242.          */
  2243.         if (free_leaf_list == NULL)
  2244.         {
  2245.             get_free_list(atree_leaf, free_leaf_list);
  2246.         }
  2247.  
  2248.         node = (LPATREE) free_leaf_list;
  2249.         free_leaf_list = free_leaf_list -> next;
  2250.     }
  2251.     else {
  2252.  
  2253.         /*
  2254.          * add to free_node_list if necessary.
  2255.          */
  2256.         if (free_node_list == NULL)
  2257.         {
  2258.             get_free_list(atree_node, free_node_list);
  2259.         }
  2260.  
  2261.         node = (LPATREE) free_node_list;
  2262.         free_node_list = free_node_list -> next;
  2263.     }
  2264.  
  2265.     node -> c_tag = tag;
  2266.     return(node);
  2267. }
  2268. #undef get_free_list
  2269.  
  2270. /*
  2271.  * function reclaim_node()
  2272.  *
  2273.  * returns a node to its appropriate free_list
  2274.  */
  2275.  
  2276. private void NEAR PASCAL
  2277. reclaim_node(tree)
  2278.  
  2279. LPATREE tree;
  2280.  
  2281. {
  2282.     if (tree -> c_tag == LEAF)
  2283.     {
  2284.         tree -> leaf.next = free_leaf_list;
  2285.         free_leaf_list = (LPATREE_LEAF) tree;
  2286.     }
  2287.     else
  2288.     {
  2289.         tree -> node.next = free_node_list;
  2290.         free_node_list = (LPATREE_NODE) tree;
  2291.     }
  2292. }
  2293.  
  2294. /*
  2295.  * This routine recursively creates a random tree in the previously allocated
  2296.  * space starting at _tree_. It returns a pointer giving the next available
  2297.  * space for other calls.
  2298.  */
  2299.  
  2300. private LPATREE NEAR PASCAL
  2301. build_tree(connection,complemented,start,end)
  2302.  
  2303. LPINT connection;
  2304. bool_t far *complemented;
  2305. int start;
  2306. int end;
  2307.  
  2308. {
  2309.     LPATREE node;
  2310.     int mid;
  2311.  
  2312.     /* Are we at a leaf? */
  2313.  
  2314.     if (start == end)
  2315.     {
  2316.         node = get_node(LEAF);
  2317.         node -> l_comp = complemented[start];
  2318.         node -> l_bit_no = connection[start];
  2319.     }
  2320.     else
  2321.     {
  2322.         /* This is a node. */
  2323.  
  2324.         node = get_node(AND);
  2325.         node -> c_tag = RANDOM(4);
  2326.  
  2327.         node -> n_cnt_left =
  2328.           (node -> c_tag == LEFT || node -> c_tag == OR) ? ABOVEMID : BELOWMID;
  2329.         node -> n_cnt_right =
  2330.           (node -> c_tag == RIGHT || node -> c_tag == OR) ? ABOVEMID : BELOWMID;
  2331.  
  2332.         /* clear the signals */
  2333.  
  2334.         node -> n_sig_right = UNEVALUATED;
  2335.         node -> n_sig_left = UNEVALUATED;
  2336.  
  2337.         /* Create descendants */
  2338.  
  2339.         mid = start + ((end - start)/2);
  2340.         node -> n_child[LEFT_CHILD]
  2341.            = build_tree(connection, complemented, start, mid);
  2342.         node -> n_child[RIGHT_CHILD]
  2343.            = build_tree(connection, complemented, mid+1, end);
  2344.     }
  2345.     return(node);
  2346. }
  2347.  
  2348. /*
  2349.  * print_tree routine prints out an atree to the
  2350.  * file pointed to by _fp_
  2351.  */
  2352.  
  2353. private void NEAR PASCAL
  2354. print_tree(tree,indent,verbosity,hOut)
  2355.  
  2356. LPATREE tree;
  2357. int indent;
  2358. int verbosity;
  2359. int hOut;
  2360.  
  2361. {
  2362.     int i;
  2363.     char szBuffer[80];
  2364.  
  2365.     if (tree -> c_tag != LEAF)
  2366.     {
  2367.         print_tree(tree -> n_child[RIGHT_CHILD], indent + 3, verbosity, hOut);
  2368.     }
  2369.  
  2370.     for (i = 0; i < indent; i++)
  2371.     {
  2372.         Printf(" ",0);
  2373.         _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
  2374.     }
  2375.  
  2376.     switch (tree -> c_tag)
  2377.     {
  2378.     case AND:
  2379.         Printf("AND\r\n",0);
  2380.         _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
  2381.         break;
  2382.  
  2383.     case LEFT:
  2384.         Printf("LEFT\r\n",0);
  2385.         _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
  2386.         break;
  2387.  
  2388.     case RIGHT:
  2389.         Printf("RIGHT\r\n",0);
  2390.         _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
  2391.         break;
  2392.  
  2393.     case OR:
  2394.         Printf("OR\r\n",0);
  2395.         _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
  2396.         break;
  2397.  
  2398.     case LEAF:
  2399.         wsprintf(szBuffer,"%cLEAF : %d\r\n",
  2400.                tree -> l_comp ? '~' : '\0', tree -> l_bit_no);
  2401.         _lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
  2402.         break;
  2403.     }
  2404.  
  2405.     if (tree -> c_tag != LEAF)
  2406.     {
  2407.        print_tree(tree -> n_child[LEFT_CHILD], indent + 3, verbosity, hOut);
  2408.     }
  2409. }
  2410.  
  2411. /*
  2412.  * bool_t train(tree,vec,result)
  2413.  *
  2414.  * LPATREE tree;
  2415.  * LPBITVEC vec;
  2416.  * bool result;
  2417.  *
  2418.  * This routine is actually responsible for the training of a tree for a
  2419.  * single input vector and result. If the tree gets the correct result
  2420.  * before the adaptation step occurs, the routine returns TRUE, otherwise,
  2421.  * false.
  2422.  */
  2423.  
  2424. private bool_t NEAR PASCAL
  2425. train(tree,vec,desired)
  2426.  
  2427. LPATREE tree;
  2428. LPBIT_VEC vec;
  2429. bool_t desired;
  2430.  
  2431. {
  2432.     bool_t correct;
  2433.  
  2434.     /* Adapt the tree */
  2435.  
  2436.     correct = (bool_t)atree_eval(tree,vec) == desired;
  2437.  
  2438.     adapt(tree,vec,desired);
  2439.  
  2440.     /* What does the tree currently think ?*/
  2441.  
  2442.     correct = (bool_t)atree_eval(tree,vec) == desired;
  2443.  
  2444.     if (!correct)
  2445.     {
  2446.         adapt(tree,vec,desired);
  2447.     }
  2448.  
  2449.     return(correct);
  2450. }
  2451.  
  2452. /*
  2453.  * adapt(tree,vec,result)
  2454.  *
  2455.  * LPATREE tree;
  2456.  * LPBIT_VEC vec;
  2457.  * bool result;
  2458.  *
  2459.  */
  2460.  
  2461. private void NEAR PASCAL
  2462. adapt(tree,vec,desired)
  2463.  
  2464. LPATREE tree;
  2465. LPBIT_VEC vec;
  2466. bool_t desired;
  2467.  
  2468. {
  2469.     register int lres;
  2470.     register int rres;
  2471.     register int funct;
  2472.  
  2473.  
  2474. /*
  2475.  * INCR and DECR implement bounded counters, remembering that TRUE == 1,
  2476.  * how much should be added to t when t == MAXSET ?
  2477.  */
  2478.  
  2479. #define INCR(t) t += (t != MAXSET)
  2480. #define DECR(t) t -= (t != MINSET)
  2481.  
  2482.     funct = tree -> c_tag;
  2483.  
  2484.     if (funct != LEAF)
  2485.     {
  2486.         /* If the left child is unevaluated, evaluate it */
  2487.  
  2488.         if ((lres = tree -> n_sig_left) == UNEVALUATED)
  2489.         {
  2490.             lres = atree_eval(tree -> n_child[LEFT_CHILD], vec);
  2491.             tree -> n_sig_left = lres;
  2492.         }
  2493.  
  2494.         /* If the right child is unevaluated, evaluate it */
  2495.  
  2496.         if ((rres = tree -> n_sig_right) == UNEVALUATED)
  2497.         {
  2498.             rres = atree_eval(tree -> n_child[RIGHT_CHILD], vec);
  2499.             tree -> n_sig_right = rres;
  2500.         }
  2501.  
  2502.         /* Update the counters if needed */
  2503.  
  2504.         if (lres != rres)
  2505.         {
  2506.             if (lres)
  2507.             {
  2508.                 (void) (desired ? (INCR(tree -> n_cnt_left))
  2509.                                 : (DECR(tree -> n_cnt_left)));
  2510.             }
  2511.             else
  2512.             {
  2513.                 (void) (desired ? (INCR(tree -> n_cnt_right))
  2514.                                 : (DECR(tree -> n_cnt_right)));
  2515.             }
  2516.  
  2517.             /* has the node function changed? */
  2518.     
  2519.             tree -> c_tag = node_function(tree);
  2520.             funct = tree -> c_tag;
  2521.         }
  2522.     
  2523.         /* Assign responsibility to the left child */
  2524.     
  2525.         if (rres != desired || funct != (rres ? OR : AND))
  2526.         {
  2527.             adapt(tree -> n_child[LEFT_CHILD], vec, desired);
  2528.         }
  2529.     
  2530.         /* Assign responsibility to the right child */
  2531.     
  2532.         if (lres != desired || funct != (lres ? OR : AND))
  2533.         {
  2534.             adapt(tree -> n_child[RIGHT_CHILD], vec, desired);
  2535.         }
  2536.     }
  2537. #undef INCR
  2538. #undef DECR
  2539. }
  2540.  
  2541. private char NEAR PASCAL
  2542. node_function(tree)
  2543.  
  2544. LPATREE tree;
  2545. {
  2546.     int result;
  2547.  
  2548.     if ((tree -> n_cnt_left) >= ABOVEMID)
  2549.     {
  2550.         result = (tree -> n_cnt_right >= ABOVEMID) ? OR : LEFT;
  2551.     }
  2552.     else
  2553.     {
  2554.         result = (tree -> n_cnt_right >= ABOVEMID) ? RIGHT : AND;
  2555.     }
  2556.  
  2557.     return(result);
  2558. }
  2559.  
  2560. /*
  2561.  * compress_tree:
  2562.  *   Alters the respresentation of an atree into a fast_tree.
  2563.  * A fast_tree is essentially a list of leaves; each leaf in the
  2564.  * list contains two pointers to subsequent leaves to evaluate,
  2565.  * one for each possible result of evaluating the current leaf.
  2566.  * A next pointer of NULL indicates that the evaluation is complete,
  2567.  * and the result of the tree is the result of the current leaf.
  2568.  *
  2569.  * parameters:
  2570.  *   'next_if_0' and 'next_if_1' each hold the location of the
  2571.  * next leaf to evaluate if the value of the current 'node' is
  2572.  * known.  Of course, for the root these are NULL.  'leaf_num' is the
  2573.  * current index into 'ftree'; it starts at the last leaf.
  2574.  *
  2575.  * notes:
  2576.  *   For non-leaf nodes, we traverse the children in reverse order
  2577.  * because we need to know the first leaf of a node's sibling (this
  2578.  * is the next leaf to evaluate if any children of 'node' produce a
  2579.  * tag value).  If we go backwards, we know that this is the last
  2580.  * leaf we visited.
  2581.  */
  2582.  
  2583. private void NEAR PASCAL
  2584. compress_tree(node, next_if_0, next_if_1, ftree, leaf_num)
  2585.  
  2586. LPATREE node;
  2587. LPFAST_TREE next_if_0;
  2588. LPFAST_TREE next_if_1;
  2589. LPFAST_TREE ftree;
  2590. LPINT leaf_num;
  2591.  
  2592. {
  2593.  
  2594.     assert(*leaf_num >= 0);
  2595.     switch (node -> c_tag)
  2596.     {
  2597.     case LEAF:
  2598.         ftree[*leaf_num].next[0] = next_if_0;
  2599.         ftree[*leaf_num].next[1] = next_if_1;
  2600.         ftree[*leaf_num].bit_no = node -> l_bit_no;
  2601.         ftree[*leaf_num].comp = node -> l_comp;
  2602.         (*leaf_num)--;
  2603.         break;
  2604.     case AND:
  2605.         compress_tree(node->n_child[1], next_if_0, next_if_1, ftree, leaf_num);
  2606.         compress_tree(node->n_child[0], next_if_0, &(ftree[*leaf_num + 1]), ftree,
  2607.                       leaf_num);
  2608.         break;
  2609.     case OR:
  2610.         compress_tree(node->n_child[1], next_if_0, next_if_1, ftree, leaf_num);
  2611.         compress_tree(node->n_child[0], &(ftree[*leaf_num + 1]), next_if_1, ftree,
  2612.                       leaf_num);
  2613.         break;
  2614.     case LEFT:
  2615.         compress_tree(node->n_child[0], next_if_0, next_if_1, ftree, leaf_num);
  2616.         break;
  2617.     case RIGHT:
  2618.         compress_tree(node->n_child[1], next_if_0, next_if_1, ftree, leaf_num);
  2619.         break;
  2620.     default:
  2621.         assert(0);
  2622.     }
  2623. }
  2624.  
  2625. private int NEAR PASCAL
  2626. count_leaves(tree, fold)
  2627.  
  2628. LPATREE tree;
  2629. int fold;
  2630.  
  2631. {
  2632.     if (tree -> c_tag == LEAF)
  2633.     {
  2634.         return 1;
  2635.     }
  2636.     else if (fold && tree -> c_tag == LEFT)
  2637.     {
  2638.         return count_leaves(tree -> n_child[LEFT_CHILD], fold);
  2639.     }
  2640.     else if (fold && tree -> c_tag == RIGHT)
  2641.     {
  2642.         return count_leaves(tree -> n_child[RIGHT_CHILD], fold);
  2643.     }
  2644.     else
  2645.     {
  2646.         return count_leaves(tree -> n_child[LEFT_CHILD], fold)
  2647.              + count_leaves(tree -> n_child[RIGHT_CHILD], fold);
  2648.     }
  2649. }
  2650.  
  2651. /*
  2652.  * function: store_tree
  2653.  *
  2654.  * Stores _tree_ onto _stream_ using postfix notation.
  2655.  * Returns non-zero on failure.
  2656.  */
  2657.  
  2658. private int NEAR PASCAL
  2659. store_tree(tree, stream)
  2660.  
  2661. LPATREE tree;
  2662. FILE *stream;
  2663.  
  2664. {
  2665.     int error;
  2666.  
  2667.     if (tree -> c_tag == LEAF)
  2668.     {
  2669.         error = fprintf(stream, "%s%d ",
  2670.                         tree -> l_comp ? "!" : "", tree -> l_bit_no) == EOF;
  2671.     }
  2672.     else
  2673.     {
  2674.         error = store_tree(tree -> n_child[LEFT_CHILD], stream)
  2675.              || store_tree(tree -> n_child[RIGHT_CHILD], stream);
  2676.         if (!error)
  2677.         {
  2678.             switch (tree -> c_tag)
  2679.             {
  2680.             case AND:
  2681.                 error = fprintf(stream, "&") == EOF;
  2682.                 break;
  2683.             case OR:
  2684.                 error = fprintf(stream, "|") == EOF;
  2685.                 break;
  2686.             case LEFT:
  2687.                 error = fprintf(stream, "L") == EOF;
  2688.                 break;
  2689.             case RIGHT:
  2690.                 error = fprintf(stream, "R") == EOF;
  2691.                 break;
  2692.             }
  2693.         }
  2694.     }
  2695.     return(error);
  2696. }
  2697.  
  2698. /*
  2699.  * function: get_token
  2700.  *
  2701.  * Reads the next token from _stream_ and returns information about it
  2702.  * in _t_.  Returns 0 for success, 1 for failure.
  2703.  */
  2704.  
  2705. private int NEAR PASCAL
  2706. get_token(stream, t)
  2707.  
  2708. FILE *stream;
  2709. token_t far *t;
  2710.  
  2711. {
  2712.     int c;
  2713.     char szBuffer[80];
  2714.  
  2715.     /* skip white space */
  2716.     while (isspace(c = getc(stream)))
  2717.        ;
  2718.  
  2719.     t -> complemented = 0;
  2720.     switch (c)
  2721.     {
  2722.     case EOF:
  2723.     case 'L':
  2724.     case 'R':
  2725.     case '&':
  2726.     case '|':
  2727.     case ';':
  2728.         t -> token = c;
  2729.       break;
  2730.     case '!':
  2731.         t -> complemented = 1;
  2732.         /* skip white space */
  2733.         while (isspace(c = getc(stream)))
  2734.            ;
  2735.          
  2736.         if (!isdigit(c))
  2737.         {
  2738.             wsprintf(szBuffer,"expecting digit after '!', offset %ld\n",
  2739.                            ftell(stream));
  2740.             MessageBox(NULL, szBuffer, "get_token", MB_OK | MB_ICONEXCLAMATION);
  2741.             return(1);
  2742.         }
  2743.         /* FALLTHRU */
  2744.  
  2745.     case '0': case '1': case '2': case '3': case '4':
  2746.     case '5': case '6': case '7': case '8': case '9':
  2747.         t -> token = LEAF_TOKEN;
  2748.         t -> bit_no = c - '0';
  2749.         while (isdigit(c = getc(stream)))
  2750.         {
  2751.             t -> bit_no = t -> bit_no * 10 + c - '0';
  2752.         }
  2753.         (void) ungetc(c, stream);
  2754.         break;
  2755.  
  2756.     default:
  2757.         wsprintf(szBuffer, "unexpected symbol: '%c', offset %ld\n", c, ftell(stream));
  2758.         MessageBox(NULL, szBuffer, "get_token", MB_OK | MB_ICONEXCLAMATION);
  2759.         return(1);
  2760.     }
  2761.  
  2762.     return(0);
  2763. }
  2764.