Teach lint about C99's _Bool and _Complex, plus some related gcc
authorguenther <guenther@openbsd.org>
Sat, 24 Jul 2010 22:17:03 +0000 (22:17 +0000)
committerguenther <guenther@openbsd.org>
Sat, 24 Jul 2010 22:17:03 +0000 (22:17 +0000)
extensions: __real__ and __imag__ operators, the use of '~' for
complex conjugation, and 'i' or 'j' as a suffix for complex constants.
While this doesn't handle folding and overflow detection for complex
constants correctly, it's good enough to make it through libm...and
found several bugs once it could do so.

"no objections" miod@, krw@

13 files changed:
include/complex.h
include/stdbool.h
usr.bin/xlint/lint1/decl.c
usr.bin/xlint/lint1/emit1.c
usr.bin/xlint/lint1/externs1.h
usr.bin/xlint/lint1/lint.h
usr.bin/xlint/lint1/lint1.h
usr.bin/xlint/lint1/op.h
usr.bin/xlint/lint1/scan.l
usr.bin/xlint/lint1/tree.c
usr.bin/xlint/lint2/chk.c
usr.bin/xlint/lint2/emit2.c
usr.bin/xlint/lint2/read.c

index aa89d70..be85c7c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: complex.h,v 1.2 2008/12/04 03:52:31 ray Exp $ */
+/*     $OpenBSD: complex.h,v 1.3 2010/07/24 22:17:03 guenther Exp $    */
 /*
  * Copyright (c) 2008 Martynas Venckus <martynas@openbsd.org>
  *
@@ -28,6 +28,8 @@
 #define _Complex       __complex__
 #endif
 #define _Complex_I     1.0fi
+#elif defined(lint)
+#define _Complex_I     1.0fi
 #endif
 
 #define complex                _Complex
index cc1104c..3430413 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: stdbool.h,v 1.4 2007/10/02 14:06:16 otto Exp $ */
+/* $OpenBSD: stdbool.h,v 1.5 2010/07/24 22:17:03 guenther Exp $ */
 
 /*
  * Written by Marc Espie, September 25, 1999
@@ -10,7 +10,7 @@
 
 #ifndef __cplusplus
 
-#if (defined(__GNUC__) && __GNUC__ >= 3) || defined(__PCC__)
+#if (defined(__GNUC__) && __GNUC__ >= 3) || defined(__PCC__) || defined(lint)
 /* Support for _C99: type _Bool is already built-in. */
 #define false  0
 #define true   1
index bd52fdd..3ee6f39 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: decl.c,v 1.24 2007/11/27 16:22:14 martynas Exp $      */
+/*     $OpenBSD: decl.c,v 1.25 2010/07/24 22:17:03 guenther Exp $      */
 /*     $NetBSD: decl.c,v 1.11 1995/10/02 17:34:16 jpo Exp $    */
 
 /*
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$OpenBSD: decl.c,v 1.24 2007/11/27 16:22:14 martynas Exp $";
+static char rcsid[] = "$OpenBSD: decl.c,v 1.25 2010/07/24 22:17:03 guenther Exp $";
 #endif
 
 #include <sys/param.h>
@@ -97,6 +97,9 @@ initdecl(void)
                { UNSIGN,   { 0, 0, 0,
                              SIGNED, UNSIGN,
                              0, 0, 0, 0, 0, "unsigned" } },
+               { BOOL,     { sizeof (_Bool) * CHAR_BIT, CHAR_BIT, 1,
+                             BOOL, BOOL,
+                             1, 1, 0, 1, 1, "_Bool" } },
                { CHAR,     { CHAR_BIT, CHAR_BIT, 20,
                              SCHAR, UCHAR,
                              1, 0, 0, 1, 1, "char" } },
@@ -139,6 +142,32 @@ initdecl(void)
                { LDOUBLE,  { sizeof (ldbl_t) * CHAR_BIT, 10 * CHAR_BIT, -1,
                              LDOUBLE, LDOUBLE,
                              0, 0, 1, 1, 1, "long double" } },
+               { COMPLEX,  { sizeof (float _Complex) * CHAR_BIT,
+                             8 * CHAR_BIT, -1,
+                             COMPLEX, COMPLEX,
+                             0, 0, 1, 1, 3, "float _Complex" } },
+               { DCOMPLEX, { sizeof (double _Complex) * CHAR_BIT,
+                             16 * CHAR_BIT, -1,
+                             DCOMPLEX, DCOMPLEX,
+                             0, 0, 1, 1, 3, "double _Complex" } },
+               { LDCOMPLEX,{ sizeof (long double _Complex) * CHAR_BIT,
+                             20 * CHAR_BIT, -1,
+                             LDCOMPLEX, LDCOMPLEX,
+                             0, 0, 1, 1, 3, "long double _Complex" } },
+#if 0
+               { IMAGINARY,{ sizeof (float _Imaginary) * CHAR_BIT,
+                             4 * CHAR_BIT, -1,
+                             IMAGINARY, IMAGINARY,
+                             0, 0, 1, 1, 2, "float _Imaginary" } },
+               { DIMAGINARY,{ sizeof (double _Imaginary) * CHAR_BIT,
+                             8 * CHAR_BIT, -1,
+                             DIMAGINARY, DIMAGINARY,
+                             0, 0, 1, 1, 2, "double _Imaginary" } },
+               { LDIMAGINARY,{ sizeof (long double _Imaginary) * CHAR_BIT,
+                             10 * CHAR_BIT, -1,
+                             LDIMAGINARY, LDIMAGINARY,
+                             0, 0, 1, 1, 2, "long double _Imaginary" } },
+#endif
                { VOID,     { -1, -1, -1,
                              VOID, VOID,
                              0, 0, 0, 0, 0, "void" } },
@@ -179,6 +208,7 @@ initdecl(void)
        typetab = xcalloc(NTSPEC, sizeof (type_t));
        for (i = 0; i < NTSPEC; i++)
                typetab[i].t_tspec = NOTSPEC;
+       typetab[BOOL].t_tspec = BOOL;
        typetab[CHAR].t_tspec = CHAR;
        typetab[SCHAR].t_tspec = SCHAR;
        typetab[UCHAR].t_tspec = UCHAR;
@@ -193,6 +223,12 @@ initdecl(void)
        typetab[FLOAT].t_tspec = FLOAT;
        typetab[DOUBLE].t_tspec = DOUBLE;
        typetab[LDOUBLE].t_tspec = LDOUBLE;
+       typetab[COMPLEX].t_tspec = COMPLEX;
+       typetab[DCOMPLEX].t_tspec = DCOMPLEX;
+       typetab[LDCOMPLEX].t_tspec = LDCOMPLEX;
+       typetab[IMAGINARY].t_tspec = IMAGINARY;
+       typetab[DIMAGINARY].t_tspec = DIMAGINARY;
+       typetab[LDIMAGINARY].t_tspec = LDIMAGINARY;
        typetab[VOID].t_tspec = VOID;
        /*
         * Next two are not real types. They are only used by the parser
@@ -203,7 +239,7 @@ initdecl(void)
 }
 
 /*
- * Returns a shared type structure vor arithmetic types and void.
+ * Returns a shared type structure for arithmetic types and void.
  *
  * It's important to duplicate this structure (using duptyp() or tduptyp())
  * if it is to be modified (adding qualifiers or anything else).
@@ -327,7 +363,8 @@ addtype(type_t *tp)
 
        if (tp->t_typedef) {
                if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC ||
-                   dcs->d_lmod != NOTSPEC || dcs->d_smod != NOTSPEC) {
+                   dcs->d_lmod != NOTSPEC || dcs->d_smod != NOTSPEC ||
+                   dcs->d_dmod != NOTSPEC) {
                        /*
                         * something like "typedef int a; int a b;"
                         * This should not happen with current grammar.
@@ -346,13 +383,15 @@ addtype(type_t *tp)
                 * struct/union/enum with anything else is not allowed
                 */
                if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC ||
