@@ -1629,6 +1629,145 @@ static int hier2(value *lval)
1629
1629
} /* if */
1630
1630
return FALSE;
1631
1631
} /* case */
1632
+ case tSWITCH : {
1633
+ int swdefault ,casecount ,firstcase ;
1634
+ int swtag ,csetag ,exprtag ;
1635
+ int lbl_table ,lbl_exit ,lbl_case ;
1636
+ int ident ,index ;
1637
+ int bck_allowtags ;
1638
+ cell cidx ;
1639
+ constvalue_root caselist = { NULL , NULL }; /* case list starts empty */
1640
+ constvalue * cse ,* csp ,* newval ;
1641
+ char labelname [sNAMEMAX + 1 ];
1642
+ needtoken ('(' );
1643
+ ident = expression (& val ,& swtag ,NULL ,TRUE);
1644
+ if (ident == iARRAY || ident == iREFARRAY )
1645
+ error (33 ,"-unknown-" ); /* array must be indexed */
1646
+ /* generate the code for the switch statement, the label is the address
1647
+ * of the case table (to be generated later).
1648
+ */
1649
+ lbl_table = getlabel ();
1650
+ lbl_case = 0 ; /* just to avoid a compiler warning */
1651
+ ffswitch (lbl_table );
1652
+ lbl_exit = getlabel (); /* get label number for jumping out of switch */
1653
+ casecount = 0 ;
1654
+ swdefault = FALSE;
1655
+ firstcase = TRUE;
1656
+ do {
1657
+ needtoken (tTERM );
1658
+ ident = lex (& val ,& st );
1659
+ if (ident == ')' )
1660
+ break ;
1661
+ lbl_case = getlabel ();
1662
+ setlabel (lbl_case );
1663
+ bck_allowtags = sc_allowtags ;
1664
+ sc_allowtags = FALSE; /* do not allow tagnames here */
1665
+ if (ident == tLABEL && st [0 ]== '_' && st [1 ]== '\0' ) {
1666
+ if (swdefault != FALSE)
1667
+ error (16 ); /* multiple defaults in switch */
1668
+ swdefault = TRUE;
1669
+ } else {
1670
+ if (ident != tLABEL )
1671
+ lexpush ();
1672
+ else
1673
+ error (220 ); /* expression with tag override must appear between parentheses */
1674
+ if (swdefault != FALSE)
1675
+ error (15 ); /* "default" case must be last in switch statement */
1676
+ do {
1677
+ casecount ++ ;
1678
+ stgget (& index ,& cidx ); /* mark position in code generator */
1679
+ ident = expression (& val ,& csetag ,NULL ,TRUE);
1680
+ stgdel (index ,cidx ); /* scratch generated code */
1681
+ if (ident != iCONSTEXPR )
1682
+ error (8 ); /* must be constant expression */
1683
+ check_tagmismatch (swtag ,csetag ,TRUE,-1 );
1684
+ /* Search the insertion point (the table is kept in sorted order, so
1685
+ * that advanced abstract machines can sift the case table with a
1686
+ * binary search). Check for duplicate case values at the same time.
1687
+ */
1688
+ for (csp = NULL , cse = caselist .first ;
1689
+ cse != NULL && cse -> value < val ;
1690
+ csp = cse , cse = cse -> next )
1691
+ /* nothing */ ;
1692
+ if (cse != NULL && cse -> value == val )
1693
+ error (40 ,val ); /* duplicate "case" label */
1694
+ /* Since the label is stored as a string in the "constvalue", the
1695
+ * size of an identifier must be at least 8, as there are 8
1696
+ * hexadecimal digits in a 32-bit number.
1697
+ */
1698
+ #if sNAMEMAX < 8
1699
+ #error Length of identifier (sNAMEMAX) too small.
1700
+ #endif
1701
+ assert (csp == NULL || csp -> next == cse );
1702
+ newval = insert_constval (csp ,cse ,itoh (lbl_case ),val ,0 );
1703
+ if (csp == NULL )
1704
+ caselist .first = newval ;
1705
+ if (matchtoken (tDBLDOT )) {
1706
+ cell end ;
1707
+ stgget (& index ,& cidx ); /* mark position in code generator */
1708
+ ident = expression (& end ,& csetag ,NULL ,TRUE);
1709
+ stgdel (index ,cidx ); /* scratch generated code */
1710
+ if (ident != iCONSTEXPR )
1711
+ error (8 ); /* must be constant expression */
1712
+ if (end <=val )
1713
+ error (50 ); /* invalid range */
1714
+ while (++ val <=end ) {
1715
+ casecount ++ ;
1716
+ /* find the new insertion point */
1717
+ for (csp = NULL , cse = caselist .first ;
1718
+ cse != NULL && cse -> value < val ;
1719
+ csp = cse , cse = cse -> next )
1720
+ /* nothing */ ;
1721
+ if (cse != NULL && cse -> value == val )
1722
+ error (40 ,val ); /* duplicate "case" label */
1723
+ assert (csp == NULL || csp -> next == cse );
1724
+ insert_constval (csp ,cse ,itoh (lbl_case ),val ,0 );
1725
+ } /* while */
1726
+ } /* if */
1727
+ } while (matchtoken (',' ));
1728
+ needtoken (':' ); /* ':' ends the case */
1729
+ } /* if */
1730
+ sc_allowtags = bck_allowtags ; /* reset */
1731
+ ident = expression (NULL ,& exprtag ,NULL ,FALSE);
1732
+ if (ident == iARRAY || ident == iREFARRAY )
1733
+ error (33 ,"-unknown-" ); /* array must be indexed */
1734
+ if (firstcase ) {
1735
+ tag = exprtag ;
1736
+ firstcase = FALSE;
1737
+ } else {
1738
+ check_tagmismatch (tag ,exprtag ,TRUE,-1 );
1739
+ } /* if */
1740
+ jumplabel (lbl_exit );
1741
+ } while (!matchtoken (')' ));
1742
+ #if !defined NDEBUG
1743
+ /* verify that the case table is sorted (unfortunately, duplicates can
1744
+ * occur; there really shouldn't be duplicate cases, but the compiler
1745
+ * may not crash or drop into an assertion for a user error). */
1746
+ for (cse = caselist .first ; cse != NULL && cse -> next != NULL ; cse = cse -> next )
1747
+ assert (cse -> value <= cse -> next -> value );
1748
+ #endif
1749
+ /* generate the table here, before lbl_exit (general jump target) */
1750
+ setlabel (lbl_table );
1751
+ assert (swdefault == FALSE || swdefault == TRUE);
1752
+ if (swdefault == FALSE) {
1753
+ /* store lbl_exit as the "none-matched" label in the switch table */
1754
+ strcpy (labelname ,itoh (lbl_exit ));
1755
+ } else {
1756
+ /* lbl_case holds the label of the "default" clause */
1757
+ strcpy (labelname ,itoh (lbl_case ));
1758
+ } /* if */
1759
+ ffcase (casecount ,labelname ,TRUE);
1760
+ /* generate the rest of the table */
1761
+ for (cse = caselist .first ; cse != NULL ; cse = cse -> next )
1762
+ ffcase (cse -> value ,cse -> name ,FALSE);
1763
+
1764
+ setlabel (lbl_exit );
1765
+ delete_consttable (& caselist ); /* clear list of case labels */
1766
+ clear_value (lval );
1767
+ lval -> ident = iEXPRESSION ;
1768
+ lval -> tag = tag ;
1769
+ return FALSE;
1770
+ } /* case */
1632
1771
case t__EMIT :
1633
1772
paranthese = matchtoken ('(' );
1634
1773
emit_flags |= efEXPR ;
0 commit comments