Compare commits
No commits in common. "master" and "dev-refactor" have entirely different histories.
master
...
dev-refact
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -1,14 +1,6 @@
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
.cache
|
|
||||||
|
|
||||||
out
|
out
|
||||||
bin
|
bin
|
||||||
|
|
||||||
build
|
|
||||||
Erythro
|
|
||||||
test
|
|
||||||
cmake-build-debug
|
|
||||||
|
|
||||||
*.s
|
|
||||||
*.o
|
|
|
@ -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)
|
|
20
build.json
20
build.json
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"name": "Erythro",
|
|
||||||
"author": "Curle",
|
|
||||||
|
|
||||||
"source": {
|
|
||||||
"src": [
|
|
||||||
"$root/src/*.c"
|
|
||||||
],
|
|
||||||
"inc": [
|
|
||||||
"$root/include/"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
"build": {
|
|
||||||
"compile": [
|
|
||||||
"-g -I$inc",
|
|
||||||
"$src"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
353
include/Defs.h
353
include/Defs.h
|
@ -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);
|
137
plugins/c.js
137
plugins/c.js
|
@ -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
|
@ -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)
|
||||||
|
|
172
src/Dump.c
172
src/Dump.c
|
@ -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);
|
||||||
|
|
95
src/Errors.c
95
src/Errors.c
|
@ -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);
|
|
||||||
}
|
|
135
src/Importer.c
135
src/Importer.c
|
@ -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();
|
|
||||||
|
|
||||||
}
|
|
135
src/Lexer.c
135
src/Lexer.c
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
161
src/Main.c
161
src/Main.c
|
@ -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);
|
||||||
|
|
240
src/Parser.c
240
src/Parser.c
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
129
src/Pointers.c
129
src/Pointers.c
|
@ -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;
|
|
||||||
}
|
|
1075
src/Statements.c
1075
src/Statements.c
File diff suppressed because it is too large
Load Diff
127
src/Symbols.c
127
src/Symbols.c
|
@ -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;
|
||||||
|
|
40
src/Types.c
40
src/Types.c
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
printf("%d\n", 55);
|
|
||||||
puts("more sup\n");
|
|
||||||
}
|
|
|
@ -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 = " ";
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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__ */
|
|
|
@ -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__ */
|
|
|
@ -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__ */
|
|
||||||
|
|
|
@ -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__ */
|
|
|
@ -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);
|
|
||||||
}
|
|
40
tests/gl.er
40
tests/gl.er
|
@ -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);
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
int :: printf(char* format);
|
|
|
@ -1,6 +0,0 @@
|
||||||
import "tests/import/defs.eh"
|
|
||||||
|
|
||||||
int :: main() {
|
|
||||||
printf("tests\n");
|
|
||||||
return (0);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
int :: printf(char* fmt);
|
|
|
@ -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");
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
class Test {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
java.lang.System.out.println("hi");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user