-                   dcs->d_lmod != NOTSPEC || dcs->d_smod != NOTSPEC) {
+                   dcs->d_lmod != NOTSPEC || dcs->d_smod != NOTSPEC ||
+                   dcs->d_dmod != NOTSPEC) {
                        /*
                         * remember that an error must be reported in
                         * deftyp().
                         */
                        dcs->d_terr = 1;
-                       dcs->d_atyp = dcs->d_lmod = dcs->d_smod = NOTSPEC;
+                       dcs->d_atyp = dcs->d_smod = dcs->d_lmod =
+                           dcs->d_dmod = NOTSPEC;
                }
                dcs->d_type = tp;
                return;
@@ -401,6 +440,15 @@ addtype(type_t *tp)
                        /* more than one, print error in deftyp() */
                        dcs->d_terr = 1;
                dcs->d_lmod = t;
+       } else if (t == COMPLEX || t == IMAGINARY) {
+               /*
+                * remember specifiers "_Complex" and "_Imaginary" in
+                * dcs->d_dmod
+                */
+               if (dcs->d_dmod != NOTSPEC)
+                       /* more than one, print error in deftyp() */
+                       dcs->d_terr = 1;
+               dcs->d_dmod = t;
        } else {
                /*
                 * remember specifiers "void", "char", "int", "float" or
@@ -447,7 +495,8 @@ tdeferr(type_t *td, tspec_t t)
                break;
        case LONG:
                if (t2 == INT || t2 == UINT || t2 == LONG || t2 == ULONG ||
-                   t2 == FLOAT || t2 == DOUBLE) {
+                   t2 == FLOAT || t2 == DOUBLE || t2 == COMPLEX ||
+                   t2 == IMAGINARY) {
                        /* modifying typedef with ... */
                        warning(5, "long");
                        if (t2 == INT) {
@@ -462,6 +511,14 @@ tdeferr(type_t *td, tspec_t t)
                                td = gettyp(DOUBLE);
                        } else if (t2 == DOUBLE) {
                                td = gettyp(LDOUBLE);
+                       } else if (t2 == COMPLEX) {
+                               td = gettyp(DCOMPLEX);
+                       } else if (t2 == DCOMPLEX) {
+                               td = gettyp(LDCOMPLEX);
+                       } else if (t2 == IMAGINARY) {
+                               td = gettyp(DIMAGINARY);
+                       } else if (t2 == DIMAGINARY) {
+                               td = gettyp(LDIMAGINARY);
                        }
                        td = duptyp(td);
                        td->t_typedef = 1;
@@ -657,7 +714,7 @@ setasm(void)
 void
 clrtyp(void)
 {
-       dcs->d_atyp = dcs->d_smod = dcs->d_lmod = NOTSPEC;
+       dcs->d_atyp = dcs->d_smod = dcs->d_lmod = dcs->d_dmod = NOTSPEC;
        dcs->d_scl = NOSCL;
        dcs->d_type = NULL;
        dcs->d_const = dcs->d_volatile = 0;
@@ -667,6 +724,33 @@ clrtyp(void)
        dcs->d_notyp = 0;
 }
 
+/*
+ * Merge the domain (_Complex or _Imaginary) into a type.  Returns non-zero
+ * if the merge doesn't make sense.  e.g., no "int _Complex".
+ */
+int
+mergedomain(tspec_t *tp, tspec_t domain)
+{
+       if (domain == NOTSPEC)
+               return (0);
+       if (domain != COMPLEX && domain != IMAGINARY)
+               lerror("mergedomain()");
+       switch (*tp) {
+       case FLOAT:
+               *tp = domain;
+               break;
+       case DOUBLE:
+               *tp = domain == COMPLEX ? DCOMPLEX : DIMAGINARY;
+               break;
+       case LDOUBLE:
+               *tp = domain == COMPLEX ? LDCOMPLEX : LDIMAGINARY;
+               break;
+       default:
+               return (1);
+       }
+       return (0);
+}
+
 /*
  * Create a type structure from the informations gathered in
  * the declaration stack.
@@ -676,13 +760,15 @@ clrtyp(void)
 void
 deftyp(void)
 {
-       tspec_t t, s, l;
+       tspec_t t, s, l, d;
        type_t  *tp;
        scl_t   scl;
 
-       t = dcs->d_atyp;                /* CHAR, INT, FLOAT, DOUBLE, VOID */
+       t = dcs->d_atyp;                /* BOOL, CHAR, INT, FLOAT,
+                                          DOUBLE, VOID */
        s = dcs->d_smod;                /* SIGNED, UNSIGNED */
        l = dcs->d_lmod;                /* SHORT, LONG, QUAD */
+       d = dcs->d_dmod;                /* COMPLEX, IMAGINARY */
        tp = dcs->d_type;
        scl = dcs->d_scl;
 
@@ -699,6 +785,8 @@ deftyp(void)
                case NOTSPEC:
                        t = INT;
                        /* FALLTHROUGH */
+               case BOOL:
+                       break;
                case INT:
                        if (s == NOTSPEC)
                                s = SIGNED;
@@ -728,6 +816,8 @@ deftyp(void)
                default:
                        lerror("deftyp() 2");
                }
