home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / MAWK113.ZIP / mawk113 / jmp.c < prev    next >
C/C++ Source or Header  |  1991-12-04  |  4KB  |  213 lines

  1.  
  2. /********************************************
  3. jmp.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13. /* $Log: jmp.c,v $
  14.  * Revision 5.1  1991/12/05  07:56:10  brennan
  15.  * 1.1 pre-release
  16.  *
  17. */
  18.  
  19. /* this module deals with back patching jumps, breaks and continues,
  20.    and with save and restoring code when we move code.
  21.    There are three stacks.  If we encounter a compile error, the
  22.    stacks are frozen, i.e., we do not attempt error recovery
  23.    on the stacks
  24. */
  25.  
  26.  
  27. #include "mawk.h"
  28. #include "jmp.h"
  29. #include "code.h"
  30. #include "sizes.h"
  31. #include "init.h"
  32. #include "memory.h"
  33.  
  34. extern unsigned compile_error_count ;
  35. #define error_state  (compile_error_count>0)
  36.  
  37.  
  38. /*---------- back patching jumps  ---------------*/
  39.  
  40. typedef  struct jmp {
  41. struct jmp *link ;
  42. INST *source ;
  43. } JMP ;
  44.  
  45. static JMP *jmp_top ;
  46.  
  47. void code_jmp( jtype, target)
  48.   int jtype ; 
  49.   INST *target ;
  50.   register INST *source ;
  51.  
  52.   if (error_state)  return ;
  53.  
  54.   code1(jtype) ;
  55.   source = code_ptr++ ;
  56.  
  57.   if ( target ) source->op = target - source ;
  58.   else  /* save source on jump stack */
  59.   {
  60.     register JMP *p = (JMP*) zmalloc(sizeof(JMP)) ;
  61.     p->source = source ;
  62.     p->link = jmp_top ;
  63.     jmp_top = p ;
  64.   }
  65. }
  66.  
  67. void patch_jmp(target)  /* patch a jump on the jmp_stack */
  68.   INST *target ;
  69. { register JMP *p ;
  70.  
  71.   if ( ! error_state )
  72.   {
  73. #ifdef  DEBUG
  74.     if (!jmp_top) bozo("jmp stack underflow") ;
  75. #endif
  76.  
  77.     p = jmp_top ; jmp_top = p->link ;
  78.  
  79.     p->source->op = target - p->source ;
  80.  
  81.     zfree(p, sizeof(JMP)) ;
  82.   }
  83. }
  84.  
  85.  
  86. /*-- break and continue -------*/
  87.  
  88. typedef struct bc {
  89. struct bc *link ;  /* stack as linked list */
  90. int type ;         /* 'B' or 'C' or mark start with 0 */
  91. INST *source ;     /* position of _JMP  */
  92. } BC ;
  93.  
  94. static BC *bc_top ;  
  95.  
  96.  
  97.  
  98. void BC_new()  /* mark the start of a loop */
  99.   BC_insert(0, (INST*) 0 ) ;  
  100. }
  101.  
  102. void BC_insert(type, address)
  103.   int type ; INST *address ;
  104. { register BC * p  ;
  105.  
  106.   if ( error_state )  return ;
  107.  
  108.   if ( type && ! bc_top )
  109.   {
  110.     compile_error("%s statement outside of loop",
  111.       type == 'B' ? "break" : "continue" ) ;
  112.     
  113.     return ;
  114.   }
  115.   else
  116.   {
  117.     p = (BC*) zmalloc(sizeof(BC)) ;
  118.     p->type = type ;
  119.     p->source = address ;
  120.     p->link = bc_top ;
  121.     bc_top = p ;
  122.   }
  123. }
  124.  
  125.  
  126. void BC_clear(B_address, C_address)  
  127. /* patch all break and continues for one loop */
  128. INST *B_address, *C_address ;
  129. { register  BC *p , *q ;
  130.  
  131.   if (error_state) return ;
  132.  
  133.   p = bc_top ;
  134.   /* pop down to the mark node */
  135.   while ( p->type )
  136.   {
  137.     p->source->op = (p->type == 'B' ? B_address : C_address)
  138.               - p->source ;
  139.  
  140.     q = p ; p = p->link ; zfree(q, sizeof(BC)) ;
  141.   }
  142.   /* remove the mark node */
  143.   bc_top = p->link ;
  144.   zfree(p, sizeof(BC)) ;
  145. }
  146.  
  147. /*-----  moving code --------------------------*/
  148.  
  149. /* a stack to hold some pieces of code while 
  150.    reorganizing loops .
  151.    This used to be used on all loops.  Now it is used
  152.    only for the 3rd expression on a for loop and
  153.    for the fist part of a range pattern
  154. */
  155.  
  156. typedef  struct mc {  /* mc -- move code */
  157. struct mc *link ;
  158. INST *code ;
  159. unsigned len ;
  160. }  MC ;
  161.  
  162. static MC *mc_top ;
  163.  
  164.  
  165. void code_push( code, len)
  166.   INST *code ; unsigned len ;
  167.   register MC *p ;
  168.  
  169.   if (! error_state ) 
  170.   {
  171.     p = (MC*) zmalloc(sizeof(MC)) ;
  172.     p->len = len ;
  173.     p->link = mc_top ;
  174.     mc_top = p ;
  175.  
  176.     if ( len )
  177.     {
  178.       p->code = (INST*) zmalloc(sizeof(INST)*len) ;
  179.       (void) memcpy(p->code, code, SIZE_T(sizeof(INST)*len)) ;
  180.     }
  181.   }
  182. }
  183.  
  184. /* copy the code at the top of the mc stack to target.
  185.    return the number of INSTs moved */
  186.  
  187. unsigned code_pop(target) 
  188.   INST *target ;
  189.   register MC *p ;
  190.   unsigned retval ;
  191.  
  192.   if (error_state)  return 0 ;
  193.  
  194. #ifdef  DEBUG
  195.   if ( ! mc_top ) bozo("mc underflow") ;
  196. #endif
  197.  
  198.   p = mc_top ; mc_top = p->link ;
  199.   
  200.   if ( retval = p->len )
  201.   {
  202.     (void) memcpy(target, p->code, SIZE_T(p->len*sizeof(INST))) ;
  203.     zfree(p->code, p->len*sizeof(INST)) ; 
  204.   }
  205.  
  206.   zfree(p, sizeof(MC)) ;
  207.   return retval ;
  208. }
  209.