switch.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* $Header$ */
  2. /* S W I T C H - S T A T E M E N T A D M I N I S T R A T I O N */
  3. #include <em.h>
  4. #include "debug.h"
  5. #include "botch_free.h"
  6. #include "density.h"
  7. #include "Lpars.h"
  8. #include "idf.h"
  9. #include "label.h"
  10. #include "arith.h"
  11. #include "switch.h"
  12. #include "code.h"
  13. #include "storage.h"
  14. #include "assert.h"
  15. #include "expr.h"
  16. #include "type.h"
  17. extern char options[];
  18. #define compact(nr, low, up) (nr != 0 && (up - low) / nr <= (DENSITY - 1))
  19. static struct switch_hdr *switch_stack = 0;
  20. code_startswitch(expr)
  21. struct expr *expr;
  22. {
  23. /* Check the expression, stack a new case header and
  24. fill in the necessary fields.
  25. */
  26. register label l_table = text_label();
  27. register label l_break = text_label();
  28. register struct switch_hdr *sh = new_switch_hdr();
  29. int fund = any2arith(&expr, SWITCH); /* INT, LONG or DOUBLE */
  30. switch (fund) {
  31. case LONG:
  32. if (options['R'])
  33. warning("long in switch");
  34. break;
  35. case DOUBLE:
  36. error("float/double in switch");
  37. erroneous2int(&expr);
  38. break;
  39. }
  40. stat_stack(l_break, NO_LABEL);
  41. sh->sh_break = l_break;
  42. sh->sh_default = 0;
  43. sh->sh_table = l_table;
  44. sh->sh_nrofentries = 0;
  45. sh->sh_type = expr->ex_type; /* the expression switched */
  46. sh->sh_lowerbd = sh->sh_upperbd = (arith)0; /* immaterial ??? */
  47. sh->sh_entries = (struct case_entry *) 0; /* case-entry list */
  48. sh->next = switch_stack; /* push onto switch-stack */
  49. switch_stack = sh;
  50. code_expr(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
  51. /* evaluate the switch expr. */
  52. C_bra(l_table); /* goto start of switch_table */
  53. }
  54. code_endswitch()
  55. {
  56. register struct switch_hdr *sh = switch_stack;
  57. register label tablabel;
  58. register struct case_entry *ce;
  59. if (sh->sh_default == 0) /* no default occurred yet */
  60. sh->sh_default = sh->sh_break;
  61. C_bra(sh->sh_break); /* skip the switch table now */
  62. C_df_ilb(sh->sh_table); /* switch table entry */
  63. tablabel = data_label(); /* the rom must have a label */
  64. C_df_dlb(tablabel);
  65. C_rom_ilb(sh->sh_default);
  66. if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
  67. /* CSA */
  68. register arith val;
  69. C_rom_cst(sh->sh_lowerbd);
  70. C_rom_cst(sh->sh_upperbd - sh->sh_lowerbd);
  71. ce = sh->sh_entries;
  72. for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
  73. ASSERT(ce);
  74. if (val == ce->ce_value) {
  75. C_rom_ilb(ce->ce_label);
  76. ce = ce->next;
  77. }
  78. else
  79. C_rom_ilb(sh->sh_default);
  80. }
  81. C_lae_dlb(tablabel, (arith)0); /* perform the switch */
  82. C_csa(sh->sh_type->tp_size);
  83. }
  84. else { /* CSB */
  85. C_rom_cst((arith)sh->sh_nrofentries);
  86. for (ce = sh->sh_entries; ce; ce = ce->next) {
  87. /* generate the entries: value + prog.label */
  88. C_rom_cst(ce->ce_value);
  89. C_rom_ilb(ce->ce_label);
  90. }
  91. C_lae_dlb(tablabel, (arith)0); /* perform the switch */
  92. C_csb(sh->sh_type->tp_size);
  93. }
  94. C_df_ilb(sh->sh_break);
  95. switch_stack = sh->next; /* unstack the switch descriptor */
  96. /* free the allocated switch structure */
  97. ce = sh->sh_entries;
  98. while (ce) {
  99. register struct case_entry *tmp = ce->next;
  100. free_case_entry(ce);
  101. ce = tmp;
  102. }
  103. free_switch_hdr(sh);
  104. stat_unstack();
  105. }
  106. code_case(expr)
  107. struct expr *expr;
  108. {
  109. register arith val;
  110. register struct case_entry *ce;
  111. register struct switch_hdr *sh = switch_stack;
  112. if (sh == 0) {
  113. error("case statement not in switch");
  114. return;
  115. }
  116. if (expr->ex_flags & EX_ERROR) {
  117. /* is probably 0 anyway */
  118. return;
  119. }
  120. expr->ex_type = sh->sh_type;
  121. cut_size(expr);
  122. ce = new_case_entry();
  123. C_df_ilb(ce->ce_label = text_label());
  124. ce->ce_value = val = expr->VL_VALUE;
  125. if (sh->sh_entries == 0) {
  126. /* first case entry */
  127. ce->next = (struct case_entry *) 0;
  128. sh->sh_entries = ce;
  129. sh->sh_lowerbd = sh->sh_upperbd = val;
  130. sh->sh_nrofentries = 1;
  131. }
  132. else {
  133. /* second etc. case entry */
  134. /* find the proper place to put ce into the list */
  135. register struct case_entry *c1 = sh->sh_entries, *c2 = 0;
  136. if (val < sh->sh_lowerbd)
  137. sh->sh_lowerbd = val;
  138. else
  139. if (val > sh->sh_upperbd)
  140. sh->sh_upperbd = val;
  141. while (c1 && c1->ce_value < ce->ce_value) {
  142. c2 = c1;
  143. c1 = c1->next;
  144. }
  145. /* At this point three cases are possible:
  146. 1: c1 != 0 && c2 != 0:
  147. insert ce somewhere in the middle
  148. 2: c1 != 0 && c2 == 0:
  149. insert ce right after the head
  150. 3: c1 == 0 && c2 != 0:
  151. append ce to last element
  152. The case c1 == 0 && c2 == 0 cannot occur, since
  153. the list is guaranteed not to be empty.
  154. */
  155. if (c1) {
  156. if (c1->ce_value == ce->ce_value) {
  157. error("multiple case entry for value %ld",
  158. ce->ce_value);
  159. free_case_entry(ce);
  160. return;
  161. }
  162. if (c2) {
  163. ce->next = c2->next;
  164. c2->next = ce;
  165. }
  166. else {
  167. ce->next = sh->sh_entries;
  168. sh->sh_entries = ce;
  169. }
  170. }
  171. else {
  172. ASSERT(c2);
  173. ce->next = (struct case_entry *) 0;
  174. c2->next = ce;
  175. }
  176. (sh->sh_nrofentries)++;
  177. }
  178. }
  179. code_default()
  180. {
  181. register struct switch_hdr *sh = switch_stack;
  182. if (sh == 0) {
  183. error("default not in switch");
  184. return;
  185. }
  186. if (sh->sh_default != 0) {
  187. error("multiple entry for default in switch");
  188. return;
  189. }
  190. C_df_ilb(sh->sh_default = text_label());
  191. }