Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Bird Programming Language: Part 3

, 1 Jan 2013 GPL3
A new general purpose language that aims to be fast, high level and simple to use.
Bird-noexe.zip
Bird
Archives
crt2.o
crtbegin.o
crtend.o
libadvapi32.a
libcomctl32.a
libcomdlg32.a
libgcc.a
libgdi32.a
libglu32.a
libkernel32.a
libmingw32.a
libmingwex.a
libmoldname.a
libmsvcrt.a
libopengl32.a
libshell32.a
libstdc++.a
libuser32.a
libwinmm.a
libwsock32.a
Libraries
BirdCore
Array.bird
BigInteger.bird
BinaryRW.bird
BirdCore.a
BirdCore.blib
CategoryData.dat
Console.bird
Convert.bird
Debug.bird
Entry.bird
Environment.bird
Exception.bird
Float.bird
LEB128.bird
Math.bird
Memory.bird
Object.bird
Random.bird
Reflection.bird
StandardC.bird
Stream.bird
String.bird
ToLowerData.dat
ToUpperData.dat
Types.bird
ValueType.bird
Win32.bird
x86Helper.bird
BlitzMax
.bmx
Launcher.bmx.gui.release.win32.x86.o
appstub.release.win32.x86.a
bank.release.win32.x86.a
bankstream.release.win32.x86.a
blitz.release.win32.x86.a
BlitzMax.a
BlitzMax.bird
BlitzMax.blib
d3d7max2d.release.win32.x86.a
d3d9max2d.release.win32.x86.a
directx.release.win32.x86.a
dxgraphics.release.win32.x86.a
event.release.win32.x86.a
filesystem.release.win32.x86.a
font.release.win32.x86.a
glgraphics.release.win32.x86.a
glmax2d.release.win32.x86.a
graphics.release.win32.x86.a
hook.release.win32.x86.a
keycodes.release.win32.x86.a
Launcher.bmx
libpng.release.win32.x86.a
linkedlist.release.win32.x86.a
math.release.win32.x86.a
max2d.release.win32.x86.a
opengl.release.win32.x86.a
pixmap.release.win32.x86.a
pngloader.release.win32.x86.a
polledinput.release.win32.x86.a
standardio.release.win32.x86.a
stdc.release.win32.x86.a
stream.release.win32.x86.a
system.release.win32.x86.a
textstream.release.win32.x86.a
win32.release.win32.x86.a
zlib.release.win32.x86.a
PrgLinec.bmx
Samples
Circles
Circles.bird
CppMain.bird
Fire
Fire.bird
Higher Order Functions
C#
Higher Order Functions.v11.suo
Properties
Test.bird
msvcrt.lib
Reflection
Reflection.bird
Squares
Squares.bird
Template
Template.bird
Source
Base
Bird.v11.suo
Expressions
Identifiers
Languages
NativeCode
Properties
Recognizers
Expressions
Scopes
x86
Thumbs.db
Bird.zip
crt2.o
crtbegin.o
crtend.o
libadvapi32.a
libcomctl32.a
libcomdlg32.a
libgcc.a
libgdi32.a
libglu32.a
libkernel32.a
libmingw32.a
libmingwex.a
libmoldname.a
libmsvcrt.a
libopengl32.a
libshell32.a
libstdc++.a
libuser32.a
libwinmm.a
libwsock32.a
Binaries
ar.exe
Bird.exe
fasm.exe
ld.exe
libiconv-2.dll
libintl-8.dll
Array.bird
BigInteger.bird
BinaryRW.bird
BirdCore.a
BirdCore.blib
CategoryData.dat
Console.bird
Convert.bird
Debug.bird
Entry.bird
Environment.bird
Exception.bird
Float.bird
LEB128.bird
Math.bird
Memory.bird
Object.bird
Random.bird
Reflection.bird
StandardC.bird
Stream.bird
String.bird
ToLowerData.dat
ToUpperData.dat
Types.bird
ValueType.bird
Win32.bird
x86Helper.bird
Launcher.bmx.gui.release.win32.x86.o
appstub.release.win32.x86.a
bank.release.win32.x86.a
bankstream.release.win32.x86.a
blitz.release.win32.x86.a
BlitzMax.a
BlitzMax.bird
BlitzMax.blib
d3d7max2d.release.win32.x86.a
d3d9max2d.release.win32.x86.a
directx.release.win32.x86.a
dxgraphics.release.win32.x86.a
event.release.win32.x86.a
filesystem.release.win32.x86.a
font.release.win32.x86.a
glgraphics.release.win32.x86.a
glmax2d.release.win32.x86.a
graphics.release.win32.x86.a
hook.release.win32.x86.a
keycodes.release.win32.x86.a
Launcher.bmx
libpng.release.win32.x86.a
linkedlist.release.win32.x86.a
math.release.win32.x86.a
max2d.release.win32.x86.a
opengl.release.win32.x86.a
pixmap.release.win32.x86.a
pngloader.release.win32.x86.a
polledinput.release.win32.x86.a
standardio.release.win32.x86.a
stdc.release.win32.x86.a
stream.release.win32.x86.a
system.release.win32.x86.a
textstream.release.win32.x86.a
win32.release.win32.x86.a
zlib.release.win32.x86.a
PrgLinec.bmx
PrgLinec.exe
Circles.bird
CppMain.bird
Fire.bird
Higher Order Functions.v11.suo
Test.bird
msvcrt.lib
Reflection.bird
Squares.bird
Template.bird
Bird.v11.suo
Thumbs.db
using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;
using System.Globalization;
using System.Reflection;
using System.Linq;

