/* * xtc - The eXTensible Compiler * Copyright (C) 2006-2011 Robert Grimm * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ package xtc.type; import java.util.ArrayList; import xtc.Constants; import xtc.util.SymbolTable; /** * A factory for programmatically and concisely creating C types. * * @author Robert Grimm * @version $Revision: 1.3 $ */ public class CFactory { /** A constant void. */ private static final Type CONST_VOID; /** A constant char. */ private static final Type CONST_CHAR; /** A pointer to void. */ private static final Type PTR_2_VOID; /** A pointer to constant void. */ private static final Type PTR_2_CONST_VOID; /** A pointer to char. */ private static final Type PTR_2_CHAR; /** A pointer to constant char. */ private static final Type PTR_2_CONST_CHAR; static { CONST_VOID = VoidT.TYPE.annotate().attribute(Constants.ATT_CONSTANT).seal(); CONST_CHAR = NumberT.CHAR.annotate().attribute(Constants.ATT_CONSTANT).seal(); PTR_2_VOID = new PointerT(VoidT.TYPE).seal(); PTR_2_CONST_VOID = new PointerT(CONST_VOID).seal(); PTR_2_CHAR = new PointerT(NumberT.CHAR).seal(); PTR_2_CONST_CHAR = new PointerT(CONST_CHAR).seal(); } // ========================================================================= /** The prefix for declarations. */ private String prefix; /** The symbol table scope. */ private SymbolTable.Scope scope; /** * Create a new C factory. * * @param prefix The prefix for declarations. * @param scope The symbol table scope. */ public CFactory(String prefix, SymbolTable.Scope scope) { this.prefix = prefix; this.scope = scope; } // ========================================================================= /** * Get the canonical void type. * * @return <code>VoidT.TYPE</code>. */ public Type v() { return VoidT.TYPE; } /** * Get a constant void type. * * @return A sealed constant void type. */ public Type cv() { return CONST_VOID; } /** * Get the canonical char type. * * @return <code>NumberT.CHAR</code>. */ public Type c() { return NumberT.CHAR; } /** * Get a constant char type. * * @return A sealed constant char type. */ public Type cc() { return CONST_CHAR; } /** * Get the canonical int type. * * @return <code>NumberT.INT</code>. */ public Type i() { return NumberT.INT; } /** * Get the canonical sizeof type. * * @return <code>NumberT.SIZEOF</code>. */ public Type size() { return C.SIZEOF; } /** * Create a new pointer type. * * @param type The pointed-to type. * @return The new pointer type. */ public PointerT p(Type type) { return new PointerT(type); } /** * Create a new restricted pointer type. * * @param type The pointed-to type. * @return The new restricted pointer type. */ public Type pr(Type type) { return new PointerT(type).annotate().attribute(Constants.ATT_RESTRICT); } /** * Get a pointer to void. * * @return A sealed pointer to void. */ public Type p2v() { return PointerT.TO_VOID; } /** * Get a pointer to a constant void. * * @return A sealed pointer to constant void. */ public Type p2cv() { return PTR_2_CONST_VOID; } /** * Get a pointer to char. * * @return A sealed pointer to char. */ public Type p2c() { return PTR_2_CHAR; } /** * Get a pointer to constant char. * * @return A sealed pionter to constant char. */ public Type p2cc() { return PTR_2_CONST_CHAR; } /** * Create a new function type with no parameters and a void return * type. * * @return The new function type. */ public Type f() { return f(v()); } /** * Create a new function type with no parameters. * * @param result The result type. * @return The new function type. */ public Type f(Type result) { return new FunctionT(result, new ArrayList<Type>(0), false). attribute(Constants.ATT_STYLE_NEW); } /** * Create a new function type. * * @param result The result type. * @param param The parameter type. * @return The new function type. */ public Type f(Type result, Type param) { ArrayList<Type> params = new ArrayList<Type>(1); params.add(param); FunctionT function = new FunctionT(result, params, false); function.addAttribute(Constants.ATT_STYLE_NEW); return function; } /** * Create a new function type. * * @param result The result type. * @param param1 The first parameter type. * @param param2 The second parameter type. * @return The new function type. */ public Type f(Type result, Type param1, Type param2) { ArrayList<Type> params = new ArrayList<Type>(2); params.add(param1); params.add(param2); FunctionT function = new FunctionT(result, params, false); function.addAttribute(Constants.ATT_STYLE_NEW); return function; } /** * Create a new function type. * * @param result The result type. * @param param1 The first parameter type. * @param param2 The second parameter type. * @param param3 The third parameter type. * @return The new function type. */ public Type f(Type result, Type param1, Type param2, Type param3) { ArrayList<Type> params = new ArrayList<Type>(3); params.add(param1); params.add(param2); params.add(param3); FunctionT function = new FunctionT(result, params, false); function.addAttribute(Constants.ATT_STYLE_NEW); return function; } /** * Create a new function type. * * @param result The result type. * @param param1 The first parameter type. * @param param2 The second parameter type. * @param param3 The third parameter type. * @param param4 The fourth parameter type. * @return The new function type. */ public Type f(Type result, Type param1, Type param2, Type param3, Type param4) { ArrayList<Type> params = new ArrayList<Type>(4); params.add(param1); params.add(param2); params.add(param3); params.add(param4); FunctionT function = new FunctionT(result, params, false); function.addAttribute(Constants.ATT_STYLE_NEW); return function; } // ========================================================================= /** * Mark the specified type as constant. Note that this method * directly modifies the specified type. * * @param type The type. * @return The constant type. */ public Type constant(Type type) { return type.attribute(Constants.ATT_CONSTANT); } /** * Mark the specified type as builtin. Note that this method * directly modifies the specified type. * * @param type The type. * @return The builtin type. */ public Type builtin(Type type) { return type.attribute(Constants.ATT_BUILTIN); } // ========================================================================= /** * Add the specified declaration to this factory's symbol table * scope. The specified name is prefixed with this factory's * prefix. The specified type is marked as a built-in type. If the * <code>nofix</code> flag is set, this method also adds a * declaration without this factory's prefix. * * @param nofix The nofix flag. * @param name The name. * @param type The type. * @return This factory. */ public CFactory decl(boolean nofix, String name, Type type) { if (nofix) { scope.define(name, builtin(type)); } scope.define(prefix + name, builtin(type)); return this; } // ========================================================================= /** * Declare built-in functions for C in this factory's symbol table * scope. * * @param nofix The flag for whether to also declare symbols without * this factory's prefix. */ public void declareBuiltIns(boolean nofix) { // C99 7.20.3 decl(nofix, "calloc", f(p2v(), size(), size())); decl(nofix, "free", f(v(), p2v())); decl(nofix, "malloc", f(p2v(), size())); decl(nofix, "realloc", f(p2v(), p2v(), size())); // C99 7.20.4 decl(nofix, "abort", f()); decl(nofix, "atexit", f(i(), p(f()))); decl(nofix, "exit", f(v(), i())); decl(nofix, "_Exit", f(v(), i())); decl(nofix, "getenv", f(p2c(), p(cc()))); decl(nofix, "system", f(i(), p(cc()))); // C99 7.21.2 decl(nofix, "memcpy", f(p2v(), pr(v()), pr(cv()), size())); // C99 7.21.6 decl(nofix, "memset", f(p2v(), p2v(), i(), size())); // GCC extension decl(nofix, "stpcpy", f(p2c(), p2c(), p(cc()))); // Mac OS 10.6 (Snow Leopard) memory checks in /usr/include/secure/_string.h decl(nofix, "__memcpy_chk", f(p2v(), p2v(), p2cv(), size(), size())); decl(nofix, "__memmove_chk", f(p2v(), p2v(), p2cv(), size(), size())); decl(nofix, "__memset_chk", f(p2v(), p2v(), i(), size(), size())); decl(nofix, "__strcpy_chk", f(p2c(), pr(c()), pr(cc()), size())); decl(nofix, "__stpcpy_chk", f(p2c(), p2c(), p2cc(), size())); decl(nofix, "__strncpy_chk", f(p2c(), pr(c()), pr(cc()), size(), size())); decl(nofix, "__strcat_chk", f(p2c(), pr(c()), pr(cc()), size())); decl(nofix, "__strncat_chk", f(p2c(), pr(c()), pr(cc()), size(), size())); // Mac OS 10.7 (Lion) memory checks in /usr/include/secure/_string.h decl(nofix, "__stpncpy_chk", f(p2c(), pr(c()), pr(cc()), size(), size())); } }