Compare commits

..

No commits in common. "master" and "dev-refactor" have entirely different histories.

69 changed files with 1381 additions and 6224 deletions

8
.gitignore vendored
View File

@ -1,14 +1,6 @@
.idea .idea
.vscode .vscode
.cache
out out
bin bin
build
Erythro
test
cmake-build-debug
*.s
*.o

View File

@ -1,26 +0,0 @@
cmake_minimum_required(VERSION 3.21)
project(Erythro C)
set(CMAKE_C_STANDARD 11)
include_directories(include)
add_executable(Erythro
include/Data.h
include/Defs.h
src/assemble/AssemblerDispatcher.c
src/assemble/Win32GASAssembler.c
src/assemble/LinuxGASAssembler.c
src/assemble/JVMAssembler.c
src/assemble/QBEAssembler.c
src/Delegate.c
src/Dump.c
src/Lexer.c
src/Main.c
src/Parser.c
src/Pointers.c
src/Statements.c
src/Symbols.c
src/Types.c
src/Importer.c
src/Errors.c)

View File

@ -1,20 +0,0 @@
{
"name": "Erythro",
"author": "Curle",
"source": {
"src": [
"$root/src/*.c"
],
"inc": [
"$root/include/"
]
},
"build": {
"compile": [
"-g -I$inc",
"$src"
]
}
}

View File

@ -4,7 +4,6 @@
/*************/ /*************/
#pragma once #pragma once
#include <stdio.h> #include <stdio.h>
#include <Defs.h> #include <Defs.h>
#include <stdbool.h> #include <stdbool.h>
@ -14,53 +13,40 @@
#endif #endif
#define TEXTLEN 512 #define TEXTLEN 512
#define SYMBOLS 1024
// All currently open source files.
extern_ struct FileData** Files;
// The source file currently being operated on.
extern_ struct FileData* CurrentFile;
// The file we are writing into; CurrentFile -> OutputFile
extern_ FILE* OutputFile;
// Symbol tables.
extern_ struct SymbolTableEntry* Globals, *GlobalsEnd; extern_ struct SymbolTableEntry* Globals, *GlobalsEnd;
extern_ struct SymbolTableEntry* Locals, *LocalsEnd; extern_ struct SymbolTableEntry* Locals, *LocalsEnd;
extern_ struct SymbolTableEntry* Params, *ParamsEnd; extern_ struct SymbolTableEntry* Params, *ParamsEnd;
extern_ struct SymbolTableEntry* Structs, *StructsEnd; extern_ struct SymbolTableEntry* Structs, *StructsEnd;
extern_ struct SymbolTableEntry* CompositeMembers, * CompositeMembersEnd; extern_ struct SymbolTableEntry* StructMembers, *StructMembersEnd;
extern_ struct SymbolTableEntry* EnumMembers, * EnumMembersEnd;
extern_ struct SymbolTableEntry* Unions, *UnionsEnd; extern_ struct SymbolTableEntry* Unions, *UnionsEnd;
extern_ struct SymbolTableEntry* Enums, *EnumsEnd; extern_ struct SymbolTableEntry* Enums, *EnumsEnd;
extern_ struct SymbolTableEntry* Types, * TypesEnd;
// Whether we should dump the syntax tree before starting to assemble the file.
extern_ bool OptDumpTree; extern_ bool OptDumpTree;
// Whether we should keep the assembly files after successfully linking.
extern_ bool OptKeepAssembly; extern_ bool OptKeepAssembly;
// Whether to stop at compilation and dumping - skip assembly and binary creation altogether.
extern_ bool OptAssembleFiles; extern_ bool OptAssembleFiles;
// Whether to stop at assembly - skip linking into a binary.
extern_ bool OptLinkFiles; extern_ bool OptLinkFiles;
// Whether to output extended debugging information.
extern_ bool OptVerboseOutput; extern_ bool OptVerboseOutput;
// The name of the binary we want to create.
extern_ char* OutputFileName; extern_ char* OutputFileName;
// The sizes of each of the core types, in bytes. extern_ char* CurrentASMFile, *CurrentObjectFile;
extern_ int TypeSizes[5]; extern_ int TypeSizes[5];
// The name of the Assembler Module that we should use.
extern_ char* OptAssemblerName;
// The Assembler Module to call to when performing generation operations.
extern_ struct AssemblerModule* Assembler;
// The names of each token in the language, synchronized to the TokenTypes enum.
extern_ char* TokenNames[]; extern_ char* TokenNames[];
extern_ char* OperationNames[];
// The names of the storage scopes.
extern_ char* ScopeNames[];
extern_ int CurrentFunction;
extern_ struct SymbolTableEntry* FunctionEntry;
extern_ int Line;
extern_ int Overread; extern_ int Overread;
extern_ FILE* SourceFile;
extern_ FILE* OutputFile;
extern_ struct Token CurrentToken;
extern_ char CurrentIdentifier[TEXTLEN + 1]; extern_ char CurrentIdentifier[TEXTLEN + 1];
extern_ int CurrentGlobal;
extern_ int CurrentLocal;

View File

@ -4,14 +4,12 @@
/*************/ /*************/
#pragma once #pragma once
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
/* /*
* ARithmetic tokens are prefixed AR. * ARithmetic tokens are prefixed AR.
* LIteral tokens are prefixed LI. * LIteral tokens are prefixed LI.
@ -68,7 +66,6 @@ enum TokenTypes {
LI_INT, // Integer literal LI_INT, // Integer literal
LI_STR, // String literal LI_STR, // String literal
LI_SEMIC, // ; LI_SEMIC, // ;
LI_COLON, // :
LI_LBRAC, // { LI_LBRAC, // {
LI_RBRAC, // } LI_RBRAC, // }
@ -80,8 +77,6 @@ enum TokenTypes {
LI_RPARE, // ) LI_RPARE, // )
LI_COM, // , LI_COM, // ,
LI_DOT, // .
LI_ARROW, // ->
TY_IDENTIFIER, // Identifier name. Variable, function, etc. TY_IDENTIFIER, // Identifier name. Variable, function, etc.
TY_NONE, // No return type. Literal void. TY_NONE, // No return type. Literal void.
@ -91,12 +86,6 @@ enum TokenTypes {
TY_VOID, // "void" type keyword TY_VOID, // "void" type keyword
KW_FUNC, // :: function name incoming KW_FUNC, // :: function name incoming
KW_BREAK, // "break" keyword
KW_CONTINUE, // "continue" keyword
KW_SWITCH, // "switch" keyword
KW_DEFAULT, // "default" keyword
KW_CASE, // "case" keyword
KW_PRINT, KW_PRINT,
KW_IF, KW_IF,
@ -104,12 +93,7 @@ enum TokenTypes {
KW_WHILE, KW_WHILE,
KW_FOR, KW_FOR,
KW_RETURN, KW_RETURN,
KW_STRUCT, KW_STRUCT
KW_UNION,
KW_ENUM,
KW_ALIAS,
KW_IMPORT
}; };
/* /*
@ -123,9 +107,6 @@ enum TokenTypes {
* *
* It is important that Tokens and Operations are logically separated, * It is important that Tokens and Operations are logically separated,
* but that the Operation's index is the same as the Token that invokes it. * but that the Operation's index is the same as the Token that invokes it.
*
* Every five elements, an index is assigned. These are the natural indices.
* They are marked to make navigation of the Syntax Tree easier.
*/ */
enum SyntaxOps { enum SyntaxOps {
@ -134,32 +115,32 @@ enum SyntaxOps {
OP_BOOLOR, // Boolean OR two statements OP_BOOLOR, // Boolean OR two statements
OP_BOOLAND, // Boolean AND two statements OP_BOOLAND, // Boolean AND two statements
OP_BITOR, // Bitwise OR a number OP_BITOR, // Bitwise OR a number
OP_BITXOR = 5, // Bitwise XOR a number OP_BITXOR, // Bitwise XOR a number
OP_BITAND, // Bitwise AND a number OP_BITAND, // Bitwise AND a number
OP_EQUAL, // Compare equality OP_EQUAL, // Compare equality
OP_INEQ, // Compare inequality OP_INEQ, // Compare inequality
OP_LESS, // Less than? OP_LESS, // Less than?
OP_GREAT = 10, // Greater than? OP_GREAT, // Greater than?
OP_LESSE, // Less than or Equal to? OP_LESSE, // Less than or Equal to?
OP_GREATE, // Greater than or Equal to? OP_GREATE, // Greater than or Equal to?
OP_SHIFTL, // Arithmetic Shift Left (Multiply by 2) OP_SHIFTL, // Arithmetic Shift Left (Multiply by 2)
OP_SHIFTR, // Arithmetic Shift Right (Divide by 2) OP_SHIFTR, // Arithmetic Shift Right (Divide by 2)
OP_ADD = 15, // Add two numbers. OP_ADD, // Add two numbers.
OP_SUBTRACT, // Subtract two numbers. OP_SUBTRACT, // Subtract two numbers.
OP_MULTIPLY, // Multiply two numbers. OP_MULTIPLY, // Multiply two numbers.
OP_DIVIDE, // Divide two numbers. OP_DIVIDE, // Divide two numbers.
OP_PREINC, // Increment var before reference. OP_PREINC, // Increment var before reference.
OP_PREDEC = 20, // Decrement var before reference. OP_PREDEC, // Decrement var before reference.
OP_POSTINC, // Increment var after reference. OP_POSTINC, // Increment var after reference.
OP_POSTDEC, // Decrement var after reference. OP_POSTDEC, // Decrement var after reference.
OP_BITNOT, // Invert a number bitwise OP_BITNOT, // Invert a number bitwise
OP_BOOLNOT, // Invert a statement logically OP_BOOLNOT, // Invert a statement logically
OP_NEGATE = 25, // Negate a number (turn a positive number negative) OP_NEGATE, // Negate a number (turn a positive number negative)
OP_BOOLCONV, // Convert an expression to a boolean.s OP_BOOLCONV, // Convert an expression to a boolean.s
@ -167,7 +148,7 @@ enum SyntaxOps {
OP_DEREF, // Get the value of the address in a pointer OP_DEREF, // Get the value of the address in a pointer
TERM_INTLITERAL, // Integer Literal. This is a virtual operation, so it's a terminal. TERM_INTLITERAL, // Integer Literal. This is a virtual operation, so it's a terminal.
TERM_STRLITERAL = 30, // String Literal. Also terminal. TERM_STRLITERAL, // String Literal. Also terminal.
REF_IDENT, // Reference (read) an identifier (variable). REF_IDENT, // Reference (read) an identifier (variable).
@ -175,34 +156,18 @@ enum SyntaxOps {
OP_SCALE, // We have a pointer that needs to be scaled! OP_SCALE, // We have a pointer that needs to be scaled!
OP_CALL, // Call a function OP_CALL, // Call a function
OP_RET = 35, // Return from a function OP_RET, // Return from a function
OP_COMP, // Compound statements need a way to be "glued" together. This is one of those mechanisms OP_COMP, // Compound statements need a way to be "glued" together. This is one of those mechanisms
OP_IF, // If statement OP_IF, // If statement
OP_LOOP, // FOR, WHILE OP_LOOP, // FOR, WHILE
OP_PRINT, // Print statement OP_PRINT, // Print statement
OP_FUNC = 40, // Define a function OP_FUNC, // Define a function
OP_BREAK, // Break out of the loop
OP_CONTINUE, // Continue the loop
OP_SWITCH, // Switch statement
OP_DEFAULT, // Default case
OP_CASE = 45 // Case
}; };
/** // A node in a Binary Tree that forms the syntax of Erythro
* The way syntax is stored by the parser and assembled into a usable file.
* An ASTNode forms an item in a linked list.
*
* Thus, you can traverse up and down a tree of ASTNodes easily.
*
* Walking the tree is as simple as reading the Operation and recursively reading the Left, Middle and Right nodes as called for.
* For example, an if-else statement uses all three subnodes.
*
* This means that AST Nodes aren't exactly a binary tree, but a syntax tree nonetheless.
*/
struct ASTNode { struct ASTNode {
int Operation; // SyntaxOps Index int Operation; // SyntaxOps Index
int ExprType; // Value->IntValue's DataType int ExprType; // Value->IntValue's DataType
@ -217,12 +182,6 @@ struct ASTNode {
}; };
}; };
/**
* Describes the basic unit of syntax in the language.
* A token has a type (an index into the TokenTypes enum) and a value.
*
* The value represents the numerical value of an integer literal, etc.
*/
struct Token { struct Token {
int type; int type;
int value; int value;
@ -239,76 +198,26 @@ struct SymbolTableEntry {
struct SymbolTableEntry* CompositeType; // A pointer to the start of a Symbol Table list that represents a certain Composite type struct SymbolTableEntry* CompositeType; // A pointer to the start of a Symbol Table list that represents a certain Composite type
int Structure; // An entry in StructureType - metadata on how to process the data int Structure; // An entry in StructureType - metadata on how to process the data
int Storage; // The scope of this symbol - decides when it is discarded. int Storage; // The scope of this symbol - decides when it is discarded.
int Length; // Size of an array, or the number of parameters in a function
int Size; // Total size in bytes.
int* InitialValues;
int IntValue; // For an enum - The value of an Enum entry
union { union {
int EndLabel; // For a function - The number of the label to jump to, in order to exit this function (if applicable) int EndLabel; // For a function - The number of the label to jump to, in order to exit this function (if applicable)
int Length; // For an array - The length of the symbol in units of 1 element -- the size of an array, for example.
int IntValue; // For an enum - The value of an Enum entry
};
union {
int SinkOffset; // For a variable - How many times must we sink the rbp to get to this symbol in the stack? int SinkOffset; // For a variable - How many times must we sink the rbp to get to this symbol in the stack?
int Elements; // For a function - How many parameters?
}; };
struct SymbolTableEntry* NextSymbol; // The next symbol in a list struct SymbolTableEntry* NextSymbol; // The next symbol in a list
struct SymbolTableEntry* Start; // The first member in a list struct SymbolTableEntry* Start; // The first member in a list
}; };
/**
* Information about a given source file.
*
* A file that starts the parsing of another file will never confuse the parser.
*
* It is the end goal that the parser will be multithreaded, operating on a single file at a time.
*
* Note that files do not contain their own symbol tables - these are global.
*/
struct FileData {
// Whether or not this file will accept definitions of functions.
bool AllowDefinitions;
// A FILE stream that we can read the file from.
FILE* Stream;
// The filename of the source code
char* SourceName;
// The filename of the assembly output
char* AssemblyName;
// The filename of the assembled object code
char* ObjectName;
// The line of the file we are currently working on, -1 if it is finished
long CurrentLine;
// The column of the file we are currently working on, -1 if it is finished
long CurrentColumn;
// The depth of the loop currently being parsed.
long CurrentLoopDepth;
// The column that was last marked as "valid", the start of the error block if something goes wrong.
long CurrentSafeColumn;
// Whether or not we are currently parsing a switch statement - changes the behavior of compound statements!
bool SwitchStatement;
// The symbol currently being lexed - TokenTypes index and integer value.
struct Token CurrentSymbol;
// The function currently being parsed - null if in global scope or if finished.
struct SymbolTableEntry* FunctionEntry;
// Once ready, the full AST trees of this file.
struct ASTNode* Tree;
};
enum StorageScope { enum StorageScope {
SC_GLOBAL = 1, // Global Scope SC_GLOBAL = 1, // Global Scope
SC_STRUCT, // Struct Definitions SC_STRUCT, // Struct Definitions
SC_UNION, // Union Definitions
SC_ENUM, // Enum Definitions SC_ENUM, // Enum Definitions
SC_ENUMENTRY, // Enum Entry Names SC_MEMBER, // The members of Structs or Enums
SC_ALIAS, // Typedef aliases
SC_MEMBER, // The members of Structs or Unions
//SC_CLASS, // Class-local definitions //SC_CLASS, // Class-local definitions
//SC_STATIC, // Static storage definitions //SC_STATIC, // Static storage definitions
SC_PARAM, // Function parameters SC_PARAM, // Function parameters
@ -335,9 +244,6 @@ enum DataTypes {
DAT_STRUCT = 80, // Struct Data DAT_STRUCT = 80, // Struct Data
DAT_UNION, // Union Data DAT_UNION, // Union Data
DAT_ENUM, // Enum Data
DAT_ALIAS, // Alias Definition
DAT_NONE, // No type, no work needed.
}; };
/* /*
@ -348,9 +254,9 @@ enum DataTypes {
enum StructureType { enum StructureType {
ST_VAR, // This is variable ST_VAR, // This is variable
ST_FUNC, // This is a function ST_FUNC, // This is a function
ST_ARR, // This is an array ST_ARR // This is an array
ST_RUCT, // This is a struct // This is an enum
ST_ENUM, // This is an enum // This is a struct
// This is a typedef // This is a typedef
}; };
@ -360,13 +266,9 @@ enum StructureType {
* * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char* Suffixate(char* String, char Suffix); char* Suffixate(char* String, char Suffix);
char* Compile(char* InputFile);
void Compile(struct FileData* InputFile); char* Assemble(char* InputFile);
void Link(char* Output, char* Objects[]);
void Assemble(struct FileData* InputFile);
void Link(char* Output, struct FileData* Objects[], int ObjectsLength);
void DisplayUsage(char* ProgName); void DisplayUsage(char* ProgName);
@ -374,17 +276,15 @@ void DisplayUsage(char* ProgName);
* * * * * * * * * L E X I N G * * * * * * * * * * * * * * * * * * L E X I N G * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void Tokenise(); void Tokenise();
void VerifyToken(int Type, char* TokenExpected); void VerifyToken(int Type, char* TokenExpected);
bool OptionallyConsume(int Type); void RejectToken(struct Token* Token);
static int ReadIdentifier(int Char, char* Buffer, int Limit); static int ReadIdentifier(int Char, char* Buffer, int Limit);
static int ReadKeyword(char* Str); static int ReadKeyword(char* Str);
void ImportModule();
/* * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * *
* * * * * T Y P E S * * * * * * * * * * * T Y P E S * * * * * *
* * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * */
@ -392,11 +292,9 @@ void ImportModule();
struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation); struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation);
int TypeIsInt(int Type); int TypeIsInt(int Type);
int TypeIsPtr(int Type); int TypeIsPtr(int Type);
char* TypeNames(int Type); char* TypeNames(int Type);
int TypeSize(int Type, struct SymbolTableEntry* Composite); int TypeSize(int Type, struct SymbolTableEntry* Composite);
@ -425,75 +323,48 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence);
struct ASTNode* ParsePrimary(void); struct ASTNode* ParsePrimary(void);
struct ASTNode* ParseStatement(void); struct ASTNode* ParseStatement(void);
struct ASTNode* PrefixStatement(); struct ASTNode* PrefixStatement();
struct ASTNode* PostfixStatement(); struct ASTNode* PostfixStatement();
void ParseGlobals(); void ParseGlobals();
int ParseDeclarationList(struct SymbolTableEntry** CompositeType, int ClassType, int StatementEndSymbool, int TerminateSymbol, struct ASTNode** Tree); struct ASTNode* ParseFunction(int Type);
struct ASTNode* ParseCompound(); struct ASTNode* ParseCompound();
struct SymbolTableEntry* BeginCompositeDeclaration(int Type); struct SymbolTableEntry* BeginStructDeclaration();
struct ASTNode* GetExpressionList();
struct ASTNode* ParseExpressionList(int terminateToken);
struct ASTNode* CallFunction(); struct ASTNode* CallFunction();
struct ASTNode* ReturnStatement(); struct ASTNode* ReturnStatement();
struct ASTNode* BreakStatement(); int ParseOptionalPointer();
struct ASTNode* ContinueStatement();
int ValueAt(int Type); int ValueAt(int Type);
int PointerTo(int Type); int PointerTo(int Type);
struct ASTNode* AccessArray(); struct ASTNode* AccessArray();
struct ASTNode* AccessMember(bool Deref);
int ParseTokenToOperation(int Token); int ParseTokenToOperation(int Token);
struct ASTNode* PrintStatement(void);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * S Y M B O L T A B L E * * * * * * * * * * * * S Y M B O L T A B L E * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void DumpAllLists();
void DumpList(struct SymbolTableEntry* List);
struct SymbolTableEntry* FindSymbol(char* Symbol); struct SymbolTableEntry* FindSymbol(char* Symbol);
struct SymbolTableEntry* FindLocal(char* Symbol); struct SymbolTableEntry* FindLocal(char* Symbol);
struct SymbolTableEntry* FindGlobal(char* Symbol); struct SymbolTableEntry* FindGlobal(char* Symbol);
struct SymbolTableEntry* FindStruct(char* Symbol); struct SymbolTableEntry* FindStruct(char* Symbol);
struct SymbolTableEntry* FindAlias(char* Symbol);
struct SymbolTableEntry* FindEnum(char* Symbol);
struct SymbolTableEntry* FindEnumMember(char* Symbol);
struct SymbolTableEntry* FindUnion(char* Symbol);
struct SymbolTableEntry* FindMember(char* Symbol); struct SymbolTableEntry* FindMember(char* Symbol);
void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node); void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node);
void FreeLocals(); void FreeLocals();
void ClearTables(); void ClearTables();
struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset, struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset, struct SymbolTableEntry* CompositeType);
struct SymbolTableEntry* CompositeType);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * C O N T R O L S T A T U S * * * * * * * * C O N T R O L S T A T U S * * * *
@ -507,110 +378,85 @@ void DieDecimal(char* Error, int Number);
void DieChar(char* Error, int Char); void DieChar(char* Error, int Char);
void DieBinary(char* Error, int Number);
void ErrorReport(char* message, ...);
void Safe();
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * C O D E G E N E R A T I O N * * * * * * * * C O D E G E N E R A T I O N * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int PrimitiveSize (int); int AssembleTree(struct ASTNode* Node, int Register, int ParentOp);
/** void DeallocateAllRegisters();
* All of the functions required to be implemented by an Assembler Module.
*/
struct AssemblerVtable {
// Entry Point
int (*AssembleTree)(struct ASTNode*, int, int, int, int);
// Register management
void (*DeallocateAllRegisters)();
int (*RetrieveRegister)();
void (*DeallocateRegister)(int);
// Alignment
int (*AsAlignMemory)(int, int, int);
int (*AsCalcOffset)(int);
void (*AsNewStackFrame)();
// Basic operations
int (*AsLoad)(int);
int (*AsAdd)(int, int);
int (*AsMul)(int, int);
int (*AsSub)(int, int);
int (*AsDiv)(int, int);
int (*AsLdGlobalVar)(struct SymbolTableEntry*, int);
int (*AsLdLocalVar)(struct SymbolTableEntry*, int);
int (*AsStrGlobalVar)(struct SymbolTableEntry*, int);
int (*AsStrLocalVar)(struct SymbolTableEntry*, int);
int (*AsDeref)(int, int);
int (*AsStrDeref)(int, int, int);
int (*AsAddr)(struct SymbolTableEntry*);
int (*AsNewString)(char*);
int (*AsLoadString)(int);
// Comparisons int RetrieveRegister();
int (*AsEqual)(int, int);
int (*AsIneq)(int, int);
int (*AsLess)(int, int);
int (*AsGreat)(int, int);
int (*AsLessE)(int, int);
int (*AsGreatE)(int, int);
// Binary operations void DeallocateRegister(int Register);
int (*AsBitwiseAND)(int, int);
int (*AsBitwiseOR)(int, int);
int (*AsBitwiseXOR)(int, int);
int (*AsNegate)(int);
int (*AsInvert)(int);
int (*AsBooleanNOT)(int);
int (*AsShiftLeft)(int, int);
int (*AsShiftRight)(int, int);
// Comparisons int PrimitiveSize(int Type);
int (*AsBooleanConvert)(int, int, int); int AsAlignMemory(int Type, int Offset, int Direction);
int (*AsCompareJmp)(int, int, int, int);
int (*AsCompare)(int, int, int);
// Loops and jumps int AsLoad(int Value);
int (*AsIf)(struct ASTNode*, int, int); int AsAdd(int Left, int Right);
int (*AsWhile)(struct ASTNode*); int AsMul(int Left, int Right);
int (*AsSwitch)(struct ASTNode*); int AsSub(int Left, int Right);
void (*AsSwitchTable)(int, int, int, int*, int*, int); int AsDiv(int Left, int Right);
int (*NewLabel)();
void (*AsJmp)(int);
void (*AsLabel)(int);
// Call and return int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation);
int (*AsShl)(int, int); int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation);
int (*AsReturn)(struct SymbolTableEntry*, int); int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register);
int (*AsCallWrapper)(struct ASTNode*); int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register);
void (*AsCopyArgs)(int, int);
int (*AsCall)(struct SymbolTableEntry*, int);
void (*AssemblerPrint)(int);
// Preamble and epilogue int AsCalcOffset(int Type);
void (*AsGlobalSymbol)(struct SymbolTableEntry*); void AsNewStackFrame();
void (*AssemblerPreamble)();
void (*AsFunctionPreamble)(struct SymbolTableEntry*);
void (*AsFunctionEpilogue)(struct SymbolTableEntry*);
};
struct AssemblerModule{ int AsDeref(int Reg, int Type);
char* name; int AsStrDeref(int Register1, int Register2, int Type);
const struct AssemblerVtable* vtable; int AsAddr(struct SymbolTableEntry* Entry);
};
int RegisterModule(struct AssemblerModule*); void AsGlobalSymbol(struct SymbolTableEntry* Entry);
int AsNewString(char* Value);
void RegisterAllModules();
// Module List int AsLoadString(int ID);
void RegisterQBE();
void RegisterWin32ASM(); int AsEqual(int Left, int Right);
void RegisterLinuxASM(); int AsIneq(int Left, int Right);
void RegisterJVM(); int AsLess(int Left, int Right);
int AsGreat(int Left, int Right);
int AsLessE(int Left, int Right);
int AsGreatE(int Left, int Right);
int AsBitwiseAND(int Left, int Right);
int AsBitwiseOR(int Left, int Right);
int AsBitwiseXOR(int Left, int Right);
int AsNegate(int Register);
int AsInvert(int Register);
int AsBooleanNOT(int Register);
int AsShiftLeft(int Left, int Right);
int AsShiftRight(int Left, int Right);
int AsBooleanConvert(int Register, int Operation, int Label);
int AsCompareJmp(int Operation, int RegisterLeft, int RegisterRight, int Label);
int AsCompare(int Operation, int RegisterLeft, int RegisterRight);
int AsIf(struct ASTNode* Node);
int NewLabel(void);
void AsJmp(int Label);
void AsLabel(int Label);
int AsShl(int Register, int Val);
int AsReturn(struct SymbolTableEntry* Entry, int Register);
int AsCallWrapper(struct ASTNode* Node);
void AsCopyArgs(int Register, int Position);
int AsCall(struct SymbolTableEntry* Entry, int Args);
int AsWhile(struct ASTNode* Node);
void AssemblerPrint(int Register);
void AssemblerPreamble();
void AsFunctionPreamble(struct SymbolTableEntry* Entry);
void AsFunctionEpilogue(struct SymbolTableEntry* Entry);
/* * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * *
@ -618,14 +464,11 @@ void RegisterJVM();
* * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * */
struct SymbolTableEntry* BeginVariableDeclaration(int Type, struct SymbolTableEntry* Composite, int Scope); struct SymbolTableEntry* BeginVariableDeclaration(int Type, struct SymbolTableEntry* Composite, int Scope);
struct ASTNode* ParseIdentifier(void);
struct ASTNode* IfStatement(); struct ASTNode* IfStatement();
struct ASTNode* WhileStatement(); struct ASTNode* WhileStatement();
struct ASTNode* ForStatement(); struct ASTNode* ForStatement();
struct ASTNode* SwitchStatement();
void DumpTree(struct ASTNode* node, int level); void DumpTree(struct ASTNode* node, int level);