namespace Bird
{
	public enum OperatingSystem : byte
	{
		Windows,
		Linux,
		MacOSX,
	}

	public class MessageStringsException : Exception
	{
		public string _Message;

		public override string Message
		{
			get { return _Message; }
		}

		public MessageStringsException(string Message)
		{
			this._Message = Message;
		}
	}

	public class MessageStrings
	{
		public Dictionary<string, string> Strings;

		public string this[string Key]
		{
			get { return Strings[Key]; }
		}

		public MessageStrings()
		{
			Process(CultureInfo.CurrentCulture);
		}

		public void Read(CultureInfo Culture)
		{
			var Name = Culture.TwoLetterISOLanguageName;
			var f = "Messages." + Name + ".txt";
			if (!File.Exists(f))
			{
				f = "Messages.en.txt";
				if (!File.Exists(f))
					throw new MessageStringsException("Can't find message file");
			}

			Read(f);
		}

		public void Read(string FileName)
		{
			var Stream = File.OpenRead(FileName);
			Read(Stream);
			Stream.Dispose();
		}

		public void Read(Stream Stream)
		{
			var Reader = new StreamReader(Stream);
			Process(Reader.ReadToEnd());
			Reader.Dispose();
		}

		public void Process(CultureInfo Culture)
		{
			var f = "Messages_" + Culture.TwoLetterISOLanguageName;
			var Ret = Resource.ResourceManager.GetString(f);
			if (Ret == null && (Ret = Resource.ResourceManager.GetString("Messages_en")) == null)
				throw new MessageStringsException("Can't find message file");

			Process(Ret);
		}

		public void Process(string String)
		{
			Strings = new Dictionary<string, string>();
			var Start = 0;
			var LineIndex = 0;

			for (var i = 0; i < String.Length; i++)
			{
				var Chr = String[i];
				if (Chr == '\n')
				{
					LineIndex++;
					var Line = String.Substring(Start, i - Start).Trim();
					ProcessLine(Line, LineIndex);
					Start = i + 1;
				}
			}
		}

		public void ProcessLine(string Line, int LineIndex)
		{
			if (Line.Length == 0 || Line.StartsWith("//") || Line.StartsWith("'"))
				return;

			var Pos = Line.IndexOf('=');
			if (Pos == -1) throw new MessageStringsException("Missing '=' at line " + LineIndex);

			var Key = Line.Substring(0, Pos).Trim();
			var Value = Line.Substring(Pos + 1).Trim();
			if (Key.Length == 0 || Value.Length == 0)
				throw new MessageStringsException("Missing key or value at line " + LineIndex);

			if (Value.Length < 2 || Value[0] != '\"' || Value[Value.Length - 1] != '\"')
				throw new MessageStringsException("Invalid value at line " + LineIndex);
			else Value = Value.Substring(1, Value.Length - 2);

			Strings.Add(Key, Value);
		}
	}

	public enum MessageSeverity : byte
	{
		Error = 0,
		Warning = 1,
		Info = 2
	}

