//is this const or not public static void PushTypeQualifier(string qualifier) { var spec = new CDeclarationSpecifier(); spec.SpeciferType = CDeclarationSpecifierType.Const; spec.ConstType = constTypeFromString(qualifier); PushDeclSpec(spec); }
internal static void PushTypeDefName(string p) { var declspec = new CDeclarationSpecifier(); declspec.SpeciferType = CDeclarationSpecifierType.Name; declspec.name = p; PushDeclSpec(declspec); }
//enum decl is a specifier //the only case where this is not also a definition, is in function prototypes (enum name x), and other weird places. this is one of the cruftyer parts of c public static void PushEnumDeclaration(string idString) { var spec = new CDeclarationSpecifier(); spec.SpeciferType = CDeclarationSpecifierType.Type; spec.type = CType.DeclareEnum(idString); PushDeclSpec(spec); }
//void, arithmetic type, typedefed name public static void PushTypeSpecifier(string typeName) { var spec = new CDeclarationSpecifier(); spec.SpeciferType = CDeclarationSpecifierType.Type; spec.type = CType.CTypeFromName(typeName); PushDeclSpec(spec); }
//declaration specifiers //storage specifers //http://en.cppreference.com/w/c/language/storage_duration public static void PushStorageClassSpecifier(string specifier) { var spec = new CDeclarationSpecifier(); spec.SpeciferType = CDeclarationSpecifierType.Storage; spec.StorageClass = StorageClassFromString(specifier); PushDeclSpec(spec); }
//exit function scope public static void EndFunctionDefinition(int numSpecifiers) { CIdentifier.ExitFunctionScope(); List <CDeclarationSpecifier> specs = new List <CDeclarationSpecifier>(); for (int i = 0; i < numSpecifiers; i++) { specs.Add(PopDeclSpec()); } CDeclarationSpecifier typeSpec = specs.First(spec => spec.SpeciferType == CDeclarationSpecifierType.Type); CDeclarationSpecifier storageClass = specs.FirstOrDefault(spec => spec.SpeciferType == CDeclarationSpecifierType.Storage); CDeclarator paramDecl = PopDeclarator(); CIdentifier.DefineFunction(paramDecl.TypeModifier.ModifyType(typeSpec.type), paramDecl.Identifer, storageClass == null ? CStorageClass.Ignore : storageClass.StorageClass); }
//paramaters //define param in function scope or function prototype scope public static void ParamaterDeclaration(int numSpecifiers) { List <CDeclarationSpecifier> specs = new List <CDeclarationSpecifier>(); for (int i = 0; i < numSpecifiers; i++) { specs.Add(PopDeclSpec()); } CDeclarationSpecifier typeSpec = specs.First(spec => spec.SpeciferType == CDeclarationSpecifierType.Type); //ignore const and register specifiers on params CDeclarator declarator = PopDeclarator(); CParamater param = CIdentifier.CreateFunctionParameter( declarator.Identifer, declarator.TypeModifier != null ? declarator.TypeModifier.ModifyType(typeSpec.type) : typeSpec.type ); PushParam(param); }
private static void PushDeclSpec(CDeclarationSpecifier declSpec) { declSpecs.Push(declSpec); }
//storage and linkage //http://en.cppreference.com/w/c/language/storage_duration /* * Every object has a property called storage duration, which limits the object lifetime. There are four kinds of storage duration in C: * * automatic storage duration. * The storage is allocated when the block in which the object was declared is entered and * deallocated when it is exited by any means (goto, return, reaching the end). If the block is entered recursively, a new allocation is performed for every recursion level. All function parameters and non-static block-scope objects have this storage duration. * * static storage duration. * The storage duration is the entire execution of the program, * and the value stored in the object is initialized only once, prior to main function. * All objects declared static and all objects with either internal or external linkage have this storage duration. * * thread storage duration. NOT SUPPORTED * * allocated storage duration. * The storage is allocated and deallocated on request, using dynamic memory allocation functions. * * Linkage * Linkage refers to the ability of an identifier (variable or function) to be referred to in other scopes. * If a variable or function with the same identifier is declared in several scopes, * but cannot be referred to from all of them, then several instances of the variable are generated. * * The following linkages are recognized: * * no linkage. * The identifier can be referred to only from the scope it is in. * All function parameters and all non-extern block-scope variables (including the ones declared static) have this linkage. * * internal linkage. * The identifier can be referred to from all scopes in the current translation unit. * All static identifiers (both functions and variables) have this linkage. * * external linkage. * The identifier can be referred to from any other translation units in the entire program. * All non-static functions, all extern variables (unless earlier declared static), and all file-scope non-static variables have this linkage. * * Names at file scope that are const and not extern have external linkage in C * * Storage-class specifiers specify one of the following combinations of storage duration and linkage * auto - automatic duration and no linkage (on stack) * register - NOT SUPPORTED * static - static duration and internal linkage (unless at block scope) (in data or rodata segment) * extern - static duration and external linkage (unless already declared internal) (on heap) * * If no storage-class specifier is provided, the defaults are: * extern for all functions * extern for objects at file scope * auto for objects at block scope * * For any struct or union declared with a storage-class specifier, * the storage duration (but not linkage) applies to their members, recursively. * * Function declarations at block scope can use extern or none at all. * Function declarations at file scope can use extern or static. */ //scope //http://en.cppreference.com/w/c/language/scope /*Each identifier that appears in a C program is visible (that is, may be used) only in some possibly discontiguous portion of the source code called its scope. * Within a scope, an identifier may designate more than one entity only if the entities are in different name spaces. * C has four kinds of scopes: * block scope * file scope * function scope * function prototype scope * * Nested scopes * If two different entities named by the same identifier are in scope at the same time, * and the scopes are nested, * the declaration that appears in the inner scope hides the declaration that appears in the outer scope * * Block Scope * The scope of any identifier declared inside a compound statement, * including function bodies, * or in any expression, declaration, or statement appearing in * if, switch, for, while, or do-while statement, * or within the parameter list of a function definition * begins at the point of declaration and ends at the end of the block or statement in which it was declared. * * File scope * The scope of any identifier declared outside of any block or parameter list begins at the point of declaration and ends at the end of the translation unit (file). * File-scope identifiers have external linkage and static storage duration by default. * * Function scope * A label (and only a label) declared inside a function is in scope everywhere in that function, in all nested blocks, before and after its own declaration. * * Function prototype scope * The scope of a name introduced in the parameter list of a function declaration ends at the end of the function declarator. */ //declarations //http://en.cppreference.com/w/c/language/declarations //A declaration is a C language construct that introduces one or more identifiers into the program and specifies their meaning and properties. //Declarations may appear in any scope. Each declaration ends with a semicolon (just like a statement) and consists of two distinct parts: /* * specifiers-and-qualifiers - whitespace-separated list of, in any order, * exactly one type specifier: * void * the name of an arithmetic type * the name of an atomic type * a name earlier introduced by a typedef declaration * struct, union, or enum specifier * zero or one storage-class specifiers: * typedef, * auto, * static, * extern * optional const * * declarators-and-initializers - comma-separated list of declarators * (each declarator provides additional type information and/or the identifier to declare). * Declarators may be accompanied by initializers. */ public static void Declaration(int numSpecifier, int numDeclarators) { List <CDeclarationSpecifier> specifiers = new List <CDeclarationSpecifier>(); for (int i = 0; i < numSpecifier; i++) { specifiers.Add(PopDeclSpec()); } //TODO hanldle unsigned, signed, long, typedef name IEnumerable <CDeclarationSpecifier> typeSpecs = specifiers.Where(spec => spec.SpeciferType == CDeclarationSpecifierType.Type); CType resolvedType = CType.ResolveTypeFromSpecifers(typeSpecs); IEnumerable <CDeclarationSpecifier> typeDefNames = specifiers.Where(spec => spec.SpeciferType == CDeclarationSpecifierType.Name); CDeclarationSpecifier storageClass = specifiers.FirstOrDefault(spec => spec.SpeciferType == CDeclarationSpecifierType.Storage); CDeclarationSpecifier constQualifier = specifiers.FirstOrDefault(spec => spec.SpeciferType == CDeclarationSpecifierType.Const); List <CDeclarator> declarators = new List <CDeclarator>(); for (int i = 0; i < numDeclarators; i++) { declarators.Add(PopDeclarator()); } List <CIdentifier> declared = new List <CIdentifier>(); foreach (CDeclarator declarator in declarators) { CIdentifier id = CIdentifier.CreateIdentifierInCurrentScope(declarator.Identifer, declarator.TypeModifier != null ? declarator.TypeModifier.ModifyType(resolvedType) : resolvedType, storageClass == null ? CStorageClass.Ignore : storageClass.StorageClass, constQualifier == null ? CConstType.Ignore : constQualifier.ConstType); if (declarator.Init != null) { id.Init = declarator.Init; } declared.Add(id); } if (declared.Count == 0) { if (storageClass != null && storageClass.StorageClass == CStorageClass.Typedef) { //this is a typedef foreach (var defSpec in typeDefNames) { CType.TypeDef(defSpec.name, resolvedType); } } else { //this is a declaration without a declarator var name = typeDefNames.First(); CIdentifier id = CIdentifier.CreateIdentifierInCurrentScope(name.name, resolvedType, storageClass == null ? CStorageClass.Ignore : storageClass.StorageClass, constQualifier == null ? CConstType.Ignore : constQualifier.ConstType); declared.Add(id); } } PushDecl(new CDeclaration(declared)); }