- 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 HaveDefault; /* Remember if we had a default label */
- 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;
- HaveDefault = 0;
-
- /* 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 (!IsClassInt (lval.e_tptr)) {
- Error ("Switch quantity not an integer");
- }
-
- /* Check the range of the expression */
- Val = lval.e_const;
- switch (*eval->e_tptr) {
-
- case T_SCHAR:
- /* Signed char */
- if (Val < -128 || Val > 127) {
- Error ("Range error");
- }
- break;
-
- case T_UCHAR:
- if (Val < 0 || Val > 255) {
- Error ("Range error");
- }
- break;
-
- case T_INT:
- if (Val < -32768 || Val > 32767) {
- Error ("Range error");
- }
- break;
-
- case T_UINT:
- if (Val < 0 || Val > 65535) {
- Error ("Range error");
- }
- 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);
- }
-
- /* Remember that we had a default label */
- HaveDefault = 1;
- }
-
- }
-
- }