	public enum MessageId
	{
		UnknownError = 1000,
		NoMacro,
		NotValidName,
		WrongParamList,
		MacroAlreadyDefined,
		NoParamName,
		ParamCount,
		NoEndif,
		UnknownType,
		WrongDefinition,
		// ConstStringErr,
		ZNumErr,
		ConstNumErr,
		UnknownOp,
		CantCall,
		MustBeConst,
		CannotConvert,
		InvalidScopeIndent,
		UnknownId,
		OpsInGblScope,
		NotExpected,
		PreprocError,
		TypeNotSpecified,
		IdAlreadyDefined,
		DeficientExpr,
		DeficientDoWhile,
		LoopWithoutDo,
		CantOpApplied,
		CallingNotFunc,
		MissingParam,
		MissingThen,
		AsmNotRId,
		NotAllPathReturn,
		AssignRValue,
		UnknownCommand,
		ImplicitlyCast,
		ForToDownToUntil,
		NoForVar,
		MoreForVar,
		NoForInitValue,
		NeedThenElse,
		WrongSettings,
		EntryNotFound,
		EntryNotSpecified,
		ImpExpGlbScope,
		CannotConvertConst,
		UnassignedVar,
		AddressOfRValue,
		MustBeGlobal,
		Untyped,
		CannotDeclVar,
		CantOpApplied2,
		UnknownType2,
		SameEnumValue,
		DefFuncParamVal,
		UnBreakCountinueable,
		CaseWithoutSwitch,
		CaseSystaxErr,
		SwitchNoCaseDef,
		SwitchAlreadyHasDef,
		EnumValOverflow,
		LabelAlreadyDefined,
		UnknownLabel,
		ConstOutOfRange,
		ReadOnly,
		CallConvErr,
		UntypedFunction,
		CannotInherit,
		TypeCannotBeSpecified,
		NoConstructor,
		CantDeclare,
		Static,
		NonStatic,
		ExternNonMSCoff,
		FuncCannotHaveInnerScope,
		CannotGetSize,
		MacroWithoutValue,
		VarFuncRetType,
		NonStaticInStaticClass,
		//SealedErr,
		//StaticSealed,
		CannotInheritStatic,
		CannotInheritSealed,
		NoParamLessConstructor,
		HasntGotMembers,
		CycleInStructured,
		MustBeUnnamed,
		UnassignedVar2,
		CannotBeThisType,
		MustBeNamed,
		MustHaveInitVal,
		FileDoesntExists,
		CantLoadFile,
		EnumTypeError,
		CantBeConst,
		ConstsCantBeStatic,
		CantUseConstructors,
		CannotCalcConst,
		GuidCannotUsed,
		InvalidGuidFormat,
		SameOverloads,
		AmbiguousReference,
		MoreAccessModifier,
		CantAccessPrivate,
		CantAccessProtected,
		PrivateInOtherLib,
		ProtPrivInNonStructured,
		OverrideVirtual,
		StructorFuncModifier,
		VirtualAbstractContainer,
		NoOverridable,
		OverrideNonvirtual,
		PrivateVirtual,
		MustBeInteger,
		OverrideSealed,
		NobaseError,
		NobaseClassbase,
		ArrayLengthTooSmall,
		ArrayLengthTooBig,
		ArrayDifferentTypes,
		ArrayInvalidType,
		WithMustBeStructured,
		InvalidCast,
		CantAccessInternal,
		MissingTypeParams,
		ReinterpretSize,
		ArrayInvalidLength,
		CharInvalidLength,
		InvalidOp,
		ReturnTypeNotTuple,
		RetVarAlreadySpecified,
		CannotDeclFunc,
		CannotReturn,
		IncompatibleMods,
		AbstractInner,
		AbstractInNonAbstract,
		StaticCallAbstract,
		LessAccessable,
		StructParamLessCtor,
		InvalidNumberOfIds,
		ClassMustBeAbstract,
		MultipleRadix,
		InvalidEscapeSequence,
		//QuotationMark,
		InvalidAddressType,
		ExprVarDeclInitVal,
		NoPropertyGetter,
		NoPropertySetter,
		UnaccessableGetter,
		UnaccessableSetter,
		PropertyAccessLevel,
		ModifierCantBeUsed,
		ModifierCantBeUsed2,
		EntryMustBePublic,
		UnnamedIdentifier,
		AssemblyNotFound,
		ParamIsntOptional,
		CannotHaveInitVal,
		ParamAlreadySpecified,
		ParamNotSpecified,
		IdDescPtrFromLocal,
		ForInvalidTupleSize,
		ForInvalidOp,
		InvalidAlign,
		NotAlignedEnough,
		IndexOutOfRange,
		MissingPropertyIndices,
		ParamlessSelfIndexer,
		UnimplementedWithIndices,
		OperatorModifiers,
		UnknownOpFunc,
		CastOpInvalidTypes,
		NoncastOpInvalidTypes,
		ArrayInitializerLength,
		ArrayLengthNotSpecified,
		NoMatchingCommand,
		CannotLeaveFinally,
		MustBeType,
		MustBeClass,
		NoIdDataPointer,
		UnassignedReadonly,
		GenericParamCount,
		ParamArrayMustBeTheLast,
		UnnamedParamAfterNamed,
		CatchesAllException,
		NonGenericIdentifier,
        BaseIdNotImplemented,
		