+               if (mergedomain(&t, d))
+                       dcs->d_terr = 1;
                if (t != INT && t != CHAR && (s != NOTSPEC || l != NOTSPEC)) {
                        dcs->d_terr = 1;
                        l = s = NOTSPEC;
@@ -1059,7 +1149,7 @@ decl1str(sym_t *dsym)
                                warning(34);
                        }
                } else if (t != INT && t != UINT && t != LONG &&
-                   t != ULONG && t != QUAD && t != UQUAD) {
+                   t != ULONG && t != QUAD && t != UQUAD && t != BOOL) {
                        /* illegal bit-field type */
                        error(35);
                        sz = tp->t_flen;
@@ -1985,6 +2075,8 @@ eqtype(type_t *tp1, type_t *tp2, int ignqual, int promot, int *warn)
                if (promot) {
                        if (t == FLOAT) {
                                t = DOUBLE;
+                       } else if (t == BOOL) {
+                               t = INT;
                        } else if (t == CHAR || t == SCHAR) {
                                t = INT;
                        } else if (t == UCHAR) {
@@ -1994,6 +2086,10 @@ eqtype(type_t *tp1, type_t *tp2, int ignqual, int promot, int *warn)
                        } else if (t == USHORT) {
                                /* CONSTCOND */
                                t = INT_MAX < USHRT_MAX ? UINT : INT;
+                       } else if (t == COMPLEX) {
+                               t = DCOMPLEX;
+                       } else if (t == IMAGINARY) {
+                               t = DIMAGINARY;
                        }
                }
 
@@ -2087,9 +2183,11 @@ mnoarg(type_t *tp, int *warn)
                        *warn = 1;
        }
        for (arg = tp->t_args; arg != NULL; arg = arg->s_nxt) {
-               if ((t = arg->s_type->t_tspec) == FLOAT ||
+               if ((t = arg->s_type->t_tspec) == FLOAT || t == BOOL ||
                    t == CHAR || t == SCHAR || t == UCHAR ||
-                   t == SHORT || t == USHORT) {
+                   t == SHORT || t == USHORT || t == COMPLEX ||
+                   t == DCOMPLEX || t == LDCOMPLEX || t == IMAGINARY ||
+                   t == DIMAGINARY || t == LDIMAGINARY) {
                        if (warn != NULL)
                                *warn = 1;
                }
index 0ee39c3..03f471e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: emit1.c,v 1.7 2007/03/21 03:31:19 tedu Exp $  */
+/*     $OpenBSD: emit1.c,v 1.8 2010/07/24 22:17:03 guenther Exp $      */
 /*     $NetBSD: emit1.c,v 1.4 1995/10/02 17:21:28 jpo Exp $    */
 
 /*
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$OpenBSD: emit1.c,v 1.7 2007/03/21 03:31:19 tedu Exp $";
+static char rcsid[] = "$OpenBSD: emit1.c,v 1.8 2010/07/24 22:17:03 guenther Exp $";
 #endif
 
 #include <ctype.h>
@@ -48,6 +48,7 @@ static        void    outfstrg(strg_t *);
  * The type is written as a sequence of substrings, each of which describes a
  * node of type type_t
  * a node is coded as follows:
+ *     _Bool                   B
  *     char                    C
  *     signed char             s C
  *     unsigned char           u C
@@ -62,6 +63,12 @@ static       void    outfstrg(strg_t *);
  *     float                   s D
  *     double                  D
  *     long double             l D
+ *     float _Complex          s X
+ *     double _Complex         X
+ *     long double _Complex    l X
+ *     float _Imaginary        s J
+ *     double _Imaginary       J
+ *     long double _Imaginary  l J
  *     void                    V
  *     *                       P
  *     [n]                     A n
@@ -93,6 +100,7 @@ outtype(type_t *tp)
                if ((ts = tp->t_tspec) == INT && tp->t_isenum)
                        ts = ENUM;
                switch (ts) {
+               case BOOL:      t = 'B';        s = '\0';       break;
                case CHAR:      t = 'C';        s = '\0';       break;
                case SCHAR:     t = 'C';        s = 's';        break;
                case UCHAR:     t = 'C';        s = 'u';        break;
@@ -107,6 +115,12 @@ outtype(type_t *tp)
                case FLOAT:     t = 'D';        s = 's';        break;
                case DOUBLE:    t = 'D';        s = '\0';       break;
                case LDOUBLE:   t = 'D';        s = 'l';        break;
+               case COMPLEX:   t = 'X';        s = 's';        break;
+               case DCOMPLEX:  t = 'X';        s = '\0';       break;
+               case LDCOMPLEX: t = 'X';        s = 'l';        break;
+               case IMAGINARY:  t = 'J';       s = 's';        break;
+               case DIMAGINARY: t = 'J';       s = '\0';       break;
+               case LDIMAGINARY:t = 'J';       s = 'l';        break;
                case VOID:      t = 'V';        s = '\0';       break;
                case PTR:       t = 'P';        s = '\0';       break;
                case ARRAY:     t = 'A';        s = '\0';       break;
index 437c0d8..d9d1929 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: externs1.h,v 1.15 2006/05/29 20:47:22 cloder Exp $    */
+/*     $OpenBSD: externs1.h,v 1.16 2010/07/24 22:17:03 guenther Exp $  */
 /*     $NetBSD: externs1.h,v 1.7 1995/10/02 17:31:39 jpo Exp $ */
 
 /*
@@ -138,6 +138,7 @@ extern      void    pushdecl(scl_t);
 extern void    popdecl(void);
 extern void    setasm(void);
 extern void    clrtyp(void);
+extern int     mergedomain(tspec_t *, tspec_t);
 extern void    deftyp(void);
 extern int     length(type_t *, const char *);
 extern int     getbound(type_t *);
index 8ecadbe..570832e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: lint.h,v 1.6 2006/05/29 20:47:22 cloder Exp $ */
+/*     $OpenBSD: lint.h,v 1.7 2010/07/24 22:17:03 guenther Exp $       */
 /*     $NetBSD: lint.h,v 1.2 1995/07/03 21:24:18 cgd Exp $     */
 
 /*
@@ -45,6 +45,7 @@ typedef enum {
        NOTSPEC,
        SIGNED,         /* keyword "signed", only used in the parser */
        UNSIGN,         /* keyword "unsigned", only used in the parser */
+       BOOL,           /* _Bool */
        CHAR,           /* char */
        SCHAR,          /* signed char */
        UCHAR,          /* unsigned char */
@@ -59,6 +60,12 @@ typedef enum {
        FLOAT,          /* float */
        DOUBLE,         /* double */
        LDOUBLE,        /* long double */
+       COMPLEX,        /* float _Complex */
+       DCOMPLEX,       /* double _Complex */
+       LDCOMPLEX,      /* long double _Complex */
+       IMAGINARY,      /* float _Imaginary */
+       DIMAGINARY,     /* double _Imaginary */
+       LDIMAGINARY,    /* long double _Imaginary */
        VOID,           /* void */
        STRUCT,         /* structure tag */
        UNION,          /* union tag */
@@ -83,7 +90,8 @@ typedef       struct {
        u_int   tt_isutyp : 1;          /* 1 if unsigned integer type */
        u_int   tt_isftyp : 1;          /* 1 if floating point type */
        u_int   tt_isatyp : 1;          /* 1 if arithmetic type */
-       u_int   tt_issclt : 1;          /* 1 if scalar type */
+       u_int   tt_domain : 2;          /* 0 if non-scalar, 1 if real,
+                                          2 if imaginary, 3 if complex */
        char    *tt_name;               /* type name */
 } ttab_t;
 
@@ -96,7 +104,9 @@ typedef      struct {
 #define isutyp(t)      (ttab[t].tt_isutyp)
 #define isftyp(t)      (ttab[t].tt_isftyp)
 #define isatyp(t)      (ttab[t].tt_isatyp)
-#define issclt(t)      (ttab[t].tt_issclt)
+#define issclt(t)      (ttab[t].tt_domain != 0)
+#define iscomplex(t)   (ttab[t].tt_domain == 3)
+#define isimag(t)      (ttab[t].tt_domain == 2)
 
 extern ttab_t  ttab[];
 
index d4d3f8e..39f24fe 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: lint1.h,v 1.13 2006/04/18 02:59:40 cloder Exp $       */
+/*     $OpenBSD: lint1.h,v 1.14 2010/07/24 22:17:03 guenther Exp $     */
 /*     $NetBSD: lint1.h,v 1.6 1995/10/02 17:31:41 jpo Exp $    */
 
 /*
@@ -224,6 +224,7 @@ typedef     struct sym {
                tqual_t _s_tqu; /* qualifier (only for keywords) */
                struct  sym *_s_args; /* arguments in old style function
                                         definitions */
+               op_t    _s_op;  /* op type (only for operators) */
        } u;
        struct  sym *s_link;    /* next symbol with same hash value */
        struct  sym **s_rlink;  /* pointer to s_link of prev. symbol */
@@ -236,6 +237,7 @@ typedef     struct sym {
 #define        s_etyp  u._s_et
 #define        s_tspec u._s_tsp
 #define        s_tqual u._s_tqu
+#define        s_op    u._s_op
 #define        s_args  u._s_args
 
 /*
@@ -294,9 +296,10 @@ typedef    struct tnode {
  *
  */
 typedef        struct dinfo {
-       tspec_t d_atyp;         /* VOID, CHAR, INT, FLOAT or DOUBLE */
-       tspec_t d_smod;         /* SIGNED or UNSIGN */
-       tspec_t d_lmod;         /* SHORT, LONG or QUAD */
+       tspec_t d_atyp;         /* NOTSPEC, VOID, CHAR, INT, FLOAT or DOUBLE */
+       tspec_t d_smod;         /* sign: NOTSPEC, SIGNED or UNSIGN */
+       tspec_t d_lmod;         /* length: NOTSPEC, SHORT, LONG or QUAD */
+       tspec_t d_dmod;         /* domain: NOTSPEC, COMPLEX or IMAGINARY */
        scl_t   d_scl;          /* storage class */
        type_t  *d_type;        /* after deftyp() pointer to the type used
                                   for all declarators */
index 80d5563..2198822 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: op.h,v 1.3 2005/11/29 20:09:57 cloder Exp $   */
+/*     $OpenBSD: op.h,v 1.4 2010/07/24 22:17:03 guenther Exp $ */
 /*     $NetBSD: op.h,v 1.2 1995/07/03 21:24:27 cgd Exp $       */
 
 /*
@@ -114,6 +114,8 @@ typedef     enum {
        LOAD,
        PUSH,
        RETURN,
+       REAL,           /* gcc extension: __real__ */
+       IMAG,           /* gcc extension: __imag__ */
        INIT,           /* pseudo op, not used in trees */
        CASE,           /* pseudo op, not used in trees */
        FARG            /* pseudo op, not used in trees */
index a8cf8d7..55002ff 100644 (file)
@@ -1,5 +1,5 @@
 %{
-/*     $OpenBSD: scan.l,v 1.31 2007/09/05 16:32:17 fgsch Exp $ */
+/*     $OpenBSD: scan.l,v 1.32 2010/07/24 22:17:03 guenther Exp $      */
 /*     $NetBSD: scan.l,v 1.8 1995/10/23 13:38:51 jpo Exp $     */
 
 /*
@@ -34,7 +34,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$OpenBSD: scan.l,v 1.31 2007/09/05 16:32:17 fgsch Exp $";
+static char rcsid[] = "$OpenBSD: scan.l,v 1.32 2010/07/24 22:17:03 guenther Exp $";
 #endif
 
 #include <stdlib.h>
@@ -91,6 +91,7 @@ OD    [0-7]
 HD     [0-9A-Fa-f]
 EX     ([eE][+-]?[0-9]+)
 HEX    ([pP][+-]?[0-9]+)
+FSUFF  ([fFlL][iIjJ]?|[iIjJ][fFlL]?)?
 
 %%
 
@@ -98,12 +99,12 @@ HEX ([pP][+-]?[0-9]+)
 0{OD}*[lLuU]*                  return (icon(8));
 {NZD}{D}*[lLuU]*               return (icon(10));
 0[xX]{HD}+[lLuU]*              return (icon(16));
-{D}+\.{D}*{EX}?[fFlL]?         |
-{D}+{EX}[fFlL]?                        |
-\.{D}+{EX}?[fFlL]?             return (fcon());
-0[xX]{HD}+\.{HD}*{HEX}[fFlL]?  |
-0[xX]{HD}+{HEX}[fFlL]?         |
-0[xX]\.{HD}+{HEX}[fFlL]?       return (fhexcon());
+{D}+\.{D}*{EX}?{FSUFF}         |
+{D}+{EX}{FSUFF}                        |
+\.{D}+{EX}?{FSUFF}             return (fcon());
+0[xX]{HD}+\.{HD}*{HEX}{FSUFF}  |
+0[xX]{HD}+{HEX}{FSUFF}         |
+0[xX]\.{HD}+{HEX}{FSUFF}       return (fhexcon());
 "="                            return (operator(T_ASSIGN, ASSIGN));
 "*="                           return (operator(T_OPASS, MULASS));
 "/="                           return (operator(T_OPASS, DIVASS));
@@ -189,6 +190,7 @@ static      struct  kwtab {
                scl_t   kw_scl;         /* storage class if kw_token T_SCLASS */
                tspec_t kw_tspec;       /* type spec. if kw_token T_TYPE or T_SOU */
                tqual_t kw_tqual;       /* type qual. if kw_token T_QUAL */
+               op_t    kw_op;          /* operator if kw_token T_UNOP */
        } kw_u;
        u_int   kw_stdc : 1;    /* STDC keyword */
        u_int   kw_gcc : 1;     /* GCC keyword */
@@ -198,9 +200,12 @@ static     struct  kwtab {
        { "__asm__",            T_ASM,          { 0 },          0, 0 },
        { "__attribute__",      T_ATTRIBUTE,    { 0 },          0, 0 },
        { "auto",               T_SCLASS,       { AUTO },       0, 0 },
+       { "_Bool",              T_TYPE,         { BOOL },       1, 0 },
        { "break",              T_BREAK,        { 0 },          0, 0 },
        { "case",               T_CASE,         { 0 },          0, 0 },
        { "char",               T_TYPE,         { CHAR },       0, 0 },
+       { "_Complex",           T_TYPE,         { COMPLEX },    1, 0 },
+       { "__complex__",        T_TYPE,         { COMPLEX },    0, 1 },
        { "const",              T_QUAL,         { CONST },      1, 0 },
        { "__const__",          T_QUAL,         { CONST },      0, 0 },
        { "__const",            T_QUAL,         { CONST },      0, 0 },
@@ -215,12 +220,15 @@ static    struct  kwtab {
        { "for",                T_FOR,          { 0 },          0, 0 },
        { "goto",               T_GOTO,         { 0 },          0, 0 },
        { "if",                 T_IF,           { 0 },          0, 0 },
+       { "__imag__",           T_UNOP,         { IMAG },       0, 0 /*1*/ },
+/*     { "_Imaginary",         T_TYPE,         { IMAGINARY },  1, 0 }, */
        { "inline",             T_SCLASS,       { INLINE },     1, 0 },
        { "__inline__",         T_SCLASS,       { INLINE },     0, 0 },
        { "__inline",           T_SCLASS,       { INLINE },     0, 0 },
        { "int",                T_TYPE,         { INT },        0, 0 },
        { "__lint_equal__",     T_LEQUAL,       { 0 },          0, 0 },
        { "long",               T_TYPE,         { LONG },       0, 0 },
+       { "__real__",           T_UNOP,         { REAL },       0, 0 /*1*/ },
        { "register",           T_SCLASS,       { REG },        0, 0 },
        { "__restrict",         T_QUAL,         { RESTRICT },   0, 0 },
        { "__restrict__",       T_QUAL,         { RESTRICT },   0, 0 },
@@ -247,6 +255,7 @@ static      struct  kwtab {
 #define kw_scl         kw_u.kw_scl
 #define kw_tspec       kw_u.kw_tspec
 #define kw_tqual       kw_u.kw_tqual
+#define kw_op          kw_u.kw_op
 
 /* Symbol table */
 static sym_t   *symtab[HSHSIZ1];
@@ -292,6 +301,8 @@ initscan(void)
                        sym->s_scl = kw->kw_scl;
                } else if (kw->kw_token == T_QUAL) {
                        sym->s_tqual = kw->kw_tqual;
+               } else if (kw->kw_token == T_UNOP) {
+                       sym->s_op = kw->kw_op;
                }
                h = hash(sym->s_name);
                if ((sym->s_link = symtab[h]) != NULL)
@@ -444,6 +455,8 @@ keyw(sym_t *sym)
                yylval.y_tspec = sym->s_tspec;
        } else if (t == T_QUAL) {
                yylval.y_tqual = sym->s_tqual;
+       } else if (t == T_UNOP) {
+               yylval.y_op = sym->s_op;
        }
        return (t);
 }
@@ -627,6 +640,7 @@ fcon(void)
        const   char *cp;
        int     len;
        tspec_t typ;
+       tspec_t domain = NOTSPEC;
        char    c, *eptr;
        double  d;
        float   f;
@@ -634,15 +648,29 @@ fcon(void)
        cp = yytext;
        len = yyleng;
 
-       if ((c = cp[len - 1]) == 'f' || c == 'F') {
+       c = cp[len - 1];
+       if (c == 'i' || c == 'I' || c == 'j' || c == 'J') {
+               domain = COMPLEX;               /* XXX should be IMAGINARY */
+               len--;
+               c = cp[len - 1];
+       }
+       if (c == 'f' || c == 'F') {
                typ = FLOAT;
                len--;
+               c = cp[len - 1];
        } else if (c == 'l' || c == 'L') {
                typ = LDOUBLE;
                len--;
+               c = cp[len - 1];
        } else {
                typ = DOUBLE;
        }
+       if (c == 'i' || c == 'I' || c == 'j' || c == 'J') {
+               if (domain != NOTSPEC)
+                       lerror("fcon() 2");     /* can't happen */
+               domain = COMPLEX;               /* XXX should be IMAGINARY */
+               len--;
+       }
 
        errno = 0;
        d = strtod(cp, &eptr);
@@ -661,12 +689,15 @@ fcon(void)
                }
        }
 
-       (yylval.y_val = xcalloc(1, sizeof (val_t)))->v_tspec = typ;
+       yylval.y_val = xcalloc(1, sizeof (val_t));
        if (typ == FLOAT) {
                yylval.y_val->v_ldbl = f;
        } else {
                yylval.y_val->v_ldbl = d;
        }
+       if (mergedomain(&typ, domain))
+               lerror("fcon() 3");
+       yylval.y_val->v_tspec = typ;
 
        return (T_CON);
 }
@@ -684,6 +715,7 @@ fhexcon(void)
        const   char *cp;
        int     len;
        tspec_t typ;
+       tspec_t domain = NOTSPEC;
        char    c;
        double  d;
        float   f;
@@ -691,15 +723,29 @@ fhexcon(void)
        cp = yytext;
        len = yyleng;
 
-       if ((c = cp[len - 1]) == 'f' || c == 'F') {
+       c = cp[len - 1];
+       if (c == 'i' || c == 'I' || c == 'j' || c == 'J') {
+               domain = COMPLEX;               /* XXX should be IMAGINARY */
+               len--;
+               c = cp[len - 1];
+       }
+       if (c == 'f' || c == 'F') {
                typ = FLOAT;
                len--;
+               c = cp[len - 1];
        } else if (c == 'l' || c == 'L') {
                typ = LDOUBLE;
                len--;
+               c = cp[len - 1];
        } else {
                typ = DOUBLE;
        }
+       if (c == 'i' || c == 'I' || c == 'j' || c == 'J') {
+               if (domain != NOTSPEC)
+                       lerror("fhexcon() 1");  /* can't happen */
+               domain = COMPLEX;               /* XXX should be IMAGINARY */
+               len--;
+       }
 
        /* arbitrary value, until strtod can cope */
        d = 1.0;
@@ -708,12 +754,15 @@ fhexcon(void)
                f = (float)d;
        }
 
-       (yylval.y_val = xcalloc(1, sizeof (val_t)))->v_tspec = typ;
+       yylval.y_val = xcalloc(1, sizeof (val_t));
        if (typ == FLOAT) {
                yylval.y_val->v_ldbl = f;
        } else {
                yylval.y_val->v_ldbl = d;
        }
+       if (mergedomain(&typ, domain))
+               lerror("fhexcon() 2");
+       yylval.y_val->v_tspec = typ;
 
        return (T_CON);
 }
index c674be2..0ed9c24 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tree.c,v 1.46 2007/10/17 20:10:44 chl Exp $   */
+/*     $OpenBSD: tree.c,v 1.47 2010/07/24 22:17:03 guenther Exp $      */
 /*     $NetBSD: tree.c,v 1.12 1995/10/02 17:37:57 jpo Exp $    */
 
 /*
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$OpenBSD: tree.c,v 1.46 2007/10/17 20:10:44 chl Exp $";
+static char rcsid[] = "$OpenBSD: tree.c,v 1.47 2010/07/24 22:17:03 guenther Exp $";
 #endif
 
 #include <stdlib.h>
@@ -203,6 +203,10 @@ initmtab(void)
                    "PUSH" } },
                { RETURN, { 1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,
                    "RETURN" } },
+               { REAL, { 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,
+                   "__real__" } },
+               { IMAG, { 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,
+                   "__imag__" } },
                { INIT,   { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
                    "INIT" } },
                { FARG,   { 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
@@ -629,6 +633,17 @@ build(op_t op, tnode_t *ln, tnode_t *rn)
        case QUEST:
                ntn = mktnode(op, rn->tn_type, ln, rn);
                break;
+       case REAL:
+       case IMAG:
+               rtp = ln->tn_type;
+               if (rtp->t_tspec == COMPLEX)
+                       rtp = gettyp(FLOAT);
+               else if (rtp->t_tspec == DCOMPLEX)
+                       rtp = gettyp(DOUBLE);
+               else if (rtp->t_tspec == LDCOMPLEX)
+                       rtp = gettyp(LDOUBLE);
+               ntn = mktnode(op, rtp, ln, rn);
+               break;
        default:
                rtp = mp->m_logop ? gettyp(INT) : ln->tn_type;
                if (!mp->m_binary && rn != NULL)
@@ -747,6 +762,9 @@ typeok(op_t op, farg_t *farg, tnode_t *ln, tnode_t *rn)
        }
 
        if (mp->m_rqint) {
+               if (op == COMPL && iscomplex(lt)) {
+                       /* use of '~' for complex conjugation is a GNUism */
+               } else
                /* integer types required */
                if (!isityp(lt) || (mp->m_binary && !isityp(rt))) {
                        incompat(op, lt, rt);
@@ -1434,6 +1452,8 @@ mktnode(op_t op, type_t *type, tnode_t *ln, tnode_t *rn)
                } else {
                        lerror("mktnode() 2");
                }
+       } else if (op == REAL || op == IMAG) {
+               ntn->tn_lvalue = ln->tn_lvalue;
        }
 
        return (ntn);
