-static void cascadeswitch (struct expent* eval)
-/* Handle a switch statement for chars with a cmp cascade for the selector */
-{
- unsigned exitlab; /* Exit label */
- unsigned nextlab; /* Next case label */
- unsigned codelab; /* Label that starts the actual selector code */
- int havebreak; /* Remember if we exited with break */
- int lcount; /* Label count */
- unsigned flags; /* Code generator flags */
- struct expent lval; /* Case label expression */
- long val; /* Case label value */
-
-
- /* Create a loop so we may break out, init labels */
- exitlab = GetLabel ();
- addloop (oursp, 0, exitlab, 0, 0);
-
- /* Setup some variables needed in the loop below */
- flags = TypeOf (eval->e_tptr) | CF_CONST | CF_FORCECHAR;
- codelab = nextlab = 0;
- havebreak = 1;
-
- /* Parse the labels */
- lcount = 0;
- while (curtok != TOK_RCURLY) {
-
- if (curtok == TOK_CASE || curtok == TOK_DEFAULT) {
-
- /* If the code for the previous selector did not end with a
- * break statement, we must jump over the next selector test.
- */
- if (!havebreak) {
- /* Define a label for the code */
- if (codelab == 0) {
- codelab = GetLabel ();
- }
- g_jump (codelab);
- }
-
- /* If we have a cascade label, emit it */
- if (nextlab) {
- g_defloclabel (nextlab);
- nextlab = 0;
- }
-
- while (curtok == TOK_CASE || curtok == TOK_DEFAULT) {
-
- /* Parse the selector */
- if (curtok == TOK_CASE) {
-
- /* Count labels */
- ++lcount;
-
- /* Skip the "case" token */
- NextToken ();
-
- /* Read the selector expression */
- constexpr (&lval);
- if (!IsInt (lval.e_tptr)) {
- Error (ERR_ILLEGAL_TYPE);
- }
-
- /* Check the range of the expression */
- val = lval.e_const;
- switch (*eval->e_tptr) {
-
- case T_CHAR:
- /* Signed char */
- if (val < -128 || val > 127) {
- Error (ERR_RANGE);
- }
- break;
-
- case T_UCHAR:
- if (val < 0 || val > 255) {
- Error (ERR_RANGE);
- }
- break;
-
- case T_INT:
- if (val < -32768 || val > 32767) {
- Error (ERR_RANGE);
- }
- break;
-
- case T_UINT:
- if (val < 0 || val > 65535) {
- Error (ERR_RANGE);
- }
- break;
-
- default:
- Internal ("Invalid type: %02X", *eval->e_tptr & 0xFF);
- }
-
- /* Skip the colon */
- ConsumeColon ();
-
- /* Emit a compare */
- g_cmp (flags, val);
-
- /* If another case follows, we will jump to the code if
- * the condition is true.
- */
- if (curtok == TOK_CASE) {
- /* Create a code label if needed */
- if (codelab == 0) {
- codelab = GetLabel ();
- }
- g_falsejump (CF_NONE, codelab);
- } else if (curtok != TOK_DEFAULT) {
- /* No case follows, jump to next selector */
- if (nextlab == 0) {
- nextlab = GetLabel ();
- }
- g_truejump (CF_NONE, nextlab);
- }
-
- } else {
-
- /* Default case */
- NextToken ();
-
- /* Skip the colon */
- ConsumeColon ();
-
- /* Handle the pathologic case: DEFAULT followed by CASE */
- if (curtok == TOK_CASE) {
- if (codelab == 0) {
- codelab = GetLabel ();
- }
- g_jump (codelab);
- }
- }
-
- }