		PreprocWarning = 2000,
		EmptyScope,
		SingleThread,
		AssignSameVar,
		UnreachableCode,
		UnusedId,
		CastToSameType,
		CmpSameVariable,
		AssignedButNeverUsed,
		ConstExpression,
        HidingRequired,
        HidingUnnecessary,

		NoMessage = 3000,
		PreprocInfo,
	}

	public class MessageList
	{
		public MessageStrings Strings;
		public List<string> Messages;
		public object LockObject;
		public bool CollectMessages = true;
#if DEBUG
		public bool ExceptionOnError = false;
#else
		public bool ExceptionOnError = false;
#endif

		public MessageList(MessageStrings Strings = null)
		{
			this.Strings = Strings;
			this.LockObject = new object();
		}

		public void Add(string Message, string Id)
		{
			Add(Id + ": " + Message + ".");
		}

		public void Add(string Message, string Id, string Extra)
		{
			Message = Id + ": " + Message + ": " + Extra + ".";
			Add(Message);
		}

		public void Add(string Message, string Id, string File, int Line, int Char, int Length)
		{
			var PosStr = File + ", " + Line + ", " + Char + ", " + Length;
			Message = Id + "(" + PosStr + "): " + Message + ".";
			Add(Message);
		}

		public void Add(string Message)
		{
			if (!CollectMessages) return;

			lock (LockObject)
			{
				if (Messages == null)
					Messages = new List<string>();

				Messages.Add(Message);
			}
		}

		public void Add(MessageId MessageId, CodeString Extra, params string[] Params)
		{
			if (MessageId == MessageId.NoMessage)
				throw new ArgumentOutOfRangeException("Invalid message", "Message");

			if (Strings == null)
				throw new InvalidOperationException("There's no instance of MessageStrings");

			var Severity = (MessageSeverity)((int)MessageId / 1000 - 1);
			var ErrId = Severity.ToString() + " " + ((int)MessageId).ToString();

			var Description = (string)null;
			if (MessageId != MessageId.PreprocError && MessageId != MessageId.PreprocInfo && MessageId != MessageId.PreprocWarning)
				Description = String.Format(Strings[MessageId.ToString()], Params);

			if (MessageId != Bird.MessageId.EntryNotFound && Severity == MessageSeverity.Error && ExceptionOnError)
				throw new ApplicationException(Description);

			if (Extra.File != null)
			{
				var File = "'" + Path.GetFileName(Extra.File.Path) + "'";
				var Line = Extra.File.GetLineCount(0, Extra.Index) - 1;
				var Char = Extra.Index - Extra.File.GetLinePosition(Line);

				if (Description == null) Description = Extra.ToString();
				Add(Description, ErrId, File, Line, Char, Extra.Length);
			}
			else if (Extra.IsValid)
			{
				Add(Description, ErrId, Extra.ToString());
			}
			else
			{
				Add(Description, ErrId);
			}
		}

		public void Add(MessageId MessageId, String Extra, params string[] Params)
		{
			Add(MessageId, new CodeString(Extra), Params);
		}

		public void Add(MessageId MessageId)
		{
			Add(MessageId, new CodeString());
		}

		public void Add(MessageList List)
		{
			if (!CollectMessages) return;

			lock (LockObject)
			{
				if (Messages == null)
					Messages = new List<string>();

				Messages.AddRange(List.Messages);
			}
		}

