From 8ce7d5ad9aebaa9e2a9e40491e3232f7c12600c0 Mon Sep 17 00:00:00 2001 From: aNNiMON Date: Sat, 11 May 2024 18:42:44 +0300 Subject: [PATCH] Adapt to new version --- classes/bas.class.php | 356 ++++++++++++----------------- classes/lis.class.php | 514 ++++++++++++++++++++++++------------------ compile.php | 2 +- 3 files changed, 433 insertions(+), 439 deletions(-) diff --git a/classes/bas.class.php b/classes/bas.class.php index f91603f..064d860 100644 --- a/classes/bas.class.php +++ b/classes/bas.class.php @@ -1,13 +1,25 @@ decompile(); //$code - декомпилированный код BAS + echo $code; + ----------------------------------------------------------------- + $bas->obfuscation('newbas.bas'); //обфусцировать открытый BAS, и сохранить + его с именем newbas.bas */ class BAS { @@ -15,8 +27,6 @@ class BAS { public $file; public $data; - /* EXAMPLE, $bas->new BAS("Autorun.bas"); */ - function __construct($files) { $this->file = $files; $this->init(); @@ -26,199 +36,89 @@ class BAS { $this->data = file_get_contents($this->file); } - /* EXAMPLE, $output = $bas->decompile(); */ - function decompile() { $ops = array( - " STOP ", - " POP ", - " RETURN ", - " END ", - " NEW ", - " RUN ", - " DIR ", - " DEG ", - " RAD ", - " BYE ", - " GOTO ", - " GOSUB ", - " SLEEP ", - " PRINT ", - " REM ", - " DIM ", - " IF", - " THEN ", - " CLS ", - " PLOT ", - " DRAWLINE ", - " FILLRECT ", - " DRAWRECT ", - " FILLROUNDRECT ", - " DRAWROUNDRECT ", - " FILLARC ", - " DRAWARC ", - " DRAWSTRING ", - " SETCOLOR ", - " BLIT ", - " FOR ", - " TO ", - " STEP ", - " NEXT ", - " INPUT ", - " LIST ", - " ENTER ", - " LOAD ", - " SAVE ", - " DELETE ", - " EDIT ", - " TRAP ", - " OPEN ", - " CLOSE ", - " NOTE ", - " POINT ", - " PUT ", - " GET ", - " DATA ", - " RESTORE ", - " READ ", - "=", - "<>", - "<", - "<=", - ">", - ">=", - "(", - ")", - ",", - "+", - "-", - "-", - "*", - "/", - "^", - " BITAND ", - " BITOR ", - " BITXOR ", - " NOT ", - " AND ", - " OR ", - "SCREENWIDTH", - "SCREENHEIGHT", - " ISCOLOR ", - " NUMCOLORS ", - "STRINGWIDTH", - "STRINGHEIGHT", - "LEFT$", - "MID$", - "RIGHT$", - "CHR$", - "STR$", - "LEN", - "ASC", - "VAL", - " UP ", - " DOWN ", - " LEFT ", - " RIGHT ", - " FIRE ", - " GAMEA ", - " GAMEB ", - " GAMEC ", - " GAMED ", - " DAYS ", - " MILLISECONDS ", - " YEAR ", - " MONTH ", - " DAY ", - " HOUR ", - " MINUTE ", - " SECOND ", - " MILLISECOND ", - "RND", - " ERR ", - " FRE ", - "MOD", - "EDITFORM ", - "GAUGEFORM ", - "CHOICEFORM", - "DATEFORM", - "MESSAGEFORM", - "LOG", - "EXP", - "SQR", - "SIN", - "COS", - "TAN", - "ASIN", - "ACOS", - "ATAN", - "ABS", - "=", - "#", - " PRINT ", - " INPUT ", - ":", - " GELGRAB ", - " DRAWGEL ", - " SPRITEGEL ", - " SPRITEMOVE ", - " SPRITEHIT ", - "READDIR$", - "PROPERTY$", - " GELLOAD ", - " GELWIDTH", - " GELHEIGHT", - " PLAYWAV ", - " PLAYTONE ", - " INKEY", - "SELECT", - "ALERT ", - " SETFONT ", - " MENUADD ", - " MENUITEM", - " MENUREMOVE ", - " CALL ", - " ENDSUB " + " STOP ", " POP ", " RETURN ", " END ", " NEW ", " RUN ", " DIR ", " DEG ", " RAD ", " BYE ", " GOTO ", + " GOSUB ", " SLEEP ", " PRINT ", " REM ", " DIM ", " IF ", " THEN ", " CLS ", " PLOT ", " DRAWLINE ", + " FILLRECT ", " DRAWRECT ", " FILLROUNDRECT ", " DRAWROUNDRECT ", " FILLARC ", + " DRAWARC ", " DRAWSTRING ", " SETCOLOR ", " BLIT ", " FOR ", " TO ", " STEP ", " NEXT ", " INPUT ", + " LIST ", " ENTER ", " LOAD ", " SAVE ", " DELETE ", " EDIT ", " TRAP ", " OPEN ", " CLOSE ", + " NOTE ", " POINT ", " PUT ", " GET ", " DATA ", " RESTORE ", " READ ", "=", "<>", "<", "<=", + ">", ">=", "(", ")", ",", "+", "-", "-", "*", "/", "^", " BITAND ", " BITOR ", " BITXOR ", " NOT ", + " AND ", " OR ", "SCREENWIDTH", "SCREENHEIGHT", " ISCOLOR ", " NUMCOLORS ", "STRINGWIDTH", "STRINGHEIGHT", + "LEFT$", "MID$", "RIGHT$", "CHR$", "STR$", "LEN", "ASC", "VAL", " UP ", " DOWN ", " LEFT ", " RIGHT ", + " FIRE ", " GAMEA ", " GAMEB ", " GAMEC ", " GAMED ", " DAYS ", " MILLISECONDS ", + " YEAR ", " MONTH ", " DAY ", " HOUR ", " MINUTE ", " SECOND ", " MILLISECOND ", "RND", " ERR ", + " FRE ", "MOD", "EDITFORM ", "GAUGEFORM ", "CHOICEFORM", "DATEFORM", "MESSAGEFORM", + "LOG", "EXP", "SQR", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN", "ABS", "=", "#", " PRINT ", + " INPUT ", ":", " GELGRAB ", " DRAWGEL ", " SPRITEGEL ", " SPRITEMOVE ", " SPRITEHIT ", + "READDIR$", "PROPERTY$", " GELLOAD ", " GELWIDTH", " GELHEIGHT", " PLAYWAV ", " PLAYTONE ", + " INKEY", "SELECT", "ALERT ", " SETFONT ", " MENUADD ", " MENUITEM", " MENUREMOVE ", + " CALL ", " ENDSUB ", " REPAINT", "SENDSMS ", " RAND", " ALPHAGEL ", " COLORALPHAGEL ", " PLATFORMREQUEST ", " DELGE L", " DELSPRITE ", "MKDIR" ); - if ($this->readInt($this->data) != "4d420001") { - // $this->init(); + ///version of BAS + switch ($this->readInt($this->data)) { + case '4d420001': + $version = 1; + break; + case '4d420191': + $version = 2; + break; + default: + $version = 0; + break; + } + if ($version == 0) { return -1; } else { $isDIM = false; - $varnum = hexdec($this->readShort($this->data)); ///количество переменных + $varnum = hexdec($this->readShort($this->data)); ///number variable $varname = []; $main = ''; - //чтение имен переменных - for ($i = 0; $i < $varnum; $i++) { - $num = hexdec($this->readShort($this->data)); ///длина имени переменной + for ($i = 0; $i < $varnum; $i++) { //read variable name + $num = hexdec($this->readShort($this->data)); ///name length for ($ii = 0; $ii < $num; $ii++) { $varname[$i] = $varname[$i] ?? ''; $varname[$i] .= substr($this->data, 0, 1); $this->readByte($this->data); } - $this->readByte($this->data); + /// end read variable name + $this->readByte($this->data); // variable type } - ///echo $varname[0]; - $codeln = hexdec($this->readShort($this->data)); //длина остального кода + //float + if ($version == 2) { + $floatnum = hexdec($this->readShort($this->data)); + for ($i = 0; $i < $floatnum; $i++) { + $byte[3] = $this->readByte($this->data, false); + $byte[2] = $this->readByte($this->data, false); + $byte[1] = $this->readByte($this->data, false); + $byte[0] = $this->readByte($this->data, false); + $tfloat = unpack('f', $byte[0] . $byte[1] . $byte[2] . $byte[3]); //uncpack float + $float[$i] = round($tfloat[1], 7); + } + } + + $codeln = hexdec($this->readShort($this->data)); if ($codeln != strlen($this->data)) { $this->init(); return -2; } - //for($i=0; $i<$codeln; $i++) ///чтение кода + + ///read code while (strlen($this->data) > 0) { $line = ""; - $line .= hexdec($this->readShort($this->data)); //пишем номер строки - $lineS = hexdec($this->readByte($this->data)); //длина строки + $line .= hexdec($this->readShort($this->data)); //write number of line + $lineS = hexdec($this->readByte($this->data)); //length line $isl = 1; unset($lims); - for ($ii = 0; $ii < $lineS - 4; $ii++) { ///читаем операторы строки в массив + for ($ii = 0; $ii < $lineS - 4; $ii++) { ///read operators $lims[$ii] = $this->readByte($this->data); } - $cur = 0; //позиция чтения - while ($cur < count($lims)) { //декомпилятор + $cur = 0; //position of read + while ($cur < count($lims)) { //decompilation start $opType = $lims[$cur]; $cur++; - if (hexdec($opType) == 0xfc) { ///присваивание + if (hexdec($opType) == 0xfc) { /// variable $varNum = hexdec($lims[$cur]); $limsIndex = $cur - 2; @@ -227,37 +127,35 @@ class BAS { if ($isl == 1) { $line .= " " . $varname[$varNum]; - } else + } else { $line .= $varname[$varNum]; - - + } $cur++; - } else { ///оператор + } else { ///operator $isl = 0; switch (hexdec($opType)) { case 0x0e: - $line .= " REM \""; - $str = hexdec($lims[$cur]); ///длина + $line .= " REM "; + $str = hexdec($lims[$cur]); /// len $cur++; for ($i = 0; $i < $str; $i++) { $line .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur]))); $cur++; } - $line .= "\""; break; case 0xfd: $line .= "\""; - $str = hexdec($lims[$cur]); ///длина + $str = hexdec($lims[$cur]); $cur++; for ($i = 0; $i < $str; $i++) { - $line .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur]))); + $line .= str_replace('"', '\"', iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur])))); $cur++; } $line .= "\""; break; case 0x30: $line .= " DATA "; - $str = hexdec($lims[$cur]); ///длина + $str = hexdec($lims[$cur]); $cur++; for ($i = 0; $i < $str; $i++) { $line .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur]))); @@ -286,25 +184,29 @@ class BAS { $line .= (hexdec($lims[$cur]) * 16777216 + hexdec($lims[$cur + 1]) * 65536 + hexdec($lims[$cur + 2]) * 256 + hexdec($lims[$cur + 3])); $cur = $cur + 4; break; - case 0xfe: - (int) $exp = $this->tosbyte(hexdec($lims[$cur + 3])); - $m = (hexdec($lims[$cur]) * 65536 + hexdec($lims[$cur + 1]) * 256 + hexdec($lims[$cur + 2])) / 500000; - $e = 1; - if ($exp > 0) { - $d = 1; - for ($i = 0; $i < $exp; $i++) - $d = $d * 10; - $e = $d; + case 0xfe: //float + if ($version == 1) { + $exp = (int) $this->tosbyte(hexdec($lims[$cur + 3])); + $m = (hexdec($lims[$cur]) * 65536 + hexdec($lims[$cur + 1]) * 256 + hexdec($lims[$cur + 2])) / 500000; + $e = 1; + if ($exp > 0) { + $d = 1; + for ($i = 0; $i < $exp; $i++) + $d = $d * 10; + $e = $d; + } + if ($exp < 0) { + $d = 1; + for ($i = $exp; $i < 0; $i++) + $d = $d / 10; + $e = $d; + } + $line .= (float) ($m * $e); + $cur = $cur + 4; + } else { + $line .= $float[hexdec($lims[$cur])]; + $cur++; } - if ($exp < 0) { - $d = 1; - for ($i = $exp; $i < 0; $i++) - $d = $d / 10; - $e = $d; - } - $line .= (float) ($m * $e); - - $cur = $cur + 4; break; default: $line .= $ops[hexdec($opType)]; @@ -326,34 +228,54 @@ class BAS { } function obfuscation($name) { - if ($this->readInt($this->data) != "4d420001") { - /// $this->init(); + switch ($this->readInt($this->data)) { + case '4d420001': + $version = 1; + break; + case '4d420191': + $version = 2; + break; + default: + $version = 0; + break; + } + if ($version == 0) { return -1; } else { $main = ""; - $main .= pack('H*', "4d420001"); //writeHex - + if ($version == 1) + $main .= pack('H*', "4d420001"); //writeHex + else + $main .= pack('H*', "4d420191"); $varnum = hexdec($this->readShort($this->data)); $main .= pack('n*', $varnum); //writeShort - // $main.= $this->writeUTF("hello"); - /// echo hexdec($this->readShort($this->data)); for ($i = 0; $i < $varnum; $i++) { //пропуск переменных $this->readUTF($this->data); $main .= $this->writeUTF(" "); $main .= pack('H*', $this->readByte($this->data)); } + + if ($version == 2) { //пропуск float для MB191 + $floatnum = hexdec($this->readShort($this->data)); + $main .= pack('n*', $floatnum); + for ($i = 0; $i < $varnum; $i++) { + $main .= pack('H*', $this->readInt($this->data)); + } + } + + $leng = hexdec($this->readShort($this->data)); - $main .= pack('n*', $leng + 7); + if ($version == 1) + $main .= pack('n*', $leng + 7); + else + $main .= pack('n*', $leng + 1); for ($i = 0; $i < $leng; $i++) { $main .= pack('H*', $this->readByte($this->data)); } - $main .= pack('H*', "FFFF"); - file_put_contents($name, $main); } - $this->init(); return 0; } @@ -378,21 +300,21 @@ class BAS { return bin2hex(substr($text, 0, 2)); } - function readByte($text) { + function readByte($text, $dec = true) { $this->data = substr($text, 1, strlen($text)); - return bin2hex(substr($text, 0, 1)); + if ($dec) + return bin2hex(substr($text, 0, 1)); + else + return substr($text, 0, 1); } function readUTF() { - // $this->data = substr($text, 1, strlen($text)); - // return bin2hex(substr($text, 0, 1)); $to = hexdec($this->readShort($this->data)); $bombom = ""; while ($to <> 0) { $bombom .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($this->readByte($this->data)))); $to--; } - // $this->readByte($this->data); return $bombom; } diff --git a/classes/lis.class.php b/classes/lis.class.php index af40810..02ec45c 100644 --- a/classes/lis.class.php +++ b/classes/lis.class.php @@ -1,42 +1,55 @@ BAS для MobileBASIC - * *Автор - Андрей Рейгант (HoldFast) - * *http://mbteam.ru - * * +/* + * ************************************************************ + | Компилятор LIS=>BAS для MobileBASIC + | (с) Андрей Рейгант + | http://vk.com/holdfast + | http://mbteam.ru + * ************************************************************ + | Пример: + ------------------------------------------------------------- + * ** открыть исходный код MobileBASIC для компиляции в файл Autorun.bas + $lis = new LIS('10 SLEEP 5000', 'Autorun.bas'); + + | или $lis = new LIS(file_get_contents('code.lis'),'Autorun.bas'); + + * ** компилировать файл + $lis->compile(); + + * ************************************************************ */ class LIS { - public $data, $file, $save, $coderror, $bufbody, $buffer, $compile = false; - public $lines = ['']; - public $ltypes = ['']; + public $data, $file, $save, $coderror, $warning, $bufbody, $buffer, $compile = false; + public $lines = []; + public $ltypes = []; public $lexems = []; - public $vars = ['']; - public $vtypes = ['']; + public $vars = []; + public $vtypes = []; public $currLine; + public $float = array(); + public $ver = 1; //Version (1 - 1.8.2, 2 - 1.9.1) const INT = 0, FLOAT = 1, STR = 2; const Operator = 0, Integer = 1, Float = 2, String = 3, Variable = 4, Data = 5, ArrayByte = 6; - public $ops = array("STOP", "POP", "RETURN", "END", "NEW", "RUN", "DIR", "DEG", "RAD", "BYE", "GOTO", "GOSUB", "SLEEP", "PRINT", "REM", "DIM", "IF", "THEN", "CLS", "PLOT", "DRAWLINE", "FILLRECT", "DRAWRECT", "FILLROUNDRECT", "DRAWROUNDRECT", "FILLARC", "DRAWARC", "DRAWSTRING", "SETCOLOR", "BLIT", "FOR", "TO", "STEP", "NEXT", "INPUT", "LIST", "ENTER", "LOAD", "SAVE", "DELETE", "EDIT", "TRAP", "OPEN", "CLOSE", "NOTE", "POINT", "PUT", "GET", "DATA", "RESTORE", "READ", "=", "<>", "<", "<=", ">", ">=", "(", ")", ",", "+", "-", "-", "*", "/", "^", "BITAND", "BITOR", "BITXOR", "NOT", "AND", "OR", "SCREENWIDTH", "SCREENHEIGHT", "ISCOLOR", "NUMCOLORS", "STRINGWIDTH", "STRINGHEIGHT", "LEFT$", "MID$", "RIGHT$", "CHR$", "STR$", "LEN", "ASC", "VAL", "UP", "DOWN", "LEFT", "RIGHT", "FIRE", "GAMEA", "GAMEB", "GAMEC", "GAMED", "DAYS", "MILLISECONDS", "YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND", "MILLISECOND", "RND", "ERR", "FRE", "MOD", "EDITFORM", "GAUGEFORM", "CHOICEFORM", "DATEFORM", "MESSAGEFORM", "LOG", "EXP", "SQR", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN", "ABS", "=", "#", "PRINT", "INPUT", ":", "GELGRAB", "DRAWGEL", "SPRITEGEL", "SPRITEMOVE", "SPRITEHIT", "READDIR$", "PROPERTY$", "GELLOAD", "GELWIDTH", "GELHEIGHT", "PLAYWAV", "PLAYTONE", "INKEY", "SELECT", "ALERT", "SETFONT", "MENUADD", "MENUITEM", "MENUREMOVE", "CALL", "ENDSUB"); + public $ops = array("STOP", "POP", "RETURN", "END", "NEW", "RUN", "DIR", "DEG", "RAD", "BYE", "GOTO", "GOSUB", "SLEEP", "PRINT", "REM", "DIM", "IF", "THEN", "CLS", "PLOT", "DRAWLINE", "FILLRECT", "DRAWRECT", "FILLROUNDRECT", "DRAWROUNDRECT", "FILLARC", "DRAWARC", "DRAWSTRING", "SETCOLOR", "BLIT", "FOR", "TO", "STEP", "NEXT", "INPUT", "LIST", "ENTER", "LOAD", "SAVE", "DELETE", "EDIT", "TRAP", "OPEN", "CLOSE", "NOTE", "POINT", "PUT", "GET", "DATA", "RESTORE", "READ", "=", "<>", "<", "<=", ">", ">=", "(", ")", ",", "+", "-", "-", "*", "/", "^", "BITAND", "BITOR", "BITXOR", "NOT", "AND", "OR", "SCREENWIDTH", "SCREENHEIGHT", "ISCOLOR", "NUMCOLORS", "STRINGWIDTH", "STRINGHEIGHT", "LEFT$", "MID$", "RIGHT$", "CHR$", "STR$", "LEN", "ASC", "VAL", "UP", "DOWN", "LEFT", "RIGHT", "FIRE", "GAMEA", "GAMEB", "GAMEC", "GAMED", "DAYS", "MILLISECONDS", "YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND", "MILLISECOND", "RND", "ERR", "FRE", "MOD", "EDITFORM", "GAUGEFORM", "CHOICEFORM", "DATEFORM", "MESSAGEFORM", "LOG", "EXP", "SQR", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN", "ABS", "=", "#", "PRINT", "INPUT", ":", "GELGRAB", "DRAWGEL", "SPRITEGEL", "SPRITEMOVE", "SPRITEHIT", "READDIR$", "PROPERTY$", "GELLOAD", "GELWIDTH", "GELHEIGHT", "PLAYWAV", "PLAYTONE", "INKEY", "SELECT", "ALERT", "SETFONT", "MENUADD", "MENUITEM", "MENUREMOVE", "CALL", "ENDSUB", "REPAINT", "SENDSMS", "RAND", "ALPHAGEL", "COLORALPHAGEL", "PLATFORMREQUEST", "DELGEL", "DELSPRITE", "MKDIR"); public $keywords = array("STOP", "POP", "RETURN", "END", "RUN", "DIR", "DEG", "RAD", "BYE", "CLS", "ENDSUB"); - public $functions = array("SCREENHEIGHT", "SCREENWIDTH", "ISCOLOR", "NUMCOLORS", "STRINGWIDTH", "STRINGHEIGHT", "LEFT$", "MID$", "RIGHT$", "CHR$", "STR$", "LEN", "ASC", "VAL", "UP", "DOWN", "LEFT", "RIGHT", "FIRE", "GAMEA", "GAMEB", "GAMEC", "GAMED", "DAYS", "MILLISECONDS", "YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND", "MILLISECOND", "RND", "ERR", "FRE", "MOD", "EDITFORM", "GAUGEFORM", "CHOICEFORM", "DATEFORM", "MESSAGEFORM", "LOG", "EXP", "SQR", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN", "ABS", "SPRITEHIT", "READDIR$", "PROPERTY$", "GELWIDTH", "GELHEIGHT", "INKEY", "SELECT", "MENUITEM", "MENUREMOVE"); + public $functions = array("NEW", "GOTO", "GOSUB", "SLEEP", "PRINT", "REM", "DIM", "IF", "THEN", "PLOT", "DRAWLINE", "FILLRECT", "DRAWRECT", "FILLROUNDRECT", "DRAWROUNDRECT", "FILLARC", "DRAWARC", "DRAWSTRING", "SETCOLOR", "BLIT", "FOR", "TO", "STEP", "NEXT", "INPUT", "LIST", "ENTER", "LOAD", "SAVE", "DELETE", "EDIT", "TRAP", "OPEN", "CLOSE", "NOTE", "POINT", "PUT", "GET", "DATA", "RESTORE", "READ", "BITAND", "BITOR", "BITXOR", "NOT", "AND", "OR", "SCREENWIDTH", "SCREENHEIGHT", "ISCOLOR", "NUMCOLORS", "STRINGWIDTH", "STRINGHEIGHT", "LEFT$", "MID$", "RIGHT$", "CHR$", "STR$", "LEN", "ASC", "VAL", "UP", "DOWN", "LEFT", "RIGHT", "FIRE", "GAMEA", "GAMEB", "GAMEC", "GAMED", "DAYS", "MILLISECONDS", "YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND", "MILLISECOND", "RND", "ERR", "FRE", "MOD", "EDITFORM", "GAUGEFORM", "CHOICEFORM", "DATEFORM", "MESSAGEFORM", "LOG", "EXP", "SQR", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN", "ABS", "=", "#", "PRINT", "INPUT", ":", "GELGRAB", "DRAWGEL", "SPRITEGEL", "SPRITEMOVE", "SPRITEHIT", "READDIR$", "PROPERTY$", "GELLOAD", "GELWIDTH", "GELHEIGHT", "PLAYWAV", "PLAYTONE", "INKEY", "SELECT", "ALERT", "SETFONT", "MENUADD", "MENUITEM", "MENUREMOVE", "CALL", "SENDSMS", "RAND", "ALPHAGEL", "COLORALPHAGEL", "PLATFORMREQUEST", "DELGEL", "DELSPRITE", "MKDIR"); + public $func191 = array("REPAINT", "SENDSMS", "RAND", "ALPHAGEL", "COLORALPHAGEL", "PLATFORMREQUEST", "DELGEL", "DELSPRITE", "MKDIR"); - function __construct($name, $newname) { + function __construct($name, $newname, $v = 1) { $this->file = $name; $this->save = $newname; - } - - function init() { - $this->data = file_get_contents($this->file); + if ($v > 0 && $v < 3) + $this->ver = $v; } function compile() { if (!$this->compile) { - $this->init(); $string = explode("\n", $this->data); - for ($i = 0; $i < count($string); $i++) { if (trim($string[$i]) != "") { $this->lines[] = trim($string[$i]); @@ -45,17 +58,18 @@ class LIS { $this->analize(); if ($this->coderror != "") - return $this->coderror; + return array("error", $this->coderror); $this->compileCode(); file_put_contents($this->save, $this->buffer); $this->compile = true; + if ($this->warning != "") + return array("warning", $this->warning); } } function analize() { - $this->currLine = 1; - - for ($i = 1; $i < count($this->lines); $i++) { + $this->currLine = 0; + for ($i = 0; $i < count($this->lines); $i++) { $this->analizeLine($this->lines[$i]); $this->check($this->currLine); $this->currLine++; @@ -65,20 +79,19 @@ class LIS { } function check($lineNum) { - - // for($i=0; $ilexems[$lineNum]); $i++){ - // echo $this->lexems[$lineNum][$i]; - //} - // echo "\n"; - $bracketCount = 0; if ($this->ltypes[$lineNum][0] != self::Integer) { - $this->coderror = "Invalid line number [" . $this->lexems[$lineNum][0] . "] "; - // return; + $this->error("Invalid line number [" . $this->lexems[$lineNum][0] . "] "); } + if ($this->ltypes[$lineNum][1] == self::Variable) { + if (!in_array($this->lexems[$lineNum][2], $this->ops)) { + $this->error("Error function [" . $this->lexems[$lineNum][1] . "] on line " . $this->lexems[$lineNum][0]); + } + } + if (strlen($this->lexems[$lineNum][1]) == 0) + $this->error("Error at line[" . $this->lexems[$lineNum][0] . "] "); for ($i = 0; $i < count($this->lexems[$lineNum]); $i++) { - if ($this->lexems[$lineNum][$i] == "(") $bracketCount++; if ($this->lexems[$lineNum][$i] == ")") @@ -87,44 +100,75 @@ class LIS { for ($ii = 0; $ii < count($this->lexems[$lineNum]); $ii++) { $i = $ii; + + if ($this->lexems[$lineNum][$ii] == ">" && $this->lexems[$lineNum][$ii + 1] == "=") { + $this->lexems[$lineNum][$ii] = '>='; + $this->lexems[$lineNum][$ii + 1] = ''; + $this->ltype[$lineNum][$ii + 1] = ''; + } elseif ($this->lexems[$lineNum][$ii] == "<" && $this->lexems[$lineNum][$ii + 1] == "=") { + $this->lexems[$lineNum][$ii] = '<='; + $this->lexems[$lineNum][$ii + 1] = ''; + $this->ltype[$lineNum][$ii + 1] = ''; + } elseif ($this->lexems[$lineNum][$ii] == "<" && $this->lexems[$lineNum][$ii + 1] == ">") { + $this->lexems[$lineNum][$ii] = '<>'; + $this->lexems[$lineNum][$ii + 1] = ''; + $this->ltype[$lineNum][$ii + 1] = ''; + } + + if ($this->ltypes[$lineNum][$i] == Variable) { + if ($this->lexems[$lineNum][$i - 1] == '$' || $this->lexems[$lineNum][$i - 1] == '%') + $this->error("Uncorrect variable name [" . $this->lexems[$lineNum][$i] . "] on line " . $this->lexems[$lineNum][0]);; + } + if ($this->lexems[$lineNum][$i] == "=") { + if (mb_strlen($this->lexems[$lineNum][$i + 1]) < 1) + $this->error("Null after [" . $this->lexems[$lineNum][$i] . "] on line " . $this->lexems[$lineNum][0]); + } if ($this->ltypes[$lineNum][$i] == self::Operator) { - if (in_array($this->lexems[$lineNum][$i], $this->keywords)) { - if (!($i == count($this->lexems[$lineNum]) - 1 || $this->lexems[$lineNum][$i + 1] == ":")) - $this->coderror = "Operator must have 0 arguments [" . $this->lexems[$lineNum][$i] . "] on line " . $this->lexems[$lineNum][0]; - return; - } elseif (in_array($this->lexems[$lineNum][$i], $this->functions)) { - if ($i == count($this->lexems[$lineNum]) - 1 || $this->lexems[$lineNum][$i + 1] != "(") - $this->coderror = "Error function [" . $this->lexems[$lineNum][$i] . "] on line " . $this->lexems[$lineNum][0]; - return; - } elseif (!in_array($this->lexems[$lineNum][$i], $this->functions) && mb_strlen($this->lexems[$lineNum][$i]) > 1) { - if ($i == count($this->lexems[$lineNum]) - 1 || $this->lexems[$lineNum][$i + 1] == ":") { - $this->coderror = "Operator must have arguments [" . $this->lexems[$lineNum][$i] . "]"; - return; - } elseif ($this->lexems[$lineNum][$i + 1] == "(" && $this->lexems[$lineNum][$i] != "TO" && $this->lexems[$lineNum][$i] != "STEP") { - $this->coderror = "Not an operator [" . $this->lexems[$lineNum][$i] . "]"; - return; - } - } - - - if ($this->lexems[$lineNum][$i] == "DIM") { - $this->lexems[$lineNum][$i + 2] = ""; - $this->ltypes[$lineNum][$i + 2] = self::ArrayByte; - } - - if ($i < count($this->ltypes[$lineNum]) - 1) - if ($this->ltypes[$lineNum][$i] == self::Variable && $this->lexems[$lineNum][$i + 1] == "(") { { + if ($this->ver == 1 && in_array($this->lexems[$lineNum][$i], $this->func191)) { + if ($this->lexems[$lineNum][$i] != "REPAINT") + $this->error("Operator [" . $this->lexems[$lineNum][$i] . "] is not supported in MobileBASIC 1.8.6 on line " . $this->lexems[$lineNum][0]); else { + $this->warn("Operator [REPAINT] not support in MobileBASIC 1.8.6, this operator will removed from code. Select 1.9.1 version of basic to use operator REPAINT"); + if ($this->lexems[$lineNum][$i - 1] == ":") { + $this->lexems[$lineNum][$i] = ""; + $this->lexems[$lineNum][$i - 1] = ""; + } elseif ($this->lexems[$lineNum][$i + 1] = ":") { + $this->lexems[$lineNum][$i] = ""; $this->lexems[$lineNum][$i + 1] = ""; - $this->ltypes[$lineNum][$i + 1] = self::ArrayByte; } + else + $this->lexems[$lineNum] = ""; } + } elseif (in_array($this->lexems[$lineNum][$i], $this->keywords)) { + if (!($i == count($this->lexems[$lineNum]) - 1 || $this->lexems[$lineNum][$i + 1] == ":")) + $this->error("Operator must have 0 arguments [" . $this->lexems[$lineNum][$i] . "] on line " . $this->lexems[$lineNum][0]); + } + elseif (in_array($this->lexems[$lineNum][$i], $this->functions)) { + if ($i == count($this->lexems[$lineNum]) - 1 || $this->lexems[$lineNum][$i + 1] == ":" + || $this->lexems[$lineNum][$i + 1] != "(" && $this->lexems[$lineNum][$i + 1] != ":" + && mb_strlen($this->lexems[$lineNum][$i + 1]) < 1) + $this->error("Error function [" . $this->lexems[$lineNum][$i] . "] on line " . $this->lexems[$lineNum][0]); + } + elseif (!in_array($this->lexems[$lineNum][$i], $this->functions) && mb_strlen($this->lexems[$lineNum][$i]) > 1) { + if ($i == count($this->lexems[$lineNum]) - 1 || $this->lexems[$lineNum][$i + 1] == ":") { + $this->error("Operator must have arguments [" . $this->lexems[$lineNum][$i] . "] on line " . $this->lexems[$lineNum][0]); + } elseif ($this->lexems[$lineNum][$i + 1] == "(" && $this->lexems[$lineNum][$i] != "TO" && $this->lexems[$lineNum][$i] != "STEP") { + $this->error("Not an operator [" . $this->lexems[$lineNum][$i] . "] on line " . $this->lexems[$lineNum][0]); + } + } + if ($this->lexems[$lineNum][$i] == "DIM") { + array_splice($this->lexems[$lineNum], $i + 2, 0, ""); + array_splice($this->ltypes[$lineNum], $i + 2, 0, self::ArrayByte); + } + } elseif ($this->ltypes[$lineNum][$i] == self::Variable && $this->lexems[$lineNum][$i + 1] == "(") { + array_splice($this->lexems[$lineNum], $i + 1, 0, ""); + array_splice($this->ltypes[$lineNum], $i + 1, 0, self::ArrayByte); } } if ($bracketCount != 0) { - $this->coderror = "Error: any brakets no open/close"; + $this->error("Error: Some bracket not opened/closed on line " . $this->lexems[$lineNum][0]); return; } } @@ -170,16 +214,11 @@ class LIS { if ($startPos >= mb_strlen($line)) break; } - - - $op = mb_strtoupper($op); $this->lexems[$this->currLine][] = $op; // echo "лан, не урчи"; - $isData = false; $data = ""; - if ($op == "DATA" || $op == "REM") { $isData = true; $startPos++; @@ -189,18 +228,10 @@ class LIS { } $this->lexems[$this->currLine][] = $data; } - if (!in_array($op, $this->ops)) { if (!in_array($op, $this->vars)) $this->vars[] = $op; - if ($this->endWith($op, "$")) { - $this->vtypes[] = self::STR; - } elseif ($this->endWith($op, "%")) { - $this->vtypes[] = self::INT; - } else - $this->vtypes[] = self::FLOAT; $this->ltypes[$this->currLine][] = self::Variable; - // } } else { $this->ltypes[$this->currLine][] = self::Operator; if ($isData) { @@ -212,15 +243,15 @@ class LIS { //STRING elseif (mb_substr($line, $startPos, 1) == '"') { $startPos++; - while (!(mb_substr($line, $startPos, 1) == '"')) { - $op .= mb_substr($line, $startPos, 1); + while (!(mb_substr($line, $startPos, 1) == '"') || (mb_substr($line, $startPos - 1, 1) == '\\')) { + if ((mb_substr($line, $startPos, 1)) != '\\') + $op .= mb_substr($line, $startPos, 1); $startPos++; if ($startPos >= mb_strlen($line)) { - $this->coderror = "Error complie: Not forund close \""; + $this->coderror = "Error complie: Not found close \" on line " . $this->lexems[$this->currLine][0]; break; } } - $startPos++; $this->lexems[$this->currLine][] = '"' . $op . '"'; $this->ltypes[$this->currLine][] = self::String; @@ -257,9 +288,12 @@ class LIS { if (!$error) { $this->lexems[$this->currLine][] = $op; - if ($containPoint) + if ($containPoint) { $this->ltypes[$this->currLine][] = self::Float; - else + if (!in_array($op, $this->float)) { + $this->float[] = $op; + } + } else $this->ltypes[$this->currLine][] = self::Integer; } } @@ -275,27 +309,28 @@ class LIS { } else $startPos++; } - return $startPos - $initPos; } function compileHead() { $buf = ""; - $buf .= pack('H*', "4d420001"); - $buf .= pack('n*', count($this->vars) - 1); - for ($i = 1; $i < count($this->vars); $i++) { + if ($this->ver == 1) + $buf .= pack('H*', "4d420001"); + else + $buf .= pack('H*', "4d420191"); + $buf .= pack('n*', count($this->vars)); + for ($i = 0; $i < count($this->vars); $i++) { $buf .= $this->writeUTF($this->vars[$i]); - switch ($this->vtypes[$i]) { - case self::INT: - $buf .= pack('H*', "00"); + $type = substr($this->vars[$i], -1); + switch ($type) { + case '$': + $buf .= pack('H*', "02"); break; - - case self::FLOAT: + default: $buf .= pack('H*', "01"); break; - - case self::STR: - $buf .= pack('H*', "02"); + case '%': + $buf .= pack('H*', "00"); break; } } @@ -308,151 +343,188 @@ class LIS { $ltypes = $this->ltypes; $buf = ""; - for ($currLine = 1; $currLine < count($lexems) + 1; $currLine++) { + for ($currLine = 0; $currLine < count($lexems); $currLine++) { $line = ""; - $buf .= pack('n*', $lexems[$currLine][0]); - + $notnull = false; for ($currLex = 1; $currLex < count($lexems[$currLine]); $currLex++) { - /////Operator - - $ifStarted = false; - $forStarted = false; - if ($ltypes[$currLine][$currLex] == self::Operator) { - if (trim($lexems[$currLine][$currLex]) == "IF") { - $ifStarted = true; - } elseif (trim($lexems[$currLine][$currLex]) == "THEN") { - $ifStarted = false; - } elseif (trim($lexems[$currLine][$currLex]) == "FOR") { - $forStarted = true; - } - - for ($i = 0; $i < count($this->ops); $i++) { - if (trim($lexems[$currLine][$currLex]) == $this->ops[$i]) { - if (trim($lexems[$currLine][$currLex]) == "=") { - if ($ifStarted) { - $i = "33"; - } else if ($forStarted) { - $i = "7b"; - $forStarted = false; - } else { - $i = "f6"; - } - } else { - $i = dechex($i); - if (strlen($i) < 2) - $i = "0" . $i; - } - /// echo $i; - $line .= pack('H*', $i); - break; - } - } - } - /////Variable - if ($ltypes[$currLine][$currLex] == self::Variable) { - for ($i = 1; $i < count($this->vars); $i++) { - if (trim($lexems[$currLine][$currLex]) == trim($this->vars[$i])) { - $line .= pack('H*', "FC"); - $i = dechex($i - 1); - //echo $i; - if (strlen($i) < 2) - $i = "0" . $i; - $line .= pack('H*', $i); - break; - } - } - } - - if ($ltypes[$currLine][$currLex] == self::ArrayByte) { - $line .= pack('H*', "F7"); - } - - - if ($ltypes[$currLine][$currLex] == self::Integer) { - if (strlen($lexems[$currLine][$currLex]) > 5) - $ltypes[$currLine][$currLex] = self::Float; - else { - $val = intval($lexems[$currLine][$currLex]); - if ($val <= 127) { - $line .= pack('H*', "F8"); - $i = dechex($val); - if (strlen($i) < 2) - $i = "0" . $i; - $line .= pack('H*', $i); - } elseif ($val >= 128 && $val <= 255) { - $line .= pack('H*', "F9"); - $i = dechex($val); - if (strlen($i) < 2) - $i = "0" . $i; - $line .= pack('H*', $i); - } elseif ($val >= 256 && $val < 65536) { - $line .= pack('H*', "FA"); - $line .= pack('n*', $val); - } else { - $line .= pack('H*', "FB"); - // $line .= pack('I',$val); - $line .= pack('c', $this->shiftRight($val, 24) & 0xFF); - $line .= pack('c', $this->shiftRight($val, 16) & 0xFF); - $line .= pack('c', $this->shiftRight($val, 8) & 0xFF); - $line .= pack('c', $this->shiftRight($val, 0) & 0xFF); - } - } - } - ///// - - if ($ltypes[$currLine][$currLex] == self::String) { - $text = mb_substr($lexems[$currLine][$currLex], 1, mb_strlen($lexems[$currLine][$currLex]) - 2); - if (preg_match('//u', $text)) - $text = iconv("UTF-8", "WINDOWS-1251", $text); - $line .= pack('H*', "FD"); - $line .= $this->writeTEXT($text); - } - - if ($ltypes[$currLine][$currLex] == self::Data) { - $line .= $this->writeTEXT($lexems[$currLine][$currLex]); - } - - if ($ltypes[$currLine][$currLex] == self::Float) { - $line .= pack('H*', "FE"); - - $exp = 0x80; - - $num = doubleval($lexems[$currLine][$currLex]); - if ($num < 1) { - while ($num < 1) { - $num = $num * 10; - $exp--; - } - } else if ($num >= 10) { - while ($num >= 10) { - $num = $num / 10; - $exp++; - } - } - $radix = ($num * 500000); - - $line .= pack('c', $this->shiftRight($radix, 16) & 0xFF); - $line .= pack('c', $this->shiftRight($radix, 8) & 0xFF); - $line .= pack('c', $this->shiftRight($radix, 0) & 0xFF); - $line .= pack("c", $exp); + if ($lexems[$currLine][$currLex] != "") { + $notnull = true; + break; } } + if ($notnull) { + $buf .= pack('n*', $lexems[$currLine][0]); - $len = dechex(strlen($line) + 4); - if (mb_strlen($len) < 2) - $len = "0" . $len; - $buf .= pack('H*', $len) . $line . pack('H*', 'FF'); + for ($currLex = 1; $currLex < count($lexems[$currLine]); $currLex++) { + /////Operator + + $ifStarted = false; + $forStarted = false; + if ($ltypes[$currLine][$currLex] == self::Operator) { + if (trim($lexems[$currLine][$currLex]) == "IF") { + $ifStarted = true; + } elseif (trim($lexems[$currLine][$currLex]) == "THEN") { + $ifStarted = false; + } elseif (trim($lexems[$currLine][$currLex]) == "FOR") { + $forStarted = true; + } + + for ($i = 0; $i < count($this->ops); $i++) { + if (trim($lexems[$currLine][$currLex]) == $this->ops[$i]) { + if (trim($lexems[$currLine][$currLex]) == "=") { + if ($ifStarted) { + $i = "33"; + } else if ($forStarted) { + $i = "7b"; + $forStarted = false; + } else { + $i = "f6"; + } + } else { + $i = dechex($i); + if (strlen($i) < 2) + $i = "0" . $i; + } + if (mb_strtoupper($i) == "3D") { + if ($ltypes[$currLine][$currLex - 1] != Integer && $ltypes[$currLine][$currLex - 1] != Float && $ltypes[$currLine][$currLex - 1] != Variable && $lexems[$currLine][$currLex - 1] != ")") + $i = "3e"; + } + + $line .= pack('H*', $i); + break; + } + } + } + /////Variable + if ($ltypes[$currLine][$currLex] == self::Variable) { + for ($i = 0; $i < count($this->vars); $i++) { + if (trim($lexems[$currLine][$currLex]) == trim($this->vars[$i])) { + $line .= pack('H*', "FC"); + $i = dechex($i); + //echo $i; + if (strlen($i) < 2) + $i = "0" . $i; + $line .= pack('H*', $i); + break; + } + } + } + + if ($ltypes[$currLine][$currLex] == self::ArrayByte) { + $line .= pack('H*', "F7"); + } + + + if ($ltypes[$currLine][$currLex] == self::Integer) { + if (strlen($lexems[$currLine][$currLex]) > 5) + $ltypes[$currLine][$currLex] = self::Float; + else { + $val = intval($lexems[$currLine][$currLex]); + if ($val <= 127) { + $line .= pack('H*', "F8"); + $i = dechex($val); + if (strlen($i) < 2) + $i = "0" . $i; + $line .= pack('H*', $i); + } elseif ($val >= 128 && $val <= 255) { + $line .= pack('H*', "F9"); + $i = dechex($val); + if (strlen($i) < 2) + $i = "0" . $i; + $line .= pack('H*', $i); + } elseif ($val >= 256 && $val < 65536) { + $line .= pack('H*', "FA"); + $line .= pack('n*', $val); + } else { + $line .= pack('H*', "FB"); + $line .= pack('c', $this->shiftRight($val, 24) & 0xFF); + $line .= pack('c', $this->shiftRight($val, 16) & 0xFF); + $line .= pack('c', $this->shiftRight($val, 8) & 0xFF); + $line .= pack('c', $this->shiftRight($val, 0) & 0xFF); + } + } + } + ///// + + if ($ltypes[$currLine][$currLex] == self::String) { + $text = mb_substr($lexems[$currLine][$currLex], 1, mb_strlen($lexems[$currLine][$currLex]) - 2); + if (preg_match('//u', $text)) + $text = iconv("UTF-8", "WINDOWS-1251", $text); + $line .= pack('H*', "FD"); + $line .= $this->writeTEXT($text); + } + + if ($ltypes[$currLine][$currLex] == self::Data) { + $line .= $this->writeTEXT($lexems[$currLine][$currLex]); + } + + if ($ltypes[$currLine][$currLex] == self::Float) { + if ($this->ver == 1) { + $line .= pack('H*', "FE"); + + $exp = 0x80; + + $num = doubleval($lexems[$currLine][$currLex]); + if ($num < 1) { + while ($num < 1) { + $num = $num * 10; + $exp--; + } + } else if ($num >= 10) { + while ($num >= 10) { + $num = $num / 10; + $exp++; + } + } + $radix = ($num * 500000); + $line .= pack('c', $this->shiftRight($radix, 16) & 0xFF); + $line .= pack('c', $this->shiftRight($radix, 8) & 0xFF); + $line .= pack('c', $this->shiftRight($radix, 0) & 0xFF); + $line .= pack("c", $exp); + } else { + ///write float number + for ($i = 0; $i < count($this->float); $i++) { + if (trim($lexems[$currLine][$currLex]) == trim($this->float[$i])) { + //echo $lexems[$currLine][$currLex]; + //echo trim($this->float[$i]); + $line .= pack('H*', "FE"); + $i = dechex($i); + //echo $i; + if (strlen($i) < 2) + $i = "0" . $i; + //echo $i.' '; + $line .= pack('H*', $i); + break; + } + } + } + } + } + + $len = dechex(strlen($line) + 4); + if (mb_strlen($len) < 2) + $len = "0" . $len; + $buf .= pack('H*', $len) . $line . pack('H*', 'FF'); + } } $this->bufbody = $buf; $this->compileHead(); } + function error($text) { + if (empty($this->coderror)) + $this->coderror = $text; + } + + function warn($text) { + if (empty($this->warning)) + $this->warning = $text; + } + function writeUTF($text) { $pack = pack('n*', mb_strlen($text)); - $pack .= pack('a*', $text); - return $pack; } diff --git a/compile.php b/compile.php index 0988ccd..188f0b1 100644 --- a/compile.php +++ b/compile.php @@ -20,7 +20,7 @@ if (($_GET['compile'] ?? '') != 'yes'){ } else { if (is_uploaded_file($_FILES["lis"]["tmp_name"])) { $namebas = "bas".rand(1000,99999).".bas"; - $bas = new LIS($_FILES['lis']['tmp_name'], './tmp/'.$namebas); + $bas = new LIS(file_get_contents($_FILES['lis']['tmp_name']), './tmp/'.$namebas); $log = $bas->compile(); if ($log == '') { echo 'Файл успешно скомпилирован!
Скачать';