home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / GAMES / infocom_src.lha / input.c < prev    next >
Text File  |  1993-03-03  |  13KB  |  614 lines

  1. /*
  2. **    File:    input.c
  3. **
  4. **    (C)opyright 1987-1992 InfoTaskforce.
  5. */
  6.  
  7. #include    "infocom.h"
  8.  
  9. /*
  10. **    Input Routine Global Variables
  11. **
  12. **    Note:
  13. **        The variable "end_of_sentence" is of type "byte *"
  14. **        NOT "byte_ptr" - these definitions are different
  15. **        for MSDOS Compilers ("byte_ptr" is huge).
  16. */
  17.  
  18. byte        ws_buff_strt[TABLE_SIZE] ;
  19. byte        *end_of_sentence ;
  20. word        num_vocab_words ;
  21. word        vocab_entry_size ;
  22. word        strt_vocab_table ;
  23. word        end_vocab_table ;
  24. word        initial_chop ;
  25. boolean        has_initial_chop ;
  26. char        ws_table[] =    { ' ','\t','\r','.',',','?','\0','\0' } ;
  27.  
  28. Void
  29. init_vocab ( vocab_strt )
  30. byte_ptr    vocab_strt ;
  31. {
  32.     extern byte_ptr        base_ptr ;
  33.  
  34.     word                shift ;
  35.     word                num ;
  36.  
  37.     /*    Note:
  38.     **        'strt_vocab_table' and 'end_vocab_table' are given
  39.     **        as offsets from the start of the data_file. These
  40.     **        offsets are guaranteed to be no more than 16 bits
  41.     **        long since only a two byte offset is required by
  42.     **        the 'parse_buffer ()' routine. Hence we can use a
  43.     **        'word' to represent them.
  44.     */
  45.  
  46.     num = *vocab_strt++ ;
  47.     vocab_strt += num ;
  48.     vocab_entry_size = *vocab_strt++ ;
  49.     shift = *(vocab_strt++) << 8 ;
  50.     shift |= *vocab_strt++ ;
  51.     strt_vocab_table = (word)( vocab_strt - base_ptr ) ;
  52.  
  53.     if ( ((signed_word)shift) > 0 )
  54.     {
  55.         num_vocab_words = shift ;
  56.         initial_chop = vocab_entry_size ;
  57.         shift >>= 1 ;
  58.         do
  59.         {
  60.             initial_chop <<= 1 ;
  61.             shift >>= 1 ;
  62.         } while ( shift != 0 ) ;
  63.         has_initial_chop = TRUE ;
  64.     }
  65.     else
  66.     {
  67.         num_vocab_words = -((signed_word)shift) ;
  68.         has_initial_chop = FALSE ;
  69.     }
  70.  
  71.     end_vocab_table = strt_vocab_table + vocab_entry_size * (num_vocab_words-1);
  72. }
  73.  
  74. Void
  75. init_input ( vocab )
  76. word    vocab ;
  77. {
  78.     extern byte_ptr        base_ptr ;
  79.     extern byte_ptr        main_vocab_list ;
  80.  
  81.     word                num ;
  82.     byte_ptr            p ;
  83.     byte                *q ;
  84.     byte                *r ;
  85.  
  86.     /*
  87.     **    Note:
  88.     **        The variables "q" and "r" are of type "byte *"
  89.     **        NOT "byte_ptr" - these definitions are different
  90.     **        for MSDOS Compilers ("byte_ptr" is huge).
  91.     */
  92.  
  93.     main_vocab_list = base_ptr + vocab ;
  94.  
  95.     p = main_vocab_list ;
  96.     num = *p++ ;
  97.     q = ws_buff_strt ;
  98.     while ( num-- )
  99.         *q++ = *p++ ;
  100.     end_of_sentence = q ;
  101.     r = (byte *)ws_table ;
  102.     while ( *r != '\0' )
  103.         *q++ = *r++ ;
  104.     *q = '\0' ;
  105.  
  106.     init_vocab ( main_vocab_list ) ;
  107. }
  108.  
  109. Void
  110. input ()
  111. {
  112.     extern header        data_head ;
  113.     extern word            default_param_stack[] ;
  114.     extern word            param_stack[] ;
  115.     extern byte_ptr        base_ptr ;
  116.     extern byte_ptr        main_vocab_list ;
  117.  
  118.     byte_ptr            in_buf_strt ;
  119.     byte_ptr            word_buff_strt ;
  120.  
  121.     /*
  122.     **    Empty the Print Buffer
  123.     */
  124.  
  125.     if ( data_head.z_code_version <= VERSION_3 )
  126.         prt_status () ;
  127.  
  128.     flush_prt_buff () ;
  129.  
  130.     default_param_stack[0] = 4 ;
  131.     default_param_stack[2] = 0 ;
  132.     default_param_stack[3] = 0xFFFF ;
  133.     default_param_stack[4] = 0 ;
  134.     parameter_copy ( default_param_stack,param_stack ) ;
  135.  
  136.     /*
  137.     **    Get an Input Line and Parse it.
  138.     **
  139.     **    On entry:
  140.     **            param_stack[1] = char_offset ;
  141.     **            param_stack[2] = word_offset ;
  142.     **            param_stack[3] = ? ;            <- ADVANCED Version Only.
  143.     **            param_stack[4] = ? ;            <- ADVANCED Version Only.
  144.     */
  145.  
  146.     in_buf_strt = base_ptr + param_stack[1] ;
  147.     word_buff_strt = base_ptr + param_stack[2] ;
  148.     read_line ( in_buf_strt ) ;
  149.  
  150.     switch ( data_head.z_code_version )
  151.     {
  152.         case VERSION_1:
  153.         case VERSION_2:
  154.         case VERSION_3:
  155.                         std_parse_buffer ( in_buf_strt,word_buff_strt ) ;
  156.                         break ;
  157.         case VERSION_4:
  158.                         plus_parse_buffer ( in_buf_strt,word_buff_strt ) ;
  159.                         break ;
  160.         case VERSION_5:
  161.         default:
  162.                         if ( param_stack[2] != 0 )
  163.                             advanced_parse_buffer ( in_buf_strt,word_buff_strt,main_vocab_list,(word)0 ) ;
  164.                         store ( (word)'\n' ) ;
  165.                         break ;
  166.     }
  167. }
  168.  
  169. Void
  170. read_line ( buffer )
  171. byte_ptr    buffer ;
  172. {
  173.     register byte_ptr    char_ptr ;
  174.     register byte        buffer_size ;
  175.     register byte        count ;
  176.     register char        ch ;
  177.  
  178.     /*
  179.     **    The first byte of the buffer contains the buffer length.
  180.     **    The second byte contains the number of characters put in the buffer.
  181.     */
  182.  
  183.     buffer_size = *buffer++ ;
  184.     char_ptr = ++buffer ;
  185.     count = 0 ;
  186.     while (( ch = read_char ()) != '\n' )
  187.     {
  188.         if ( ch == '\b' )
  189.         {
  190.             if ( char_ptr != buffer )
  191.             {
  192.                 --char_ptr ;
  193.                 --count ;
  194.             }
  195.         }
  196.         else
  197.         {
  198.             /*
  199.             **    Make it Lower Case
  200.             */
  201.  
  202.             if (( ch >= 'A' ) && ( ch <= 'Z' ))
  203.                 ch += ( 'a' - 'A' ) ;
  204.             *char_ptr++ = (byte)ch ;
  205.             ++count ;
  206.  
  207.             /*
  208.             **    Check to see if Buffer is full
  209.             */
  210.  
  211.             if ( count == buffer_size )
  212.             {
  213.                 /*
  214.                 **    Flush remaining characters
  215.                 */
  216.  
  217.                 new_line () ;
  218.                 display ( "Input line too long. Flushing: " ) ;
  219.                 while (( ch = read_char ()) != '\n' )
  220.                     print_char ( (word)ch ) ;
  221.                 new_line () ;
  222.                 break ;
  223.             }
  224.         }
  225.     }
  226.     /*
  227.     **    Record the number of characters in the buffer.
  228.     */
  229.  
  230.     *(--buffer) = count ;
  231. }
  232.  
  233. word
  234. look_up ( coded,encoded_size )
  235. word    coded[] ;
  236. word    encoded_size ;
  237. {
  238.     register long_word    v_ptr ;
  239.     register word        chop ;
  240.     register word        data ;
  241.     word                page ;
  242.     word                offset ;
  243.     int                    i ;
  244.  
  245.     /*    Note:
  246.     **        'strt_vocab_table' and 'end_vocab_table' are given
  247.     **        as offsets from the start of the data_file. These
  248.     **        offsets are guaranteed to be no more than 16 bits
  249.     **        long since only a two byte offset is required by
  250.     **        the 'parse_buffer ()' routine. Hence we can use a
  251.     **        'word' to represent them.
  252.     */
  253.  
  254.     chop = initial_chop ;
  255.     v_ptr = strt_vocab_table + chop - vocab_entry_size ;
  256.     do
  257.     {
  258.         i = 0 ;
  259.         chop >>= 1 ;
  260.         page = (word)( v_ptr / BLOCK_SIZE ) ;
  261.         offset = (word)( v_ptr % BLOCK_SIZE ) ;
  262.         data = get_word ( &page,&offset ) ;
  263.         while ( coded[i] == data )
  264.         {
  265.             if ( ++i < (int)encoded_size )
  266.                 data = get_word ( &page,&offset ) ;
  267.             else
  268.                 return ( (word)v_ptr ) ;
  269.         }
  270.         if ( coded[i] > data )
  271.         {
  272.             v_ptr += chop ;
  273.             if ( v_ptr > ((long_word)end_vocab_table) )
  274.                 v_ptr = ((long_word)end_vocab_table) ;
  275.         }
  276.         else
  277.             v_ptr -= chop ;
  278.     } while ( chop >= vocab_entry_size ) ;
  279.     return ( (word)0 ) ;
  280. }
  281.  
  282. /*
  283. **    Standard Version Input Routines
  284. */
  285.  
  286. Void
  287. std_parse_buffer ( in_buf_strt,word_buff_strt )
  288. byte_ptr    in_buf_strt ;
  289. byte_ptr    word_buff_strt ;
  290. {
  291.     word                coded[STD_ENCODED_SIZE] ;
  292.     byte                the_word[STD_CHARS_PER_WORD + 1] ;
  293.     boolean                white_space ;
  294.     register word        offset ;
  295.     register byte_ptr    in_buf_end ;
  296.     register byte_ptr    last_word ;
  297.     register byte_ptr    wd_ptr ;
  298.     register byte_ptr    char_ptr ;
  299.     register byte        *ws ;
  300.     register byte        word_count ;
  301.     register byte        ch ;
  302.     register int        i ;
  303.  
  304.     /*
  305.     **    Note:
  306.     **        The variable "ws" is of type "byte *"
  307.     **        NOT "byte_ptr" - these definitions are
  308.     **        different for MSDOS Compilers ("byte_ptr" is huge).
  309.     */
  310.  
  311.     word_count = 0 ;
  312.     char_ptr = in_buf_strt + 1 ;
  313.     in_buf_end = in_buf_strt + 2 + *char_ptr++ ;
  314.     wd_ptr = word_buff_strt + 2 ;
  315.  
  316.     i = 0 ;
  317.     while (( char_ptr != in_buf_end ) || ( i != 0 ))
  318.     {
  319.         i = 0 ;
  320.         last_word = char_ptr ;
  321.         white_space = FALSE ;
  322.         while (( char_ptr != in_buf_end ) && ( !white_space ))
  323.         {
  324.             ch = *char_ptr++ ;
  325.             ws = ws_buff_strt ;
  326.             while (( *ws != ch ) && ( *ws != 0 ))
  327.                 ++ws ;
  328.             if ( *ws == ch )
  329.             {
  330.                 white_space = TRUE ;
  331.                 if ( i != 0 )
  332.                     --char_ptr ;
  333.                 if (( i == 0 ) && ( ws < end_of_sentence ))
  334.                     the_word[i++] = ch ;
  335.             }
  336.             else
  337.             {
  338.                 if ( i < (int)STD_CHARS_PER_WORD )
  339.                     the_word[i++] = ch ;
  340.             }
  341.         }
  342.  
  343.         if ( i != 0 )
  344.         {
  345.  
  346.             /*
  347.             **    First byte of buffer contains the buffer length
  348.             */
  349.  
  350.             if ( word_count == *word_buff_strt )
  351.             {
  352.                 display ( "Too many words typed. Flushing: " ) ;
  353.                 *in_buf_end = 0 ;
  354.                 display ( (char *)last_word ) ;
  355.                 new_line () ;
  356.                 *(word_buff_strt + 1) = *word_buff_strt ;
  357.                 return ;
  358.             }
  359.             else
  360.             {
  361.                 ++word_count ;
  362.                 *( wd_ptr + 2 ) = (byte)(char_ptr - last_word) ;
  363.                 *( wd_ptr + 3 ) = (byte)(last_word - in_buf_strt) ;
  364.                 the_word[i] = 0 ;
  365.                 std_encode ( the_word,coded ) ;
  366.                 offset = look_up ( coded,STD_ENCODED_SIZE ) ;
  367.                 *(wd_ptr + 1) = (byte)offset ;
  368.                 *wd_ptr = (byte)(offset >> 8) ;
  369.                 wd_ptr += 4 ;
  370.             }
  371.         }
  372.     }
  373.     *(word_buff_strt + 1) = word_count ;
  374. }
  375.  
  376. /*
  377. **    Plus Version Input Routines
  378. */
  379.  
  380. Void
  381. plus_parse_buffer ( in_buf_strt,word_buff_strt )
  382. byte_ptr    in_buf_strt ;
  383. byte_ptr    word_buff_strt ;
  384. {
  385.     word                coded[PLUS_ENCODED_SIZE] ;
  386.     byte                the_word[PLUS_CHARS_PER_WORD + 1] ;
  387.     boolean                white_space ;
  388.     register word        offset ;
  389.     register byte_ptr    in_buf_end ;
  390.     register byte_ptr    last_word ;
  391.     register byte_ptr    wd_ptr ;
  392.     register byte_ptr    char_ptr ;
  393.     register byte        *ws ;
  394.     register byte        word_count ;
  395.     register byte        ch ;
  396.     register int        i ;
  397.  
  398.     /*
  399.     **    Note:
  400.     **        The variable "ws" is of type "byte *"
  401.     **        NOT "byte_ptr" - these definitions are
  402.     **        different for MSDOS Compilers ("byte_ptr" is huge).
  403.     */
  404.  
  405.     word_count = 0 ;
  406.     char_ptr = in_buf_strt + 1 ;
  407.     in_buf_end = in_buf_strt + 2 + *char_ptr++ ;
  408.     wd_ptr = word_buff_strt + 2 ;
  409.  
  410.     i = 0 ;
  411.     while (( char_ptr != in_buf_end ) || ( i != 0 ))
  412.     {
  413.         i = 0 ;
  414.         last_word = char_ptr ;
  415.         white_space = FALSE ;
  416.         while (( char_ptr != in_buf_end ) && ( !white_space ))
  417.         {
  418.             ch = *char_ptr++ ;
  419.             ws = ws_buff_strt ;
  420.             while (( *ws != ch ) && ( *ws != 0 ))
  421.                 ++ws ;
  422.             if ( *ws == ch )
  423.             {
  424.                 white_space = TRUE ;
  425.                 if ( i != 0 )
  426.                     --char_ptr ;
  427.                 if (( i == 0 ) && ( ws < end_of_sentence ))
  428.                     the_word[i++] = ch ;
  429.             }
  430.             else
  431.             {
  432.                 if ( i < (int)PLUS_CHARS_PER_WORD )
  433.                     the_word[i++] = ch ;
  434.             }
  435.         }
  436.  
  437.         if ( i != 0 )
  438.         {
  439.  
  440.             /*
  441.             **    First byte of buffer contains the buffer length
  442.             */
  443.  
  444.             if ( word_count == *word_buff_strt )
  445.             {
  446.                 display ( "Too many words typed. Flushing: " ) ;
  447.                 *in_buf_end = 0 ;
  448.                 display ( (char *)last_word ) ;
  449.                 new_line () ;
  450.                 *(word_buff_strt + 1) = *word_buff_strt ;
  451.                 return ;
  452.             }
  453.             else
  454.             {
  455.                 ++word_count ;
  456.                 *( wd_ptr + 2 ) = (byte)(char_ptr - last_word) ;
  457.                 *( wd_ptr + 3 ) = (byte)(last_word - in_buf_strt) ;
  458.                 the_word[i] = 0 ;
  459.                 plus_encode ( the_word,coded ) ;
  460.                 offset = look_up ( coded,PLUS_ENCODED_SIZE ) ;
  461.                 *(wd_ptr + 1) = (byte)offset ;
  462.                 *wd_ptr = (byte)(offset >> 8) ;
  463.                 wd_ptr += 4 ;
  464.             }
  465.         }
  466.     }
  467.     *(word_buff_strt + 1) = word_count ;
  468. }
  469.  
  470. /*
  471. **    Advanced Version Input Routines
  472. */
  473.  
  474. word
  475. scan_buffer ( start,length )
  476. byte_ptr    *start ;
  477. word        length ;
  478. {
  479.     extern byte            *end_of_sentence ;
  480.  
  481.     register boolean    white_space ;
  482.     register byte_ptr    char_ptr ;
  483.     register byte_ptr    end_of_buffer ;
  484.     register byte        *ws ;
  485.     register byte        ch ;
  486.     register word        count ;
  487.  
  488.     /*
  489.     **    Note:
  490.     **        The variable "ws" is of type "byte *"
  491.     **        NOT "byte_ptr" - these definitions are
  492.     **        different for MSDOS Compilers ("byte_ptr" is huge).
  493.     */
  494.  
  495.     count = 0 ;
  496.     white_space = FALSE ;
  497.     char_ptr = *start ;
  498.     end_of_buffer = *start + length ;
  499.     while (( char_ptr != end_of_buffer ) && ( !white_space ))
  500.     {
  501.         ch = *char_ptr++ ;
  502.         ws = ws_buff_strt ;
  503.         if ( ch <= 0x7F )
  504.         {
  505.             while (( *ws != ch ) && ( *ws != 0 ))
  506.                 ++ws ;
  507.             if ( *ws == ch )
  508.                 white_space = TRUE ;
  509.             else
  510.                 ++count ;
  511.         }
  512.         else
  513.             white_space = TRUE ;
  514.         if (( white_space == TRUE ) && ( count == 0 ))
  515.         {
  516.             if ( ws >= end_of_sentence )
  517.             {
  518.                 *start = char_ptr ;
  519.                 white_space = FALSE ;
  520.             }
  521.             else
  522.                 ++count ;
  523.         }
  524.     }
  525.     return ( count ) ;
  526. }
  527.  
  528. Void
  529. buffer_copy ( start,length,buffer,size )
  530. byte_ptr    start ;
  531. word        length ;
  532. byte        *buffer ;
  533. word        size ;
  534. {
  535.     /*
  536.     **    Note:
  537.     **        The parameter "buffer" is of type "byte *"
  538.     **        NOT "byte_ptr" - these definitions are
  539.     **        different for MSDOS Compilers ("byte_ptr" is huge).
  540.     */
  541.  
  542.     if ( length > size )
  543.         length = size ;
  544.     while ( length-- )
  545.         *buffer++ = *start++ ;
  546.     *buffer = 0 ;
  547. }
  548.  
  549. word
  550. get_code ( start,length,coded )
  551. byte_ptr    *start ;
  552. word        length ;
  553. word        coded[] ;
  554. {
  555.     byte    the_word[PLUS_CHARS_PER_WORD + 1] ;
  556.  
  557.     if (( length = scan_buffer ( start,length )) != 0 )
  558.     {
  559.         buffer_copy ( *start,length,the_word,PLUS_CHARS_PER_WORD ) ;
  560.         plus_encode ( the_word,coded ) ;
  561.     }
  562.     return ( length ) ;
  563. }
  564.  
  565. Void
  566. advanced_parse_buffer ( in_buf_strt,word_buff_strt,vocab_strt,ignore_offset )
  567. byte_ptr    in_buf_strt ;
  568. byte_ptr    word_buff_strt ;
  569. byte_ptr    vocab_strt ;
  570. word        ignore_offset ;
  571. {
  572.     register word        offset ;
  573.     register word        count ;
  574.     register word        num_bytes ;
  575.     register byte_ptr    in_buf_end ;
  576.     register byte_ptr    wd_ptr ;
  577.     byte_ptr            char_ptr ;
  578.     word                coded[PLUS_ENCODED_SIZE] ;
  579.  
  580.     init_vocab ( vocab_strt ) ;
  581.     char_ptr = in_buf_strt + 1 ;
  582.     num_bytes = *char_ptr++ ;
  583.     in_buf_end = char_ptr + num_bytes ;
  584.     wd_ptr = word_buff_strt + 1 ;
  585.     *wd_ptr++ = 0 ;
  586.  
  587.     while (( num_bytes = (byte)( in_buf_end - char_ptr )) != 0 )
  588.     {
  589.         if (( count = get_code ( &char_ptr,num_bytes,coded )) == 0 )
  590.             return ;
  591.  
  592.         if ( *(word_buff_strt + 1) == *word_buff_strt )
  593.         {
  594.             display ( "Too many words typed. Flushing: " ) ;
  595.             *in_buf_end = 0 ;
  596.             display ( (char *)char_ptr ) ;
  597.             new_line () ;
  598.             return ;
  599.         }
  600.  
  601.         ++(*(word_buff_strt + 1)) ;
  602.         offset = look_up ( coded,PLUS_ENCODED_SIZE ) ;
  603.         if (( offset != 0 ) || ( ignore_offset == 0 ))
  604.         {
  605.             *(wd_ptr + 1) = (byte)offset ;
  606.             *wd_ptr = (byte)(offset >> 8) ;
  607.         }
  608.         *( wd_ptr + 2 ) = (byte)count ;
  609.         *( wd_ptr + 3 ) = (byte)(char_ptr - in_buf_strt) ;
  610.         wd_ptr += 4 ;
  611.         char_ptr += count ;
  612.     }
  613. }
  614.