		public void WriteToConsole()
		{
			if (Messages != null)
			{
				for (var i = 0; i < Messages.Count; i++)
					Console.WriteLine(Messages[i]);
			}
		}
	}

	public enum ImageFormat : byte
	{
		GUI,
		Console,
		AsDLL,
		DLL,
		MSCoff,
	}

	[Flags]
	public enum CompilerStateFlags : byte
	{
		DebugMode = 1,
		RuntimeChecks = 2,
	}

	public class CompilerState
	{ 
		public DataList Data = new DataList();
		public CompilerStateFlags Flags;
		public BirdBuilder Builder;
		public MessageStrings Strings;
		public MessageList Messages;
		public OperatingSystem OperatingSystem = OperatingSystem.Windows;
		public ImageFormat Format = ImageFormat.GUI;
		public string CodeOutFile, LibOutFile;
		public Stream CodeOut, LibOut;
		public string AssemblyName = "Assembly";

		public GlobalContainer GlobalContainer;
		public IArchitecture Arch;
		public Language Language;

#if DEBUG
		public bool Parallel = false;
#else
		public bool Parallel = true;
#endif
		public string Entry;
		public CallingConvention DefaultCallConv = CallingConvention.BirdCall;
		public int TabSize = 4;

		public bool Compile(CodeFile[] CodeFiles, List<AssemblyPath> Assemblies = null, List<IncBinReference> IncBins = null)
		{
			Reset();
			InitializeScopes(CodeFiles);
			DefineMacroes();

			if (Assemblies != null)
			{
				var RetValue = true;
				for (var i = 0; i < Assemblies.Count; i++)
					if (GlobalContainer.GetLoadedAssembly(Assemblies[i].Name) == null)
					{
						if (GlobalContainer.LoadAssembly(Assemblies[i]) == null)
							RetValue = false;
					}

				if (!RetValue)
					return false;
			}

			if (IncBins != null)
			{
				var RetValue = true;
				for (var i = 0; i < IncBins.Count; i++)
				{
					var File = IncBins[i].File;
					var FileInfo = new FileInfo(File);

					if (!FileInfo.Exists)
					{
						Messages.Add(MessageId.FileDoesntExists, new CodeString(File));
						RetValue = false;
						continue;
					}

					var IncBin = new IncludedBinary(IncBins[i].Name, File, FileInfo.Length);
					GlobalContainer.IncludedBinaries.Add(IncBin);
				}

				if (!RetValue)
					return false;
			}

			GlobalContainer.SearchCommonIdentifiers();
			return Arch.Compile(this, CodeFiles);
		}

		void DefineMacroes()
		{
            var Preprocessor = GlobalContainer.Preprocessor;
            if (OperatingSystem == OperatingSystem.Windows) Preprocessor.Define("OPERATING_SYSTEM", "Windows");
            else if (OperatingSystem == OperatingSystem.Linux) Preprocessor.Define("OPERATING_SYSTEM", "Linux");
            else if (OperatingSystem == OperatingSystem.MacOSX) Preprocessor.Define("OPERATING_SYSTEM", "MacOSX");
			else throw new ApplicationException();
		}

		void InitializeScopes(CodeFile[] CodeFiles)
		{
			if (string.IsNullOrEmpty(AssemblyName))
				throw new InvalidOperationException("Assembly hasn't been set up");

			if (CodeOut == null || LibOut == null)
				throw new InvalidOperationException("Output streams haven't been set up");

			var Random = new Random();
			var Assembly = new Assembly(this, AssemblyName);
			Assembly.Random = Random.Next();

			GlobalContainer = new GlobalContainer(this);
			GlobalContainer.OutputAssembly = Assembly;
			
			for (var i = 0; i < CodeFiles.Length; i++)
			{
				var AssemblyScope = new AssemblyScope(GlobalContainer, Assembly, CodeFiles[i]);
				GlobalContainer.GlobalNamespace.AddScope(AssemblyScope);
				GlobalContainer.Children.Add(AssemblyScope);
			}

			GlobalContainer.GlobalNamespaceScope = new AssemblyScope(GlobalContainer, Assembly);
			GlobalContainer.GlobalNamespace.AddScope(GlobalContainer.GlobalNamespaceScope);
			GlobalContainer.Children.Add(GlobalContainer.GlobalNamespaceScope);
		}