@@ -1715,6 +1735,10 @@ iiconv(op_t op, farg_t *farg, tspec_t nt, tspec_t ot, type_t *tp, tnode_t *tn)
        if (op == CVT)
                return;
 
+       /* logical ops return int, so silently convert int to _Bool */
+       if (ot == INT && nt == BOOL)
+               return;
+
        if (rank(nt) < rank(ot)) {
                /* coercion from greater to lesser width */
                if (op == FARG) {
@@ -1842,6 +1866,8 @@ cvtcon(op_t op, farg_t *farg, type_t *tp, val_t *nv, val_t *v)
 
        if (ot == FLOAT || ot == DOUBLE || ot == LDOUBLE) {
                switch (nt) {
+               case BOOL:
+                       max = 1;                min = 0;                break;
                case CHAR:
                        max = CHAR_MAX;         min = CHAR_MIN;         break;
                case UCHAR:
@@ -1873,11 +1899,21 @@ cvtcon(op_t op, farg_t *farg, type_t *tp, val_t *nv, val_t *v)
                        /* Already an error because of float --> ptr */
                case LDOUBLE:
                        max = LDBL_MAX;         min = -LDBL_MAX;        break;
+               case COMPLEX:
+                       max = FLT_MAX;          min = -FLT_MAX;         break;
+               case DCOMPLEX:
+                       max = DBL_MAX;          min = -DBL_MAX;         break;
+               case LDCOMPLEX:
+                       max = LDBL_MAX;         min = -LDBL_MAX;        break;
+               case IMAGINARY:
+               case DIMAGINARY:
+               case LDIMAGINARY:
+                       max = 0;                min = 0;                break;
                default:
                        lerror("cvtcon() 1");
                }
                if (v->v_ldbl > max || v->v_ldbl < min) {
-                       if (nt == LDOUBLE)
+                       if (nt == LDOUBLE || nt == LDCOMPLEX)
                                lerror("cvtcon() 2");
                        if (op == FARG) {
                                /* %s arg #%d: conv. of %s to %s is out of range */
@@ -1900,15 +1936,18 @@ cvtcon(op_t op, farg_t *farg, type_t *tp, val_t *nv, val_t *v)
                                (u_quad_t)v->v_ldbl : (quad_t)v->v_ldbl;
                }
        } else {
-               if (nt == FLOAT) {
+               if (nt == FLOAT || nt == COMPLEX) {
                        nv->v_ldbl = (ot == PTR || isutyp(ot)) ?
                               (float)(u_quad_t)v->v_quad : (float)v->v_quad;
-               } else if (nt == DOUBLE) {
+               } else if (nt == DOUBLE || nt == DCOMPLEX) {
                        nv->v_ldbl = (ot == PTR || isutyp(ot)) ?
                               (double)(u_quad_t)v->v_quad : (double)v->v_quad;
-               } else if (nt == LDOUBLE) {
+               } else if (nt == LDOUBLE || nt == LDCOMPLEX) {
                        nv->v_ldbl = (ot == PTR || isutyp(ot)) ?
                               (ldbl_t)(u_quad_t)v->v_quad : (ldbl_t)v->v_quad;
+               } else if (nt == IMAGINARY || nt == DIMAGINARY ||
+                   nt == LDIMAGINARY) {
+                       nv->v_ldbl = 0;
                } else {
                        rchk = 1;               /* Check for lost precision. */
                        nv->v_quad = v->v_quad;
@@ -2200,6 +2239,7 @@ tyname(type_t *tp)
                t = ENUM;
 
        switch (t) {
+       case BOOL:      s = "_Bool";                    break;
        case CHAR:      s = "char";                     break;
        case UCHAR:     s = "unsigned char";            break;
        case SCHAR:     s = "signed char";              break;
@@ -2214,6 +2254,12 @@ tyname(type_t *tp)
        case FLOAT:     s = "float";                    break;
        case DOUBLE:    s = "double";                   break;
        case LDOUBLE:   s = "long double";              break;
+       case COMPLEX:   s = "float _Complex";           break;
+       case DCOMPLEX:  s = "double _Complex";          break;
+       case LDCOMPLEX: s = "long double _Complex";     break;
+       case IMAGINARY:  s = "float _Imaginary";        break;
+       case DIMAGINARY: s = "double _Imaginary";       break;
+       case LDIMAGINARY:s = "long double _Imaginary";  break;
        case PTR:       s = "pointer";                  break;
        case ENUM:      s = "enum";                     break;
        case STRUCT:    s = "struct";                   break;
@@ -2757,6 +2803,9 @@ fold(tnode_t *tn)
        case OR:
                q = utyp ? ul | ur : sl | sr;
                break;
+       case REAL:
+       case IMAG:
+               q = sl;
        default:
                lerror("fold() 5");
        }
@@ -2897,6 +2946,10 @@ foldflt(tnode_t *tn)
        case NE:
                v->v_quad = l != r;
                break;
+       case REAL:
+       case IMAG:
+               v->v_ldbl = l;
+               break;
        default:
                lerror("foldflt() 4");
        }
@@ -2933,6 +2986,8 @@ bldszoftrm(tnode_t *tn)
        case STAR:
        case NAME:
        case STRING:
+       case REAL:
+       case IMAG:
                break;
        default:
                warning(312, modtab[tn->tn_op].m_name);
@@ -3504,6 +3559,8 @@ chkmisc(tnode_t *tn, int vctx, int tctx, int eqwarn, int fcall, int rvdisc,
        case XORASS:
        case SHLASS:
        case SHRASS:
+       case REAL:
+       case IMAG:
                if (ln->tn_op == NAME && (reached || rchflg)) {
                        sc = ln->tn_sym->s_scl;
                        /*
index 5dddd17..5ec065a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: chk.c,v 1.16 2007/05/26 00:36:04 krw Exp $    */
+/*     $OpenBSD: chk.c,v 1.17 2010/07/24 22:17:03 guenther Exp $       */
 /*     $NetBSD: chk.c,v 1.2 1995/07/03 21:24:42 cgd Exp $      */
 
 /*
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$OpenBSD: chk.c,v 1.16 2007/05/26 00:36:04 krw Exp $";
+static char rcsid[] = "$OpenBSD: chk.c,v 1.17 2010/07/24 22:17:03 guenther Exp $";
 #endif
 
 #include <stdlib.h>
@@ -83,6 +83,9 @@ inittyp(void)
                { UNSIGN,   { 0, 0, 0,
                                      SIGNED, UNSIGN,
                                      0, 0, 0, 0, 0, "unsigned" } },
+               { BOOL,     { sizeof (_Bool) * CHAR_BIT, CHAR_BIT, 1,
+                                     BOOL, BOOL,
+                                     1, 1, 0, 1, 1, "_Bool" } },
                { CHAR,     { CHAR_BIT, CHAR_BIT, 20,
                                      SCHAR, UCHAR,
                                      1, 0, 0, 1, 1, "char" } },
@@ -125,6 +128,18 @@ inittyp(void)
                { LDOUBLE,  { sizeof (ldbl_t) * CHAR_BIT, 10 * CHAR_BIT, -1,
                                      LDOUBLE, LDOUBLE,
                                      0, 0, 1, 1, 1, "long double" } },
+               { COMPLEX,  { sizeof (_Complex float) * CHAR_BIT,
+                                     8 * CHAR_BIT, -1,
+                                     COMPLEX, COMPLEX,
+                                     0, 0, 1, 1, 1, "float _Complex" } },
+               { DCOMPLEX, { sizeof (double _Complex) * CHAR_BIT,
+                                     16 * CHAR_BIT, -1,
+                                     DCOMPLEX, DCOMPLEX,
+                                     0, 0, 1, 1, 1, "double _Complex" } },
+               { LDCOMPLEX,{ sizeof (long double _Complex) * CHAR_BIT,
+                                     20 * CHAR_BIT, -1,
+                                     LDCOMPLEX, LDCOMPLEX,
+                                     0, 0, 1, 1, 1, "long double _Complex" } },
                { VOID,     { -1, -1, -1,
                                      VOID, VOID,
                                      0, 0, 0, 0, 0, "void" } },
index de032bd..08d796a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: emit2.c,v 1.5 2005/11/20 17:09:55 cloder Exp $        */
+/*     $OpenBSD: emit2.c,v 1.6 2010/07/24 22:17:03 guenther Exp $      */
 /*     $NetBSD: emit2.c,v 1.2 1995/07/03 21:24:44 cgd Exp $    */
 
 /*
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$OpenBSD: emit2.c,v 1.5 2005/11/20 17:09:55 cloder Exp $";
+static char rcsid[] = "$OpenBSD: emit2.c,v 1.6 2010/07/24 22:17:03 guenther Exp $";
 #endif
 
 #include <err.h>
@@ -58,6 +58,7 @@ outtype(type_t *tp)
                if ((ts = tp->t_tspec) == INT && tp->t_isenum)
                        ts = ENUM;
                switch (ts) {
+               case BOOL:      t = 'B';        s = '\0';       break;
                case CHAR:      t = 'C';        s = '\0';       break;
                case SCHAR:     t = 'C';        s = 's';        break;
                case UCHAR:     t = 'C';        s = 'u';        break;
@@ -72,6 +73,12 @@ outtype(type_t *tp)
                case FLOAT:     t = 'D';        s = 's';        break;
                case DOUBLE:    t = 'D';        s = '\0';       break;
                case LDOUBLE:   t = 'D';        s = 'l';        break;
+               case COMPLEX:   t = 'X';        s = 's';        break;
+               case DCOMPLEX:  t = 'X';        s = '\0';       break;
+               case LDCOMPLEX: t = 'X';        s = 'l';        break;
+               case IMAGINARY:  t = 'J';       s = 's';        break;
+               case DIMAGINARY: t = 'J';       s = '\0';       break;
+               case LDIMAGINARY:t = 'J';       s = 'l';        break;
                case VOID:      t = 'V';        s = '\0';       break;
                case PTR:       t = 'P';        s = '\0';       break;
                case ARRAY:     t = 'A';        s = '\0';       break;
index d59bf93..615c6a9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: read.c,v 1.9 2005/12/01 05:06:40 cloder Exp $ */
+/*     $OpenBSD: read.c,v 1.10 2010/07/24 22:17:03 guenther Exp $      */
 /*     $NetBSD: read.c,v 1.2 1995/07/03 21:24:59 cgd Exp $     */
 
 /*
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$OpenBSD: read.c,v 1.9 2005/12/01 05:06:40 cloder Exp $";
+static char rcsid[] = "$OpenBSD: read.c,v 1.10 2010/07/24 22:17:03 guenther Exp $";
 #endif
 
 #include <stdio.h>
@@ -517,6 +517,9 @@ inptype(const char *cp, const char **epp)
        }
 
        switch (c) {
+       case 'B':
+               tp->t_tspec = BOOL;
+               break;
        case 'C':
                tp->t_tspec = s == 's' ? SCHAR : (s == 'u' ? UCHAR : CHAR);
                break;
@@ -535,6 +538,14 @@ inptype(const char *cp, const char **epp)
        case 'D':
                tp->t_tspec = s == 's' ? FLOAT : (s == 'l' ? LDOUBLE : DOUBLE);
                break;
+       case 'X':
+               tp->t_tspec = s == 's' ? COMPLEX : (s == 'l' ?
+                   LDCOMPLEX : DCOMPLEX);
+               break;
+       case 'J':
+               tp->t_tspec = s == 's' ? IMAGINARY : (s == 'l' ?
+                   LDIMAGINARY : DIMAGINARY);
+               break;
        case 'V':
                tp->t_tspec = VOID;
                break;
@@ -649,6 +660,9 @@ gettlen(const char *cp, const char **epp)
        t = NOTSPEC;
 
        switch (c) {
+       case 'B':
+               t = BOOL;
+               break;
        case 'C':
                if (s == 's') {
                        t = SCHAR;
@@ -695,6 +709,24 @@ gettlen(const char *cp, const char **epp)
                        t = DOUBLE;
                }
                break;
+       case 'X':
+               if (s == 's') {
+                       t = COMPLEX;
+               } else if (s == 'l') {
+                       t = LDCOMPLEX;
+               } else if (s == '\0') {
+                       t = DCOMPLEX;
+               }
+               break;
+       case 'J':
+               if (s == 's') {
+                       t = IMAGINARY;
+               } else if (s == 'l') {
+                       t = LDIMAGINARY;
+               } else if (s == '\0') {
+                       t = DIMAGINARY;
+               }
+               break;
        case 'V':
                if (s == '\0')
                        t = VOID;