557 lines
26 KiB
PHP
557 lines
26 KiB
PHP
<?php
|
||
|
||
/*
|
||
* ************************************************************
|
||
| Компилятор 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, $warning, $bufbody, $buffer, $compile = false;
|
||
public $lines = [];
|
||
public $ltypes = [];
|
||
public $lexems = [];
|
||
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", "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("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, $v = 1) {
|
||
$this->file = $name;
|
||
$this->save = $newname;
|
||
if ($v > 0 && $v < 3)
|
||
$this->ver = $v;
|
||
}
|
||
|
||
function compile() {
|
||
if (!$this->compile) {
|
||
$string = explode("\n", $this->data);
|
||
for ($i = 0; $i < count($string); $i++) {
|
||
if (trim($string[$i]) != "") {
|
||
$this->lines[] = trim($string[$i]);
|
||
}
|
||
}
|
||
|
||
$this->analize();
|
||
if ($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 = 0;
|
||
for ($i = 0; $i < count($this->lines); $i++) {
|
||
$this->analizeLine($this->lines[$i]);
|
||
$this->check($this->currLine);
|
||
$this->currLine++;
|
||
if ($this->coderror != "")
|
||
break;
|
||
}
|
||
}
|
||
|
||
function check($lineNum) {
|
||
$bracketCount = 0;
|
||
if ($this->ltypes[$lineNum][0] != self::Integer) {
|
||
$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] == ")")
|
||
$bracketCount--;
|
||
}
|
||
|
||
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 ($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] = "";
|
||
}
|
||
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->error("Error: Some bracket not opened/closed on line " . $this->lexems[$lineNum][0]);
|
||
return;
|
||
}
|
||
}
|
||
|
||
function analizeLine($line) {
|
||
$i = 0;
|
||
while ($i < mb_strlen($line)) {
|
||
$i += $this->readToken($line, $i);
|
||
if ($this->coderror != "")
|
||
break;
|
||
}
|
||
}
|
||
|
||
function isLetter($ch) {
|
||
return ($ch >= 'A' && $ch <= 'Z')
|
||
|| ($ch >= 'a' && $ch <= 'z');
|
||
}
|
||
|
||
function isDigit($ch) {
|
||
return ($ch >= '0' && $ch <= '9');
|
||
}
|
||
|
||
function isLetterOrDigit($ch) {
|
||
return $this->isLetter($ch) || $this->isDigit($ch);
|
||
}
|
||
|
||
function isVariablePartSymbol($ch) {
|
||
return ($ch == '_' || $ch == '$' || $ch == '%');
|
||
}
|
||
|
||
function isValidVariableChar($ch) {
|
||
return $this->isLetterOrDigit($ch) || $this->isVariablePartSymbol($ch);
|
||
}
|
||
|
||
function readToken($line, $startPos) {
|
||
$initPos = $startPos;
|
||
$op = "";
|
||
|
||
if ($this->isLetter(mb_substr($line, $startPos, 1))) {
|
||
while ($this->isValidVariableChar(mb_substr($line, $startPos, 1))) {
|
||
$op .= mb_substr($line, $startPos, 1);
|
||
$startPos++;
|
||
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++;
|
||
while ($startPos < mb_strlen($line)) {
|
||
$data .= mb_substr($line, $startPos, 1);
|
||
$startPos++;
|
||
}
|
||
$this->lexems[$this->currLine][] = $data;
|
||
}
|
||
if (!in_array($op, $this->ops)) {
|
||
if (!in_array($op, $this->vars))
|
||
$this->vars[] = $op;
|
||
$this->ltypes[$this->currLine][] = self::Variable;
|
||
} else {
|
||
$this->ltypes[$this->currLine][] = self::Operator;
|
||
if ($isData) {
|
||
$this->ltypes[$this->currLine][] = self::Data;
|
||
}
|
||
}
|
||
}
|
||
|
||
//STRING
|
||
elseif (mb_substr($line, $startPos, 1) == '"') {
|
||
$startPos++;
|
||
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 found close \" on line " . $this->lexems[$this->currLine][0];
|
||
break;
|
||
}
|
||
}
|
||
$startPos++;
|
||
$this->lexems[$this->currLine][] = '"' . $op . '"';
|
||
$this->ltypes[$this->currLine][] = self::String;
|
||
}
|
||
// NUMBER
|
||
elseif ($this->isDigit(mb_substr($line, $startPos, 1))) {
|
||
while ($this->isDigit(mb_substr($line, $startPos, 1))
|
||
|| mb_substr($line, $startPos, 1) == '.'
|
||
|| mb_substr($line, $startPos, 1) == 'e' || mb_substr($line, $startPos, 1) == 'E') {
|
||
$op .= mb_substr($line, $startPos, 1);
|
||
if (mb_substr($line, $startPos, 1) == 'e' || mb_substr($line, $startPos, 1) == 'E') {
|
||
$op .= mb_substr($line, $startPos + 1, 1);
|
||
$startPos += 2;
|
||
} else
|
||
$startPos++;
|
||
if ($startPos >= mb_strlen($line))
|
||
break;
|
||
}
|
||
|
||
$containPoint = false;
|
||
$error = false;
|
||
|
||
for ($i = 0; $i < mb_strlen($op); $i++) {
|
||
if ($op[$i] == '.') {
|
||
if (!$containPoint)
|
||
$containPoint = true;
|
||
else {
|
||
// exit;
|
||
$this->coderror = "NumberLexem contains more than one point [" . $op . "]";
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!$error) {
|
||
$this->lexems[$this->currLine][] = $op;
|
||
if ($containPoint) {
|
||
$this->ltypes[$this->currLine][] = self::Float;
|
||
if (!in_array($op, $this->float)) {
|
||
$this->float[] = $op;
|
||
}
|
||
} else
|
||
$this->ltypes[$this->currLine][] = self::Integer;
|
||
}
|
||
}
|
||
///SYMBOL
|
||
else {
|
||
if (mb_substr($line, $startPos, 1) != ' ' && mb_substr($line, $startPos, 1) < 'А') {
|
||
$this->lexems[$this->currLine][] = mb_substr($line, $startPos, 1);
|
||
$this->ltypes[$this->currLine][] = self::Operator;
|
||
$startPos++;
|
||
} elseif (mb_substr($line, $startPos, 1) >= 'А' && mb_substr($line, $startPos, 1) <= 'я') {
|
||
$this->coderror = "SymbolLexem not recognized [" . $line[$startPos] . "]";
|
||
return;
|
||
} else
|
||
$startPos++;
|
||
}
|
||
return $startPos - $initPos;
|
||
}
|
||
|
||
function compileHead() {
|
||
$buf = "";
|
||
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]);
|
||
$type = substr($this->vars[$i], -1);
|
||
switch ($type) {
|
||
case '$':
|
||
$buf .= pack('H*', "02");
|
||
break;
|
||
default:
|
||
$buf .= pack('H*', "01");
|
||
break;
|
||
case '%':
|
||
$buf .= pack('H*', "00");
|
||
break;
|
||
}
|
||
}
|
||
$buf .= pack('n*', strlen($this->bufbody));
|
||
$this->buffer = $buf . $this->bufbody;
|
||
}
|
||
|
||
function compileCode() {
|
||
$lexems = $this->lexems;
|
||
$ltypes = $this->ltypes;
|
||
|
||
$buf = "";
|
||
for ($currLine = 0; $currLine < count($lexems); $currLine++) {
|
||
$line = "";
|
||
$notnull = false;
|
||
for ($currLex = 1; $currLex < count($lexems[$currLine]); $currLex++) {
|
||
if ($lexems[$currLine][$currLex] != "") {
|
||
$notnull = true;
|
||
break;
|
||
}
|
||
}
|
||
if ($notnull) {
|
||
$buf .= pack('n*', $lexems[$currLine][0]);
|
||
|
||
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;
|
||
}
|
||
|
||
function writeTEXT($text) {
|
||
$len = dechex(strlen($text));
|
||
if (strlen($len) < 2)
|
||
$len = "0" . $len;
|
||
$pack = pack('H*', $len);
|
||
|
||
$pack .= pack('a*', $text);
|
||
|
||
return $pack;
|
||
}
|
||
|
||
function shiftRight($a, $b) {
|
||
if (is_numeric($a) && $a < 0) {
|
||
return ($a >> $b) + (2 << ~$b);
|
||
} else {
|
||
return ($a >> $b);
|
||
}
|
||
}
|
||
|
||
function endWith($haystack, $needle) {
|
||
$length = strlen($needle);
|
||
if ($length == 0) {
|
||
return true;
|
||
}
|
||
return (substr($haystack, -$length) === $needle);
|
||
}
|
||
} |