/* $OpenBSD: gcc_compat.c,v 1.6 2008/08/17 18:40:12 ragge Exp $ */ /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Routines to support some of the gcc extensions to C. */ #ifdef GCC_COMPAT #include "pass1.h" #include "cgram.h" #include static struct kw { char *name, *ptr; int rv; } kw[] = { /* * Do NOT change the order of these entries unless you know * what you're doing! */ /* 0 */ { "__asm", NULL, C_ASM }, /* 1 */ { "__signed", NULL, 0 }, /* 2 */ { "__inline", NULL, C_FUNSPEC }, /* 3 */ { "__const", NULL, 0 }, /* 4 */ { "__asm__", NULL, C_ASM }, /* 5 */ { "__inline__", NULL, C_FUNSPEC }, /* 6 */ { "__thread", NULL, 0 }, /* 7 */ { "__FUNCTION__", NULL, 0 }, /* 8 */ { "__volatile", NULL, 0 }, /* 9 */ { "__volatile__", NULL, 0 }, /* 10 */{ "__restrict", NULL, -1 }, { NULL, NULL, 0 }, }; void gcc_init() { struct kw *kwp; for (kwp = kw; kwp->name; kwp++) kwp->ptr = addname(kwp->name); } #define TS "\n#pragma tls\n# %d\n" #define TLLEN sizeof(TS)+10 /* * See if a string matches a gcc keyword. */ int gcc_keyword(char *str, NODE **n) { char tlbuf[TLLEN], *tw; struct kw *kwp; int i; for (i = 0, kwp = kw; kwp->name; kwp++, i++) if (str == kwp->ptr) break; if (kwp->name == NULL) return 0; if (kwp->rv) return kwp->rv; switch (i) { case 1: /* __signed */ *n = mkty((TWORD)SIGNED, 0, MKSUE(SIGNED)); return C_TYPE; case 3: /* __const */ *n = block(QUALIFIER, NIL, NIL, CON, 0, 0); return C_QUALIFIER; case 6: /* __thread */ snprintf(tlbuf, TLLEN, TS, lineno); tw = &tlbuf[strlen(tlbuf)]; while (tw > tlbuf) cunput(*--tw); return -1; case 7: /* __FUNCTION__ */ if (cftnsp == NULL) { uerror("__FUNCTION__ outside function"); yylval.strp = ""; } else yylval.strp = cftnsp->sname; /* XXX - not C99 */ return C_STRING; case 8: /* __volatile */ case 9: /* __volatile__ */ *n = block(QUALIFIER, NIL, NIL, VOL, 0, 0); return C_QUALIFIER; } cerror("gcc_keyword"); return 0; } #endif