		public CompilerState(BirdBuilder Builder, MessageStrings Strings, IArchitecture Arch, Language Language)
		{
			Messages = new MessageList(Strings);

			this.Builder = Builder;
			this.Arch = Arch;
			this.Language = Language;
			this.Strings = Strings;
		}

		public string GenerateName(Identifier Id)
		{
			if (Id == null)
				throw new ArgumentNullException("Id");

			var Out = (string)null;
			var Gens = Language.NameGenerators;
            for (var i = 0; i < Gens.Length; i++)
			{
				var Res = Gens[i].GenerateName(this, Id, ref Out);
				if (Res != SimpleRecResult.Unknown)
				{
					if (Res == SimpleRecResult.Succeeded)
					{
						if (string.IsNullOrEmpty(Out))
							throw new ApplicationException("Generated identifier name cannot be null or empty");

						return Out;
					}

					if (Res == SimpleRecResult.Failed)
						throw new ApplicationException("Failed to generate identifier name");
				}
			}

			throw new ApplicationException("None of the name generators can handle this identifier");
		}

		public void SetOutput(string CodeOut, string LibOut)
		{
			CodeOutFile = CodeOut = Path.GetFullPath(CodeOut);
			LibOutFile = LibOut = Path.GetFullPath(LibOut);

			this.CodeOut = new FileStream(CodeOut, FileMode.Create);
			this.LibOut = new FileStream(LibOut, FileMode.Create);
		}

		public void SetOutput(Stream CodeOut, Stream LibOut)
		{
			this.CodeOut = CodeOut;
			this.LibOut = LibOut;
		}

		public void DisposeOutput()
		{
			CodeOut.Dispose();
			LibOut.Dispose();
		}

		public int CalcPow2Size(int Size)
		{
			var M = Arch.MaxStructPow2Size;
			if (Size < M) return Helper.Pow2(Size);
			else if (Size % M != 0) return Size + (M - Size % M);
			else return Size;
		}

		public CompilerState(BirdBuilder Builder, IArchitecture Arch, Language Language)
			: this(Builder, new MessageStrings(), Arch, Language)
		{
		}

		public void Reset()
		{
			_AutoLabelIndex = 0;
		}

		int _AutoLabelIndex = 0;
		public int AutoLabel
		{
			get
			{
				if (!Parallel) _AutoLabelIndex++;
				else Interlocked.Increment(ref _AutoLabelIndex);
				return _AutoLabelIndex;
			}
		}

		public CodeString AutoVarName
		{
			get
			{
				return new CodeString(AutoLabel.ToString());
			}
		}

		public CodeString GetInnerScope(CodeString Code)
		{
			if (Language.InnerScopeRecognizer == null) return Code;
			return Language.InnerScopeRecognizer.GetInnerScope(this, Code);
		}

		public CodeString GetInnerScope(CodeString Code, CodeString Command, bool Warning = true)
		{
			var Inner = GetInnerScope(Code);
			if (!Inner.IsValid) return new CodeString();

			Inner = Inner.Trim();
			if (Inner.Length == 0 && Warning)
				Messages.Add(MessageId.EmptyScope, Command);

			return Inner;
		}

		public CodeString GetInnerScope(CodeString Code, int Position, bool Warning = true)
		{
			return GetInnerScope(Code.Substring(Position).Trim(), Code.Substring(0, Position).Trim(), Warning);
		}

		public FunctionParameter[] GetParameters(IdContainer Container, CodeString Parameters)
		{
			var DeclList = VarDeclarationList.Create(Container, Parameters);
			if (DeclList == null) return null;

			var RetValue = DeclList.ToFuncParams(new PluginForGlobals(Container), Mode: VarDeclConvMode.Normal);
			if (RetValue == null || RetValue.Contains(null)) return null;
			return RetValue;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

Share

About the Author

Dávid Kocsis
Student
Hungary Hungary
I've been programming for 8 years. My first big project was a remake of a nice bomberman game called Dyna Blaster. When i was little i played a lot with it. Now i'm working on a new programming language and code generator.
I would like to work with someone, so feel free to contact me about it.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141220.1 | Last Updated 1 Jan 2013
Article Copyright 2012 by Dávid Kocsis
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid