Adapt to new version
This commit is contained in:
parent
cb81c9b6ce
commit
8ce7d5ad9a
@ -1,13 +1,25 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/* CREATE BY HoldFast
|
/*
|
||||||
//Андрей Рейгант
|
* ****************************************************************
|
||||||
//MBTEAM.RU
|
CREATE BY HoldFast
|
||||||
|
Андрей Рейгант
|
||||||
|
http://vk.com/holdfast
|
||||||
|
MBTEAM.RU
|
||||||
|
* ****************************************************************
|
||||||
Коды ответов:
|
Коды ответов:
|
||||||
-1: неверный BAS-файЛ
|
-1: неверный BAS-файл
|
||||||
-2: файл нельзя декмопилировать, поскольку он обфусцирован
|
-2: файл нельзя декмопилировать, поскольку он обфусцирован
|
||||||
0: файл успешно обфусцирован
|
0: файл успешно обфусцирован
|
||||||
|
* ****************************************************************
|
||||||
|
Пример:
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
$bas = new BAS('Autorun.bas'); ///Открываем BAS
|
||||||
|
$code = $bas->decompile(); //$code - декомпилированный код BAS
|
||||||
|
echo $code;
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
$bas->obfuscation('newbas.bas'); //обфусцировать открытый BAS, и сохранить
|
||||||
|
его с именем newbas.bas
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class BAS {
|
class BAS {
|
||||||
@ -15,8 +27,6 @@ class BAS {
|
|||||||
public $file;
|
public $file;
|
||||||
public $data;
|
public $data;
|
||||||
|
|
||||||
/* EXAMPLE, $bas->new BAS("Autorun.bas"); */
|
|
||||||
|
|
||||||
function __construct($files) {
|
function __construct($files) {
|
||||||
$this->file = $files;
|
$this->file = $files;
|
||||||
$this->init();
|
$this->init();
|
||||||
@ -26,199 +36,89 @@ class BAS {
|
|||||||
$this->data = file_get_contents($this->file);
|
$this->data = file_get_contents($this->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EXAMPLE, $output = $bas->decompile(); */
|
|
||||||
|
|
||||||
function decompile() {
|
function decompile() {
|
||||||
$ops = array(
|
$ops = array(
|
||||||
" STOP ",
|
" STOP ", " POP ", " RETURN ", " END ", " NEW ", " RUN ", " DIR ", " DEG ", " RAD ", " BYE ", " GOTO ",
|
||||||
" POP ",
|
" GOSUB ", " SLEEP ", " PRINT ", " REM ", " DIM ", " IF ", " THEN ", " CLS ", " PLOT ", " DRAWLINE ",
|
||||||
" RETURN ",
|
" FILLRECT ", " DRAWRECT ", " FILLROUNDRECT ", " DRAWROUNDRECT ", " FILLARC ",
|
||||||
" END ",
|
" DRAWARC ", " DRAWSTRING ", " SETCOLOR ", " BLIT ", " FOR ", " TO ", " STEP ", " NEXT ", " INPUT ",
|
||||||
" NEW ",
|
" LIST ", " ENTER ", " LOAD ", " SAVE ", " DELETE ", " EDIT ", " TRAP ", " OPEN ", " CLOSE ",
|
||||||
" RUN ",
|
" NOTE ", " POINT ", " PUT ", " GET ", " DATA ", " RESTORE ", " READ ", "=", "<>", "<", "<=",
|
||||||
" DIR ",
|
">", ">=", "(", ")", ",", "+", "-", "-", "*", "/", "^", " BITAND ", " BITOR ", " BITXOR ", " NOT ",
|
||||||
" DEG ",
|
" AND ", " OR ", "SCREENWIDTH", "SCREENHEIGHT", " ISCOLOR ", " NUMCOLORS ", "STRINGWIDTH", "STRINGHEIGHT",
|
||||||
" RAD ",
|
"LEFT$", "MID$", "RIGHT$", "CHR$", "STR$", "LEN", "ASC", "VAL", " UP ", " DOWN ", " LEFT ", " RIGHT ",
|
||||||
" BYE ",
|
" FIRE ", " GAMEA ", " GAMEB ", " GAMEC ", " GAMED ", " DAYS ", " MILLISECONDS ",
|
||||||
" GOTO ",
|
" YEAR ", " MONTH ", " DAY ", " HOUR ", " MINUTE ", " SECOND ", " MILLISECOND ", "RND", " ERR ",
|
||||||
" GOSUB ",
|
" FRE ", "MOD", "EDITFORM ", "GAUGEFORM ", "CHOICEFORM", "DATEFORM", "MESSAGEFORM",
|
||||||
" SLEEP ",
|
"LOG", "EXP", "SQR", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN", "ABS", "=", "#", " PRINT ",
|
||||||
" PRINT ",
|
" INPUT ", ":", " GELGRAB ", " DRAWGEL ", " SPRITEGEL ", " SPRITEMOVE ", " SPRITEHIT ",
|
||||||
" REM ",
|
"READDIR$", "PROPERTY$", " GELLOAD ", " GELWIDTH", " GELHEIGHT", " PLAYWAV ", " PLAYTONE ",
|
||||||
" DIM ",
|
" INKEY", "SELECT", "ALERT ", " SETFONT ", " MENUADD ", " MENUITEM", " MENUREMOVE ",
|
||||||
" IF",
|
" CALL ", " ENDSUB ", " REPAINT", "SENDSMS ", " RAND", " ALPHAGEL ", " COLORALPHAGEL ", " PLATFORMREQUEST ", " DELGE L", " DELSPRITE ", "MKDIR"
|
||||||
" 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 "
|
|
||||||
);
|
);
|
||||||
if ($this->readInt($this->data) != "4d420001") {
|
///version of BAS
|
||||||
// $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;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
$isDIM = false;
|
$isDIM = false;
|
||||||
$varnum = hexdec($this->readShort($this->data)); ///количество переменных
|
$varnum = hexdec($this->readShort($this->data)); ///number variable
|
||||||
$varname = [];
|
$varname = [];
|
||||||
$main = '';
|
$main = '';
|
||||||
//чтение имен переменных
|
for ($i = 0; $i < $varnum; $i++) { //read variable name
|
||||||
for ($i = 0; $i < $varnum; $i++) {
|
$num = hexdec($this->readShort($this->data)); ///name length
|
||||||
$num = hexdec($this->readShort($this->data)); ///длина имени переменной
|
|
||||||
for ($ii = 0; $ii < $num; $ii++) {
|
for ($ii = 0; $ii < $num; $ii++) {
|
||||||
$varname[$i] = $varname[$i] ?? '';
|
$varname[$i] = $varname[$i] ?? '';
|
||||||
$varname[$i] .= substr($this->data, 0, 1);
|
$varname[$i] .= substr($this->data, 0, 1);
|
||||||
$this->readByte($this->data);
|
$this->readByte($this->data);
|
||||||
}
|
}
|
||||||
$this->readByte($this->data);
|
/// end read variable name
|
||||||
|
$this->readByte($this->data); // variable type
|
||||||
}
|
}
|
||||||
///echo $varname[0];
|
//float
|
||||||
$codeln = hexdec($this->readShort($this->data)); //длина остального кода
|
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)) {
|
if ($codeln != strlen($this->data)) {
|
||||||
$this->init();
|
$this->init();
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
//for($i=0; $i<$codeln; $i++) ///чтение кода
|
|
||||||
|
///read code
|
||||||
while (strlen($this->data) > 0) {
|
while (strlen($this->data) > 0) {
|
||||||
$line = "";
|
$line = "";
|
||||||
$line .= hexdec($this->readShort($this->data)); //пишем номер строки
|
$line .= hexdec($this->readShort($this->data)); //write number of line
|
||||||
$lineS = hexdec($this->readByte($this->data)); //длина строки
|
$lineS = hexdec($this->readByte($this->data)); //length line
|
||||||
$isl = 1;
|
$isl = 1;
|
||||||
unset($lims);
|
unset($lims);
|
||||||
for ($ii = 0; $ii < $lineS - 4; $ii++) { ///читаем операторы строки в массив
|
for ($ii = 0; $ii < $lineS - 4; $ii++) { ///read operators
|
||||||
$lims[$ii] = $this->readByte($this->data);
|
$lims[$ii] = $this->readByte($this->data);
|
||||||
}
|
}
|
||||||
$cur = 0; //позиция чтения
|
$cur = 0; //position of read
|
||||||
while ($cur < count($lims)) { //декомпилятор
|
while ($cur < count($lims)) { //decompilation start
|
||||||
$opType = $lims[$cur];
|
$opType = $lims[$cur];
|
||||||
$cur++;
|
$cur++;
|
||||||
if (hexdec($opType) == 0xfc) { ///присваивание
|
if (hexdec($opType) == 0xfc) { /// variable
|
||||||
$varNum = hexdec($lims[$cur]);
|
$varNum = hexdec($lims[$cur]);
|
||||||
|
|
||||||
$limsIndex = $cur - 2;
|
$limsIndex = $cur - 2;
|
||||||
@ -227,37 +127,35 @@ class BAS {
|
|||||||
|
|
||||||
if ($isl == 1) {
|
if ($isl == 1) {
|
||||||
$line .= " " . $varname[$varNum];
|
$line .= " " . $varname[$varNum];
|
||||||
} else
|
} else {
|
||||||
$line .= $varname[$varNum];
|
$line .= $varname[$varNum];
|
||||||
|
}
|
||||||
|
|
||||||
$cur++;
|
$cur++;
|
||||||
} else { ///оператор
|
} else { ///operator
|
||||||
$isl = 0;
|
$isl = 0;
|
||||||
switch (hexdec($opType)) {
|
switch (hexdec($opType)) {
|
||||||
case 0x0e:
|
case 0x0e:
|
||||||
$line .= " REM \"";
|
$line .= " REM ";
|
||||||
$str = hexdec($lims[$cur]); ///длина
|
$str = hexdec($lims[$cur]); /// len
|
||||||
$cur++;
|
$cur++;
|
||||||
for ($i = 0; $i < $str; $i++) {
|
for ($i = 0; $i < $str; $i++) {
|
||||||
$line .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur])));
|
$line .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur])));
|
||||||
$cur++;
|
$cur++;
|
||||||
}
|
}
|
||||||
$line .= "\"";
|
|
||||||
break;
|
break;
|
||||||
case 0xfd:
|
case 0xfd:
|
||||||
$line .= "\"";
|
$line .= "\"";
|
||||||
$str = hexdec($lims[$cur]); ///длина
|
$str = hexdec($lims[$cur]);
|
||||||
$cur++;
|
$cur++;
|
||||||
for ($i = 0; $i < $str; $i++) {
|
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++;
|
$cur++;
|
||||||
}
|
}
|
||||||
$line .= "\"";
|
$line .= "\"";
|
||||||
break;
|
break;
|
||||||
case 0x30:
|
case 0x30:
|
||||||
$line .= " DATA ";
|
$line .= " DATA ";
|
||||||
$str = hexdec($lims[$cur]); ///длина
|
$str = hexdec($lims[$cur]);
|
||||||
$cur++;
|
$cur++;
|
||||||
for ($i = 0; $i < $str; $i++) {
|
for ($i = 0; $i < $str; $i++) {
|
||||||
$line .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($lims[$cur])));
|
$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]));
|
$line .= (hexdec($lims[$cur]) * 16777216 + hexdec($lims[$cur + 1]) * 65536 + hexdec($lims[$cur + 2]) * 256 + hexdec($lims[$cur + 3]));
|
||||||
$cur = $cur + 4;
|
$cur = $cur + 4;
|
||||||
break;
|
break;
|
||||||
case 0xfe:
|
case 0xfe: //float
|
||||||
(int) $exp = $this->tosbyte(hexdec($lims[$cur + 3]));
|
if ($version == 1) {
|
||||||
$m = (hexdec($lims[$cur]) * 65536 + hexdec($lims[$cur + 1]) * 256 + hexdec($lims[$cur + 2])) / 500000;
|
$exp = (int) $this->tosbyte(hexdec($lims[$cur + 3]));
|
||||||
$e = 1;
|
$m = (hexdec($lims[$cur]) * 65536 + hexdec($lims[$cur + 1]) * 256 + hexdec($lims[$cur + 2])) / 500000;
|
||||||
if ($exp > 0) {
|
$e = 1;
|
||||||
$d = 1;
|
if ($exp > 0) {
|
||||||
for ($i = 0; $i < $exp; $i++)
|
$d = 1;
|
||||||
$d = $d * 10;
|
for ($i = 0; $i < $exp; $i++)
|
||||||
$e = $d;
|
$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;
|
break;
|
||||||
default:
|
default:
|
||||||
$line .= $ops[hexdec($opType)];
|
$line .= $ops[hexdec($opType)];
|
||||||
@ -326,34 +228,54 @@ class BAS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function obfuscation($name) {
|
function obfuscation($name) {
|
||||||
if ($this->readInt($this->data) != "4d420001") {
|
switch ($this->readInt($this->data)) {
|
||||||
/// $this->init();
|
case '4d420001':
|
||||||
|
$version = 1;
|
||||||
|
break;
|
||||||
|
case '4d420191':
|
||||||
|
$version = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$version = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($version == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
$main = "";
|
$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));
|
$varnum = hexdec($this->readShort($this->data));
|
||||||
$main .= pack('n*', $varnum); //writeShort
|
$main .= pack('n*', $varnum); //writeShort
|
||||||
// $main.= $this->writeUTF("hello");
|
|
||||||
/// echo hexdec($this->readShort($this->data));
|
|
||||||
for ($i = 0; $i < $varnum; $i++) { //пропуск переменных
|
for ($i = 0; $i < $varnum; $i++) { //пропуск переменных
|
||||||
$this->readUTF($this->data);
|
$this->readUTF($this->data);
|
||||||
$main .= $this->writeUTF(" ");
|
$main .= $this->writeUTF(" ");
|
||||||
$main .= pack('H*', $this->readByte($this->data));
|
$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));
|
$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++) {
|
for ($i = 0; $i < $leng; $i++) {
|
||||||
$main .= pack('H*', $this->readByte($this->data));
|
$main .= pack('H*', $this->readByte($this->data));
|
||||||
}
|
}
|
||||||
|
|
||||||
$main .= pack('H*', "FFFF");
|
$main .= pack('H*', "FFFF");
|
||||||
|
|
||||||
file_put_contents($name, $main);
|
file_put_contents($name, $main);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->init();
|
$this->init();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -378,21 +300,21 @@ class BAS {
|
|||||||
return bin2hex(substr($text, 0, 2));
|
return bin2hex(substr($text, 0, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
function readByte($text) {
|
function readByte($text, $dec = true) {
|
||||||
$this->data = substr($text, 1, strlen($text));
|
$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() {
|
function readUTF() {
|
||||||
// $this->data = substr($text, 1, strlen($text));
|
|
||||||
// return bin2hex(substr($text, 0, 1));
|
|
||||||
$to = hexdec($this->readShort($this->data));
|
$to = hexdec($this->readShort($this->data));
|
||||||
$bombom = "";
|
$bombom = "";
|
||||||
while ($to <> 0) {
|
while ($to <> 0) {
|
||||||
$bombom .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($this->readByte($this->data))));
|
$bombom .= iconv("WINDOWS-1251", "UTF-8", chr(hexdec($this->readByte($this->data))));
|
||||||
$to--;
|
$to--;
|
||||||
}
|
}
|
||||||
// $this->readByte($this->data);
|
|
||||||
return $bombom;
|
return $bombom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,42 +1,55 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/* Компилятор LIS=>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 {
|
class LIS {
|
||||||
|
|
||||||
public $data, $file, $save, $coderror, $bufbody, $buffer, $compile = false;
|
public $data, $file, $save, $coderror, $warning, $bufbody, $buffer, $compile = false;
|
||||||
public $lines = [''];
|
public $lines = [];
|
||||||
public $ltypes = [''];
|
public $ltypes = [];
|
||||||
public $lexems = [];
|
public $lexems = [];
|
||||||
public $vars = [''];
|
public $vars = [];
|
||||||
public $vtypes = [''];
|
public $vtypes = [];
|
||||||
public $currLine;
|
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 INT = 0, FLOAT = 1, STR = 2;
|
||||||
const Operator = 0, Integer = 1, Float = 2, String = 3, Variable = 4, Data = 5, ArrayByte = 6;
|
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 $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->file = $name;
|
||||||
$this->save = $newname;
|
$this->save = $newname;
|
||||||
}
|
if ($v > 0 && $v < 3)
|
||||||
|
$this->ver = $v;
|
||||||
function init() {
|
|
||||||
$this->data = file_get_contents($this->file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function compile() {
|
function compile() {
|
||||||
if (!$this->compile) {
|
if (!$this->compile) {
|
||||||
$this->init();
|
|
||||||
$string = explode("\n", $this->data);
|
$string = explode("\n", $this->data);
|
||||||
|
|
||||||
for ($i = 0; $i < count($string); $i++) {
|
for ($i = 0; $i < count($string); $i++) {
|
||||||
if (trim($string[$i]) != "") {
|
if (trim($string[$i]) != "") {
|
||||||
$this->lines[] = trim($string[$i]);
|
$this->lines[] = trim($string[$i]);
|
||||||
@ -45,17 +58,18 @@ class LIS {
|
|||||||
|
|
||||||
$this->analize();
|
$this->analize();
|
||||||
if ($this->coderror != "")
|
if ($this->coderror != "")
|
||||||
return $this->coderror;
|
return array("error", $this->coderror);
|
||||||
$this->compileCode();
|
$this->compileCode();
|
||||||
file_put_contents($this->save, $this->buffer);
|
file_put_contents($this->save, $this->buffer);
|
||||||
$this->compile = true;
|
$this->compile = true;
|
||||||
|
if ($this->warning != "")
|
||||||
|
return array("warning", $this->warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function analize() {
|
function analize() {
|
||||||
$this->currLine = 1;
|
$this->currLine = 0;
|
||||||
|
for ($i = 0; $i < count($this->lines); $i++) {
|
||||||
for ($i = 1; $i < count($this->lines); $i++) {
|
|
||||||
$this->analizeLine($this->lines[$i]);
|
$this->analizeLine($this->lines[$i]);
|
||||||
$this->check($this->currLine);
|
$this->check($this->currLine);
|
||||||
$this->currLine++;
|
$this->currLine++;
|
||||||
@ -65,20 +79,19 @@ class LIS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function check($lineNum) {
|
function check($lineNum) {
|
||||||
|
|
||||||
// for($i=0; $i<count($this->lexems[$lineNum]); $i++){
|
|
||||||
// echo $this->lexems[$lineNum][$i];
|
|
||||||
//}
|
|
||||||
// echo "\n";
|
|
||||||
|
|
||||||
$bracketCount = 0;
|
$bracketCount = 0;
|
||||||
if ($this->ltypes[$lineNum][0] != self::Integer) {
|
if ($this->ltypes[$lineNum][0] != self::Integer) {
|
||||||
$this->coderror = "Invalid line number [" . $this->lexems[$lineNum][0] . "] ";
|
$this->error("Invalid line number [" . $this->lexems[$lineNum][0] . "] ");
|
||||||
// return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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++) {
|
for ($i = 0; $i < count($this->lexems[$lineNum]); $i++) {
|
||||||
|
|
||||||
if ($this->lexems[$lineNum][$i] == "(")
|
if ($this->lexems[$lineNum][$i] == "(")
|
||||||
$bracketCount++;
|
$bracketCount++;
|
||||||
if ($this->lexems[$lineNum][$i] == ")")
|
if ($this->lexems[$lineNum][$i] == ")")
|
||||||
@ -87,44 +100,75 @@ class LIS {
|
|||||||
|
|
||||||
for ($ii = 0; $ii < count($this->lexems[$lineNum]); $ii++) {
|
for ($ii = 0; $ii < count($this->lexems[$lineNum]); $ii++) {
|
||||||
$i = $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 ($this->ltypes[$lineNum][$i] == self::Operator) {
|
||||||
if (in_array($this->lexems[$lineNum][$i], $this->keywords)) {
|
if ($this->ver == 1 && in_array($this->lexems[$lineNum][$i], $this->func191)) {
|
||||||
if (!($i == count($this->lexems[$lineNum]) - 1 || $this->lexems[$lineNum][$i + 1] == ":"))
|
if ($this->lexems[$lineNum][$i] != "REPAINT")
|
||||||
$this->coderror = "Operator must have 0 arguments [" . $this->lexems[$lineNum][$i] . "] on line " . $this->lexems[$lineNum][0];
|
$this->error("Operator [" . $this->lexems[$lineNum][$i] . "] is not supported in MobileBASIC 1.8.6 on line " . $this->lexems[$lineNum][0]); else {
|
||||||
return;
|
$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");
|
||||||
} elseif (in_array($this->lexems[$lineNum][$i], $this->functions)) {
|
if ($this->lexems[$lineNum][$i - 1] == ":") {
|
||||||
if ($i == count($this->lexems[$lineNum]) - 1 || $this->lexems[$lineNum][$i + 1] != "(")
|
$this->lexems[$lineNum][$i] = "";
|
||||||
$this->coderror = "Error function [" . $this->lexems[$lineNum][$i] . "] on line " . $this->lexems[$lineNum][0];
|
$this->lexems[$lineNum][$i - 1] = "";
|
||||||
return;
|
} elseif ($this->lexems[$lineNum][$i + 1] = ":") {
|
||||||
} elseif (!in_array($this->lexems[$lineNum][$i], $this->functions) && mb_strlen($this->lexems[$lineNum][$i]) > 1) {
|
$this->lexems[$lineNum][$i] = "";
|
||||||
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] == "(") { {
|
|
||||||
$this->lexems[$lineNum][$i + 1] = "";
|
$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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,16 +214,11 @@ class LIS {
|
|||||||
if ($startPos >= mb_strlen($line))
|
if ($startPos >= mb_strlen($line))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$op = mb_strtoupper($op);
|
$op = mb_strtoupper($op);
|
||||||
$this->lexems[$this->currLine][] = $op;
|
$this->lexems[$this->currLine][] = $op;
|
||||||
// echo "лан, не урчи";
|
// echo "лан, не урчи";
|
||||||
|
|
||||||
$isData = false;
|
$isData = false;
|
||||||
$data = "";
|
$data = "";
|
||||||
|
|
||||||
if ($op == "DATA" || $op == "REM") {
|
if ($op == "DATA" || $op == "REM") {
|
||||||
$isData = true;
|
$isData = true;
|
||||||
$startPos++;
|
$startPos++;
|
||||||
@ -189,18 +228,10 @@ class LIS {
|
|||||||
}
|
}
|
||||||
$this->lexems[$this->currLine][] = $data;
|
$this->lexems[$this->currLine][] = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in_array($op, $this->ops)) {
|
if (!in_array($op, $this->ops)) {
|
||||||
if (!in_array($op, $this->vars))
|
if (!in_array($op, $this->vars))
|
||||||
$this->vars[] = $op;
|
$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;
|
$this->ltypes[$this->currLine][] = self::Variable;
|
||||||
// }
|
|
||||||
} else {
|
} else {
|
||||||
$this->ltypes[$this->currLine][] = self::Operator;
|
$this->ltypes[$this->currLine][] = self::Operator;
|
||||||
if ($isData) {
|
if ($isData) {
|
||||||
@ -212,15 +243,15 @@ class LIS {
|
|||||||
//STRING
|
//STRING
|
||||||
elseif (mb_substr($line, $startPos, 1) == '"') {
|
elseif (mb_substr($line, $startPos, 1) == '"') {
|
||||||
$startPos++;
|
$startPos++;
|
||||||
while (!(mb_substr($line, $startPos, 1) == '"')) {
|
while (!(mb_substr($line, $startPos, 1) == '"') || (mb_substr($line, $startPos - 1, 1) == '\\')) {
|
||||||
$op .= mb_substr($line, $startPos, 1);
|
if ((mb_substr($line, $startPos, 1)) != '\\')
|
||||||
|
$op .= mb_substr($line, $startPos, 1);
|
||||||
$startPos++;
|
$startPos++;
|
||||||
if ($startPos >= mb_strlen($line)) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$startPos++;
|
$startPos++;
|
||||||
$this->lexems[$this->currLine][] = '"' . $op . '"';
|
$this->lexems[$this->currLine][] = '"' . $op . '"';
|
||||||
$this->ltypes[$this->currLine][] = self::String;
|
$this->ltypes[$this->currLine][] = self::String;
|
||||||
@ -257,9 +288,12 @@ class LIS {
|
|||||||
|
|
||||||
if (!$error) {
|
if (!$error) {
|
||||||
$this->lexems[$this->currLine][] = $op;
|
$this->lexems[$this->currLine][] = $op;
|
||||||
if ($containPoint)
|
if ($containPoint) {
|
||||||
$this->ltypes[$this->currLine][] = self::Float;
|
$this->ltypes[$this->currLine][] = self::Float;
|
||||||
else
|
if (!in_array($op, $this->float)) {
|
||||||
|
$this->float[] = $op;
|
||||||
|
}
|
||||||
|
} else
|
||||||
$this->ltypes[$this->currLine][] = self::Integer;
|
$this->ltypes[$this->currLine][] = self::Integer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,27 +309,28 @@ class LIS {
|
|||||||
} else
|
} else
|
||||||
$startPos++;
|
$startPos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $startPos - $initPos;
|
return $startPos - $initPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compileHead() {
|
function compileHead() {
|
||||||
$buf = "";
|
$buf = "";
|
||||||
$buf .= pack('H*', "4d420001");
|
if ($this->ver == 1)
|
||||||
$buf .= pack('n*', count($this->vars) - 1);
|
$buf .= pack('H*', "4d420001");
|
||||||
for ($i = 1; $i < count($this->vars); $i++) {
|
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]);
|
$buf .= $this->writeUTF($this->vars[$i]);
|
||||||
switch ($this->vtypes[$i]) {
|
$type = substr($this->vars[$i], -1);
|
||||||
case self::INT:
|
switch ($type) {
|
||||||
$buf .= pack('H*', "00");
|
case '$':
|
||||||
|
$buf .= pack('H*', "02");
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
case self::FLOAT:
|
|
||||||
$buf .= pack('H*', "01");
|
$buf .= pack('H*', "01");
|
||||||
break;
|
break;
|
||||||
|
case '%':
|
||||||
case self::STR:
|
$buf .= pack('H*', "00");
|
||||||
$buf .= pack('H*', "02");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,151 +343,188 @@ class LIS {
|
|||||||
$ltypes = $this->ltypes;
|
$ltypes = $this->ltypes;
|
||||||
|
|
||||||
$buf = "";
|
$buf = "";
|
||||||
for ($currLine = 1; $currLine < count($lexems) + 1; $currLine++) {
|
for ($currLine = 0; $currLine < count($lexems); $currLine++) {
|
||||||
$line = "";
|
$line = "";
|
||||||
$buf .= pack('n*', $lexems[$currLine][0]);
|
$notnull = false;
|
||||||
|
|
||||||
for ($currLex = 1; $currLex < count($lexems[$currLine]); $currLex++) {
|
for ($currLex = 1; $currLex < count($lexems[$currLine]); $currLex++) {
|
||||||
/////Operator
|
if ($lexems[$currLine][$currLex] != "") {
|
||||||
|
$notnull = true;
|
||||||
$ifStarted = false;
|
break;
|
||||||
$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 ($notnull) {
|
||||||
|
$buf .= pack('n*', $lexems[$currLine][0]);
|
||||||
|
|
||||||
$len = dechex(strlen($line) + 4);
|
for ($currLex = 1; $currLex < count($lexems[$currLine]); $currLex++) {
|
||||||
if (mb_strlen($len) < 2)
|
/////Operator
|
||||||
$len = "0" . $len;
|
|
||||||
$buf .= pack('H*', $len) . $line . pack('H*', 'FF');
|
$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->bufbody = $buf;
|
||||||
$this->compileHead();
|
$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) {
|
function writeUTF($text) {
|
||||||
$pack = pack('n*', mb_strlen($text));
|
$pack = pack('n*', mb_strlen($text));
|
||||||
|
|
||||||
$pack .= pack('a*', $text);
|
$pack .= pack('a*', $text);
|
||||||
|
|
||||||
return $pack;
|
return $pack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ if (($_GET['compile'] ?? '') != 'yes'){
|
|||||||
} else {
|
} else {
|
||||||
if (is_uploaded_file($_FILES["lis"]["tmp_name"])) {
|
if (is_uploaded_file($_FILES["lis"]["tmp_name"])) {
|
||||||
$namebas = "bas".rand(1000,99999).".bas";
|
$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();
|
$log = $bas->compile();
|
||||||
if ($log == '') {
|
if ($log == '') {
|
||||||
echo 'Файл успешно скомпилирован!<br><a href="tmp/'.$namebas.'">Скачать</a>';
|
echo 'Файл успешно скомпилирован!<br><a href="tmp/'.$namebas.'">Скачать</a>';
|
||||||
|
Loading…
Reference in New Issue
Block a user