123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- ' Copyright (c) 2013-2019 Bruce A Henderson
- '
- ' Based on the public domain Monkey "trans" by Mark Sibly
- '
- ' This software is provided 'as-is', without any express or implied
- ' warranty. In no event will the authors be held liable for any damages
- ' arising from the use of this software.
- '
- ' Permission is granted to anyone to use this software for any purpose,
- ' including commercial applications, and to alter it and redistribute it
- ' freely, subject to the following restrictions:
- '
- ' 1. The origin of this software must not be misrepresented; you must not
- ' claim that you wrote the original software. If you use this software
- ' in a product, an acknowledgment in the product documentation would be
- ' appreciated but is not required.
- '
- ' 2. Altered source versions must be plainly marked as such, and must not be
- ' misrepresented as being the original software.
- '
- ' 3. This notice may not be removed or altered from any source
- ' distribution.
- '
- SuperStrict
- Import BRL.LinkedList
- Import BRL.Map
- Import BRL.FileSystem
- Import Pub.zlib
- Import BRL.Math
- Import "options.bmx"
- Import "base.stringhelper.bmx"
- Import "base64.bmx"
- Import "enums.c"
- ' debugging help
- Const DEBUG:Int = False
- Const ABORT_ON_NULL:Int = True
- Const PROFILER:Int = False
- Const DEBUGSTOP_ON_ERROR:Int = False
- Const SHOW_INTERNALERR_LOCATION:Int = True
- Global ENV_LANG$
- Global _errInfo$
- Global _errStack:TList = New TList
- ' bytes offset to the first field
- Global OBJECT_BASE_OFFSET:Int = 8
- ' 4 bytes on 32-bit, 8 bytes on 64-bit
- Global POINTER_SIZE:Int = 4
- Global _symbols$[]=[ "..","[]",":*",":/",":+",":-",":|",":&",":~~",":shr",":shl",":sar",":mod"]
- Global _symbols_map$[]=[ "..","[]","*=","/=","+=","-=","|=","&=","^=",">>=", "<<=",">>=","%=" ]
- Function PushErr( errInfo$ )
- _errStack.AddLast _errInfo
- _errInfo=errInfo
- End Function
- Function PopErr()
- _errInfo=String(_errStack.RemoveLast())
- End Function
- Function Err( err$ )
- If DEBUGSTOP_ON_ERROR Then
- DebugStop ' useful for debugging!
- End If
- Throw "Compile Error: "+err + "~n" + _errInfo + "~n"
- End Function
- Function Warn( err$ )
- 'If DEBUGSTOP_ON_ERROR Then
- ' DebugStop ' useful for debugging!
- 'End If
- Print "Compile Warning: "+err + "~n" + _errInfo + "~n"
- End Function
- Function FormatError:String(path:String, line:Int, char:Int)
- Return "[" + path + ";" + line + ";" + char + "]"
- End Function
- Function InternalErr(errorLocation:String)
- If DEBUGSTOP_ON_ERROR Then
- DebugStop ' useful for debugging!
- End If
- Local locationMsg:String
- If SHOW_INTERNALERR_LOCATION And errorLocation Then locationMsg = " in " + errorLocation
- Throw "Compile Error: Internal Error" + locationMsg + ".~nPlease report the issue, with an example if possible, to https://github.com/bmx-ng/bcc/issues/new~n" + _errInfo + "~n"
- End Function
- Function IsSpace:Int( ch:Int )
- Return ch<=Asc(" ") Or ch=$A0 ' NO-BREAK SPACE (U+00A0)
- End Function
- Function IsDigit:Int( ch:Int )
- Return ch>=Asc("0") And ch<=Asc("9")
- End Function
- Function IsAlpha:Int( ch:Int )
- Return (ch>=Asc("A") And ch<=Asc("Z")) Or (ch>=Asc("a") And ch<=Asc("z"))
- End Function
- Function IsBinDigit:Int( ch:Int )
- Return ch=Asc("0") Or ch=Asc("1")
- End Function
- Function IsHexDigit:Int( ch:Int )
- Return IsDigit(ch) Or (ch>=Asc("A") And ch<=Asc("F")) Or (ch>=Asc("a") And ch<=Asc("f"))
- End Function
- Function Todo()
- Err "TODO!"
- End Function
- Function IsStandardFunc:Int(func:String)
- func = func.ToLower()
-
- Global funcs:String = ";isalnum;isalpha;isascii;isblank;iscntrl;isdigit;isgraph;islower;isprint;ispunct;isspace;isupper;isxdigit;" + ..
- "strlen;_wgetenv;_wputenv;"
-
- Return funcs.Find(func) > 0
- End Function
- Function mapSymbol:String(sym:String)
- For Local i:Int = 0 Until _symbols.length
- If sym = _symbols[i] Then
- Return _symbols_map[i]
- End If
- Next
- Return sym
- End Function
- 'enquote depending on ENV_LANG
- '
- Function LangEnquote$( str$ )
- str=EscapeString(str)
- ' str=str.Replace( "~0","\0" ) 'Fix me?
- For Local i:Int=0 Until str.Length
- If str[i]>=32 And str[i]<128 Continue
- Local t$,n:Int=str[i]
- While n
- Local c:Int=(n&15)+48
- If c>=58 c:+97-58
- t=Chr( c )+t
- n=(n Shr 4) & $0fffffff
- Wend
- If Not t t="0"
- If ENV_LANG = "cpp" Then
- 'Case "cpp"
- t="~q~q\x"+t+"~q~q"
- Else
- t="\u"+("0000"+t)[-4..]
- End If
- str=str[..i]+t+str[i+1..]
- i:+t.Length-1
- Next
- str="~q"+str+"~q"
- If ENV_LANG="cpp" str="L"+str
- Return str
- End Function
- Function EscapeString$(str$)
- str=str.Replace( "\","\\" )
- str=str.Replace( "~q","\~q" )
- str=str.Replace( "~n","\n" )
- str=str.Replace( "~r","\r" )
- str=str.Replace( "~t","\t" )
- Return str
- End Function
- Function EscapeLines:String(str:String)
- str=str.Replace("~n", "Newline")
- Return str
- End Function
- Function BmxEnquote$( str$ )
- str=str.Replace( "~~","~~~~" )
- str=str.Replace( "~q","~~q" )
- str=str.Replace( "~n","~~n" )
- str=str.Replace( "~r","~~r" )
- str=str.Replace( "~t","~~t" )
- str=str.Replace( "~0","~~0" )
- str="~q"+str+"~q"
- Return str
- End Function
- Function BmxUnquote$( str$, unicodeConvert:Int = False )
- If str.length = 1 Or str[str.length - 1] <> Asc("~q") Then
- Err "Expecting expression but encountered malformed string literal"
- End If
- str=str[1..str.Length-1]
- If unicodeConvert Then
- Local pos:Int = str.Find("~~")
- While pos <> -1
- If pos + 1 < str.length Then
- If str[pos + 1] >= Asc("1") And str[pos + 1] <= Asc("9") Then
- Local p2:Int = str.Find("~~", pos + 1)
- If p2 <> -1 Then
- Local s:String = Chr(str[pos + 1.. p2].ToInt())
- str = str[..pos] + s + str[p2 + 1..]
- End If
- End If
- End If
-
- pos = str.Find("~~", pos + 1)
- Wend
- End If
- str=str.Replace( "~~~~","~~z" ) 'a bit dodgy - uses bad esc sequence ~z
- str=str.Replace( "~~q","~q" )
- str=str.Replace( "~~n","~n" )
- str=str.Replace( "~~r","~r" )
- str=str.Replace( "~~t","~t" )
- str=str.Replace( "~~0","~0" )
- str=str.Replace( "~~z","~~" )
- Return str
- End Function
- Type TStack Extends TList
- Method Push(obj:Object)
- AddFirst(obj)
- End Method
- Method Length:Int()
- Return count()
- End Method
-
- Method Get:Object(index:Int)
- Return ValueAtIndex(index)
- End Method
-
- Method Pop:Object()
- Return RemoveFirst()
- End Method
-
- End Type
- Type TStringList Extends TList
- Method Join:String(s:String)
- Local arr:String[] = New String[count()]
- Local index:Int
- For Local t:String = EachIn Self
- arr[index] = t
- index :+ 1
- Next
-
- Return s.Join(arr)
- End Method
- End Type
- Type TKeyValue
- Field key:Object
- Field value:Object
-
- Method Create:TKeyValue(key:Object,value:Object)
- Self.key = key
- Self.value = value
- Return Self
- End Method
-
- Method Compare:Int(other:Object)
- If Not TKeyValue(other) Return 0
- Return key.Compare(TKeyValue(other).key)
- End Method
-
- End Type
- Type TUnorderedMap
- Field list:TList = New TList
- Field map:TMap = New TMap
-
- Field valuesList:TList = New TList
- Method Insert( key:Object,value:Object )
- list.AddLAst(New TKeyValue.Create(key, value))
- valuesList.AddLast(value)
- map.Insert(key, value)
- End Method
-
- Method Keys:TList()
- Local klist:TList = New TList
- For Local kv:TKeyValue = EachIn list
- klist.AddLast(kv.key)
- Next
- Return klist
- End Method
-
- Method Values:TList()
- 'Local vlist:TList = New TList
- 'For Local kv:TKeyValue = EachIn list
- ' vlist.AddLast(kv.value)
- 'Next
- Return valuesList
- End Method
-
- Method Contains:Int( key:Object )
- Return map.Contains(key)
- End Method
-
- Method ValueForKey:Object( key:Object )
- Return map.ValueForKey(key)
- End Method
- End Type
- Function MakeKeywords:String()
- Local keywords:String
-
- keywords :+ "import brl.classes~n"
- keywords :+ "Asc%(v$)=~qbrl_blitz_keywords_asc~q~n"
- keywords :+ "Chr$(v%)=~qbrl_blitz_keywords_chr~q~n"
- keywords :+ "Len%(v:Object)=~qbrl_blitz_keywords_len~q~n"
- keywords :+ "IncbinPtr@*(v$)=~qbbIncbinPtr~q~n"
- keywords :+ "IncbinLen%(v$)=~qbbIncbinLen~q~n"
-
- Return keywords
- End Function
- Function FilePath:String(path:String)
- Local baseDir:String = ExtractDir(path)
- Local bmxDir:String = baseDir + "/.bmx"
-
- If FileType(bmxDir) <> FILETYPE_DIR Then
- Throw "Missing : " + bmxDir
- End If
-
- Return bmxDir
- End Function
- Function BuildHeaderName:String(path:String)
- If opt_buildtype = BUILDTYPE_MODULE Then
- path = opt_modulename + "_" + StripDir(path)
- Else
- Local dir:String = ExtractDir(path).ToLower().Replace("/.bmx","")
- dir = dir[dir.findLast("/") + 1..]
- If dir.EndsWith(".mod") Then
- dir = dir.Replace(".mod", "")
- End If
- Local file:String = StripDir(path).ToLower()
- path = dir + "_" + file
- End If
-
- Return TStringHelper.Sanitize(path, , True)
- End Function
- Rem
- bbdoc: Get the header file name from a given module ident, optionally with include path.
- End Rem
- Function ModuleHeaderFromIdent:String(ident:String, includePath:Int = False)
- Local ns:String = ident[..ident.find(".")]
- Local name:String = ident[ident.find(".") + 1..]
-
- Local file:String = name + ".bmx" + FileMung() + ".h"
-
- If includePath Then
- file = ns + ".mod/" + name + ".mod/.bmx/" + file
- End If
-
- Return file
- End Function
- Function HeaderFile:String(path:String, mung:String)
- Local fileDir:String = FilePath(path)
- Local file:String = StripDir(path)
-
- Return fileDir + "/" + file + mung + ".h"
- End Function
- Function OutputFilePath:String(path:String, mung:String, suffix:String, bmxDir:Int = False)
- Local fileDir:String = FilePath(path)
- If bmxDir Then
- fileDir :+ "/.bmx"
- End If
- Local file:String = StripDir(path)
-
- Return fileDir + "/" + file + mung + "." + suffix
- End Function
- Function FileMung:String(makeApp:Int = False)
- Local m:String = "."
-
- If makeApp Then
- Select opt_apptype
- Case APPTYPE_CONSOLE
- m :+ "console."
- Case APPTYPE_GUI
- m :+ "gui."
- End Select
- End If
-
- If opt_release Then
- m :+ "release"
- Else
- m :+ "debug"
- End If
-
- ' If opt_threaded Then
- ' m :+ ".mt"
- ' End If
-
- m :+ "." + opt_platform
-
- m :+ "." + opt_arch
-
- Return m
- End Function
- Function HeaderComment:String()
- ' TODO
- End Function
- Type TTemplateRecord
- Field start:Int
- Field file:String
- Field source:String
-
- Method Create:TTemplateRecord(start:Int, file:String, source:String)
- Self.start = start
- Self.file = file
- Self.source = source
- Return Self
- End Method
-
- Method ToString:String()
- Local s:Byte Ptr = source.ToUTF8String()
- ?Not bmxng
- Local slen:Int = strlen_(s)
- ?bmxng
- Local slen:UInt = strlen_(s)
- ?
- ?Not bmxng
- Local dlen:Int = slen + 12
- ?bmxng And (win32 Or ptr32)
- Local dlen:UInt = slen + 12
- ?bmxng And ptr64 And Not win32
- Local dlen:ULong = slen + 12
- ?
- Local data:Byte[dlen]
-
- compress2(data, dlen, s, slen, 9)
-
- MemFree(s)
-
- Local t:String = "{" + start +","+ slen +","+ LangEnquote(file) + ","
-
- t :+ LangEnquote(TBase64.Encode(data, Int(dlen), 0, TBase64.DONT_BREAK_LINES))
- Return t + "}"
- End Method
-
- Function Load:TTemplateRecord(start:Int, file:String, size:Int, source:String)
-
- ?Not bmxng
- Local dlen:Int = size + 1
- ?bmxng And (win32 Or ptr32)
- Local dlen:UInt = size + 1
- ?bmxng And ptr64 And Not win32
- Local dlen:ULong = size + 1
- ?
- Local data:Byte[dlen]
-
- Local s:Byte[] = TBase64.Decode(source)
- ?Not bmxng
- uncompress(data, dlen, s, s.length)
- ?bmxng
- uncompress(data, dlen, s, UInt(s.length))
- ?
- Return New TTemplateRecord.Create(start, file, String.FromUTF8String(data))
- End Function
- End Type
- Type TCallback
- Method Callback(obj:Object) Abstract
- End Type
- Extern
- Function strlen_:Int(s:Byte Ptr)="strlen"
- Function bmx_enum_next_power(char:Int, val:Long Var, ret:Long Var)
- End Extern
|