View File

@ -1,137 +0,0 @@
const child = require("child_process");
const fs = require("fs");
let defaultCompiler = "gcc";
let tempDir;
let defaultLinkFlags = "%.o"
let defaultOutput = "$name"
let linkCache = "";
module.exports = {
/**
* Preprocess the buildscript.
* If it contains compile, assemble and link steps, it does nothing
* If it contains compile but no build, it implicitly adds it with the default arguments.
* @param {object} buildscript the JSON buildscript object
*/
extensionC: function(buildscript) {
console.log("c.js processing buildscript");
if(!("link" in buildscript.build)) {
console.log("Inserting link step for gcc");
buildscript.build["link"] = [defaultLinkFlags];
}
if(!("output" in buildscript.build)) {
console.log("Inserting output step");
buildscript.build["output"] = [defaultOutput];
}
tempDir = process.cwd() + "/bsTemp/";
if(!fs.existsSync(tempDir)) {
console.log("Creating temporary dir for object files");
fs.mkdirSync(tempDir);
}
},
extensionH: function() {},
extensionO: function() {},
extensionLD: function() {},
/**
* Called when it is time to execute the compile step.
* It is passed the array of strings associated with the step in the buildscript.
* @param {...string} params the list of strings
*/
stepCompile: function(...params) {
let cwd = process.cwd().replace(/\\/g, "/");
let compileFlags = "";
// Check whether we're doubly listed
if(Array.isArray(params[0])) {
params = params[0];
}
for(var param of params) {
console.log("stepCompile: param", param);
if(param.startsWith("-")) {
compileFlags = param;
} else {
let binPath = param.substr(param.lastIndexOf(cwd) + cwd.length + 1);
binPath = binPath.substr(0, binPath.lastIndexOf("."));
binPath = cwd + "/bsTemp/" + binPath;
// generate the file structure for it to go into
fs.mkdirSync(binPath.substr(0, binPath.lastIndexOf("/")), {recursive: true});
if(param.substr(param.lastIndexOf(".") + 1) != "c"
&& param.substr(param.lastIndexOf(".") + 1) != "s") {
fs.copyFileSync(param, binPath + ".o");
} else {
let compilerCommand =
defaultCompiler +
" -c " + param +
" -o " + binPath + ".o "
+ compileFlags;
child.execSync(compilerCommand);
}
}
}
},
/**
* Take in the compiled binary object files,
* prepare the link command, and save it for the link execution.
* @param {...string} params the object files to link.
*/
stepLink: function(...params) {
let linkerCommand = "";
// Check whether we're doubly listed
if(Array.isArray(params[0])) {
params = params[0];
}
for(var param of params) {
console.log("stepLink: param", param);
linkerCommand += param + " ";
}
linkCache = linkerCommand;
},
/**
* Take in the name of a file, execute the link command to save the output.
* @param {string} output the name of the wanted file
*/
stepOutput: function(output) {
// Check whether we're doubly listed
if(Array.isArray(output[0])) {
output = output[0];
}
let linkerCommand = defaultCompiler + " -o " + process.cwd() + "/" + output + " " + linkCache;
console.log("stepOutput: param", output, "command", linkerCommand);
child.execSync(linkerCommand);
},
/**
* Set the name of the compiler to be used.
* @param {string} comp
*/
setCompiler: function(comp) {
// Check whether we're doubly listed
if(Array.isArray(comp[0])) {
comp = comp[0];
}
defaultCompiler = comp;
console.log("Set compiler to", comp);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -62,19 +62,19 @@ char* Suffixate(char* String, char Suffix) {
* For Erythro code, this is .er * For Erythro code, this is .er
* The generated assembly will have the extension .s * The generated assembly will have the extension .s
* *
* @param InputFile: A pointer to the data that we should use to compile this file. * @param InputFile: The filename of the Erythro Source code to compile
* @return the filename of the generated PECOFF32+ assembly * @return the filename of the generated PECOFF32+ assembly
*/ */
void Compile(struct FileData* InputFile) { char* Compile(char* InputFile) {
char* OutputName; char* OutputName;
OutputName = Suffixate(InputFile->SourceName, 's'); OutputName = Suffixate(InputFile, 's');
if(OutputName == NULL) { if(OutputName == NULL) {
fprintf(stderr, "%s must have a suffix.\r\n", InputFile->SourceName); fprintf(stderr, "%s must have a suffix.\r\n", InputFile);
exit(1); exit(1);
} }
if ((InputFile->Stream = fopen(InputFile->SourceName, "r")) == NULL) { if((SourceFile = fopen(InputFile, "r")) == NULL) {
fprintf(stderr, "Unable to open %s: %s\n", InputFile->SourceName, strerror(errno)); fprintf(stderr, "Unable to open %s: %s\n", InputFile, strerror(errno));
exit(1); exit(1);
} }
@ -83,25 +83,22 @@ void Compile(struct FileData* InputFile) {
exit(1); exit(1);
} }
InputFile->AssemblyName = OutputName; Line = 1;
CurrentFile = InputFile;
CurrentFile->CurrentLine = 1;
Overread = '\n'; Overread = '\n';
CurrentGlobal = 0;
CurrentLocal = SYMBOLS - 1;
if(OptVerboseOutput) if(OptVerboseOutput)
printf("Compiling %s\r\n", CurrentFile->SourceName); printf("Compiling %s\r\n", InputFile);
Tokenise(); Tokenise();
Assembler->vtable->AssemblerPreamble(); AssemblerPreamble();
ParseGlobals(); ParseGlobals();
// Output.Tree = ParseGlobals();
fclose(OutputFile); fclose(OutputFile);
return OutputName;
} }
/* /*
@ -118,28 +115,27 @@ void Compile(struct FileData* InputFile) {
* *
*/ */
void Assemble(struct FileData* InputFile) { char* Assemble(char* InputFile) {
char Command[TEXTLEN]; char Command[TEXTLEN];
int Error; int Error;
char* OutputName; char* OutputName;
OutputName = Suffixate(InputFile->AssemblyName, 'o'); OutputName = Suffixate(InputFile, 'o');
if(OutputName == NULL) { if(OutputName == NULL) {
fprintf(stderr, "%s must have a suffix.\r\n", InputFile->AssemblyName); fprintf(stderr, "%s must have a suffix.\r\n", InputFile);
exit(1); exit(1);
} }
InputFile->ObjectName = OutputName; snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile);
snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile->AssemblyName);
if(OptVerboseOutput) if(OptVerboseOutput)
printf("%s\n", Command); printf("%s\n", Command);
Error = system(Command); Error = system(Command);
if(Error != 0) { if(Error != 0) {
fprintf(stderr, "Assembling of %s failed with error code %d\n", InputFile->AssemblyName, Error); fprintf(stderr, "Assembling of %s failed with code %d\n", InputFile, Error);
exit(1); exit(1);
} }
return OutputName;
} }
/* /*
@ -154,8 +150,8 @@ void Assemble(struct FileData* InputFile) {
* *
*/ */
void Link(char* Output, struct FileData** Objects, int ObjectsLength) { void Link(char* Output, char* Objects[]) {
int Count, Size = TEXTLEN, Error, ObjectIdx = 0; int Count, Size = TEXTLEN, Error;
char Command[TEXTLEN], *CommandPtr; char Command[TEXTLEN], *CommandPtr;
CommandPtr = Command; CommandPtr = Command;
@ -163,11 +159,11 @@ void Link(char* Output, struct FileData** Objects, int ObjectsLength) {
CommandPtr += Count; CommandPtr += Count;
Size -= Count; Size -= Count;
while (ObjectIdx < ObjectsLength - 1) { while(*Objects != NULL) {
Count = snprintf(CommandPtr, Size, "%s ", Objects[ObjectIdx]->ObjectName); Count = snprintf(CommandPtr, Size, "%s ", *Objects);
CommandPtr += Count; CommandPtr += Count;
Size -= Count; Size -= Count;
ObjectIdx++; Objects++;
} }
if(OptVerboseOutput) if(OptVerboseOutput)

View File

@ -16,12 +16,12 @@ static int GenerateSrg() {
* Walk the Node tree, and dump the AST tree to stdout. * Walk the Node tree, and dump the AST tree to stdout.
*/ */
void DumpTree(struct ASTNode* Node, int level) { void DumpTree(struct ASTNode* Node, int level) {
int Lstart, Lend; int Lfalse, Lstart, Lend;
// Handle weirdo loops and conditions first. // Handle weirdo loops and conditions first.
switch(Node->Operation) { switch(Node->Operation) {
case OP_IF: case OP_IF:
GenerateSrg(); Lfalse = GenerateSrg();
for(int i = 0; i < level; i++) for(int i = 0; i < level; i++)
fprintf(stdout, " "); fprintf(stdout, " ");
fprintf(stdout, "IF"); fprintf(stdout, "IF");
@ -43,7 +43,7 @@ void DumpTree(struct ASTNode* Node, int level) {
for(int i = 0; i < level; i++) for(int i = 0; i < level; i++)
fprintf(stdout, " "); fprintf(stdout, " ");
fprintf(stdout, "LOOP starts at %d\n", Lstart); fprintf(stdout, "LOOP starts at %d\n", Lstart);
GenerateSrg(); Lend = GenerateSrg();
DumpTree(Node->Left, level + 2); DumpTree(Node->Left, level + 2);
DumpTree(Node->Right, level + 2); DumpTree(Node->Right, level + 2);
return; return;
@ -64,140 +64,54 @@ void DumpTree(struct ASTNode* Node, int level) {
fprintf(stdout, " "); fprintf(stdout, " ");
switch (Node->Operation){ switch (Node->Operation){
case OP_COMP: case OP_COMP: fprintf(stdout, "\n\n"); return;
fprintf(stdout, "\n\n"); case OP_FUNC: fprintf(stdout, "OP_FUNC %s\n", Node->Symbol->Name); return;
return; case OP_ADD: fprintf(stdout, "OP_ADD\n"); return;
case OP_CONTINUE: case OP_SUBTRACT: fprintf(stdout, "OP_SUBTRACT\n"); return;
fprintf(stdout, "OP_CONTINUE\n"); case OP_MULTIPLY: fprintf(stdout, "OP_MULTIPLY\n"); return;
return; case OP_DIVIDE: fprintf(stdout, "OP_DIVIDE\n"); return;
case OP_BREAK: case OP_EQUAL: fprintf(stdout, "OP_EQUAL\n"); return;
fprintf(stdout, "OP_BREAK\n"); case OP_INEQ: fprintf(stdout, "OP_INEQ\n"); return;
return; case OP_LESS: fprintf(stdout, "OP_LESS\n"); return;
case OP_FUNC: case OP_GREAT: fprintf(stdout, "OP_GREAT\n"); return;
fprintf(stdout, "OP_FUNC %s\n", Node->Symbol->Name); case OP_LESSE: fprintf(stdout, "OP_LESSE\n"); return;
return; case OP_GREATE: fprintf(stdout, "OP_GREATE\n"); return;
case OP_ADD: case TERM_INTLITERAL: fprintf(stdout, "TERM_INTLITERAL %d\n", Node->IntValue); return;
fprintf(stdout, "OP_ADD\n"); case TERM_STRLITERAL: fprintf(stdout, "TERM_STRLITERAL rval L%d\n", Node->IntValue); return;
return;
case OP_SUBTRACT:
fprintf(stdout, "OP_SUBTRACT\n");
return;
case OP_MULTIPLY:
fprintf(stdout, "OP_MULTIPLY\n");
return;
case OP_DIVIDE:
fprintf(stdout, "OP_DIVIDE\n");
return;
case OP_EQUAL:
fprintf(stdout, "OP_EQUAL\n");
return;
case OP_INEQ:
fprintf(stdout, "OP_INEQ\n");
return;
case OP_LESS:
fprintf(stdout, "OP_LESS\n");
return;
case OP_GREAT:
fprintf(stdout, "OP_GREAT\n");
return;
case OP_LESSE:
fprintf(stdout, "OP_LESSE\n");
return;
case OP_GREATE:
fprintf(stdout, "OP_GREATE\n");
return;
case TERM_INTLITERAL:
fprintf(stdout, "TERM_INTLITERAL %d\n", Node->IntValue);
return;
case TERM_STRLITERAL:
fprintf(stdout, "TERM_STRLITERAL rval L%d\n", Node->IntValue);
return;
case REF_IDENT: case REF_IDENT:
fprintf(stdout, "REF_IDENT%s %s\n", Node->RVal ? " rval" : "", Node->Symbol->Name); if(Node->RVal)
return; fprintf(stdout, "REF_IDENT rval %s\n", Node->Symbol->Name);
case OP_ASSIGN: else
fprintf(stdout, "OP_ASSIGN\n"); fprintf(stdout, "REF_IDENT %s\n", Node->Symbol->Name);
return;
case OP_WIDEN:
fprintf(stdout, "OP_WIDEN\n");
return;
case OP_RET:
fprintf(stdout, "OP_RET\n");
return;
case OP_CALL:
fprintf(stdout, "OP_CALL %s\n", Node->Symbol->Name);
return;
case OP_ADDRESS:
fprintf(stdout, "OP_ADDRESS %s\n", Node->Symbol->Name);
return; return;
case OP_ASSIGN: fprintf(stdout, "OP_ASSIGN\n"); return;
case OP_WIDEN: fprintf(stdout, "OP_WIDEN\n"); return;
case OP_RET: fprintf(stdout, "OP_RET\n"); return;
case OP_CALL: fprintf(stdout, "OP_CALL %s\n", Node->Symbol->Name); return;
case OP_ADDRESS: fprintf(stdout, "OP_ADDRESS %s\n", Node->Symbol->Name); return;
case OP_DEREF: case OP_DEREF:
fprintf(stdout, "OP_DEREF %s\n", Node->RVal ? "rval" : ""); fprintf(stdout, "OP_DEREF %s\n", Node->RVal ? "rval" : ""); return;
return; case OP_SCALE: fprintf(stdout, "OP_SCALE %s\n", TypeNames(Node->Size)); return;
case OP_SCALE:
fprintf(stdout, "OP_SCALE %s\n", TypeNames(Node->Size));
return;
case OP_BOOLOR: case OP_BOOLOR: fprintf(stdout, "OP_BOOLOR\n"); return;
fprintf(stdout, "OP_BOOLOR\n"); case OP_BOOLAND: fprintf(stdout, "OP_BOOLAND\n"); return;
return; case OP_BITOR: fprintf(stdout, "OP_BITOR\n"); return;
case OP_BOOLAND: case OP_BITXOR: fprintf(stdout, "OP_BITXOR\n"); return;
fprintf(stdout, "OP_BOOLAND\n"); case OP_BITAND: fprintf(stdout, "OP_BITAND\n"); return;
return;
case OP_BITOR:
fprintf(stdout, "OP_BITOR\n");
return;
case OP_BITXOR:
fprintf(stdout, "OP_BITXOR\n");
return;
case OP_BITAND:
fprintf(stdout, "OP_BITAND\n");
return;
case OP_SHIFTL: case OP_SHIFTL: fprintf(stdout, "OP_SHIFTL\n"); return;
fprintf(stdout, "OP_SHIFTL\n"); case OP_SHIFTR: fprintf(stdout, "OP_SHIFTR\n"); return;
return;
case OP_SHIFTR:
fprintf(stdout, "OP_SHIFTR\n");
return;
case OP_PREINC: case OP_PREINC: fprintf(stdout, "OP_PREINC\n"); return;
fprintf(stdout, "OP_PREINC\n"); case OP_PREDEC: fprintf(stdout, "OP_PREDEC\n"); return;
return; case OP_POSTINC: fprintf(stdout, "OP_POSTINC\n"); return;
case OP_PREDEC: case OP_POSTDEC: fprintf(stdout, "OP_POSTDEC\n"); return;
fprintf(stdout, "OP_PREDEC\n");
return;
case OP_POSTINC:
fprintf(stdout, "OP_POSTINC\n");
return;
case OP_POSTDEC:
fprintf(stdout, "OP_POSTDEC\n");
return;
case OP_BITNOT: case OP_BITNOT: fprintf(stdout, "OP_BITNOT\n"); return;
fprintf(stdout, "OP_BITNOT\n"); case OP_BOOLNOT: fprintf(stdout, "OP_BOOLNOT\n"); return;
return; case OP_NEGATE: fprintf(stdout, "OP_NEGATE\n"); return;
case OP_BOOLNOT:
fprintf(stdout, "OP_BOOLNOT\n");
return;
case OP_NEGATE:
fprintf(stdout, "OP_NEGATE\n");
return;
case OP_BOOLCONV: case OP_BOOLCONV: fprintf(stdout, "OP_BOOLCONV\n"); return;
fprintf(stdout, "OP_BOOLCONV\n");
return;
case OP_DEFAULT:
fprintf(stdout, "OP_DEFAULT\n");
return;
case OP_CASE:
fprintf(stdout, "OP_CASE %d\n", Node->IntValue);
return;
case OP_SWITCH:
fprintf(stdout, "SWITCH\n");
return;
default: default:
DieDecimal("Unknown Dump Operator", Node->Operation); DieDecimal("Unknown Dump Operator", Node->Operation);

View File

@ -1,95 +0,0 @@
/*************/
/*GEMWIRE */
/* ERYTHRO*/
/*************/
#include <stdio.h>
#include <Defs.h>
#include <Data.h>
#include <stdarg.h>
void Safe() {
CurrentFile->CurrentSafeColumn = CurrentFile->CurrentColumn - 1;
}
void printLine(FILE* file, int ln) {
char buffer[256];
fgets(buffer, 256, file);
// Line number
printf("%03d|%s", ln + 1, buffer);
}
void printErrorLine(FILE* file, int ln) {
char firstBuffer[256], problemBuffer[256], tailBuffer[256];
// If highlight starts at column 0, don't try to print anything before it
if (CurrentFile->CurrentSafeColumn != 0)
fgets(firstBuffer, CurrentFile->CurrentSafeColumn, file);
// Print the safe column up to current column
fgets(problemBuffer, (CurrentFile->CurrentColumn > CurrentFile->CurrentSafeColumn ? CurrentFile->CurrentColumn - CurrentFile->CurrentSafeColumn : CurrentFile->CurrentColumn), file);
// Print the current column to the end of the line
if (CurrentFile->CurrentColumn > CurrentFile->CurrentSafeColumn)
fgets(tailBuffer, 256, file);
// Line number
printf("%03d|%s\033[0;31m%s\033[0m%s", ln + 1, firstBuffer, problemBuffer, tailBuffer);
}
void printHelpLine(int line, char* message) {
printf(" | %s", message);
}
void ErrorReport(char* message, ...) {
fflush(stdout);
char strbuf[256];
// Resolve varargs to a string
va_list args;
va_start(args, message);
vsprintf(strbuf, message, args);
va_end(args);
int line = CurrentFile->CurrentLine - 1;
FILE* file = fopen(CurrentFile->SourceName, "r");
int errorOnLastLine = CurrentFile->CurrentColumn == 0;
// Print context for the error - up to 2 lines above the error
if (line < 3) {
// If we're at 0 or 1, we need to be careful to not try to print -1 for example.
for (int i = 0; i < line; i++)
printLine(file, i);
} else {
// Skip to line - 2
char buffer[256];
int count = 0;
while (count < line - (errorOnLastLine ? 3 : 2)) {
fgets(buffer, 256, file);
count++;
}
if (errorOnLastLine)
printLine(file, line - 3);
printLine(file, line - 2);
if (!errorOnLastLine) printLine(file, line - 1);
}
if (errorOnLastLine) {
printErrorLine(file, line - 1);
printHelpLine(line, strbuf);
printLine(file, line);
if (!feof(file))
printLine(file, line + 1);
} else {
printErrorLine(file, line);
printHelpLine(line, strbuf);
if (!feof(file))
printLine(file, line + 1);
if (!feof(file))
printLine(file, line + 2);
}
exit(1);
}

View File

@ -1,135 +0,0 @@
/*************/
/*GEMWIRE */
/* ERYTHRO*/
/*************/
#include <Defs.h>
#include <Data.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <limits.h>
#include <sys/stat.h>
#if defined(__GNUC__) || defined(APPLE)
#include <errno.h>
#endif
#ifdef WIN32
#define realpath(N,R) _fullpath((R),(N),PATH_MAX)
#endif
/**
* The function of the importer is to read in definitions from a file, and store
* them into the symbol tables.
*
* The file to be imported is called a "module", which is Erythro terminology for C-like "headers".
* They contain extra metadata that allows for Erythro's enhanced debugging and error logging.
*
* Modules may also contain metadata about the contents within - allowing for multiple compile-time
* sourcesets with different arguments, all parsed at the same time as the source code.
*
* This allows Erythro to have first-class support for multiple-build-single-link situations,
* that would require the use of a build system like CMake in other languages.
*
*/
/**
* Read in the information of a module, check that it is valid, and then read the module itself.
* Import syntax looks like:
*
* > import "file"
*
* The string is appended to the current working directory and is checked.
* If the resulting path exists and resolves to a file, then the file's declarations are added to the symbol tables.
*
* Modules may not contain definitions. Only declarations
* TODO: Module metadata as described above.
*/
void ImportModule() {
// Skip the import keyword
Tokenise();
// Make sure there's a string after the import.
if (CurrentFile->CurrentSymbol.type != LI_STR)
Die("Import statement must be followed by a compile-time constant string.");
// Read in the string that we know must be there.
char* Module = strdup(CurrentIdentifier);
// Two strategies for finding the module; either it's relative to cwd, or it's relative to source.
bool FoundImport = false;
// Check the cwd first.
// Figure out the working directory
char CWD[PATH_MAX];
if (getcwd(CWD, sizeof(CWD)) == NULL)
DieMessage("Unable to find cwd when importing module", Module);
// Append the module name to the current working directory
char* ModulePath = malloc(strlen(CWD) + strlen(Module) + 1);
strcpy(ModulePath, CWD);
strcpy(ModulePath + strlen(CWD), "/");
strcpy(ModulePath + strlen(CWD) + 1, Module);
printf("Scanning %s for module definitions.\n", ModulePath);
// Stat the file to see if it exists
struct stat FileInfo;
if (stat(ModulePath, &FileInfo) != 0) {
free(ModulePath);
char SourcePath[PATH_MAX + 1];
realpath(CurrentFile->SourceName, SourcePath);
// Deal with windows being windows
char* SourceFolderLength = strrchr(SourcePath, '/');
if (SourceFolderLength == NULL) {
SourceFolderLength = strrchr(SourcePath, '\\');
}
*(SourceFolderLength + 1) = '\0';
size_t SourcePathLength = strlen(SourcePath);
ModulePath = malloc(SourcePathLength + sizeof(Module) + 1);
strcpy(ModulePath, SourcePath);
strcpy(ModulePath + SourcePathLength, Module);
printf("Scanning %s for module definitions.\n", ModulePath);
if (stat(ModulePath, &FileInfo) != 0)
DieMessage("Unable to access the imported module", ModulePath);
}
// At this point, the file exists and we have the path.
// Save the current file, so that we can restore it later
struct FileData* SavedFile = CurrentFile;
// Create a new file with the module name
struct FileData* ModuleData = malloc(sizeof(struct FileData));
memset(ModuleData, 0, sizeof(struct FileData));
ModuleData->AllowDefinitions = false;
ModuleData->SourceName = ModulePath;
printf("Swapping to module %s..\n\n", ModulePath);
// Parse all relevant data from the module file...
if ((ModuleData->Stream = fopen(ModuleData->SourceName, "r")) == NULL) {
fprintf(stderr, "Unable to open %s: %s\n", ModuleData->SourceName, strerror(errno));
exit(1);
}
CurrentFile = ModuleData;
CurrentFile->CurrentLine = 1;
Tokenise();
ParseGlobals();
fclose(CurrentFile->Stream);
printf("\n\nSwapping back to file %s..\n", SavedFile->SourceName);
// Reinstate the saved file
CurrentFile = SavedFile;
// Tokenise past the string we just parsed
Tokenise();
}

View File

@ -43,14 +43,10 @@ static int NextChar(void) {
return Char; return Char;
} }
Char = fgetc(CurrentFile->Stream); Char = fgetc(SourceFile);
CurrentFile->CurrentColumn++; if(Char == '\n')
Line++;
if (Char == '\n') {
CurrentFile->CurrentLine++;
CurrentFile->CurrentColumn = 0;
}
return Char; return Char;
} }
@ -95,22 +91,29 @@ static int FindDigitFromPos(char* String, char Char) {
*/ */
void VerifyToken(int Type, char* TokenExpected) { void VerifyToken(int Type, char* TokenExpected) {
if (CurrentFile->CurrentSymbol.type == Type) if(CurrentToken.type == Type)
Tokenise(); Tokenise();
else { else {
Tokenise(); printf("Expected %s on line %d\n", TokenExpected, Line);
ErrorReport("Expected %s, but got %s instead.\n", TokenExpected, TokenNames[CurrentFile->CurrentSymbol.type]);
exit(1); exit(1);
} }
} }
bool OptionallyConsume(int Type) { static struct Token* RejectedToken = NULL;
if (CurrentFile->CurrentSymbol.type == Type) {
Tokenise(); /*
return true; * Rejected Tokens and the Overread Stream are identical concepts.
} * This was implemented first, but it is no longer used.
return false; * TODO: Refactor this function out.
*/
void RejectToken(struct Token* Token) {
if(RejectedToken != NULL)
Die("Cannot reject two tokens in a row!");
RejectedToken = Token;
} }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * L I T E R A L S A N D I D E N T I F I E R S * * * * * * * * L I T E R A L S A N D I D E N T I F I E R S * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@ -120,7 +123,7 @@ bool OptionallyConsume(int Type) {
* Currently only supports the decimal numbers, despite the * Currently only supports the decimal numbers, despite the
* FindDigitFromPos function allowing conversion. * FindDigitFromPos function allowing conversion.
* *
* The function loops over the characters, multiplying by 10 and adding * The functon loops over the characters, multiplying by 10 and adding
* the new value on top, until a non-numeric character is found. * the new value on top, until a non-numeric character is found.
* At that point, it returns the non-numeric character to the Overread Stream * At that point, it returns the non-numeric character to the Overread Stream
* and returns the calculated number. * and returns the calculated number.
@ -167,7 +170,7 @@ static int ReadIdentifier(int Char, char* Buffer, int Limit) {
// This defines the valid chars in a keyword/variable/function. // This defines the valid chars in a keyword/variable/function.
while(isalpha(Char) || isdigit(Char) || Char == '_') { while(isalpha(Char) || isdigit(Char) || Char == '_') {
if (ind >= Limit - 1) { if (ind >= Limit - 1) {
printf("Identifier too long: %ld\n", CurrentFile->CurrentLine); printf("Identifier too long: %d\n", Line);
exit(1); exit(1);
} else { } else {
Buffer[ind++] = Char; Buffer[ind++] = Char;
@ -198,26 +201,16 @@ static int ReadCharLiteral() {
Char = NextChar(); Char = NextChar();
if(Char == '\\') { if(Char == '\\') {
switch(Char = NextChar()) { switch(Char = NextChar()) {
case 'a': case 'a': return '\a';
return '\a'; case 'b': return '\b';
case 'b': case 'f': return '\f';
return '\b'; case 'n': return '\n';
case 'f': case 'r': return '\r';
return '\f'; case 't': return '\t';
case 'n': case 'v': return '\v';
return '\n'; case '\\': return '\\';
case 'r': case '"': return '"';
return '\r'; case '\'': return '\'';
case 't':
return '\t';
case 'v':
return '\v';
case '\\':
return '\\';
case '"':
return '"';
case '\'':
return '\'';
default: default:
DieChar("Unknown Escape: ", Char); DieChar("Unknown Escape: ", Char);
} }
@ -245,8 +238,7 @@ static int ReadStringLiteral(char* Buffer) {
for(int i = 0; i < TEXTLEN - 1; i++) { for(int i = 0; i < TEXTLEN - 1; i++) {
if((Char = ReadCharLiteral()) == '"') { if((Char = ReadCharLiteral()) == '"') {
Buffer[i] = 0; Buffer[i] = 0; return i;
return i;
} }
Buffer[i] = Char; Buffer[i] = Char;
@ -280,35 +272,14 @@ static int ReadKeyword(char* Str) {
return KW_FUNC; return KW_FUNC;
break; break;
case 'a':
if (!strcmp(Str, "alias"))
return KW_ALIAS;
break;
case 'b':
if (!strcmp(Str, "break"))
return KW_BREAK;
break;
case 'c': case 'c':
if(!strcmp(Str, "char")) if(!strcmp(Str, "char"))
return TY_CHAR; return TY_CHAR;
if (!strcmp(Str, "continue"))
return KW_CONTINUE;
if (!strcmp(Str, "case"))
return KW_CASE;
break; break;
case 'd':
if (!strcmp(Str, "default"))
return KW_DEFAULT;
case 'e': case 'e':
if(!strcmp(Str, "else")) if(!strcmp(Str, "else"))
return KW_ELSE; return KW_ELSE;
if (!strcmp(Str, "enum"))
return KW_ENUM;
break; break;
@ -330,9 +301,6 @@ static int ReadKeyword(char* Str) {
if(!strcmp(Str, "int")) if(!strcmp(Str, "int"))
return TY_INT; return TY_INT;
if (!strcmp(Str, "import"))
return KW_IMPORT;
if(!strcmp(Str, "if")) if(!strcmp(Str, "if"))
return KW_IF; return KW_IF;
@ -357,13 +325,6 @@ static int ReadKeyword(char* Str) {
case 's': case 's':
if(!strcmp(Str, "struct")) if(!strcmp(Str, "struct"))
return KW_STRUCT; return KW_STRUCT;
if (!strcmp(Str, "switch"))
return KW_SWITCH;
break;
case 'u':
if(!strcmp(Str, "union"))
return KW_UNION;
break; break;
case 'v': case 'v':
@ -377,6 +338,7 @@ static int ReadKeyword(char* Str) {
break; break;
} }
return 0; return 0;
@ -400,7 +362,13 @@ static int ReadKeyword(char* Str) {
*/ */
void Tokenise() { void Tokenise() {
int Char, TokenType; int Char, TokenType;
struct Token* Token = &CurrentFile->CurrentSymbol; struct Token* Token = &CurrentToken;
if(RejectedToken != NULL) {
Token = RejectedToken;
RejectedToken = NULL;
return;
}
Char = FindChar(); Char = FindChar();
@ -409,10 +377,6 @@ void Tokenise() {
Token->type = LI_EOF; Token->type = LI_EOF;
return; return;
case '.':
Token->type = LI_DOT;
return;
case '+': case '+':
// + can be either "+" or "++". // + can be either "+" or "++".
Char = NextChar(); Char = NextChar();
@ -425,12 +389,10 @@ void Tokenise() {
break; break;
case '-': case '-':
// - can be either "-" or "--" or "->" // - can be either "-" or "--"
Char = NextChar(); Char = NextChar();
if(Char == '-') { if(Char == '-') {
Token->type = PPMM_MINUS; Token->type = PPMM_MINUS;
} else if (Char == '>') {
Token->type = LI_ARROW;
} else { } else {
Token->type = AR_MINUS; Token->type = AR_MINUS;
ReturnCharToStream(Char); ReturnCharToStream(Char);
@ -562,7 +524,7 @@ void Tokenise() {
if(Char == ':') { if(Char == ':') {
Token->type = KW_FUNC; Token->type = KW_FUNC;
} else { } else {
Token->type = LI_COLON; ReturnCharToStream(Char);
} }
break; break;
@ -571,7 +533,7 @@ void Tokenise() {
Token->type = LI_INT; Token->type = LI_INT;
if(NextChar() != '\'') if(NextChar() != '\'')
ErrorReport("Expected '\\'' at the end of a character.\n"); Die("Expected '\\'' at the end of a character.");
break; break;
case '"': case '"':
@ -586,20 +548,23 @@ void Tokenise() {
Token->type = LI_INT; Token->type = LI_INT;
break; break;
} else if (isalpha(Char) || } else if(isalpha(Char) || Char == '_') { // This is what defines what a variable/function/keyword can START with.
Char == '_') { // This is what defines what a variable/function/keyword can START with.
ReadIdentifier(Char, CurrentIdentifier, TEXTLEN); ReadIdentifier(Char, CurrentIdentifier, TEXTLEN);
if ((TokenType = ReadKeyword(CurrentIdentifier))) { if(TokenType = ReadKeyword(CurrentIdentifier)) {
Token->type = TokenType; Token->type = TokenType;
break; break;
} }
Token->type = TY_IDENTIFIER; Token->type = TY_IDENTIFIER;
break; break;
//printf("Line %d: Unrecognized symbol %s\n", CurrentIdentifier, Line);
//exit(1);
} }
ErrorReport("Unrecognized character: %c\n", Char);
DieChar("Unrecognized character", Char);
} }
} }

View File

@ -7,7 +7,7 @@
#define extern_ #define extern_
#include <Data.h> #include <Data.h>
#undef extern_ #undef extern_
#include <unistd.h> #include <errno.h>
int TypeSizes[5] = { 0, 1, 4, 8, 0}; // in BYTES int TypeSizes[5] = { 0, 1, 4, 8, 0}; // in BYTES
@ -47,7 +47,6 @@ char* TokenNames[] = {
"Integer literal", "Integer literal",
"String literal", "String literal",
"Statement End", "Statement End",
"Colon",
"Compound Block Start", "Compound Block Start",
"Compound Block End", "Compound Block End",
@ -59,8 +58,6 @@ char* TokenNames[] = {
"Logical Block End", "Logical Block End",
"Comma", "Comma",
"Dot",
"Arrow",
"Identifier", "Identifier",
"None Type", "None Type",
@ -70,13 +67,6 @@ char* TokenNames[] = {
"Void Type", "Void Type",
"Function keyword", "Function keyword",
"Break keyword",
"Continue keyword",
"Switch Keyword",
"Default Keyword",
"Case Keyword",
"Print Keyword", "Print Keyword",
"If keyword", "If keyword",
"Else keyword", "Else keyword",
@ -85,99 +75,19 @@ char* TokenNames[] = {
"Return keyword", "Return keyword",
"Struct keyword", "Struct keyword"
"Union keyword",
"Enum keyword",
"Alias keyword",
"Import keyword"
};
char* OperationNames[] = {
"OP_ASSIGN", // Assign an l-value
"OP_BOOLOR", // Boolean OR two statements
"OP_BOOLAND", // Boolean AND two statements
"OP_BITOR", // Bitwise OR a number
"OP_BITXOR", // Bitwise XOR a number
"OP_BITAND", // Bitwise AND a number
"OP_EQUAL", // Compare equality
"OP_INEQ", // Compare inequality
"OP_LESS", // Less than?
"OP_GREAT", // Greater than?
"OP_LESSE", // Less than or Equal to?
"OP_GREATE", // Greater than or Equal to?
"OP_SHIFTL", // Arithmetic Shift Left (Multiply by 2)
"OP_SHIFTR", // Arithmetic Shift Right (Divide by 2)
"OP_ADD", // Add two numbers.
"OP_SUBTRACT", // Subtract two numbers.
"OP_MULTIPLY", // Multiply two numbers.
"OP_DIVIDE", // Divide two numbers.
"OP_PREINC", // Increment var before reference.
"OP_PREDEC", // Decrement var before reference.
"OP_POSTINC", // Increment var after reference.
"OP_POSTDEC", // Decrement var after reference.
"OP_BITNOT", // Invert a number bitwise
"OP_BOOLNOT", // Invert a statement logically
"OP_NEGATE", // Negate a number (turn a positive number negative
"OP_BOOLCONV", // Convert an expression to a boolean.s
"OP_ADDRESS", // Fetch the address of a var
"OP_DEREF", // Get the value of the address in a pointer
"TERM_INTLITERAL", // Integer Literal. This is a virtual operation", so it's a terminal.
"TERM_STRLITERAL", // String Literal. Also terminal.
"REF_IDENT", // Reference (read) an identifier (variable).
"OP_WIDEN", // Something contains a type that needs to be casted up
"OP_SCALE", // We have a pointer that needs to be scaled!
"OP_CALL", // Call a function
"OP_RET", // Return from a function
"OP_COMP", // Compound statements need a way to be 'glued' together. This is one of those mechanisms
"OP_IF", // If statement
"OP_LOOP", // FOR", WHILE
"OP_PRINT", // Print statement
"OP_FUNC", // Define a function
"OP_BREAK", // Break out of the loop
"OP_CONTINUE", // Continue the loop
"OP_SWITCH", // Switch statement
"OP_DEFAULT", // Default case
"OP_CASE" // Case
};
char* ScopeNames[] = {
"INVALID",
"GLOBAL",
"STRUCT",
"UNION",
"ENUM",
"ENUM_ENTRY",
"ALIAS",
"MEMBER",
"PARAMETER",
"LOCAL"
}; };
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
// Option initialisers // Option initialisers
OptDumpTree = false; OptDumpTree = false;
OptKeepAssembly = true; OptKeepAssembly = false;
OptAssembleFiles = true; OptAssembleFiles = false;
OptLinkFiles = true; OptLinkFiles = true;
OptVerboseOutput = false; OptVerboseOutput = false;
OptAssemblerName = "Win32";
struct FileData* InitData = malloc(sizeof(struct FileData));
InitData->CurrentLine = 0;
CurrentFile = InitData;
// Temporary .o storage and counter // Temporary .o storage and counter
char* ObjectFiles[100];
int ObjectCount = 0; int ObjectCount = 0;
// Parse command line arguments. // Parse command line arguments.
@ -195,32 +105,24 @@ int main(int argc, char* argv[]) {
switch(argv[i][j]) { switch(argv[i][j]) {
case 'o': // output case 'o': // output
OutputFileName = argv[++i]; OutputFileName = argv[++i];
break;
case 'T': // print Tree (debug) break;
case 'T': // Debug
OptDumpTree = true; OptDumpTree = true;
break; break;
case 'c': // Compile only case 'c': // Compile only
OptAssembleFiles = true; OptAssembleFiles = true;
OptKeepAssembly = false; OptKeepAssembly = false;
OptLinkFiles = false; OptLinkFiles = false;
break; break;
case 'S': // aSsemble only case 'S': // aSsemble only
OptAssembleFiles = true; OptAssembleFiles = false;
OptKeepAssembly = true; OptKeepAssembly = true;
OptLinkFiles = false; OptLinkFiles = false;
break; break;
case 'v': // Verbose output case 'v': // Verbose output
OptVerboseOutput = true; OptVerboseOutput = true;
break; break;
case 'm': // Specify Assembler Module
OptAssemblerName = argv[++i];
break;
default: default:
DisplayUsage(argv[0]); DisplayUsage(argv[0]);
} }
@ -231,47 +133,40 @@ int main(int argc, char* argv[]) {
if(i >= argc) if(i >= argc)
DisplayUsage(argv[0]); DisplayUsage(argv[0]);
int StartOfFiles = i;
// Allocate enough files for the full specified source code
Files = malloc(sizeof(struct FileData*) * (argc - i) + 1);
memset(Files, 0, sizeof(struct FileData*) * (argc - i) + 1);
RegisterAllModules();
// For the rest of the files specified, we can iterate them right to left. // For the rest of the files specified, we can iterate them right to left.
while(i < argc) { while(i < argc) {
// Prepare the source metadata before we start compiling
struct FileData* Source = malloc(sizeof(struct FileData));
memset(Source, 0, sizeof(struct FileData));
Source->SourceName = argv[i];
Source->AllowDefinitions = true;
printf("Compiling file %d (%s)\n", i - StartOfFiles, argv[i]);
Files[i - StartOfFiles] = Source;
// Compile the file by invoking the Delegate // Compile the file by invoking the Delegate
Compile(Source); CurrentASMFile = Compile(argv[i]);
if(OptLinkFiles || OptAssembleFiles) { if(OptLinkFiles || OptAssembleFiles) {
// If we need to assemble (or link, which requires assembly) // If we need to assemble (or link, which requires assembly)
// then we invoke the Delegate again // then we invoke the Delegate again
Assemble(Source); CurrentObjectFile = Assemble(CurrentASMFile);
// We can only keep track of 99 objects, so we should crash at 98 to ensure we have enough room for the output file too.
if(ObjectCount == 98) {
fprintf(stderr, "Too many inputs");
return 1; // We use return because we're in main, rather than invoking Die.
}
// Move the ObjectCount forward.
ObjectFiles[ObjectCount++] = CurrentObjectFile;
// Clear the new, forwarded index
ObjectFiles[ObjectCount] = NULL;
} }
if(!OptKeepAssembly) if(!OptKeepAssembly)
// unlink = delete // unlink = delete
unlink(Source->AssemblyName); unlink(CurrentASMFile);
i++; i++;
} }
if(OptLinkFiles) { if(OptLinkFiles) {
// If needed, invoke the Delegate one last time. // If needed, invoke the Delegate one last time.
Link(OutputFileName, Files, (argc - StartOfFiles) + 1); Link(OutputFileName, ObjectFiles);
if(!OptAssembleFiles) { if(!OptAssembleFiles) {
// Even though we need to assemble to link, we can respect the user's options and delete the intermediary files. // Even though we need to assemble to link, we can respect the user's options and delete the intermediary files.
for (i = 0; i < (argc - StartOfFiles) + 1; i++) { for(i = 0; ObjectFiles[i] != NULL; i++)
unlink(Files[i]->AssemblyName); unlink(ObjectFiles[i]);
unlink(Files[i]->ObjectName);
}
} }
} }
@ -285,7 +180,7 @@ int main(int argc, char* argv[]) {
*/ */
void Die(char* Error) { void Die(char* Error) {
fprintf(stderr, "%s on line %ld\n", Error, CurrentFile->CurrentLine); fprintf(stderr, "%s on line %d\n", Error, Line);
fclose(OutputFile); fclose(OutputFile);
unlink(OutputFileName); unlink(OutputFileName);
exit(1); exit(1);
@ -295,7 +190,7 @@ void Die(char* Error) {
* A variant of Die with an extra String attached. * A variant of Die with an extra String attached.
*/ */
void DieMessage(char* Error, char* Reason) { void DieMessage(char* Error, char* Reason) {
fprintf(stderr, "%s: %s on line %ld\n", Error, Reason, CurrentFile->CurrentLine); fprintf(stderr, "%s: %s on line %d\n", Error, Reason, Line);
fclose(OutputFile); fclose(OutputFile);
unlink(OutputFileName); unlink(OutputFileName);
exit(1); exit(1);
@ -305,7 +200,7 @@ void DieMessage(char* Error, char* Reason) {
* A variant of Die with an extra integer attached. * A variant of Die with an extra integer attached.
*/ */
void DieDecimal(char* Error, int Number) { void DieDecimal(char* Error, int Number) {
fprintf(stderr, "%s: %d on line %ld\n", Error, Number, CurrentFile->CurrentLine); fprintf(stderr, "%s: %d on line %d\n", Error, Number, Line);
fclose(OutputFile); fclose(OutputFile);
unlink(OutputFileName); unlink(OutputFileName);
exit(1); exit(1);
@ -315,7 +210,7 @@ void DieDecimal(char* Error, int Number) {
* A variant of Die with an extra character attached. * A variant of Die with an extra character attached.
*/ */
void DieChar(char* Error, int Char) { void DieChar(char* Error, int Char) {
fprintf(stderr, "%s: %c on line %ld\n", Error, Char, CurrentFile->CurrentLine); fprintf(stderr, "%s: %c on line %d\n", Error, Char, Line);
fclose(OutputFile); fclose(OutputFile);
unlink(OutputFileName); unlink(OutputFileName);
exit(1); exit(1);

View File

@ -9,10 +9,6 @@
#include "Defs.h" #include "Defs.h"
#include "Data.h" #include "Data.h"
#if defined(__GNUC__) || defined(APPLE)
#include <errno.h>
#endif
/* /*
* The Precedence of an operator is directly related to Token Type. * The Precedence of an operator is directly related to Token Type.
* Precedence determines how soon the operator and its surrounding values * Precedence determines how soon the operator and its surrounding values
@ -43,13 +39,7 @@ static int OperatorPrecedence(int Token) {
int Prec = Precedence[Token]; int Prec = Precedence[Token];
if(Prec == 0 || Token >= PPMM_PLUS) { if(Prec == 0 || Token >= PPMM_PLUS) {
if (Token == TY_IDENTIFIER) { DieMessage("Attempting to determine operator precedence of an EOF or INT literal", TokenNames[Token]);
ErrorReport("Attempting to determine operator precedence of identifier %s\n", CurrentIdentifier);
exit(1);
}
ErrorReport("Attempting to determine operator precedence of an EOF or INT literal: %s\n", TokenNames[Token]);
exit(1);
} }
return Prec; return Prec;
@ -105,7 +95,7 @@ struct ASTNode* ConstructASTNode(int Operation, int Type,
Node = (struct ASTNode*) malloc(sizeof(struct ASTNode)); Node = (struct ASTNode*) malloc(sizeof(struct ASTNode));
if(!Node) if(!Node)
ErrorReport("Unable to allocate node: %s\n", errno); Die("Unable to allocate node!");
Node->Operation = Operation; Node->Operation = Operation;
@ -162,7 +152,7 @@ int ParseTokenToOperation(int Token) {
if(Token > LI_EOF && Token < LI_INT) if(Token > LI_EOF && Token < LI_INT)
return Token; return Token;
ErrorReport("ParseToken: Unknown token %s\n", TokenNames[Token]); DieDecimal("ParseToken: Unknown token", Token);
} }
/* /*
@ -179,18 +169,18 @@ struct ASTNode* ParsePrimary(void) {
struct ASTNode* Node; struct ASTNode* Node;
int ID; int ID;
switch (CurrentFile->CurrentSymbol.type) { switch(CurrentToken.type) {
case LI_INT: case LI_INT:
if ((CurrentFile->CurrentSymbol.value >= 0) && (CurrentFile->CurrentSymbol.value < 256)) if((CurrentToken.value >= 0) && (CurrentToken.value < 256))
Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, NULL, CurrentFile->CurrentSymbol.value); Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, NULL, CurrentToken.value);
else else
Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, CurrentFile->CurrentSymbol.value); Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, CurrentToken.value);
break; break;
case LI_STR: case LI_STR:
ID = Assembler->vtable->AsNewString(CurrentIdentifier); ID = AsNewString(CurrentIdentifier);
Node = ConstructASTLeaf(TERM_STRLITERAL, PointerTo(RET_CHAR), NULL, ID); Node = ConstructASTLeaf(TERM_STRLITERAL, PointerTo(RET_CHAR), NULL, ID);
break; break;
@ -208,8 +198,9 @@ struct ASTNode* ParsePrimary(void) {
return Node; return Node;
} }
Tokenise(); Tokenise();
Safe();
return Node; return Node;
} }
@ -220,7 +211,7 @@ struct ASTNode* ParsePrimary(void) {
* the order of operations is upheld, that the precedence of the prior * the order of operations is upheld, that the precedence of the prior
* iteration is considered, and that every error is handled. * iteration is considered, and that every error is handled.
* *
* This is where all the right-associative statements are folded, where * This is where all of the right-associative statements are folded, where
* type mismatches and widening are handled properly, and that all parsing * type mismatches and widening are handled properly, and that all parsing
* is over by the time the end tokens ") } ] ;" are encountered. * is over by the time the end tokens ") } ] ;" are encountered.
* *
@ -234,29 +225,22 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
// int LeftType, RightType; // int LeftType, RightType;
int NodeType, OpType; int NodeType, OpType;
Safe();
LeftNode = PrefixStatement(); LeftNode = PrefixStatement();
NodeType = CurrentFile->CurrentSymbol.type; NodeType = CurrentToken.type;
if (NodeType == LI_SEMIC || NodeType == LI_COLON || NodeType == LI_RPARE || NodeType == LI_RBRAS || NodeType == LI_COM || NodeType == LI_INT) { if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS || NodeType == LI_COM) {
LeftNode->RVal = 1; LeftNode->RVal = 1; return LeftNode;
return LeftNode;
} }
Safe(); while((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) || (IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) {
while ((OperatorPrecedence(NodeType) > PreviousTokenPrecedence) ||
(IsRightExpr(OpType) && OperatorPrecedence(OpType) == PreviousTokenPrecedence)) {
Tokenise(); Tokenise();
if (CurrentFile->CurrentSymbol.type == LI_RPARE) if(CurrentToken.type == LI_RPARE)
break; break;
Safe();
RightNode = ParsePrecedenceASTNode(Precedence[NodeType]); RightNode = ParsePrecedenceASTNode(Precedence[NodeType]);
Safe();
/** /**
* While parsing this node, we may need to widen some types. * While parsing this node, we may need to widen some types.
* This requires a few functions and checks. * This requires a few functions and checks.
@ -270,8 +254,8 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
LeftNode->RVal = 0; LeftNode->RVal = 0;
RightNode = MutateType(RightNode, LeftNode->ExprType, 0); RightNode = MutateType(RightNode, LeftNode->ExprType, 0);
if (RightNode == NULL) if(LeftNode == NULL)
ErrorReport("Incompatible types encountered in assignment: %s, %s\n", TypeNames(RightNode->ExprType), TypeNames(LeftNode->ExprType)); Die("Incompatible Expression encountered in assignment");
// LeftNode holds the target, the target variable in this case // LeftNode holds the target, the target variable in this case
printf("\t\tAssigning variable: %s\n", LeftNode->Symbol->Name); printf("\t\tAssigning variable: %s\n", LeftNode->Symbol->Name);
@ -280,11 +264,11 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
LeftNode = RightNode; LeftNode = RightNode;
RightNode = LeftTemp; RightNode = LeftTemp;
// Clear temps as insurance // Clear temps as ensurance
RightTemp = NULL; RightTemp = NULL;
LeftTemp = NULL; LeftTemp = NULL;
} else { } else {
printf("\t\tAttempting to handle a %s in Binary Expression parsing\r\n", TokenNames[CurrentFile->CurrentSymbol.type]); printf("\t\tAttempting to handle a %d in Binary Expression parsing\r\n", CurrentToken.type);
LeftNode->RVal = 1; LeftNode->RVal = 1;
RightNode->RVal = 1; RightNode->RVal = 1;
@ -296,7 +280,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
*/ */
if(LeftTemp == NULL && RightTemp == NULL) if(LeftTemp == NULL && RightTemp == NULL)
ErrorReport("Incompatible types in parsing nodes: %s, %s\n", TypeNames(LeftNode->ExprType), TypeNames(RightNode->ExprType)); Die("Incompatible types in parsing nodes");
/** /**
* If the left was valid, or valid for * If the left was valid, or valid for
@ -306,8 +290,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
* equivalent to LeftNode = LeftNode * equivalent to LeftNode = LeftNode
*/ */
if(LeftTemp)
if (LeftTemp != NULL)
LeftNode = LeftTemp; LeftNode = LeftTemp;
/** /**
@ -316,14 +299,21 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
* to the nature of widening types. * to the nature of widening types.
*/ */
if (RightTemp != NULL) if(RightTemp)
RightNode = RightTemp; RightNode = RightTemp;
} }
LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode, /**
NULL, 0); * Checks over, back to normal parsing.
NodeType = CurrentFile->CurrentSymbol.type; */
if(LeftTemp != NULL)
LeftNode = LeftTemp; //ConstructASTBranch(LeftType, RightNode->ExprType, LeftNode, 0);
if(RightTemp != NULL)
RightNode = RightTemp; // ConstructASTBranch(RightType, LeftNode->ExprType, RightNode, 0);
LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode, NULL, 0);
NodeType = CurrentToken.type;
if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) { if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) {
LeftNode->RVal = 1; LeftNode->RVal = 1;
return LeftNode; return LeftNode;
@ -356,11 +346,11 @@ struct ASTNode* CallFunction() {
//TODO: Test structural type! //TODO: Test structural type!
if((Function = FindSymbol(CurrentIdentifier)) == NULL || (Function->Structure != ST_FUNC)) if((Function = FindSymbol(CurrentIdentifier)) == NULL || (Function->Structure != ST_FUNC))
ErrorReport("Undeclared function: %s\n", CurrentIdentifier); DieMessage("Undeclared function", CurrentIdentifier);
VerifyToken(LI_LPARE, "("); VerifyToken(LI_LPARE, "(");
Tree = ParseExpressionList(LI_RPARE); Tree = GetExpressionList();
Tree = ConstructASTBranch(OP_CALL, Function->Type, Tree, Function, 0); Tree = ConstructASTBranch(OP_CALL, Function->Type, Tree, Function, 0);
@ -384,23 +374,25 @@ struct ASTNode* CallFunction() {
* end with a COMPOSITE operation. * end with a COMPOSITE operation.
* *
*/ */
struct ASTNode* ParseExpressionList(int terminate) { struct ASTNode* GetExpressionList() {
struct ASTNode* Tree = NULL, *Child = NULL; struct ASTNode* Tree = NULL, *Child = NULL;
int Count = 0; int Count;
Safe(); while(CurrentToken.type != LI_RPARE) {
while (CurrentFile->CurrentSymbol.type != terminate) {
// TODO: for(int x = 0;
Child = ParsePrecedenceASTNode(0); Child = ParsePrecedenceASTNode(0);
printf("\nFunction parameter %d is type %s.\n", Count, TypeNames(Child->ExprType));
Count++; Count++;
Tree = ConstructASTNode(OP_COMP, PointerTo(RET_VOID), Tree, NULL, Child, NULL, Count); Tree = ConstructASTNode(OP_COMP, PointerTo(RET_VOID), Tree, NULL, Child, NULL, Count);
if (CurrentFile->CurrentSymbol.type == terminate) switch(CurrentToken.type) {
case LI_COM:
Tokenise();
break; break;
case LI_RPARE:
VerifyToken(LI_COM, ","); break;
Safe(); default:
Die("Unexpected token in argument list");
}
} }
return Tree; return Tree;
@ -413,53 +405,31 @@ struct ASTNode* ParseExpressionList(int terminate) {
/* /*
* Handles parsing an individual statement. * Handles parsing an individual statement.
* This has the ability to parse Compounds in the case it starts with a left brace.
* This solves the dangling else problem for the parser.
* *
* It serves as a wrapper around: * It serves as a wrapper around:
* * If Statement * * If Statement
* * While Statement * * While Statement
* * For Statement * * For Statement
* * Switch Statement
* * Return Statement * * Return Statement
* * Numeric literals and variables * * Numeric literals and variables
* * Binary Expressions * * Binary Expressions
*
* @return the AST Node representing this single statement * @return the AST Node representing this single statement
*/ */
struct ASTNode* ParseStatement(void) { struct ASTNode* ParseStatement(void) {
struct ASTNode* Node; int Type;
struct SymbolTableEntry* Composite;
printf("\t\tBranch leads to type %s/%d\r\n", TokenNames[CurrentFile->CurrentSymbol.type], CurrentFile->CurrentSymbol.type); printf("\t\tBranch leads to here, type %s/%d\r\n", TokenNames[CurrentToken.type], CurrentToken.type);
switch (CurrentFile->CurrentSymbol.type) { switch(CurrentToken.type) {
case LI_LBRAC:
Tokenise();
Node = ParseCompound();
VerifyToken(LI_RBRAC, "}");
return Node;
case TY_IDENTIFIER:
if (FindAlias(CurrentIdentifier) == NULL) {
Node = ParsePrecedenceASTNode(0);
VerifyToken(LI_SEMIC, ";");
return Node;
}
case TY_CHAR: case TY_CHAR:
case TY_LONG: case TY_LONG:
case TY_INT: case TY_INT:
case KW_STRUCT: printf("\t\tNew Variable: %s\n", CurrentIdentifier);
case KW_UNION: Type = ParseOptionalPointer(NULL);
case KW_ENUM: VerifyToken(TY_IDENTIFIER, "ident");
case KW_ALIAS: BeginVariableDeclaration(Type, NULL, SC_LOCAL);
printf("\t\tTrying new Variable: %s\n", CurrentIdentifier); VerifyToken(LI_SEMIC, ";"); // TODO: single line assignment?
ParseDeclarationList(&Composite, SC_LOCAL, LI_SEMIC, LI_EOF, &Node);
VerifyToken(LI_SEMIC, ";");
Safe();
return NULL; return NULL;
case KW_SWITCH:
return SwitchStatement();
case KW_IF: case KW_IF:
return IfStatement(); return IfStatement();
@ -472,20 +442,58 @@ struct ASTNode* ParseStatement(void) {
case KW_RETURN: case KW_RETURN:
return ReturnStatement(); return ReturnStatement();
case KW_BREAK:
return BreakStatement();
case KW_CONTINUE:
return ContinueStatement();
default: default:
Node = ParsePrecedenceASTNode(0); ParsePrecedenceASTNode(0);
VerifyToken(LI_SEMIC, ";");
return Node;
} }
} }
/*
* Handles parsing multiple statements or expressions in a row.
* These are typically grouped together with the Compound tokens "{ }"
* and seperated by the semicolon ";".
*
* Single Statements are parsed until a semicolon is reached, at which
* point another statement will be parsed, or until a Right Compound
* token is reached ("}"), at which point parsing will stop.
*
* It is useful for:
* * Tightly identifying related blocks of code
* * Containing the many statements of functions
*
* @return the AST Node representing this compound statement
*
*/
struct ASTNode* ParseCompound() {
struct ASTNode* Left = NULL, *Tree;
// Compound statements are defined by comprising
// multiple statements inside { a bracket block }
VerifyToken(LI_LBRAC, "{");
while(1) {
printf("\tNew branch in compound\n");
Tree = ParseStatement();
if(Tree && (Tree->Operation == OP_PRINT || Tree->Operation == OP_ASSIGN
|| Tree->Operation == OP_RET || Tree->Operation == OP_CALL))
VerifyToken(LI_SEMIC, ";");
if(Tree) {
if(Left == NULL)
Left = Tree;
else
Left = ConstructASTNode(OP_COMP, RET_NONE, Left, NULL, Tree, NULL, 0);
}
if(CurrentToken.type == LI_RBRAC) {
VerifyToken(LI_RBRAC, "}");
return Left;
}
}
}
/* /*
* This is the entry point to the parser/lexer. * This is the entry point to the parser/lexer.
* *
@ -502,16 +510,42 @@ struct ASTNode* ParseStatement(void) {
*/ */
void ParseGlobals() { void ParseGlobals() {
struct SymbolTableEntry* Composite; struct ASTNode* Tree;
struct ASTNode* empty; int Type, FunctionComing;
printf("Parsing global definitions\r\n"); printf("Parsing global definitions\r\n");
while (CurrentFile->CurrentSymbol.type != LI_EOF) { while(1) {
// Read in a declaration, or list thereof printf("New definition incoming..\r\n\n");
ParseDeclarationList(&Composite, SC_GLOBAL, LI_SEMIC, LI_EOF, &empty); Type = ParseOptionalPointer(NULL);
//TODO: converge pathways on this block?
if(CurrentToken.type == KW_FUNC) {
VerifyToken(KW_FUNC, "::");
FunctionComing = 1;
}
VerifyToken(TY_IDENTIFIER, "ident");
if(FunctionComing && CurrentToken.type == LI_LPARE) {
printf("\tParsing function");
Tree = ParseFunction(Type);
if(Tree) {
printf("\nBeginning assembler creation of new function %s\n", Tree->Symbol->Name);
AssembleTree(Tree, -1, 0);
FreeLocals();
} else {
printf("\nFunction prototype saved\r\n");
}
} else {
printf("\tParsing global variable declaration\n");
BeginVariableDeclaration(Type, NULL, SC_GLOBAL);
VerifyToken(LI_SEMIC, ";");
}
if(CurrentToken.type == LI_EOF)
break;
// Consume semicolons if present
OptionallyConsume(LI_SEMIC);
} }
} }

View File

@ -37,7 +37,7 @@
int PointerTo(int Type) { int PointerTo(int Type) {
if((Type & 0xf) == 0xf) if((Type & 0xf) == 0xf)
ErrorReport("Unrecognized type in pointerisation: %d\n", Type); DieDecimal("Unrecognized type in pointerisation", Type);
printf("\t\tPointerising a %s\n", TypeNames(Type)); printf("\t\tPointerising a %s\n", TypeNames(Type));
return (Type + 1); return (Type + 1);
} }
@ -53,10 +53,70 @@ int PointerTo(int Type) {
int ValueAt(int Type) { int ValueAt(int Type) {
printf("\t\tDereferencing a %s\n", TypeNames(Type)); printf("\t\tDereferencing a %s\n", TypeNames(Type));
if((Type & 0xf) == 0x0) if((Type & 0xf) == 0x0)
ErrorReport("Unrecognized type in defererencing: %d (%s)\n", Type, TypeNames(Type)); DieDecimal("Unrecognized type in defererencing", Type);
return (Type - 1); return (Type - 1);
} }
/*
* Type declarations may be raw, they may be pointers.
* If they are pointers, we need to be able to check
* how many levels of indirection.
* However, being a pointer is optional.
*
* This can parase in just a lone type specifier, or
* any valid level of indirection therefore.
*
* @param Composite: unused
* @return the parsed DataType, with any indirection.
*
*/
int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
int Type;
switch(CurrentToken.type) {
case TY_VOID:
Type = RET_VOID;
Tokenise();
break;
case TY_CHAR:
Type = RET_CHAR;
Tokenise();
break;
case TY_INT:
Type = RET_INT;
Tokenise();
break;
case TY_LONG:
Type = RET_LONG;
Tokenise();
break;
case KW_STRUCT:
Type = DAT_STRUCT;
*Composite = BeginStructDeclaration();
break;
default:
DieDecimal("Illegal type for pointerisation", CurrentToken.type);
}
// Recursively scan more *s
// This makes things like:
// x = **y;
// possible.
while(1) {
Tokenise();
printf("\t\t\tType on parsing is %d\n", CurrentToken.type);
if(CurrentToken.type != AR_STAR)
break;
Type = PointerTo(Type);
// Tokenise(); TODO: is this skipping pointers?
}
return Type;
}
/* /*
* Array Accesses come in the form of x[y]. * Array Accesses come in the form of x[y].
* *
@ -74,7 +134,7 @@ struct ASTNode* AccessArray() {
printf("\tAccessing array %s as requested\r\n", CurrentIdentifier); printf("\tAccessing array %s as requested\r\n", CurrentIdentifier);
if ((Entry = FindSymbol(CurrentIdentifier)) == NULL || Entry->Structure != ST_ARR) if ((Entry = FindSymbol(CurrentIdentifier)) == NULL || Entry->Structure != ST_ARR)
ErrorReport("Accessing undeclared array: %s\n", CurrentIdentifier); DieMessage("Accessing undeclared array", CurrentIdentifier);
LeftNode = ConstructASTLeaf(OP_ADDRESS, Entry->Type, Entry, 0); LeftNode = ConstructASTLeaf(OP_ADDRESS, Entry->Type, Entry, 0);
Tokenise(); Tokenise();
@ -84,71 +144,14 @@ struct ASTNode* AccessArray() {
VerifyToken(LI_RBRAS, "]"); VerifyToken(LI_RBRAS, "]");
if(!TypeIsInt(RightNode->ExprType)) if(!TypeIsInt(RightNode->ExprType))
ErrorReport("Array index is not integer"); Die("Array index is not integer");
printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", TypeNames(RightNode->ExprType), printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", (RightNode->ExprType), TypeNames(LeftNode->ExprType));
TypeNames(LeftNode->ExprType));
RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD); RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD);
LeftNode = ConstructASTNode(OP_ADD, Entry->Type, LeftNode, NULL, RightNode, NULL, 0); LeftNode = ConstructASTNode(OP_ADD, Entry->Type, LeftNode, NULL, RightNode, NULL, 0);
printf("\tAccessArray: Preparing LeftNode for dereference.\r\n"); printf("\tAccessArray: Preparing LeftNode for dereference.\r\n");
LeftNode = ConstructASTBranch(OP_DEREF, ValueAt(LeftNode->ExprType), LeftNode, Entry, 0); LeftNode = ConstructASTBranch(OP_DEREF, ValueAt(LeftNode->ExprType), LeftNode, NULL, 0);
printf("\tArray Access constructed\r\n"); printf("\tArray Access constructed\r\n");
return LeftNode; return LeftNode;
} }
/**
* Members of enums and structs are accessed with x.y or *x->y
*
* x must be enum, struct, or pointer to struct.
* y must be a valid member of any of the above.
*
* It is a wrapper around *((imax*)x + xType.ordinal(y))
*
* @return the AST Node representing this statement.
*/
struct ASTNode* AccessMember(bool Deref) {
struct ASTNode* LeftNode, * RightNode;
struct SymbolTableEntry* CompositeVar, * TypePtr, * Member;
if ((CompositeVar = FindSymbol(CurrentIdentifier)) == NULL)
ErrorReport("Undeclared variable: %s\n", CurrentIdentifier);
if (Deref && (CompositeVar->Type != PointerTo(DAT_STRUCT) && CompositeVar->Type != PointerTo(DAT_UNION)))
ErrorReport("Undeclared struct: %s\n", CurrentIdentifier);
if (!Deref && (CompositeVar->Type != DAT_STRUCT && CompositeVar->Type != DAT_UNION))
ErrorReport("Undeclared struct: %s\n", CurrentIdentifier);
Safe();
if (Deref)
LeftNode = ConstructASTLeaf(REF_IDENT, PointerTo(CompositeVar->Type), CompositeVar, 0);
else
LeftNode = ConstructASTLeaf(OP_ADDRESS, CompositeVar->Type, CompositeVar, 0);
LeftNode->RVal = true;
TypePtr = CompositeVar->CompositeType;
Tokenise();
VerifyToken(TY_IDENTIFIER, "identifier");
for (Member = TypePtr->Start; Member != NULL; Member = Member->NextSymbol) {
printf("\tComparing composite entry %s with the wanted %s. Index %d.\r\n", Member->Name, CurrentIdentifier,
Member->SinkOffset);
if (!strcmp(Member->Name, CurrentIdentifier))
break;
}
if (Member == NULL)
ErrorReport("Invalid composite member: %s\n", CurrentIdentifier);
Safe();
RightNode = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, Member->SinkOffset);
LeftNode = ConstructASTNode(OP_ADD, PointerTo(Member->Type), LeftNode, NULL, RightNode, NULL, 0);
LeftNode = ConstructASTBranch(OP_DEREF, Member->Type, LeftNode, Member, 0);
return LeftNode;
}

File diff suppressed because it is too large Load Diff

View File

@ -7,49 +7,8 @@
#include <Defs.h> #include <Defs.h>
#include <Data.h> #include <Data.h>
/**
* Dump all symbol tables to the console.
*/
void DumpAllLists() {
printf("Initiating table dump. Expect lots of spam.\n");
printf("Global symbols:\n");
DumpList(Globals);
printf("\nLocal symbols:\n");
DumpList(Locals);
printf("\nParameters:\n");
if (CurrentFile->FunctionEntry != NULL && CurrentFile->FunctionEntry->Start != NULL)
DumpList(CurrentFile->FunctionEntry->Start);
DumpList(Params);
printf("\nStructs:\n");
DumpList(Structs);
printf("\nComposite Members:\n");
DumpList(CompositeMembers);
printf("\nEnum Members:\n");
DumpList(EnumMembers);
printf("\nUnions:\n");
DumpList(Unions);
printf("\nEnums:\n");
DumpList(Enums);
printf("\nTypes:\n");
DumpList(Types);
printf("\n\nDump over.\n");
}
/**
* Dump all the items in the list.
* Prints their names to stdout, tab separated.
*
* @param List the list to dump
*/
void DumpList(struct SymbolTableEntry* List) {
for (; List != NULL; List = List->NextSymbol)
if ((List->Name != NULL))
printf("%s\t", List->Name);
}
/* /*
* Find the position of a symbol in a given symbol table. * Find the position of a symbol in a given symbol table.
*
* @param Name: The string name of the symbol * @param Name: The string name of the symbol
* @param List: The linked list to search in. * @param List: The linked list to search in.
* @return the list if found, * @return the list if found,
@ -77,8 +36,8 @@ static struct SymbolTableEntry* SearchList(char* Name, struct SymbolTableEntry*
struct SymbolTableEntry* FindSymbol(char* Symbol) { struct SymbolTableEntry* FindSymbol(char* Symbol) {
struct SymbolTableEntry* Node; struct SymbolTableEntry* Node;
if (CurrentFile->FunctionEntry) { if(CurrentFunction) {
Node = SearchList(Symbol, CurrentFile->FunctionEntry->Start); Node = SearchList(Symbol, FunctionEntry->Start);
if(Node) if(Node)
return Node; return Node;
} }
@ -87,7 +46,6 @@ struct SymbolTableEntry* FindSymbol(char* Symbol) {
if(Node) if(Node)
return Node; return Node;
return SearchList(Symbol, Globals); return SearchList(Symbol, Globals);
} }
@ -100,8 +58,8 @@ struct SymbolTableEntry* FindSymbol(char* Symbol) {
struct SymbolTableEntry* FindLocal(char* Symbol) { struct SymbolTableEntry* FindLocal(char* Symbol) {
struct SymbolTableEntry* Node; struct SymbolTableEntry* Node;
if (CurrentFile->FunctionEntry) { if(FunctionEntry) {
Node = SearchList(Symbol, CurrentFile->FunctionEntry->Start); Node = SearchList(Symbol, FunctionEntry->Start);
if(Node) if(Node)
return Node; return Node;
} }
@ -131,50 +89,6 @@ struct SymbolTableEntry* FindStruct(char* Symbol) {
return SearchList(Symbol, Structs); return SearchList(Symbol, Structs);
} }
/*
* An override for FindSymbol.
* Searches only the defined Enums.
* @param Symbol: The string name of the symbol to search for.
* @return a pointer to the node if found, else NULL
*
*/
struct SymbolTableEntry* FindEnum(char* Symbol) {
return SearchList(Symbol, Enums);
}
/*
* An override for FindSymbol.
* Searches only the defined enum members.
* @param Symbol: The string name of the symbol to search for.
* @return a pointer to the node if found, else NULL
*
*/
struct SymbolTableEntry* FindEnumMember(char* Symbol) {
return SearchList(Symbol, EnumMembers);
}
/*
* An override for FindSymbol.
* Searches only the defined type names.
* @param Symbol: The string name of the symbol to search for.
* @return a pointer to the node if found, else NULL
*
*/
struct SymbolTableEntry* FindAlias(char* Symbol) {
return SearchList(Symbol, Types);
}
/*
* An override for FindSymbol.
* Searches only the defined Unions.
* @param Symbol: The string name of the symbol to search for.
* @return a pointer to the node if found, else NULL
*
*/
struct SymbolTableEntry* FindUnion(char* Symbol) {
return SearchList(Symbol, Unions);
}
/* /*
* An override for FindSymbol. * An override for FindSymbol.
* Searches only the defined Struct & Enum Members. * Searches only the defined Struct & Enum Members.
@ -183,7 +97,7 @@ struct SymbolTableEntry* FindUnion(char* Symbol) {
* *
*/ */
struct SymbolTableEntry* FindMember(char* Symbol) { struct SymbolTableEntry* FindMember(char* Symbol) {
return SearchList(Symbol, CompositeMembers); return SearchList(Symbol, StructMembers);
} }
/* /*
@ -200,7 +114,7 @@ struct SymbolTableEntry* FindMember(char* Symbol) {
*/ */
void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node) { void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node) {
if(Head == NULL || Tail == NULL || Node == NULL) if(Head == NULL || Tail == NULL || Node == NULL)
ErrorReport("Not enough data to append a symbol to the tables. Missing: %s\n", Head == NULL ? "Head" : Tail == NULL ? "Tail" : "Node"); Die("Not enough data to append a symbol to the tables");
if(*Tail) { if(*Tail) {
(*Tail)->NextSymbol = Node; (*Tail)->NextSymbol = Node;
@ -220,7 +134,7 @@ void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail
void FreeLocals() { void FreeLocals() {
Locals = LocalsEnd = NULL; Locals = LocalsEnd = NULL;
Params = ParamsEnd = NULL; Params = ParamsEnd = NULL;
CurrentFile->FunctionEntry = NULL; FunctionEntry = NULL;
} }
@ -231,7 +145,7 @@ void ClearTables() {
Globals = GlobalsEnd = NULL; Globals = GlobalsEnd = NULL;
Locals = LocalsEnd = NULL; Locals = LocalsEnd = NULL;
Params = ParamsEnd = NULL; Params = ParamsEnd = NULL;
CompositeMembers = CompositeMembersEnd = NULL; StructMembers = StructMembersEnd = NULL;
Structs = StructsEnd = NULL; Structs = StructsEnd = NULL;
} }
@ -247,8 +161,7 @@ void ClearTables() {
* *
* @return The SymbolTableEntry* pointer that corresponds to this newly constructed node. * @return The SymbolTableEntry* pointer that corresponds to this newly constructed node.
*/ */
struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset, struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset, struct SymbolTableEntry* CompositeType) {
struct SymbolTableEntry* CompositeType) {
struct SymbolTableEntry* Node = struct SymbolTableEntry* Node =
(struct SymbolTableEntry*) malloc(sizeof(struct SymbolTableEntry)); (struct SymbolTableEntry*) malloc(sizeof(struct SymbolTableEntry));
@ -261,35 +174,17 @@ struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Stor
Node->SinkOffset = SinkOffset; Node->SinkOffset = SinkOffset;
Node->CompositeType = CompositeType; Node->CompositeType = CompositeType;
if (TypeIsPtr(Type) || TypeIsInt(Type))
Node->Size = Length * TypeSize(Type, CompositeType);
printf("Adding a %s symbol of name %s, type %s to the tables.\n", ScopeNames[Node->Storage], Node->Name,
TypeNames(Node->Type));
switch(Storage) { switch(Storage) {
case SC_GLOBAL: case SC_GLOBAL:
AppendSymbol(&Globals, &GlobalsEnd, Node); AppendSymbol(&Globals, &GlobalsEnd, Node);
// We don't want to generate a static block for functions. // We don't want to generate a static block for functions.
if (Structure != ST_FUNC) Assembler->vtable->AsGlobalSymbol(Node); if(Structure != ST_FUNC) AsGlobalSymbol(Node);
break; break;
case SC_STRUCT: case SC_STRUCT:
AppendSymbol(&Structs, &StructsEnd, Node); AppendSymbol(&Structs, &StructsEnd, Node);
break; break;
case SC_UNION:
AppendSymbol(&Unions, &UnionsEnd, Node);
break;
case SC_ENUM:
AppendSymbol(&Enums, &EnumsEnd, Node);
break;
case SC_ALIAS:
AppendSymbol(&Types, &TypesEnd, Node);
break;
case SC_ENUMENTRY:
AppendSymbol(&EnumMembers, &EnumMembersEnd, Node);
break;
case SC_MEMBER: case SC_MEMBER:
AppendSymbol(&CompositeMembers, &CompositeMembersEnd, Node); AppendSymbol(&StructMembers, &StructMembersEnd, Node);
break;
case SC_LOCAL: case SC_LOCAL:
AppendSymbol(&Locals, &LocalsEnd, Node); AppendSymbol(&Locals, &LocalsEnd, Node);
break; break;

View File

@ -17,8 +17,7 @@
*/ */
int TypeIsInt(int Type) { int TypeIsInt(int Type) {
printf("\tComparing type %s.\n", TypeNames(Type)); return ((Type & 0xf) == 0);
return ( ((Type & 0xf) == 0) && (Type >= RET_CHAR && Type <= RET_LONG));
} }
/* /*
@ -42,16 +41,14 @@ int TypeIsPtr(int Type) {
*/ */
int PrimitiveSize(int Type) { int PrimitiveSize(int Type) {
if(TypeIsPtr(Type)) return 8; if(TypeIsPtr(Type)) return 8;
switch(Type) { switch(Type) {
case RET_CHAR: case RET_CHAR: return 1;
return 1; case RET_INT: return 4;
case RET_INT: case RET_LONG: return 8;
return 4;
case RET_LONG:
return 8;
default: default:
ErrorReport("Bad type in PrimitiveSize: %s\n", TypeNames(Type)); DieDecimal("Bad type in PrimitiveSize", Type);
} }
return 0; return 0;
} }
@ -64,7 +61,7 @@ int PrimitiveSize(int Type) {
*/ */
int TypeSize(int Type, struct SymbolTableEntry* Composite) { int TypeSize(int Type, struct SymbolTableEntry* Composite) {
if (Type == DAT_STRUCT || Type == DAT_UNION) return Composite->Length; if(Type == DAT_STRUCT) return Composite->Length;
return PrimitiveSize(Type); return PrimitiveSize(Type);
} }
@ -80,23 +77,14 @@ static char TypeBuffer[7];
*/ */
char* TypeNames(int Type) { char* TypeNames(int Type) {
switch(Type) { switch(Type) {
case RET_CHAR: case RET_CHAR: memcpy(TypeBuffer, "Char", 4); break;
memcpy(TypeBuffer, "Char", 4); case RET_INT: memcpy(TypeBuffer, "Int ", 4); break;
break; case RET_LONG: memcpy(TypeBuffer, "Long", 4); break;
case RET_INT: case RET_VOID: memcpy(TypeBuffer, "Void", 4); break;
memcpy(TypeBuffer, "Int ", 4); default: DieDecimal("Bad size for printing", Type);
break;
case RET_LONG:
memcpy(TypeBuffer, "Long", 4);
break;
case RET_VOID:
memcpy(TypeBuffer, "Void", 4);
break;
default:
break;
}; };
if(TypeIsPtr(Type)) memcpy((void*)((size_t) TypeBuffer + 4), "Ptr", 3); if(TypeIsPtr(Type)) memcpy((void*)((size_t) TypeBuffer + 4), "Ptr", 3);
else memcpy((void*) ((size_t) TypeBuffer + 4), "\0", 1); else memcpy((void*)((size_t) TypeBuffer + 4), " ", 3);
return TypeBuffer; return TypeBuffer;
} }
@ -202,7 +190,7 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) {
LeftType = Tree->ExprType; LeftType = Tree->ExprType;
printf("\tCalculating compatibility between ltype %s and rtype %s\r\n", TypeNames(LeftType), TypeNames(RightType)); printf("\tCalculating compatibility between ltype %d and rtype %d\r\n", LeftType, RightType);
if(TypeIsInt(LeftType) && TypeIsInt(RightType)) { if(TypeIsInt(LeftType) && TypeIsInt(RightType)) {
// Short-circuit for valid types // Short-circuit for valid types

View File

@ -1,40 +0,0 @@
/*************/
/*GEMWIRE */
/* ERYTHRO*/
/*************/
#include <Defs.h>
#include <Data.h>
#define MODULES_SIZE 4
struct AssemblerModule* modules[MODULES_SIZE];
static int moduleID = 0;
void RegisterAllModules() {
RegisterWin32ASM();
RegisterLinuxASM();
RegisterQBE();
RegisterJVM();
for (size_t i = 0; i < moduleID; i++) {
if (strcmp(modules[i]->name, OptAssemblerName) == 0) {
Assembler = modules[i];
break;
}
}
if (Assembler == NULL) {
DieMessage("Unable to find an Assembler for ", OptAssemblerName);
} else {
printf("Using %s assembler.\r\n", OptAssemblerName);
}
}
int RegisterModule(struct AssemblerModule* mod) {
printf("Registering Assembler Module for %s output.\r\n", mod->name);
modules[moduleID] = mod;
moduleID++;
return 0;
}

View File

@ -1,180 +0,0 @@
/*************/
/*GEMWIRE */
/* ERYTHRO*/
/*************/
#include "Defs.h"
#include "Data.h"
#define AGGREGATE(x) ":##x"
#define GLOBAL(x) "$##x"
#define TEMPORARY(x) "%##x"
#define LABEL(x) "@##x"
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * R O O T O F A S S E M B L E R * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Just a short "hack" to make sure we only dump the tree the first time this function is called
static int Started = 0;
/*
* Walk the AST tree given, and generate the assembly code that represents
* it.
*
* @param Node: The current Node to compile. If needed, its children will be parsed recursively.
* @param Register: The index of Registers to store the result of the current compilation.
* @param ParentOp: The Operation of the parent of the current Node.
*
* @return dependant on the Node. Typically the Register that stores the result of the Node's operation.
*
*/
static int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int LoopEndLabel, int ParentOp) {
int LeftVal, RightVal;
if (!Started && OptDumpTree)
DumpTree(Node, 0);
Started = 1;
printf("Current operation: %d\r\n", Node->Operation);
switch (Node->Operation) {
case OP_IF:
case OP_LOOP:
case OP_COMP:
case OP_CALL:
case OP_FUNC:
break;
}
if (Node->Left)
LeftVal = AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
if (Node->Right)
RightVal = AssembleTree(Node->Right, LeftVal, LoopBeginLabel, LoopEndLabel, Node->Operation);
switch (Node->Operation) {
case OP_ADD:
case OP_SUBTRACT:
case OP_MULTIPLY:
case OP_DIVIDE:
case OP_SCALE:
switch (Node->Size) {
case 2:
case 4:
case 8:
default:
break;
}
case OP_BREAK:
case OP_CONTINUE:
case OP_ADDRESS:
case OP_DEREF:
case OP_ASSIGN:
printf("Preparing for assignment..\r\n");
if (Node->Right == NULL)
Die("Fault in assigning a null rvalue");
printf("\tCalculating assignment for target %s:\r\n", Node->Right->Symbol->Name);
switch (Node->Right->Operation) {
case REF_IDENT:
if (Node->Right->Symbol->Storage == SC_LOCAL) (void)0;
case OP_DEREF:
default:
ErrorReport("Can't ASSIGN in AssembleTree: %s", OperationNames[Node->Operation]);
}; return 0;
case OP_WIDEN:
case OP_RET:
case OP_EQUAL:
case OP_INEQ:
case OP_LESS:
case OP_GREAT:
case OP_LESSE:
case OP_GREATE:
if (ParentOp == OP_IF || ParentOp == OP_LOOP) (void)0;
case REF_IDENT:
if (TypeIsPtr(Node->ExprType)) {
}
if (Node->RVal || ParentOp == OP_DEREF) {
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) (void)0;
} else
return -1;
case TERM_INTLITERAL:
case TERM_STRLITERAL:
case OP_PRINT:
case OP_BITAND:
case OP_BITOR:
case OP_BITXOR:
case OP_SHIFTL:
case OP_SHIFTR:
case OP_POSTINC:
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) (void)0;
case OP_POSTDEC:
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) (void)0;
case OP_PREINC:
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) (void)0;
case OP_PREDEC:
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) (void)0;
case OP_BOOLNOT:
case OP_BITNOT:
case OP_NEGATE:
case OP_BOOLCONV:
return 0;
default:
DieDecimal("Unknown ASM Operation", Node->Operation);
return 0;
}
}
static const struct AssemblerVtable JVMAssemblerVtable = {
.AssembleTree = AssembleTree
};
static const struct AssemblerModule JVMAssemblerModule = {
.name = "JVM",
.vtable = &JVMAssemblerVtable
};
void RegisterJVM() {
RegisterModule(&JVMAssemblerModule);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,180 +0,0 @@
/*************/
/*GEMWIRE */
/* ERYTHRO*/
/*************/
#include "Defs.h"
#include "Data.h"
#define AGGREGATE(x) ":##x"
#define GLOBAL(x) "$##x"
#define TEMPORARY(x) "%##x"
#define LABEL(x) "@##x"
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * R O O T O F A S S E M B L E R * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Just a short "hack" to make sure we only dump the tree the first time this function is called
static int Started = 0;
/*
* Walk the AST tree given, and generate the assembly code that represents
* it.
*
* @param Node: The current Node to compile. If needed, its children will be parsed recursively.
* @param Register: The index of Registers to store the result of the current compilation.
* @param ParentOp: The Operation of the parent of the current Node.
*
* @return dependant on the Node. Typically the Register that stores the result of the Node's operation.
*
*/
static int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int LoopEndLabel, int ParentOp) {
int LeftVal, RightVal;
if (!Started && OptDumpTree)
DumpTree(Node, 0);
Started = 1;
printf("Current operation: %d\r\n", Node->Operation);
switch (Node->Operation) {
case OP_IF:
case OP_LOOP:
case OP_COMP:
case OP_CALL:
case OP_FUNC:
break;
}
if (Node->Left)
LeftVal = AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
if (Node->Right)
RightVal = AssembleTree(Node->Right, LeftVal, LoopBeginLabel, LoopEndLabel, Node->Operation);
switch (Node->Operation) {
case OP_ADD:
case OP_SUBTRACT:
case OP_MULTIPLY:
case OP_DIVIDE:
case OP_SCALE:
switch (Node->Size) {
case 2:
case 4:
case 8:
default:
break;
}
case OP_BREAK:
case OP_CONTINUE:
case OP_ADDRESS:
case OP_DEREF:
case OP_ASSIGN:
printf("Preparing for assignment..\r\n");
if (Node->Right == NULL)
Die("Fault in assigning a null rvalue");
printf("\tCalculating assignment for target %s:\r\n", Node->Right->Symbol->Name);
switch (Node->Right->Operation) {
case REF_IDENT:
if (Node->Right->Symbol->Storage == SC_LOCAL) (void)0;
case OP_DEREF:
default:
DieDecimal("Can't ASSIGN in AssembleTree: ", Node->Operation);
}; return 0;
case OP_WIDEN:
case OP_RET:
case OP_EQUAL:
case OP_INEQ:
case OP_LESS:
case OP_GREAT:
case OP_LESSE:
case OP_GREATE:
if (ParentOp == OP_IF || ParentOp == OP_LOOP) (void)0;
case REF_IDENT:
if (TypeIsPtr(Node->ExprType)) {
}
if (Node->RVal || ParentOp == OP_DEREF) {
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) (void)0;
} else
return -1;
case TERM_INTLITERAL:
case TERM_STRLITERAL:
case OP_PRINT:
case OP_BITAND:
case OP_BITOR:
case OP_BITXOR:
case OP_SHIFTL:
case OP_SHIFTR:
case OP_POSTINC:
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) (void)0;
case OP_POSTDEC:
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) (void)0;
case OP_PREINC:
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) (void)0;
case OP_PREDEC:
if (Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) (void)0;
case OP_BOOLNOT:
case OP_BITNOT:
case OP_NEGATE:
case OP_BOOLCONV:
return 0;
default:
DieDecimal("Unknown ASM Operation", Node->Operation);
return 0;
}
}
static const struct AssemblerVtable QBEAssemblerVtable = {
.AssembleTree = AssembleTree
};
static const struct AssemblerModule QBEAssemblerModule = {
.name = "QBE",
.vtable = &QBEAssemblerVtable
};
void RegisterQBE() {
RegisterModule(&QBEAssemblerModule);
}

View File

@ -1,29 +0,0 @@
int :: printf(char* format);
alias int water;
water drink;
struct fruit {
int x,
int y
};
alias struct fruit basket;
basket food;
alias basket shop;
shop market;
int :: main() {
drink = 5;
printf("%d\n", drink);
food.x = 10;
food.y = 66;
printf("%d\n", food.y);
market.y = 150;
printf("%d\n", market.y);
return (0);
}

View File

@ -1,21 +0,0 @@
import "tests/import/defs.eh"
int :: main() {
int x;
x = 5;
while (x < 15) {
printf("%d\n", x);
if (x =? 12)
break;
if (x =? 10) {
x = x + 2;
continue;
}
x = x + 1;
}
return (0);
}

View File

@ -1,6 +0,0 @@
#include <stdio.h>
int main() {
printf("%d\n", 55);
puts("more sup\n");
}

View File

@ -6,8 +6,8 @@ int :: close(int fd);
char* textbuffer; char* textbuffer;
int :: main() { int :: main() {
long sourcefile; int sourcefile;
long count; int count;
textbuffer = " "; textbuffer = " ";

View File

@ -1,18 +0,0 @@
int :: printf(char* format);
enum fruit { apple, pear, shallot };
enum basket {
abc = 15,
def
};
enum basket thing;
enum fruit stuff;
int :: main() {
int temp;
temp = apple + pear + abc;
printf("%d\n", temp);
return (0);
}

View File

@ -1,22 +0,0 @@
#ifndef __FREEGLUT_H__
#define __FREEGLUT_H__
/*
* freeglut.h
*
* The freeglut library include file
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "freeglut_std.h"
#include "freeglut_ext.h"
/*** END OF FILE ***/
#endif /* __FREEGLUT_H__ */

View File

@ -1,271 +0,0 @@
#ifndef __FREEGLUT_EXT_H__
#define __FREEGLUT_EXT_H__
/*
* freeglut_ext.h
*
* The non-GLUT-compatible extensions to the freeglut library include file
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 2 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* Additional GLUT Key definitions for the Special key function
*/
#define GLUT_KEY_NUM_LOCK 0x006D
#define GLUT_KEY_BEGIN 0x006E
#define GLUT_KEY_DELETE 0x006F
#define GLUT_KEY_SHIFT_L 0x0070
#define GLUT_KEY_SHIFT_R 0x0071
#define GLUT_KEY_CTRL_L 0x0072
#define GLUT_KEY_CTRL_R 0x0073
#define GLUT_KEY_ALT_L 0x0074
#define GLUT_KEY_ALT_R 0x0075
/*
* GLUT API Extension macro definitions -- behaviour when the user clicks on an "x" to close a window
*/
#define GLUT_ACTION_EXIT 0
#define GLUT_ACTION_GLUTMAINLOOP_RETURNS 1
#define GLUT_ACTION_CONTINUE_EXECUTION 2
/*
* Create a new rendering context when the user opens a new window?
*/
#define GLUT_CREATE_NEW_CONTEXT 0
#define GLUT_USE_CURRENT_CONTEXT 1
/*
* Direct/Indirect rendering context options (has meaning only in Unix/X11)
*/
#define GLUT_FORCE_INDIRECT_CONTEXT 0
#define GLUT_ALLOW_DIRECT_CONTEXT 1
#define GLUT_TRY_DIRECT_CONTEXT 2
#define GLUT_FORCE_DIRECT_CONTEXT 3
/*
* GLUT API Extension macro definitions -- the glutGet parameters
*/
#define GLUT_INIT_STATE 0x007C
#define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9
#define GLUT_WINDOW_BORDER_WIDTH 0x01FA
#define GLUT_WINDOW_BORDER_HEIGHT 0x01FB
#define GLUT_WINDOW_HEADER_HEIGHT 0x01FB /* Docs say it should always have been GLUT_WINDOW_BORDER_HEIGHT, keep this for backward compatibility */
#define GLUT_VERSION 0x01FC
#define GLUT_RENDERING_CONTEXT 0x01FD
#define GLUT_DIRECT_RENDERING 0x01FE
#define GLUT_FULL_SCREEN 0x01FF
#define GLUT_SKIP_STALE_MOTION_EVENTS 0x0204
#define GLUT_GEOMETRY_VISUALIZE_NORMALS 0x0205
#define GLUT_STROKE_FONT_DRAW_JOIN_DOTS 0x0206 /* Draw dots between line segments of stroke fonts? */
/*
* New tokens for glutInitDisplayMode.
* Only one GLUT_AUXn bit may be used at a time.
* Value 0x0400 is defined in OpenGLUT.
*/
#define GLUT_AUX 0x1000
#define GLUT_AUX1 0x1000
#define GLUT_AUX2 0x2000
#define GLUT_AUX3 0x4000
#define GLUT_AUX4 0x8000
/*
* Context-related flags, see fg_state.c
* Set the requested OpenGL version
*/
#define GLUT_INIT_MAJOR_VERSION 0x0200
#define GLUT_INIT_MINOR_VERSION 0x0201
#define GLUT_INIT_FLAGS 0x0202
#define GLUT_INIT_PROFILE 0x0203
/*
* Flags for glutInitContextFlags, see fg_init.c
*/
#define GLUT_DEBUG 0x0001
#define GLUT_FORWARD_COMPATIBLE 0x0002
/*
* Flags for glutInitContextProfile, see fg_init.c
*/
#define GLUT_CORE_PROFILE 0x0001
#define GLUT_COMPATIBILITY_PROFILE 0x0002
/*
* Process loop function, see fg_main.c
*/
FGAPI void FGAPIENTRY glutMainLoopEvent( void );
FGAPI void FGAPIENTRY glutLeaveMainLoop( void );
FGAPI void FGAPIENTRY glutExit ( void );
/*
* Window management functions, see fg_window.c
*/
FGAPI void FGAPIENTRY glutFullScreenToggle( void );
FGAPI void FGAPIENTRY glutLeaveFullScreen( void );
/*
* Menu functions
*/
FGAPI void FGAPIENTRY glutSetMenuFont( int menuID, void* font );
/*
* Window-specific callback functions, see fg_callbacks.c
*/
FGAPI void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) );
FGAPI void FGAPIENTRY glutPositionFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutCloseFunc( void (* callback)( void ) );
FGAPI void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) );
/* And also a destruction callback for menus */
FGAPI void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) );
/*
* State setting and retrieval functions, see fg_state.c
*/
FGAPI void FGAPIENTRY glutSetOption ( GLenum option_flag, int value );
FGAPI int * FGAPIENTRY glutGetModeValues(GLenum mode, int * size);
/* A.Donev: User-data manipulation */
FGAPI void* FGAPIENTRY glutGetWindowData( void );
FGAPI void FGAPIENTRY glutSetWindowData(void* data);
FGAPI void* FGAPIENTRY glutGetMenuData( void );
FGAPI void FGAPIENTRY glutSetMenuData(void* data);
/*
* Font stuff, see fg_font.c
*/
FGAPI int FGAPIENTRY glutBitmapHeight( void* font );
FGAPI GLfloat FGAPIENTRY glutStrokeHeight( void* font );
FGAPI void FGAPIENTRY glutBitmapString( void* font, const unsigned char *string );
FGAPI void FGAPIENTRY glutStrokeString( void* font, const unsigned char *string );
/*
* Geometry functions, see fg_geometry.c
*/
FGAPI void FGAPIENTRY glutWireRhombicDodecahedron( void );
FGAPI void FGAPIENTRY glutSolidRhombicDodecahedron( void );
FGAPI void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, double offset[3], double scale );
FGAPI void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, double offset[3], double scale );
FGAPI void FGAPIENTRY glutWireCylinder( double radius, double height, GLint slices, GLint stacks);
FGAPI void FGAPIENTRY glutSolidCylinder( double radius, double height, GLint slices, GLint stacks);
/*
* Rest of functions for rendering Newell's teaset, found in fg_teapot.c
* NB: front facing polygons have clockwise winding, not counter clockwise
*/
FGAPI void FGAPIENTRY glutWireTeacup( double size );
FGAPI void FGAPIENTRY glutSolidTeacup( double size );
FGAPI void FGAPIENTRY glutWireTeaspoon( double size );
FGAPI void FGAPIENTRY glutSolidTeaspoon( double size );
/*
* Extension functions, see fg_ext.c
*/
typedef void (*GLUTproc)();
FGAPI GLUTproc FGAPIENTRY glutGetProcAddress( const char *procName );
/*
* Multi-touch/multi-pointer extensions
*/
#define GLUT_HAS_MULTI 1
/* TODO: add device_id parameter,
cf. http://sourceforge.net/mailarchive/forum.php?thread_name=20120518071314.GA28061%40perso.beuc.net&forum_name=freeglut-developer */
FGAPI void FGAPIENTRY glutMultiEntryFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutMultiButtonFunc( void (* callback)( int, int, int, int, int ) );
FGAPI void FGAPIENTRY glutMultiMotionFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutMultiPassiveFunc( void (* callback)( int, int, int ) );
/*
* Joystick functions, see fg_joystick.c
*/
/* USE OF THESE FUNCTIONS IS DEPRECATED !!!!! */
/* If you have a serious need for these functions in your application, please either
* contact the "freeglut" developer community at freeglut-developer@lists.sourceforge.net,
* switch to the OpenGLUT library, or else port your joystick functionality over to PLIB's
* "js" library.
*/
int glutJoystickGetNumAxes( int ident );
int glutJoystickGetNumButtons( int ident );
int glutJoystickNotWorking( int ident );
float glutJoystickGetDeadBand( int ident, int axis );
void glutJoystickSetDeadBand( int ident, int axis, float db );
float glutJoystickGetSaturation( int ident, int axis );
void glutJoystickSetSaturation( int ident, int axis, float st );
void glutJoystickSetMinRange( int ident, float *axes );
void glutJoystickSetMaxRange( int ident, float *axes );
void glutJoystickSetCenter( int ident, float *axes );
void glutJoystickGetMinRange( int ident, float *axes );
void glutJoystickGetMaxRange( int ident, float *axes );
void glutJoystickGetCenter( int ident, float *axes );
/*
* Initialization functions, see fg_init.c
*/
/* to get the typedef for va_list */
#include <stdarg.h>
FGAPI void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion );
FGAPI void FGAPIENTRY glutInitContextFlags( int flags );
FGAPI void FGAPIENTRY glutInitContextProfile( int profile );
FGAPI void FGAPIENTRY glutInitErrorFunc( void (* callback)( const char *fmt, va_list ap ) );
FGAPI void FGAPIENTRY glutInitWarningFunc( void (* callback)( const char *fmt, va_list ap ) );
/* OpenGL >= 2.0 support */
FGAPI void FGAPIENTRY glutSetVertexAttribCoord3(GLint attrib);
FGAPI void FGAPIENTRY glutSetVertexAttribNormal(GLint attrib);
FGAPI void FGAPIENTRY glutSetVertexAttribTexCoord2(GLint attrib);
/* Mobile platforms lifecycle */
FGAPI void FGAPIENTRY glutInitContextFunc(void (* callback)());
FGAPI void FGAPIENTRY glutAppStatusFunc(void (* callback)(int));
/* state flags that can be passed to callback set by glutAppStatusFunc */
#define GLUT_APPSTATUS_PAUSE 0x0001
#define GLUT_APPSTATUS_RESUME 0x0002
/*
* GLUT API macro definitions -- the display mode definitions
*/
#define GLUT_CAPTIONLESS 0x0400
#define GLUT_BORDERLESS 0x0800
#define GLUT_SRGB 0x1000
#ifdef __cplusplus
}
#endif
/*** END OF FILE ***/
#endif /* __FREEGLUT_EXT_H__ */

View File

@ -1,653 +0,0 @@
#ifndef __FREEGLUT_STD_H__
#define __FREEGLUT_STD_H__
/*
* freeglut_std.h
*
* The GLUT-compatible part of the freeglut library include file
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* Written by Pawel W. Olszta, <olszta@sourceforge.net>
* Creation date: Thu Dec 2 1999
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* Under windows, we have to differentiate between static and dynamic libraries
*/
#ifdef _WIN32
/* #pragma may not be supported by some compilers.
* Discussion by FreeGLUT developers suggests that
* Visual C++ specific code involving pragmas may
* need to move to a separate header. 24th Dec 2003
*/
/* Define FREEGLUT_LIB_PRAGMAS to 1 to include library
* pragmas or to 0 to exclude library pragmas.
* The default behavior depends on the compiler/platform.
*/
# ifndef FREEGLUT_LIB_PRAGMAS
# if ( defined(_MSC_VER) || defined(__WATCOMC__) ) && !defined(_WIN32_WCE)
# define FREEGLUT_LIB_PRAGMAS 1
# else
# define FREEGLUT_LIB_PRAGMAS 0
# endif
# endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN 1
# endif
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h>
/* Windows static library */
# ifdef FREEGLUT_STATIC
# define FGAPI
# define FGAPIENTRY
/* Link with Win32 static freeglut lib */
# if FREEGLUT_LIB_PRAGMAS
# ifdef NDEBUG
# pragma comment (lib, "freeglut_static.lib")
# else
# pragma comment (lib, "freeglut_staticd.lib")
# endif
# endif
/* Windows shared library (DLL) */
# else
# define FGAPIENTRY __stdcall
# if defined(FREEGLUT_EXPORTS)
# define FGAPI __declspec(dllexport)
# else
# define FGAPI __declspec(dllimport)
/* Link with Win32 shared freeglut lib */
# if FREEGLUT_LIB_PRAGMAS
# ifdef NDEBUG
# pragma comment (lib, "freeglut.lib")
# else
# pragma comment (lib, "freeglutd.lib")
# endif
# endif
# endif
# endif
/* Drag in other Windows libraries as required by FreeGLUT */
# if FREEGLUT_LIB_PRAGMAS
# pragma comment (lib, "glu32.lib") /* link OpenGL Utility lib */
# pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib */
# pragma comment (lib, "gdi32.lib") /* link Windows GDI lib */
# pragma comment (lib, "winmm.lib") /* link Windows MultiMedia lib */
# pragma comment (lib, "user32.lib") /* link Windows user lib */
# endif
#else
/* Non-Windows definition of FGAPI and FGAPIENTRY */
# define FGAPI
# define FGAPIENTRY
#endif
/*
* The freeglut and GLUT API versions
*/
#define FREEGLUT 1
#define GLUT_API_VERSION 4
#define GLUT_XLIB_IMPLEMENTATION 13
/* Deprecated:
cf. http://sourceforge.net/mailarchive/forum.php?thread_name=CABcAi1hw7cr4xtigckaGXB5X8wddLfMcbA_rZ3NAuwMrX_zmsw%40mail.gmail.com&forum_name=freeglut-developer */
#define FREEGLUT_VERSION_2_0 1
/*
* Always include OpenGL and GLU headers
*/
/* Note: FREEGLUT_GLES is only used to cleanly bootstrap headers
inclusion here; use GLES constants directly
(e.g. GL_ES_VERSION_2_0) for all other needs */
#ifdef FREEGLUT_GLES
# include <EGL/egl.h>
# include <GLES/gl.h>
# include <GLES2/gl2.h>
#elif __APPLE__
# include <OpenGL/gl.h>
# include <OpenGL/glu.h>
#else
# include <GL/gl.h>
# include <GL/glu.h>
#endif
/*
* GLUT API macro definitions -- the special key codes:
*/
#define GLUT_KEY_F1 0x0001
#define GLUT_KEY_F2 0x0002
#define GLUT_KEY_F3 0x0003
#define GLUT_KEY_F4 0x0004
#define GLUT_KEY_F5 0x0005
#define GLUT_KEY_F6 0x0006
#define GLUT_KEY_F7 0x0007
#define GLUT_KEY_F8 0x0008
#define GLUT_KEY_F9 0x0009
#define GLUT_KEY_F10 0x000A
#define GLUT_KEY_F11 0x000B
#define GLUT_KEY_F12 0x000C
#define GLUT_KEY_LEFT 0x0064
#define GLUT_KEY_UP 0x0065
#define GLUT_KEY_RIGHT 0x0066
#define GLUT_KEY_DOWN 0x0067
#define GLUT_KEY_PAGE_UP 0x0068
#define GLUT_KEY_PAGE_DOWN 0x0069
#define GLUT_KEY_HOME 0x006A
#define GLUT_KEY_END 0x006B
#define GLUT_KEY_INSERT 0x006C
/*
* GLUT API macro definitions -- mouse state definitions
*/
#define GLUT_LEFT_BUTTON 0x0000
#define GLUT_MIDDLE_BUTTON 0x0001
#define GLUT_RIGHT_BUTTON 0x0002
#define GLUT_DOWN 0x0000
#define GLUT_UP 0x0001
#define GLUT_LEFT 0x0000
#define GLUT_ENTERED 0x0001
/*
* GLUT API macro definitions -- the display mode definitions
*/
#define GLUT_RGB 0x0000
#define GLUT_RGBA 0x0000
#define GLUT_INDEX 0x0001
#define GLUT_SINGLE 0x0000
#define GLUT_DOUBLE 0x0002
#define GLUT_ACCUM 0x0004
#define GLUT_ALPHA 0x0008
#define GLUT_DEPTH 0x0010
#define GLUT_STENCIL 0x0020
#define GLUT_MULTISAMPLE 0x0080
#define GLUT_STEREO 0x0100
#define GLUT_LUMINANCE 0x0200
/*
* GLUT API macro definitions -- windows and menu related definitions
*/
#define GLUT_MENU_NOT_IN_USE 0x0000
#define GLUT_MENU_IN_USE 0x0001
#define GLUT_NOT_VISIBLE 0x0000
#define GLUT_VISIBLE 0x0001
#define GLUT_HIDDEN 0x0000
#define GLUT_FULLY_RETAINED 0x0001
#define GLUT_PARTIALLY_RETAINED 0x0002
#define GLUT_FULLY_COVERED 0x0003
/*
* GLUT API macro definitions -- fonts definitions
*
* Steve Baker suggested to make it binary compatible with GLUT:
*/
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WATCOMC__)
# define GLUT_STROKE_ROMAN ((void *)0x0000)
# define GLUT_STROKE_MONO_ROMAN ((void *)0x0001)
# define GLUT_BITMAP_9_BY_15 ((void *)0x0002)
# define GLUT_BITMAP_8_BY_13 ((void *)0x0003)
# define GLUT_BITMAP_TIMES_ROMAN_10 ((void *)0x0004)
# define GLUT_BITMAP_TIMES_ROMAN_24 ((void *)0x0005)
# define GLUT_BITMAP_HELVETICA_10 ((void *)0x0006)
# define GLUT_BITMAP_HELVETICA_12 ((void *)0x0007)
# define GLUT_BITMAP_HELVETICA_18 ((void *)0x0008)
#else
/*
* I don't really know if it's a good idea... But here it goes:
*/
extern void* glutStrokeRoman;
extern void* glutStrokeMonoRoman;
extern void* glutBitmap9By15;
extern void* glutBitmap8By13;
extern void* glutBitmapTimesRoman10;
extern void* glutBitmapTimesRoman24;
extern void* glutBitmapHelvetica10;
extern void* glutBitmapHelvetica12;
extern void* glutBitmapHelvetica18;
/*
* Those pointers will be used by following definitions:
*/
# define GLUT_STROKE_ROMAN ((void *) &glutStrokeRoman)
# define GLUT_STROKE_MONO_ROMAN ((void *) &glutStrokeMonoRoman)
# define GLUT_BITMAP_9_BY_15 ((void *) &glutBitmap9By15)
# define GLUT_BITMAP_8_BY_13 ((void *) &glutBitmap8By13)
# define GLUT_BITMAP_TIMES_ROMAN_10 ((void *) &glutBitmapTimesRoman10)
# define GLUT_BITMAP_TIMES_ROMAN_24 ((void *) &glutBitmapTimesRoman24)
# define GLUT_BITMAP_HELVETICA_10 ((void *) &glutBitmapHelvetica10)
# define GLUT_BITMAP_HELVETICA_12 ((void *) &glutBitmapHelvetica12)
# define GLUT_BITMAP_HELVETICA_18 ((void *) &glutBitmapHelvetica18)
#endif
/*
* GLUT API macro definitions -- the glutGet parameters
*/
#define GLUT_WINDOW_X 0x0064
#define GLUT_WINDOW_Y 0x0065
#define GLUT_WINDOW_WIDTH 0x0066
#define GLUT_WINDOW_HEIGHT 0x0067
#define GLUT_WINDOW_BUFFER_SIZE 0x0068
#define GLUT_WINDOW_STENCIL_SIZE 0x0069
#define GLUT_WINDOW_DEPTH_SIZE 0x006A
#define GLUT_WINDOW_RED_SIZE 0x006B
#define GLUT_WINDOW_GREEN_SIZE 0x006C
#define GLUT_WINDOW_BLUE_SIZE 0x006D
#define GLUT_WINDOW_ALPHA_SIZE 0x006E
#define GLUT_WINDOW_ACCUM_RED_SIZE 0x006F
#define GLUT_WINDOW_ACCUM_GREEN_SIZE 0x0070
#define GLUT_WINDOW_ACCUM_BLUE_SIZE 0x0071
#define GLUT_WINDOW_ACCUM_ALPHA_SIZE 0x0072
#define GLUT_WINDOW_DOUBLEBUFFER 0x0073
#define GLUT_WINDOW_RGBA 0x0074
#define GLUT_WINDOW_PARENT 0x0075
#define GLUT_WINDOW_NUM_CHILDREN 0x0076
#define GLUT_WINDOW_COLORMAP_SIZE 0x0077
#define GLUT_WINDOW_NUM_SAMPLES 0x0078
#define GLUT_WINDOW_STEREO 0x0079
#define GLUT_WINDOW_CURSOR 0x007A
#define GLUT_SCREEN_WIDTH 0x00C8
#define GLUT_SCREEN_HEIGHT 0x00C9
#define GLUT_SCREEN_WIDTH_MM 0x00CA
#define GLUT_SCREEN_HEIGHT_MM 0x00CB
#define GLUT_MENU_NUM_ITEMS 0x012C
#define GLUT_DISPLAY_MODE_POSSIBLE 0x0190
#define GLUT_INIT_WINDOW_X 0x01F4
#define GLUT_INIT_WINDOW_Y 0x01F5
#define GLUT_INIT_WINDOW_WIDTH 0x01F6
#define GLUT_INIT_WINDOW_HEIGHT 0x01F7
#define GLUT_INIT_DISPLAY_MODE 0x01F8
#define GLUT_ELAPSED_TIME 0x02BC
#define GLUT_WINDOW_FORMAT_ID 0x007B
/*
* GLUT API macro definitions -- the glutDeviceGet parameters
*/
#define GLUT_HAS_KEYBOARD 0x0258
#define GLUT_HAS_MOUSE 0x0259
#define GLUT_HAS_SPACEBALL 0x025A
#define GLUT_HAS_DIAL_AND_BUTTON_BOX 0x025B
#define GLUT_HAS_TABLET 0x025C
#define GLUT_NUM_MOUSE_BUTTONS 0x025D
#define GLUT_NUM_SPACEBALL_BUTTONS 0x025E
#define GLUT_NUM_BUTTON_BOX_BUTTONS 0x025F
#define GLUT_NUM_DIALS 0x0260
#define GLUT_NUM_TABLET_BUTTONS 0x0261
#define GLUT_DEVICE_IGNORE_KEY_REPEAT 0x0262
#define GLUT_DEVICE_KEY_REPEAT 0x0263
#define GLUT_HAS_JOYSTICK 0x0264
#define GLUT_OWNS_JOYSTICK 0x0265
#define GLUT_JOYSTICK_BUTTONS 0x0266
#define GLUT_JOYSTICK_AXES 0x0267
#define GLUT_JOYSTICK_POLL_RATE 0x0268
/*
* GLUT API macro definitions -- the glutLayerGet parameters
*/
#define GLUT_OVERLAY_POSSIBLE 0x0320
#define GLUT_LAYER_IN_USE 0x0321
#define GLUT_HAS_OVERLAY 0x0322
#define GLUT_TRANSPARENT_INDEX 0x0323
#define GLUT_NORMAL_DAMAGED 0x0324
#define GLUT_OVERLAY_DAMAGED 0x0325
/*
* GLUT API macro definitions -- the glutVideoResizeGet parameters
*/
#define GLUT_VIDEO_RESIZE_POSSIBLE 0x0384
#define GLUT_VIDEO_RESIZE_IN_USE 0x0385
#define GLUT_VIDEO_RESIZE_X_DELTA 0x0386
#define GLUT_VIDEO_RESIZE_Y_DELTA 0x0387
#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 0x0388
#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 0x0389
#define GLUT_VIDEO_RESIZE_X 0x038A
#define GLUT_VIDEO_RESIZE_Y 0x038B
#define GLUT_VIDEO_RESIZE_WIDTH 0x038C
#define GLUT_VIDEO_RESIZE_HEIGHT 0x038D
/*
* GLUT API macro definitions -- the glutUseLayer parameters
*/
#define GLUT_NORMAL 0x0000
#define GLUT_OVERLAY 0x0001
/*
* GLUT API macro definitions -- the glutGetModifiers parameters
*/
#define GLUT_ACTIVE_SHIFT 0x0001
#define GLUT_ACTIVE_CTRL 0x0002
#define GLUT_ACTIVE_ALT 0x0004
/*
* GLUT API macro definitions -- the glutSetCursor parameters
*/
#define GLUT_CURSOR_RIGHT_ARROW 0x0000
#define GLUT_CURSOR_LEFT_ARROW 0x0001
#define GLUT_CURSOR_INFO 0x0002
#define GLUT_CURSOR_DESTROY 0x0003
#define GLUT_CURSOR_HELP 0x0004
#define GLUT_CURSOR_CYCLE 0x0005
#define GLUT_CURSOR_SPRAY 0x0006
#define GLUT_CURSOR_WAIT 0x0007
#define GLUT_CURSOR_TEXT 0x0008
#define GLUT_CURSOR_CROSSHAIR 0x0009
#define GLUT_CURSOR_UP_DOWN 0x000A
#define GLUT_CURSOR_LEFT_RIGHT 0x000B
#define GLUT_CURSOR_TOP_SIDE 0x000C
#define GLUT_CURSOR_BOTTOM_SIDE 0x000D
#define GLUT_CURSOR_LEFT_SIDE 0x000E
#define GLUT_CURSOR_RIGHT_SIDE 0x000F
#define GLUT_CURSOR_TOP_LEFT_CORNER 0x0010
#define GLUT_CURSOR_TOP_RIGHT_CORNER 0x0011
#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 0x0012
#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 0x0013
#define GLUT_CURSOR_INHERIT 0x0064
#define GLUT_CURSOR_NONE 0x0065
#define GLUT_CURSOR_FULL_CROSSHAIR 0x0066
/*
* GLUT API macro definitions -- RGB color component specification definitions
*/
#define GLUT_RED 0x0000
#define GLUT_GREEN 0x0001
#define GLUT_BLUE 0x0002
/*
* GLUT API macro definitions -- additional keyboard and joystick definitions
*/
#define GLUT_KEY_REPEAT_OFF 0x0000
#define GLUT_KEY_REPEAT_ON 0x0001
#define GLUT_KEY_REPEAT_DEFAULT 0x0002
#define GLUT_JOYSTICK_BUTTON_A 0x0001
#define GLUT_JOYSTICK_BUTTON_B 0x0002
#define GLUT_JOYSTICK_BUTTON_C 0x0004
#define GLUT_JOYSTICK_BUTTON_D 0x0008
/*
* GLUT API macro definitions -- game mode definitions
*/
#define GLUT_GAME_MODE_ACTIVE 0x0000
#define GLUT_GAME_MODE_POSSIBLE 0x0001
#define GLUT_GAME_MODE_WIDTH 0x0002
#define GLUT_GAME_MODE_HEIGHT 0x0003
#define GLUT_GAME_MODE_PIXEL_DEPTH 0x0004
#define GLUT_GAME_MODE_REFRESH_RATE 0x0005
#define GLUT_GAME_MODE_DISPLAY_CHANGED 0x0006
/*
* Initialization functions, see fglut_init.c
*/
FGAPI void FGAPIENTRY glutInit( int* pargc, char** argv );
FGAPI void FGAPIENTRY glutInitWindowPosition( int x, int y );
FGAPI void FGAPIENTRY glutInitWindowSize( int width, int height );
FGAPI void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode );
FGAPI void FGAPIENTRY glutInitDisplayString( const char* displayMode );
/*
* Process loop function, see fg_main.c
*/
FGAPI void FGAPIENTRY glutMainLoop( void );
/*
* Window management functions, see fg_window.c
*/
FGAPI int FGAPIENTRY glutCreateWindow( const char* title );
FGAPI int FGAPIENTRY glutCreateSubWindow( int window, int x, int y, int width, int height );
FGAPI void FGAPIENTRY glutDestroyWindow( int window );
FGAPI void FGAPIENTRY glutSetWindow( int window );
FGAPI int FGAPIENTRY glutGetWindow( void );
FGAPI void FGAPIENTRY glutSetWindowTitle( const char* title );
FGAPI void FGAPIENTRY glutSetIconTitle( const char* title );
FGAPI void FGAPIENTRY glutReshapeWindow( int width, int height );
FGAPI void FGAPIENTRY glutPositionWindow( int x, int y );
FGAPI void FGAPIENTRY glutShowWindow( void );
FGAPI void FGAPIENTRY glutHideWindow( void );
FGAPI void FGAPIENTRY glutIconifyWindow( void );
FGAPI void FGAPIENTRY glutPushWindow( void );
FGAPI void FGAPIENTRY glutPopWindow( void );
FGAPI void FGAPIENTRY glutFullScreen( void );
/*
* Display-related functions, see fg_display.c
*/
FGAPI void FGAPIENTRY glutPostWindowRedisplay( int window );
FGAPI void FGAPIENTRY glutPostRedisplay( void );
FGAPI void FGAPIENTRY glutSwapBuffers( void );
/*
* Mouse cursor functions, see fg_cursor.c
*/
FGAPI void FGAPIENTRY glutWarpPointer( int x, int y );
FGAPI void FGAPIENTRY glutSetCursor( int cursor );
/*
* Overlay stuff, see fg_overlay.c
*/
FGAPI void FGAPIENTRY glutEstablishOverlay( void );
FGAPI void FGAPIENTRY glutRemoveOverlay( void );
FGAPI void FGAPIENTRY glutUseLayer( GLenum layer );
FGAPI void FGAPIENTRY glutPostOverlayRedisplay( void );
FGAPI void FGAPIENTRY glutPostWindowOverlayRedisplay( int window );
FGAPI void FGAPIENTRY glutShowOverlay( void );
FGAPI void FGAPIENTRY glutHideOverlay( void );
/*
* Menu stuff, see fg_menu.c
*/
FGAPI int FGAPIENTRY glutCreateMenu( void (* callback)( int menu ) );
FGAPI void FGAPIENTRY glutDestroyMenu( int menu );
FGAPI int FGAPIENTRY glutGetMenu( void );
FGAPI void FGAPIENTRY glutSetMenu( int menu );
FGAPI void FGAPIENTRY glutAddMenuEntry( const char* label, int value );
FGAPI void FGAPIENTRY glutAddSubMenu( const char* label, int subMenu );
FGAPI void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value );
FGAPI void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, int value );
FGAPI void FGAPIENTRY glutRemoveMenuItem( int item );
FGAPI void FGAPIENTRY glutAttachMenu( int button );
FGAPI void FGAPIENTRY glutDetachMenu( int button );
/*
* Global callback functions, see fg_callbacks.c
*/
FGAPI void FGAPIENTRY glutTimerFunc( unsigned int time, void (* callback)( int ), int value );
FGAPI void FGAPIENTRY glutIdleFunc( void (* callback)( void ) );
/*
* Window-specific callback functions, see fg_callbacks.c
*/
FGAPI void FGAPIENTRY glutKeyboardFunc( void (* callback)( unsigned char, int, int ) );
FGAPI void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) );
FGAPI void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) );
FGAPI void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) );
FGAPI void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutEntryFunc( void (* callback)( int ) );
FGAPI void FGAPIENTRY glutKeyboardUpFunc( void (* callback)( unsigned char, int, int ) );
FGAPI void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int ), int pollInterval );
FGAPI void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) );
FGAPI void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) );
FGAPI void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) );
FGAPI void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) );
FGAPI void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) );
FGAPI void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) );
/*
* State setting and retrieval functions, see fg_state.c
*/
FGAPI int FGAPIENTRY glutGet( GLenum query );
FGAPI int FGAPIENTRY glutDeviceGet( GLenum query );
FGAPI int FGAPIENTRY glutGetModifiers( void );
FGAPI int FGAPIENTRY glutLayerGet( GLenum query );
/*
* Font stuff, see fg_font.c
*/
FGAPI void FGAPIENTRY glutBitmapCharacter( void* font, int character );
FGAPI int FGAPIENTRY glutBitmapWidth( void* font, int character );
FGAPI void FGAPIENTRY glutStrokeCharacter( void* font, int character );
FGAPI int FGAPIENTRY glutStrokeWidth( void* font, int character );
FGAPI GLfloat FGAPIENTRY glutStrokeWidthf( void* font, int character ); /* GLUT 3.8 */
FGAPI int FGAPIENTRY glutBitmapLength( void* font, const unsigned char* string );
FGAPI int FGAPIENTRY glutStrokeLength( void* font, const unsigned char* string );
FGAPI GLfloat FGAPIENTRY glutStrokeLengthf( void* font, const unsigned char *string ); /* GLUT 3.8 */
/*
* Geometry functions, see fg_geometry.c
*/
FGAPI void FGAPIENTRY glutWireCube( double size );
FGAPI void FGAPIENTRY glutSolidCube( double size );
FGAPI void FGAPIENTRY glutWireSphere( double radius, GLint slices, GLint stacks );
FGAPI void FGAPIENTRY glutSolidSphere( double radius, GLint slices, GLint stacks );
FGAPI void FGAPIENTRY glutWireCone( double base, double height, GLint slices, GLint stacks );
FGAPI void FGAPIENTRY glutSolidCone( double base, double height, GLint slices, GLint stacks );
FGAPI void FGAPIENTRY glutWireTorus( double innerRadius, double outerRadius, GLint sides, GLint rings );
FGAPI void FGAPIENTRY glutSolidTorus( double innerRadius, double outerRadius, GLint sides, GLint rings );
FGAPI void FGAPIENTRY glutWireDodecahedron( void );
FGAPI void FGAPIENTRY glutSolidDodecahedron( void );
FGAPI void FGAPIENTRY glutWireOctahedron( void );
FGAPI void FGAPIENTRY glutSolidOctahedron( void );
FGAPI void FGAPIENTRY glutWireTetrahedron( void );
FGAPI void FGAPIENTRY glutSolidTetrahedron( void );
FGAPI void FGAPIENTRY glutWireIcosahedron( void );
FGAPI void FGAPIENTRY glutSolidIcosahedron( void );
/*
* Teapot rendering functions, found in fg_teapot.c
* NB: front facing polygons have clockwise winding, not counter clockwise
*/
FGAPI void FGAPIENTRY glutWireTeapot( double size );
FGAPI void FGAPIENTRY glutSolidTeapot( double size );
/*
* Game mode functions, see fg_gamemode.c
*/
FGAPI void FGAPIENTRY glutGameModeString( const char* string );
FGAPI int FGAPIENTRY glutEnterGameMode( void );
FGAPI void FGAPIENTRY glutLeaveGameMode( void );
FGAPI int FGAPIENTRY glutGameModeGet( GLenum query );
/*
* Video resize functions, see fg_videoresize.c
*/
FGAPI int FGAPIENTRY glutVideoResizeGet( GLenum query );
FGAPI void FGAPIENTRY glutSetupVideoResizing( void );
FGAPI void FGAPIENTRY glutStopVideoResizing( void );
FGAPI void FGAPIENTRY glutVideoResize( int x, int y, int width, int height );
FGAPI void FGAPIENTRY glutVideoPan( int x, int y, int width, int height );
/*
* Colormap functions, see fg_misc.c
*/
FGAPI void FGAPIENTRY glutSetColor( int color, GLfloat red, GLfloat green, GLfloat blue );
FGAPI GLfloat FGAPIENTRY glutGetColor( int color, int component );
FGAPI void FGAPIENTRY glutCopyColormap( int window );
/*
* Misc keyboard and joystick functions, see fg_misc.c
*/
FGAPI void FGAPIENTRY glutIgnoreKeyRepeat( int ignore );
FGAPI void FGAPIENTRY glutSetKeyRepeat( int repeatMode );
FGAPI void FGAPIENTRY glutForceJoystickFunc( void );
/*
* Misc functions, see fg_misc.c
*/
FGAPI int FGAPIENTRY glutExtensionSupported( const char* extension );
FGAPI void FGAPIENTRY glutReportErrors( void );
/* Comment from glut.h of classic GLUT:
Win32 has an annoying issue where there are multiple C run-time
libraries (CRTs). If the executable is linked with a different CRT
from the GLUT DLL, the GLUT DLL will not share the same CRT static
data seen by the executable. In particular, atexit callbacks registered
in the executable will not be called if GLUT calls its (different)
exit routine). GLUT is typically built with the
"/MD" option (the CRT with multithreading DLL support), but the Visual
C++ linker default is "/ML" (the single threaded CRT).
One workaround to this issue is requiring users to always link with
the same CRT as GLUT is compiled with. That requires users supply a
non-standard option. GLUT 3.7 has its own built-in workaround where
the executable's "exit" function pointer is covertly passed to GLUT.
GLUT then calls the executable's exit function pointer to ensure that
any "atexit" calls registered by the application are called if GLUT
needs to exit.
Note that the __glut*WithExit routines should NEVER be called directly.
To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */
/* to get the prototype for exit() */
#include <stdlib.h>
#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__)
FGAPI void FGAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int));
FGAPI int FGAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int));
FGAPI int FGAPIENTRY __glutCreateMenuWithExit(void (* func)(int), void (__cdecl *exitfunc)(int));
#ifndef FREEGLUT_BUILDING_LIB
#if defined(__GNUC__)
#define FGUNUSED __attribute__((unused))
#else
#define FGUNUSED
#endif
static void FGAPIENTRY FGUNUSED glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); }
#define glutInit glutInit_ATEXIT_HACK
static int FGAPIENTRY FGUNUSED glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); }
#define glutCreateWindow glutCreateWindow_ATEXIT_HACK
static int FGAPIENTRY FGUNUSED glutCreateMenu_ATEXIT_HACK(void (* func)(int)) { return __glutCreateMenuWithExit(func, exit); }
#define glutCreateMenu glutCreateMenu_ATEXIT_HACK
#endif
#endif
#ifdef __cplusplus
}
#endif
/*** END OF FILE ***/
#endif /* __FREEGLUT_STD_H__ */

View File

@ -1,21 +0,0 @@
#ifndef __GLUT_H__
#define __GLUT_H__
/*
* glut.h
*
* The freeglut library include file
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "freeglut_std.h"
/*** END OF FILE ***/
#endif /* __GLUT_H__ */

View File

@ -1,33 +0,0 @@
#include <stdio.h>
int a;
int b[1000000000000];
int x;
int main() {
b[3] = 12;
a = b[3];
printf("%d\r\n",a);
printf("%d\r\n",b[5]);
x = 0;
while(x < 500) {
b[x] = x + b[x - 1];
x = x + 1;
int tmp1;
tmp1 = b[x] - 2;
while(tmp1 < 30) {
int lol;
lol = 0;
while(lol < tmp1) {
lol = lol + 1;
printf("%d\r\n",lol);
}
tmp1 = tmp1 + 1;
}
}
return(0);
}

View File

@ -1,40 +0,0 @@
void :: glClear();
void :: glBegin();
void :: glVertex3f();
void :: glEnd();
void :: glFlush();
void :: glutInit();
void :: glutInitDisplayMode();
void :: glutInitWindowPosition();
void :: glutInitWindowSize();
void :: glutCreateWindow();
void :: glutDisplayFunc();
void :: glutMainLoop();
void :: display() {
glClear(16384);
glBegin(9);
glVertex3f(0, 0, 0);
glVertex3f(1, 0, 0);
glVertex3f(1, 1, 0);
glVertex3f(0, 1, 0);
glEnd();
glFlush();
}
int :: main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(0);
glutInitWindowSize(300, 300);
glutInitWindowPosition(100, 100);
glutCreateWindow("Hello");
glutDisplayFunc(display);
glutMainLoop();
return (0);
}

View File

@ -1 +0,0 @@
int :: printf(char* format);

View File

@ -1,6 +0,0 @@
import "tests/import/defs.eh"
int :: main() {
printf("tests\n");
return (0);
}

View File

@ -1,11 +0,0 @@
import "import/defs.eh"
int :: main() {
int x = 3, y = 14;
int z = 2 * x + y;
char* str = "Hello world";
printf("%s %d %d\n", str, x + y, z);
return (0);
}

View File

@ -1 +0,0 @@
int :: printf(char* fmt);

View File

@ -1,4 +1,4 @@
import "print.em" int :: printf(char* format);
int :: main () { int :: main () {
printf("%s\r\n", "hi there"); printf("%s\r\n", "hi there");

View File

@ -1,30 +0,0 @@
import "import/defs.eh"
long num[100];
int :: main() {
long i = 0;
long j = 0;
for (i = 0; i < 100; i++) {
num[i] = i + 1;
}
for (i = 1; (num[i] * num[i]) <= 100; i++) {
if (num[i] != 0) {
for (j = num[i] * num[i]; j <= 100; j = num[i] + j) {
num[j - 1] = 0;
}
}
}
printf("Finding primes 2..%d\n\n",100);
for (i = 1; i < 100; i++) {
if (num[i] != 0) {
printf("%d\t", num[i]);
}
}
printf("\n");
return (0);
}

View File

@ -1,14 +0,0 @@
struct a {
int x,
int y
};
int :: printf(char* fmt);
struct a str;
int :: main() {
str.y = 55;
printf("%d\n", str.y);
return (0);
}

View File

@ -1,23 +0,0 @@
int :: printf(char* fmt);
struct banana {
int x,
int y
};
struct banana bread;
struct banana* loaf;
int :: main() {
bread.y = 5;
loaf->y = 10;
printf("%d\n", bread.y);
printf("%d\n", loaf->y);
bread.x = 7;
printf("%d\n", bread.y + bread.x);
return (0);
}

View File

@ -1,25 +0,0 @@
import "import/defs.eh"
int stuff[] = { 5, 7, 9 };
int :: main() {
for (int x = 0; x < 5; x++) {
int y = 0;
switch(x) {
case 1: {
y = stuff[0];
break; }
case 2:
y = stuff[1];
break;
case 3:
y = stuff[2];
default:
y = 100;
}
printf("%d\n", y);
}
return 0;
}

View File

@ -1,5 +0,0 @@
class Test {
public static void main(String[] args) {
java.lang.System.out.println("hi");
}
}

View File

@ -1,21 +0,0 @@
int :: printf(char* format);
union fruit {
char cherry,
int apple,
int orange,
long banana
};
union fruit basket;
int :: main() {
basket.apple = 55;
printf("1 %d b\n", basket.cherry);
printf("2 %d a\n", basket.orange);
basket.orange = 100;
printf("3 %d c\n", basket.banana);
printf("4 %d d\n", basket.apple);
return (0);
}