Added str functions
This commit is contained in:
parent
d56af7f194
commit
cd901db577
|
@ -478,6 +478,9 @@ void B2C_exit(int exitCode) {
|
|||
case MEMORY_ERROR:
|
||||
locate(4,3); Print((unsigned char*)"Erreur m\xE6""\x0A""moire");
|
||||
break;
|
||||
case ARG_ERROR:
|
||||
locate(4,3); Print((unsigned char*)"Erreur argument");
|
||||
break;
|
||||
}
|
||||
locate(4,5); Print((unsigned char*)"Appuyer:[EXIT]");
|
||||
|
||||
|
@ -534,106 +537,153 @@ BCDvar *B2C_calcExp(unsigned char* exp) {
|
|||
void B2C_setAlphaVar(BCDvar *alphaVar, BCDvar *value) {
|
||||
memcpy(*alphaVar, *value, sizeof(BCDvar)-3);
|
||||
}
|
||||
void B2C_setStr(Str *value, int isString, int strNum) {
|
||||
free(strings[strNum].data);
|
||||
strings[strNum].length = value->length;
|
||||
strings[strNum].data = malloc((value->length+2)*2);
|
||||
strings[strNum].data[(value->length+1)*2] = 0x00;
|
||||
memcpy(strings[strNum].data + 2, value->data + 2, value->length * 2);
|
||||
void B2C_setStr(Str *str, Str *value, int isString) {
|
||||
free(str->data);
|
||||
str->length = value->length;
|
||||
str->data = malloc(value->length*2);
|
||||
memcpy(str->data, value->data, value->length*2);
|
||||
free_str(value);
|
||||
}
|
||||
unsigned char* B2C_strToCharArray(Str *str, int isString) {
|
||||
int j = 0;
|
||||
//Initialize the buffer
|
||||
memset(stringBuffer, 0x00, 256);
|
||||
memset(stringBuffer, 0x00, 512);
|
||||
//Goes through the string, starting at 2
|
||||
for (i = 2; i <= (str->length+1) * 2; i++) {
|
||||
for (i = 0; i < str->length; i++) {
|
||||
//Skip null bytes
|
||||
if (str->data[i]) {
|
||||
stringBuffer[j] = str->data[i];
|
||||
if ((str->data[i])&0xFF00) {
|
||||
stringBuffer[j] = (((str->data[i])&0xFF00)>>8);
|
||||
j++;
|
||||
}
|
||||
//There is normally no need to skip null bytes here
|
||||
//if ((str->data[i])&0x00FF) {
|
||||
stringBuffer[j] = ((str->data[i])&0x00FF);
|
||||
j++;
|
||||
//}
|
||||
}
|
||||
free_str(str);
|
||||
return stringBuffer;
|
||||
}
|
||||
Str *B2C_charArrayToStr(unsigned char* charArray) {
|
||||
int strPos = 2;
|
||||
int strPos = 0;
|
||||
unsigned short currentChar;
|
||||
Str *result = malloc(sizeof(Str));
|
||||
result->data = calloc(strlen((char*)charArray)+1, 2);
|
||||
result->length = 0;
|
||||
result->data = calloc(strlen((char*)charArray), 2);
|
||||
for (i = 0; charArray[i]; i++) {
|
||||
if (!(strPos%2) &&
|
||||
charArray[i] != 0xE5 &&
|
||||
charArray[i] != 0xE6 &&
|
||||
charArray[i] != 0xE7 &&
|
||||
charArray[i] != 0xF7 &&
|
||||
charArray[i] != 0xF9 &&
|
||||
charArray[i] != 0x7F) {
|
||||
strPos++;
|
||||
currentChar = 0;
|
||||
if (charArray[i] == 0xE5 ||
|
||||
charArray[i] == 0xE6 ||
|
||||
charArray[i] == 0xE7 ||
|
||||
charArray[i] == 0xF7 ||
|
||||
charArray[i] == 0xF9 ||
|
||||
charArray[i] == 0x7F) {
|
||||
currentChar = charArray[i] << 8;
|
||||
i++;
|
||||
}
|
||||
result->data[strPos] = charArray[i];
|
||||
result->data[strPos] = currentChar + charArray[i];
|
||||
strPos++;
|
||||
}
|
||||
result->length = (strPos-2)/2;
|
||||
result->length = strPos;
|
||||
return result;
|
||||
}
|
||||
BCDvar *B2C_strCmp(Str *str1, Str *str2, int isString1, int isString2) {
|
||||
unsigned char str_1[256] = {0}, str_2[256] = {0};
|
||||
int j = 0, isString;
|
||||
//Can't use strToCharArray because the buffer can't be used twice
|
||||
for (i = 2; i <= (str1->length+1) * 2; i++) {
|
||||
//Skip null bytes
|
||||
if (str1->data[i]) {
|
||||
str_1[j] = str1->data[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
for (i = 2; i <= (str2->length+1) * 2; i++) {
|
||||
//Skip null bytes
|
||||
if (str2->data[i]) {
|
||||
str_2[j] = str2->data[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
isString = isString1;
|
||||
//Can't use strcmp() because it must return -1, 0 or 1
|
||||
//so just implement strcmp while adapting free_str to free both str1 and str2
|
||||
for (i = 0; str_1[i] || str_2[i]; i++) {
|
||||
if (str_1[i] < str_2[i]) {
|
||||
free_str(str1);
|
||||
isString = isString2;
|
||||
free_str(str2);
|
||||
return &__1_;
|
||||
} else if (str_1[i] > str_2[i]) {
|
||||
free_str(str1);
|
||||
isString = isString2;
|
||||
free_str(str2);
|
||||
return &_1_;
|
||||
|
||||
BCDvar *B2C_strCmp(BCDvar *buffer, Str *str1, int isString1, Str *str2, int isString2) {
|
||||
int j, isString = isString1;
|
||||
for (i = 0; i < str1->length && i < str1->length; i++) {
|
||||
//Case 1, most common: both characters are single bytes
|
||||
if (!(str1->data[i]&0xFF00) && (str2->data[i]&0xFF00)) {
|
||||
if (str1->data[i] < str2->data[i]) {
|
||||
goto str1_lt_str2;
|
||||
} else if (str1->data[i] > str2->data[i]) {
|
||||
goto str1_gt_str2;
|
||||
}
|
||||
}
|
||||
//Case 2: str1[i] is single byte, str2[i] is multi byte
|
||||
//They can't be equal because the single byte at str1[i] can't match the multi byte prefix
|
||||
else if (!(str1->data[i]&0xFF00)) {
|
||||
if (str1->data[i] < (str2->data[i]>>8)) {
|
||||
goto str1_lt_str2;
|
||||
} else {
|
||||
goto str1_gt_str2;
|
||||
}
|
||||
}
|
||||
//Case 3: str1[i] is multi byte, str2[i] is single byte
|
||||
else if (!(str2->data[i]&0xFF00)) {
|
||||
if ((str1->data[i]>>8) < str2->data[i]) {
|
||||
goto str1_lt_str2;
|
||||
} else {
|
||||
goto str1_gt_str2;
|
||||
}
|
||||
}
|
||||
//Case 4: both are multi bytes
|
||||
else {
|
||||
if (str1->data[i] < str2->data[i]) {
|
||||
goto str1_lt_str2;
|
||||
} else if (str1->data[i] > str2->data[i]) {
|
||||
goto str1_gt_str2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//goto equalStrings;
|
||||
//equalStrings:
|
||||
buffer = &_0_;
|
||||
goto freestrs;
|
||||
|
||||
str1_gt_str2:
|
||||
buffer = &_1_;
|
||||
goto freestrs;
|
||||
|
||||
str1_lt_str2:
|
||||
buffer = &__1_;
|
||||
//goto freestrs;
|
||||
|
||||
freestrs:
|
||||
free_str(str1);
|
||||
isString = isString2;
|
||||
free_str(str2);
|
||||
return &_0_;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
BCDvar *B2C_strSrc(BCDvar *buffer, Str *str1, int isString1, Str *str2, int isString2, int n) {
|
||||
int isString = isString1;
|
||||
n--;
|
||||
exitIfNeg(n);
|
||||
for (i = n; i < str1->length-str2->length+1; i++) {
|
||||
if (!memcmp(str1->data+i, str2->data+i, str2->length*2)) {
|
||||
intToBCD(i+1, buffer);
|
||||
goto freestrs;
|
||||
}
|
||||
}
|
||||
|
||||
//str_not_found:
|
||||
buffer = &_0_;
|
||||
|
||||
freestrs:
|
||||
free_str(str1);
|
||||
isString = isString2;
|
||||
free_str(str2);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Str *B2C_strInv(Str *str, int isString) {
|
||||
Str *result = malloc(sizeof(Str));
|
||||
result->data = malloc(2*(str->length+1));
|
||||
result->data = malloc(2*str->length);
|
||||
result->length = str->length;
|
||||
for (i = 2*str->length; i >= 2; i -= 2) {
|
||||
memcpy(result->data + 2*str->length-i, str->data + i, 2);
|
||||
for (i = 0; i < str->length; i++) {
|
||||
result->data[str->length-1-i] = str->data[i];
|
||||
}
|
||||
free_str(str);
|
||||
return result;
|
||||
}
|
||||
Str *B2C_strJoin(Str *str1, Str *str2, int isString1, int isString2) {
|
||||
|
||||
Str *B2C_strJoin(Str *str1, int isString1, Str *str2, int isString2) {
|
||||
int isString = isString1;
|
||||
Str *result = malloc(sizeof(Str));
|
||||
result->data = malloc(2*(str1->length + str2->length + 1));
|
||||
result->data = malloc(2*(str1->length + str2->length));
|
||||
result->length = str1->length + str2->length;
|
||||
memcpy(result->data + 2, str1->data + 2, str1->length * 2);
|
||||
memcpy(result->data + 2 + str1->length * 2, str2->data + 2, str2->length * 2);
|
||||
memcpy(result->data, str1->data, str1->length * 2);
|
||||
memcpy(result->data+str1->length, str2->data, str2->length * 2);
|
||||
free_str(str1);
|
||||
isString = isString2;
|
||||
free_str(str2);
|
||||
|
@ -643,37 +693,47 @@ BCDvar *B2C_strLen(BCDvar *buffer, Str *str, int isString) {
|
|||
intToBCD(str->length, buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Str *B2C_strMid2args(Str *str, int isString, int start) {
|
||||
//+1 because strings are 1-indexed in casio
|
||||
return B2C_strMid(str, isString, start, str->length+1-start);
|
||||
}
|
||||
|
||||
Str *B2C_strMid(Str *str, int isString, int start, int offset) {
|
||||
Str *result = malloc(sizeof(Str));
|
||||
if (!offset) {
|
||||
start--; //In casio, strings are 1-indexed!
|
||||
exitIfNeg(start);
|
||||
exitIfNeg(offset);
|
||||
if (offset+start > str->length) {
|
||||
offset = str->length-start;
|
||||
}
|
||||
result->data = malloc((offset+2) * 2);
|
||||
//Set null byte at the end
|
||||
result->data[(offset+1) * 2] = 0x00;
|
||||
if (start > str->length) {
|
||||
start = str->length;
|
||||
}
|
||||
result->data = malloc(offset * 2);
|
||||
result->length = offset;
|
||||
//Copy the substring
|
||||
memcpy(result->data + 2, str->data + start*2, 2*offset);
|
||||
memcpy(result->data, str->data+start, 2*offset);
|
||||
free_str(str);
|
||||
return result;
|
||||
}
|
||||
Str *B2C_charAt(Str *str, int isString, int charPos) {
|
||||
//Unused at the moment - not tested
|
||||
Str *result = malloc(sizeof(Str));
|
||||
result->data = malloc(3*2);
|
||||
result->data[2*2] = 0x00;
|
||||
charPos--; //In casio, strings are 1-indexed!
|
||||
exitIfNeg(charPos);
|
||||
result->data = malloc(2);
|
||||
result->length = 1;
|
||||
memcpy(result->data+2, str->data+charPos*2, 2);
|
||||
result->data[0] = str->data[charPos];
|
||||
free_str(str);
|
||||
return result;
|
||||
}
|
||||
Str *B2C_strUpr(Str *str, int isString) {
|
||||
Str *result = malloc(sizeof(Str));
|
||||
unsigned short currentChar;
|
||||
result->data = malloc((str->length+2) * 2);
|
||||
result->data[str->length+1] = 0x00;
|
||||
memcpy(result->data+2, str->data+2, str->length * 2);
|
||||
result->data = malloc(str->length * 2);
|
||||
memcpy(result->data, str->data, str->length * 2);
|
||||
result->length = str->length;
|
||||
for (i = 3; i <= result->length*2; i+=2) {
|
||||
for (i = 0; i < result->length; i++) {
|
||||
if (result->data[i] >= 'a' && result->data[i] <= 'z') {
|
||||
result->data[i] -= 32;
|
||||
}
|
||||
|
@ -683,12 +743,10 @@ Str *B2C_strUpr(Str *str, int isString) {
|
|||
}
|
||||
Str *B2C_strLwr(Str *str, int isString) { //(almost) copy of B2C_strUpr - any changes made here must be reflected in strUpr
|
||||
Str *result = malloc(sizeof(Str));
|
||||
unsigned short currentChar;
|
||||
result->data = malloc((str->length+2) * 2);
|
||||
result->data[str->length+1] = 0x00;
|
||||
memcpy(result->data+2, str->data+2, str->length * 2);
|
||||
result->data = malloc(str->length * 2);
|
||||
memcpy(result->data, str->data, str->length * 2);
|
||||
result->length = str->length;
|
||||
for (i = 3; i <= result->length*2; i+=2) {
|
||||
for (i = 0; i < result->length; i++) {
|
||||
if (result->data[i] >= 'A' && result->data[i] <= 'Z') {
|
||||
result->data[i] += 32;
|
||||
}
|
||||
|
@ -698,34 +756,58 @@ Str *B2C_strLwr(Str *str, int isString) { //(almost) copy of B2C_strUpr - any ch
|
|||
}
|
||||
Str *B2C_strRight(Str *str, int isString, int offset) {
|
||||
Str *result = malloc(sizeof(Str));
|
||||
|
||||
result->data = malloc((offset+2)*2);
|
||||
result->data[(offset+1)*2] = 0x00;
|
||||
exitIfNeg(offset);
|
||||
result->data = malloc(offset*2);
|
||||
if (offset > str->length) offset=str->length;
|
||||
result->length = offset;
|
||||
memcpy(result->data+2, str->data + (str->length - offset + 1)*2, offset * 2);
|
||||
memcpy(result->data, str->data+(str->length-offset), offset*2);
|
||||
free_str(str);
|
||||
return result;
|
||||
}
|
||||
Str *B2C_strLeft(Str *str, int isString, int offset) {
|
||||
Str *result = malloc(sizeof(Str));
|
||||
result->data = malloc((offset+2)*2);
|
||||
result->data[(offset+1)*2] = 0x00;
|
||||
exitIfNeg(offset);
|
||||
result->data = malloc(offset*2);
|
||||
if (offset > str->length) offset=str->length;
|
||||
result->length = offset;
|
||||
memcpy(result->data+2, str->data + 2, offset * 2);
|
||||
memcpy(result->data, str->data, offset*2);
|
||||
free_str(str);
|
||||
return result;
|
||||
}
|
||||
Str *B2C_strShift(Str *str, int isString, int offset) {
|
||||
unsigned short* spaces = malloc(2*abs(offset));
|
||||
Str *result = malloc(sizeof(Str));
|
||||
for (i = 0; i < abs(offset); i++) {
|
||||
spaces[i] = (unsigned short)' ';
|
||||
}
|
||||
result->length = str->length;
|
||||
result->data = malloc(str->length*2);
|
||||
if (offset > str->length) {
|
||||
offset = str->length;
|
||||
} else if (-offset > str->length) {
|
||||
offset = -str->length;
|
||||
}
|
||||
if (offset > 0) {
|
||||
memcpy(result->data, str->data+offset, (str->length-offset)*2);
|
||||
memcpy(result->data+(str->length-offset), spaces, offset*2);
|
||||
} else {
|
||||
memcpy(result->data, spaces, -offset*2);
|
||||
memcpy(result->data-offset, str->data, (str->length+offset)*2);
|
||||
}
|
||||
free_str(str);
|
||||
return result;
|
||||
}
|
||||
Str *B2C_strRotate(Str *str, int isString, int offset) {
|
||||
Str *result = malloc(sizeof(Str));
|
||||
result->length = str->length;
|
||||
result->data = malloc((str->length+1)*2);
|
||||
result->data = malloc(str->length*2);
|
||||
offset %= str->length;
|
||||
if (offset > 0) {
|
||||
memcpy(result->data+2, str->data+2+2*offset, (str->length-offset)*2);
|
||||
memcpy(result->data+2+2*(str->length-offset), str->data+2, offset*2);
|
||||
memcpy(result->data, str->data+offset, (str->length-offset)*2);
|
||||
memcpy(result->data+(str->length-offset), str->data, offset*2);
|
||||
} else {
|
||||
memcpy(result->data+2, str->data+2+2*(str->length+offset), -offset*2);
|
||||
memcpy(result->data+2+2*-offset, str->data+2, (str->length+offset)*2);
|
||||
memcpy(result->data, str->data+(str->length+offset), -offset*2);
|
||||
memcpy(result->data-offset, str->data, (str->length+offset)*2);
|
||||
}
|
||||
free_str(str);
|
||||
return result;
|
||||
|
|
|
@ -19,8 +19,8 @@ public class B2C {
|
|||
final static boolean debugMode = true;
|
||||
|
||||
static String path = "C:\\Users\\Catherine\\Documents\\CASIO\\fx-9860G SDK\\TestB2C\\";
|
||||
static String mainProgramName = "DEMNR";
|
||||
static String pathToG1M = "C:\\Users\\Catherine\\Desktop\\goldroad.g2m";
|
||||
static String mainProgramName = "TESTSTR";
|
||||
static String pathToG1M = "C:\\Users\\Catherine\\Desktop\\teststr.g1m";
|
||||
static boolean isRealTimeGame = true;
|
||||
static boolean assureOS1Compatibility = true;
|
||||
static boolean usesAcOnTimer = true;
|
||||
|
@ -108,7 +108,7 @@ public class B2C {
|
|||
"unsigned int key;\n" +
|
||||
"int i;\n"+
|
||||
"BCDvar var[29] = {0}; //A-Z, r, theta, Ans\n"+
|
||||
"Str strings[20];\n" +
|
||||
"Str str[20];\n" +
|
||||
"Mat mat[27]; //Important thing: matrixes are (height, width) not (width, height)\n" +
|
||||
"List list[26];\n" +
|
||||
"char dummyOpCode[2] = {5, 8};\n" +
|
||||
|
@ -116,7 +116,7 @@ public class B2C {
|
|||
"BCDvar alphaVarBuffer;\n" +
|
||||
"BCDvar expressionBuffer;\n" +
|
||||
"BCDvar getkeyBuffer;\n" +
|
||||
"unsigned char stringBuffer[256] = {0};\n";
|
||||
"unsigned char stringBuffer[512] = {0};\n";
|
||||
/*"const BCDvar ZERO = {0};\n";
|
||||
for (int i = 1; i <= 9; i++) {
|
||||
main_c += "const BCDvar " + Parser.consts.get(i) + " = {0x10, 0x0" + i + "};\n";
|
||||
|
@ -124,7 +124,7 @@ public class B2C {
|
|||
main_c+="\nint AddIn_main(int isAppli, unsigned short OptionNum) {\n" +
|
||||
"\t//Initialize strings\n" +
|
||||
"\tfor (i = 0; i < 20; i++) {\n" +
|
||||
"\t\tstrings[i].length = 0;\n" +
|
||||
"\t\tstr[i].length = 0;\n" +
|
||||
"\t}\n" +
|
||||
"\tsrand((unsigned int)" + new Random().nextInt() + ");\n" +
|
||||
"\t#ifdef USES_INTERRUPTION_TIMER\n" +
|
||||
|
@ -204,9 +204,16 @@ public class B2C {
|
|||
for (int i = 0; i <= 1; i++) {
|
||||
IO.writeToFile(new File(path+externalLibs[i]), IO.readFromRelativeFile(externalLibs[i]), true);
|
||||
}
|
||||
/*for (char c = 'A'; c <= 'Z'; c++) {
|
||||
Header.addDefine(c+" "+(c-'A'));
|
||||
}*/
|
||||
//Add constants for easier reading and debugging
|
||||
for (char c = 'A'; c <= 'Z'; c++) {
|
||||
Header.addDefine("VAR_"+c+" (&var["+(c-'A')+"])");
|
||||
}
|
||||
for (char c = 'A'; c <= 'Z'; c++) {
|
||||
Header.addDefine("MAT_"+c+" (&mat["+(c-'A')+"])");
|
||||
}
|
||||
for (int i = 1; i <= 20; i++) {
|
||||
Header.addDefine("STR_"+i+" (&str["+(i-1)+"])");
|
||||
}
|
||||
Header.addDefine("FALSE 0");
|
||||
Header.addDefine("TRUE 1");
|
||||
Header.addDefine("A_GREATER_THAN_B 1");
|
||||
|
@ -214,6 +221,7 @@ public class B2C {
|
|||
Header.addDefine("A_LESS_THAN_B -1");
|
||||
Header.addDefine("NO_ERROR 1");
|
||||
Header.addDefine("MEMORY_ERROR 4");
|
||||
Header.addDefine("ARG_ERROR 8");
|
||||
Header.addDefine("INTERRUPTION_TIMER 2");
|
||||
if (usesAcOnTimer) {
|
||||
Header.addDefine("USES_INTERRUPTION_TIMER");
|
||||
|
@ -227,13 +235,14 @@ public class B2C {
|
|||
Header.addDefine("LIST_START 0x10");
|
||||
Header.addDefine("MAT_START 0x10");
|
||||
|
||||
Header.addDefine("ANS 28");
|
||||
Header.addDefine("THETA 27");
|
||||
Header.addDefine("RADIUS 26");
|
||||
Header.addDefine("VAR_ANS (&var[28])");
|
||||
Header.addDefine("VAR_THETA (&var[27])");
|
||||
Header.addDefine("VAR_RADIUS (&var[26])");
|
||||
|
||||
Header.addDefine("SETUP_LISTFILE 0x2E");
|
||||
|
||||
Header.addDefine("free_str(x) if(!isString){free(x->data); free(x);}");
|
||||
Header.addDefine("exitIfNeg(x) if((x)<0){B2C_exit(ARG_ERROR);}");
|
||||
Header.addDefine("getDigit(BCDvar, i) (((i)%2) ? (*(BCDvar))[((i)+1)/2+1]>>4 : (*(BCDvar))[((i)+1)/2+1]&0x0F)");
|
||||
Header.addDefine("getExp(BCDvar) (((*(BCDvar))[0]>>4) * 100 + ((*(BCDvar))[0]&0x0F) * 10 + ((*(BCDvar))[1]>>4))");
|
||||
Header.create();
|
||||
|
|
|
@ -12,15 +12,7 @@ public class Constants {
|
|||
* special things like 1e5, 1/3, etc.
|
||||
*/
|
||||
public static void add(String constant) {
|
||||
constant = constant.replaceAll("\\x99|\\x87", "-");
|
||||
//System.out.println(constant);
|
||||
//Interpret "." as "0.", example: -.5 = -0.5
|
||||
constant = constant.replaceAll("(?<!\\d)\\.", "0.");
|
||||
|
||||
//Remove last ".", example: 85. = 85.0 = 85
|
||||
if (constant.charAt(constant.length()-1) == '.') {
|
||||
constant = constant.substring(0, constant.length()-1);
|
||||
}
|
||||
constant = getNumberNotation(constant);
|
||||
|
||||
//Parse special operators
|
||||
//sqrt
|
||||
|
@ -89,17 +81,22 @@ public class Constants {
|
|||
}
|
||||
|
||||
public static String getVarNotation(String nb) {
|
||||
String result = getNumberNotation(nb);
|
||||
result = result.replaceAll("\\.|\\-", "_");
|
||||
return "_" + result + "_";
|
||||
}
|
||||
|
||||
public static String getNumberNotation(String nb) {
|
||||
String result;
|
||||
//System.out.println(nb);
|
||||
result = nb.replaceAll("(?<!\\d)\\.", "0.");
|
||||
//System.out.println(result);
|
||||
result = result.replaceAll("\\.|\\-|\\x99|\\x87", "_");
|
||||
result = result.replaceAll("\\x99|\\x87", "-");
|
||||
//System.out.println(result);
|
||||
//Remove last "."
|
||||
if (result.charAt(result.length()-1) == '.') {
|
||||
result = result.substring(0, result.length()-1);
|
||||
}
|
||||
return "_" + result + "_";
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isNumber(String nb) {
|
||||
|
|
|
@ -40,7 +40,7 @@ public class Header {
|
|||
//"typedef unsigned short Fontchar;\n" +
|
||||
"typedef struct {\n" +
|
||||
"\tint length;\n" +
|
||||
"\tunsigned char* data;\n" +
|
||||
"\tunsigned short* data;\n" +
|
||||
"} Str;\n\n" +
|
||||
"typedef struct {\n" +
|
||||
"\tunsigned char data[4];\n" +
|
||||
|
|
|
@ -54,7 +54,7 @@ public class IO {
|
|||
byte[] encoded;
|
||||
try {
|
||||
encoded = Files.readAllBytes(Paths.get(path));
|
||||
content = new String(encoded, "Cp1252");
|
||||
content = new String(encoded, "ISO-8859-1");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public class IO {
|
|||
content = content.substring(32);
|
||||
|
||||
//due to unicode encoding, some characters get encoded as others
|
||||
|
||||
/*
|
||||
content = content.replaceAll("\\u2020", new String(new char[]{0x86}));
|
||||
content = content.replaceAll("\\u2021", new String(new char[]{0x87}));
|
||||
content = content.replaceAll("\\u02C6", new String(new char[]{0x88}));
|
||||
|
@ -74,6 +74,7 @@ public class IO {
|
|||
content = content.replaceAll("\\u0161", new String(new char[]{0x9A}));
|
||||
content = content.replaceAll("\\u203A", new String(new char[]{0x9B}));
|
||||
content = content.replaceAll("\\u017E", new String(new char[]{0x9E}));
|
||||
*/
|
||||
//TODO actually parse the g1m
|
||||
String[] programs = content.split("PROGRAM[\\s\\S]{13}system[\\s\\S]{2}");
|
||||
|
||||
|
|
|
@ -8,7 +8,9 @@ public class Parser {
|
|||
final static int NO_OPTION = 0;
|
||||
final static int WHOLE_INSTRUCTION = 1;
|
||||
final static int CONV_TO_BCD = 2;
|
||||
final static int CONV_TO_INT = 3;
|
||||
//final static int CONV_TO_INT = 3; //Use handleIntConversion instead
|
||||
final static int CONV_TO_STR = 4;
|
||||
final static int CONV_TO_CHARARRAY = 5;
|
||||
|
||||
final static int BCD_BUFFER = 0;
|
||||
final static int STR_BUFFER = 1;
|
||||
|
@ -66,14 +68,6 @@ public class Parser {
|
|||
parse(content.substring(matchResult+1), WHOLE_INSTRUCTION);
|
||||
}
|
||||
|
||||
if (startsWithStringFunction(content)) {
|
||||
if (option == WHOLE_INSTRUCTION) {
|
||||
error("B2C does not support standalone strings!");
|
||||
} else {
|
||||
return parseStr(content);
|
||||
}
|
||||
}
|
||||
|
||||
//The easy functions: those that always have their arguments after, AND that don't return anything. (exception of =>)
|
||||
//Functions like Int or Frac have their arguments after but return a value so they can be used in a calculation.
|
||||
//Those are listed in the alphabetical order of their opcodes.
|
||||
|
@ -319,8 +313,8 @@ public class Parser {
|
|||
Integer[] args = parseArgs(content);
|
||||
return "locate(" + handleIntConversion(content.substring(2, args[0])) + ", "
|
||||
+ handleIntConversion(content.substring(args[0]+1, args[1]))
|
||||
+ "); Print((unsigned char*)"
|
||||
+ parseStr(content.substring(args[1]+1)) + "); ML_display_vram();";
|
||||
+ "); Print("
|
||||
+ parseStr(content.substring(args[1]+1), CONV_TO_CHARARRAY) + "); ML_display_vram();";
|
||||
}
|
||||
|
||||
//ClrText
|
||||
|
@ -342,16 +336,16 @@ public class Parser {
|
|||
|
||||
//End of starting functions. At this point the instruction is likely a mathematical operation, or a string,
|
||||
//or a variable assignment. Note that it can have functions inside, like the factorial or nCr function.
|
||||
|
||||
if (content.startsWith("\"") || content.startsWith(new String(new char[]{0xF9, 0x3F}))) { //it is a standalone string
|
||||
return parseStr(content);
|
||||
}
|
||||
|
||||
|
||||
//Check for assignment
|
||||
|
||||
matchResult = checkMatch(content, new String(new char[]{0x0E}));
|
||||
if (matchResult >= 0) {
|
||||
|
||||
if (option != WHOLE_INSTRUCTION) {
|
||||
error("Assignment isn't whole instruction?!");
|
||||
}
|
||||
|
||||
//Check for the Dim assignment case; in this case it's not an assignment but a method calling
|
||||
if (content.substring(matchResult+1).startsWith(new String(new char[]{0x7F, 0x46}))) {
|
||||
//The assignment is followed by a Dim. Now check if it's to a List or a Mat
|
||||
|
@ -360,8 +354,8 @@ public class Parser {
|
|||
if (content.substring(matchResult+3).startsWith(new String(new char[]{0x7F, 0x40}))) { //followed by Mat
|
||||
String result = "B2C_setDimMat(" + (content.charAt(matchResult+5)-'A') + ", ";
|
||||
if (content.startsWith(new String(new char[]{0x7F, 0x51}))) {
|
||||
result += handleIntConversion(parse(content.substring(0, matchResult) + "[1]")) + ", ";
|
||||
result += handleIntConversion(parse(content.substring(0, matchResult) + "[2]")) + ");";
|
||||
result += handleIntConversion(content.substring(0, matchResult) + "[1]") + ", ";
|
||||
result += handleIntConversion(content.substring(0, matchResult) + "[2]") + ");";
|
||||
return result;
|
||||
} else if (content.startsWith("{")) {
|
||||
Integer[] commaPos = parseArgs(content.substring(1, matchResult));
|
||||
|
@ -443,17 +437,31 @@ public class Parser {
|
|||
//Check for variable assignment
|
||||
} else if (content.substring(matchResult+1).matches("[A-Z\\xCD\\xCE]")) {
|
||||
String result = "B2C_setAlphaVar(" + getAlphaVar(content.charAt(matchResult+1))
|
||||
+ ", " + parse(content.substring(0, matchResult), CONV_TO_BCD) + ")";
|
||||
if (option == WHOLE_INSTRUCTION) {
|
||||
result += ";";
|
||||
}
|
||||
+ ", " + parse(content.substring(0, matchResult), CONV_TO_BCD) + ");";
|
||||
return result;
|
||||
|
||||
//Check for Str assignment
|
||||
} else if (content.substring(matchResult+1).startsWith(new String(new char[]{0xF9, 0x3F}))) {
|
||||
System.out.println("Parsing Str assignment, matchresult = " + matchResult);
|
||||
String result = "B2C_setStr(" + getStr(content.substring(matchResult+3))
|
||||
+ ", " + parse(content.substring(0, matchResult)) + ", " + handleString(content.substring(0, matchResult)) + ");";
|
||||
return result;
|
||||
|
||||
} else {
|
||||
error("Unknown assignment!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Check for strings
|
||||
if (startsWithStringFunction(content)) {
|
||||
if (option == WHOLE_INSTRUCTION) {
|
||||
error("B2C does not support standalone strings!");
|
||||
} else {
|
||||
return parseStr(content, option);
|
||||
}
|
||||
}
|
||||
|
||||
//at this point it is a mathematical operation
|
||||
//stock the level of the parentheses
|
||||
Integer[] parenthesesPos = parseBrackets(content);
|
||||
|
@ -526,7 +534,7 @@ public class Parser {
|
|||
content = content.substring(0, content.length()-1);
|
||||
}
|
||||
return supportAns("list[" + getList(content.substring(2, check[0])) + "].data["
|
||||
+ handleIntConversion(parse(content.substring(check[0]+1, content.length()))) + "]", option);
|
||||
+ handleIntConversion(content.substring(check[0]+1, content.length())) + "]", option);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -768,11 +776,7 @@ public class Parser {
|
|||
|
||||
boolean positionIsString = false;
|
||||
for (int i = 0; i < content.length(); i++) {
|
||||
if (content.charAt(i) == (char)0x7F ||
|
||||
content.charAt(i) == (char)0xF7 ||
|
||||
content.charAt(i) == (char)0xE5 ||
|
||||
content.charAt(i) == (char)0xE6 ||
|
||||
content.charAt(i) == (char)0xE7) {
|
||||
if (isMultibytePrefix(content.charAt(i))) {
|
||||
i += 2;
|
||||
if (i >= content.length()) {
|
||||
break;
|
||||
|
@ -845,13 +849,17 @@ public class Parser {
|
|||
*
|
||||
*/
|
||||
|
||||
public static String parseStr(String content) {
|
||||
//TODO use buffers as str and place free() after
|
||||
public static String parseStr(String content, int option) {
|
||||
System.out.println("Parsing string: "+printNonAscii(content));
|
||||
|
||||
Integer[] parenthesesPos = parseBrackets(content);
|
||||
if (startsWithStringFunction(content)) {
|
||||
|
||||
//Note that standalone strings aren't supported, there is no Str Ans; therefore, no ';'!
|
||||
|
||||
//Parse operators
|
||||
//It is easy because the only operator is the '+'
|
||||
Integer[] parenthesesPos = parseBrackets(content);
|
||||
for (int i = content.length()-1; i >= 0; i--) {
|
||||
if (content.substring(0, i).endsWith(new String(new char[]{0x89}))) {
|
||||
//test if the operator is not within parentheses
|
||||
|
@ -864,40 +872,147 @@ public class Parser {
|
|||
System.out.println("Parsing concatenation operator (+)");
|
||||
|
||||
if (!isInParentheses) {
|
||||
String str = "B2C_strcat(";
|
||||
str += parse(content.substring(0, i-1)) + ", " + parse(content.substring(i));
|
||||
str += ")";
|
||||
//Parse as StrJoin(a,b)
|
||||
String str = parse(new String(new char[]{0xF9,0x30}) + content.substring(0, i-1) + ","
|
||||
+ content.substring(i) + ")", option);
|
||||
if (option == CONV_TO_CHARARRAY) {
|
||||
return "B2C_strToCharArray(" + str + ", " + handleString(str) + ")";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Note that standalone strings aren't supported, there is no Str Ans; therefore, no ';'!
|
||||
|
||||
//Plain strings
|
||||
if (content.startsWith("\"")) {
|
||||
if (content.charAt(content.length()-1) != '"') {
|
||||
content += '"';
|
||||
}
|
||||
content = replaceNonAscii(content);
|
||||
return content;
|
||||
content = "(unsigned char*)" + replaceNonAscii(content);
|
||||
if (option == CONV_TO_CHARARRAY) {
|
||||
return content;
|
||||
}
|
||||
return "B2C_charArrayToStr(" + content + ")";
|
||||
}
|
||||
|
||||
//All subsequent str functions have parenthesis, so check if there is the right number
|
||||
if (parenthesesPos.length != 2) {
|
||||
error("Str function does not have one level of parenthesis!");
|
||||
}
|
||||
//No returns from here; always assign the result to this string!
|
||||
//This is to handle the conversion to char array/str.
|
||||
String result = "";
|
||||
|
||||
//Str function
|
||||
if (content.startsWith(new String(new char[]{0xF9, 0x3F}))) {
|
||||
return getStr(content.substring(2));
|
||||
result = getStr(content.substring(2));
|
||||
|
||||
//All subsequent str functions have parenthesis, so check if there is the right number
|
||||
} else if (parenthesesPos.length != 2) {
|
||||
error("Str function does not have one level of parenthesis! ("+parenthesesPos.length+")");
|
||||
}
|
||||
//StrRotate
|
||||
if (content.startsWith(new String(new char[]{0xF9, 0x3D}))) {
|
||||
return "B2C_strRotate(" + addStrBuffer() + parse(content.substring(2, parenthesesPos[0])) + ")";
|
||||
|
||||
//These string functions all have similar structures (arguments = str, int)
|
||||
String[] strFunctions1 = {"strLeft", "strRight", "strShift", "strRotate"};
|
||||
String[] strOpcodes1 = {new String(new char[]{0xF9,0x34}),
|
||||
new String(new char[]{0xF9,0x35}),
|
||||
new String(new char[]{0xF9,0x3C}),
|
||||
new String(new char[]{0xF9,0x3D}),
|
||||
};
|
||||
for (int i = 0; i < strFunctions1.length; i++) {
|
||||
if (content.startsWith(strOpcodes1[i])) {
|
||||
Integer[] argPos = parseArgs(content.substring(2, parenthesesPos[1]));
|
||||
if (argPos.length > 1) {
|
||||
error(strFunctions1[i]+" does not contain 2 arguments!");
|
||||
}
|
||||
if (argPos.length == 0) {
|
||||
result = "B2C_"+strFunctions1[i]+"(" + parse(content.substring(2, parenthesesPos[1])) + ", " + handleString(content.substring(2, parenthesesPos[1]))
|
||||
+ ", 1)";
|
||||
} else {
|
||||
result = "B2C_"+strFunctions1[i]+"(" + parse(content.substring(2, argPos[0]+2)) + ", " + handleString(content.substring(2, argPos[0]+2))
|
||||
+ ", " + handleIntConversion(content.substring(argPos[0]+2+1, parenthesesPos[1])) + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//These string functions all have similar structures (argument = str)
|
||||
String[] strFunctions2 = {"strInv", "strUpr", "strLwr"};
|
||||
String[] strOpcodes2 = {new String(new char[]{0xF9,0x3B}),
|
||||
new String(new char[]{0xF9,0x39}),
|
||||
new String(new char[]{0xF9,0x3A}),
|
||||
};
|
||||
|
||||
for (int i = 0; i < strFunctions2.length; i++) {
|
||||
if (content.startsWith(strOpcodes2[i])) {
|
||||
result = "B2C_"+strFunctions2[i]+"(" + parse(content.substring(2, parenthesesPos[1])) + ", " + handleString(content.substring(2, parenthesesPos[1])) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
//StrMid
|
||||
if (content.startsWith(new String(new char[]{0xF9, 0x36}))) {
|
||||
Integer[] argPos = parseArgs(content.substring(2, parenthesesPos[1]));
|
||||
if (argPos.length == 1) {
|
||||
//StrMid with only 2 arguments = StrLeft
|
||||
result = "B2C_strMid2args(" + parse(content.substring(2, argPos[0]+2)) + ", " + handleString(content.substring(2, argPos[0]+2))
|
||||
+ ", " + handleIntConversion(content.substring(argPos[0]+2+1, parenthesesPos[1])) + ")";
|
||||
} else if (argPos.length != 2) {
|
||||
error("strMid does not contain 3 arguments!");
|
||||
} else {
|
||||
result = "B2C_strMid(" + parse(content.substring(2, argPos[0]+2)) + ", " + handleString(content.substring(2, argPos[0]+2)) + ", "
|
||||
+ handleIntConversion(content.substring(argPos[0]+2+1, argPos[1]+2)) + ", " + handleIntConversion(content.substring(argPos[1]+2+1, parenthesesPos[1])) + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//StrJoin
|
||||
if (content.startsWith(new String(new char[]{0xF9, 0x30}))) {
|
||||
Integer[] argPos = parseArgs(content.substring(2, parenthesesPos[1]));
|
||||
if (argPos.length != 1) {
|
||||
error("StrJoin function does not contain 2 arguments!");
|
||||
}
|
||||
result = "B2C_strJoin(" + parse(content.substring(2, argPos[0]+2)) + ", " +handleString(content.substring(2, argPos[0]+2)) + ", "
|
||||
+ parse(content.substring(argPos[0]+2+1, parenthesesPos[1])) + ", " +handleString(content.substring(argPos[0]+2+1, parenthesesPos[1])) + ")";
|
||||
}
|
||||
|
||||
|
||||
if (option == CONV_TO_CHARARRAY) {
|
||||
return "B2C_strToCharArray(" + result + ", " + handleString(content) + ")";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return "B2C_convToStr(" + handleAlphaVar(content, NO_OPTION) + ")";
|
||||
|
||||
String result = "";
|
||||
//StrLen
|
||||
if (content.startsWith(new String(new char[]{0xF9, 0x31}))) {
|
||||
result = "B2C_strLen(" + addBCDBuffer() + ", " + parse(content.substring(2, parenthesesPos[1])) + ", " + handleString(content.substring(2, parenthesesPos[1])) + ")";
|
||||
}
|
||||
|
||||
//Both these functions have 2 strings as arguments and return a BCDvar
|
||||
//StrCmp
|
||||
else if (content.startsWith(new String(new char[]{0xF9,0x32}))) {
|
||||
Integer[] argPos = parseArgs(content.substring(2, parenthesesPos[1]));
|
||||
if (argPos.length != 1) {
|
||||
error("StrCmp function does not contain 2 arguments!");
|
||||
}
|
||||
result = "B2C_strCmp(" + addBCDBuffer() + ", " + parse(content.substring(2, argPos[0]+2)) +", " + handleString(content.substring(2, argPos[0]+2)) + ", "
|
||||
+ parse(content.substring(argPos[0]+2+1, parenthesesPos[1])) + ", "+ handleString(content.substring(argPos[0]+2+1, parenthesesPos[1])) + ")";
|
||||
}
|
||||
|
||||
//StrSrc
|
||||
else if (content.startsWith(new String(new char[]{0xF9,0x33}))) {
|
||||
Integer[] argPos = parseArgs(content.substring(2, parenthesesPos[1]));
|
||||
if (argPos.length > 2 || argPos.length < 1) {
|
||||
error("StrSrc function does not contain 2 or 3 arguments!");
|
||||
} else if (argPos.length == 1) {
|
||||
result = "B2C_strSrc(" + addBCDBuffer() + ", " + parse(content.substring(2, argPos[0]+2)) +", " + handleString(content.substring(2, argPos[0]+2)) + ", "
|
||||
+ parse(content.substring(argPos[0]+2+1, parenthesesPos[1])) + ", " +handleString(content.substring(argPos[0]+2+1, parenthesesPos[1])) + ", 1)";
|
||||
} else {
|
||||
result = "B2C_strSrc(" + addBCDBuffer() + ", " + parse(content.substring(2, argPos[0]+2)) +", " + handleString(content.substring(2, argPos[0]+2)) + ", "
|
||||
+ parse(content.substring(argPos[0]+2+1, argPos[1]+2)) +", " + handleString(content.substring(argPos[0]+2+1, argPos[1]+2))
|
||||
+ ", " + handleIntConversion(content.substring(argPos[1]+2+1, parenthesesPos[1])) + ")";
|
||||
}
|
||||
} else {
|
||||
result = handleAlphaVar(content, NO_OPTION);
|
||||
}
|
||||
|
||||
return "B2C_convToStr(" + result + ")";
|
||||
}
|
||||
|
||||
//Replace non-ASCII characters with \xXX, using string concatenation.
|
||||
|
@ -933,7 +1048,7 @@ public class Parser {
|
|||
*
|
||||
*/
|
||||
public static Integer[] parseArgs(String content) {
|
||||
System.out.println("Parsing arguments: "+content);
|
||||
System.out.println("Parsing arguments: "+printNonAscii(content));
|
||||
ArrayList<Integer> args = new ArrayList<Integer>();
|
||||
int argsBuffer = 0;
|
||||
boolean positionIsString = false;
|
||||
|
@ -942,7 +1057,7 @@ public class Parser {
|
|||
if (content.charAt(i) == ',' && argsBuffer == 0 && !positionIsString) {
|
||||
args.add(i);
|
||||
}
|
||||
if ((content.charAt(i) == '(' || content.charAt(i) == '[' || content.charAt(i) == '{') && !positionIsString) {
|
||||
if (startsWithParenthesis(content.substring(i)) && !positionIsString) {
|
||||
argsBuffer++;
|
||||
} else if ((content.charAt(i) == ')' || content.charAt(i) == ']' || content.charAt(i) == '}') && !positionIsString) {
|
||||
argsBuffer--;
|
||||
|
@ -971,20 +1086,7 @@ public class Parser {
|
|||
int bracketsLevel = 0;
|
||||
boolean currentPositionIsString = false;
|
||||
for (int i = 0; i < content.length(); i++) {
|
||||
if (!currentPositionIsString && (content.charAt(i) == '(' || content.charAt(i) == '[' || content.charAt(i) == '{' ||
|
||||
//Check for opcodes that contains parenthesis
|
||||
content.startsWith(new String(new char[]{0x7F, 0x87}), i) || //RanInt#(
|
||||
content.startsWith(new String(new char[]{0x7F, 0x47}), i) || //Fill(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x30}), i) || //StrJoin(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x34}), i) || //StrLeft(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x35}), i) || //StrRight(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x36}), i) || //StrMid(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x39}), i) || //StrUpr(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3A}), i) || //StrLwr(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3B}), i) || //StrInv(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3C}), i) || //StrShift(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3D}), i) //StrRotate(
|
||||
)) {
|
||||
if (!currentPositionIsString && startsWithParenthesis(content.substring(i))) {
|
||||
bracketsLevel++;
|
||||
if (bracketsLevel == 1) {
|
||||
bracketsPos.add(i);
|
||||
|
@ -1013,6 +1115,35 @@ public class Parser {
|
|||
return bracketsPos.toArray(new Integer[bracketsPos.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given string starts with a parenthesis (or a bracket),
|
||||
* but also with an opcode containing a parenthesis (RanInt#(, StrRotate(, etc).
|
||||
*/
|
||||
public static boolean startsWithParenthesis(String content) {
|
||||
if ((content.charAt(0) == '(' || content.charAt(0) == '[' || content.charAt(0) == '{' ||
|
||||
//Check for opcodes that contains parenthesis
|
||||
content.startsWith(new String(new char[]{0x7F, 0x87})) || //RanInt#(
|
||||
content.startsWith(new String(new char[]{0x7F, 0x47})) || //Fill(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x30})) || //StrJoin(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x31})) || //StrLen(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x32})) || //StrCmp(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x33})) || //StrSrc(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x34})) || //StrLeft(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x35})) || //StrRight(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x36})) || //StrMid(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x37})) || //Exp->Str(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x38})) || //Exp(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x39})) || //StrUpr(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3A})) || //StrLwr(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3B})) || //StrInv(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3C})) || //StrShift(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3D})) //StrRotate(
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This method replaces some basic functions (listed below).
|
||||
* Reason for this method is to avoid replacing functions in strings, which can't be done with replaceAll().
|
||||
* The replacements are the following:
|
||||
|
@ -1065,6 +1196,7 @@ public class Parser {
|
|||
public static boolean isMultibytePrefix(char prefix) {
|
||||
if (prefix == (char)0xF7 ||
|
||||
prefix == (char)0x7F ||
|
||||
prefix == (char)0xF9 ||
|
||||
prefix == (char)0xE5 ||
|
||||
prefix == (char)0xE6 ||
|
||||
prefix == (char)0xE7)
|
||||
|
@ -1073,6 +1205,7 @@ public class Parser {
|
|||
}
|
||||
/**
|
||||
* Returns true if the given string starts with a string function.
|
||||
* A string function is defined as a function that returns a string.
|
||||
* That means that Str, StrLwr, StrShift, '"', ... return true,
|
||||
* but not StrLen, StrCmp or StrSrc as they return BCDvars!
|
||||
*
|
||||
|
@ -1106,8 +1239,8 @@ public class Parser {
|
|||
public static String handleIntConversion(String content) {
|
||||
//TODO: optimise some cases like "A+2" where you could convert A then add 2
|
||||
//instead of calculating "A+2" in BCD
|
||||
if (content.matches("\\d+")) {
|
||||
return content;
|
||||
if (Constants.isNumber(content)) {
|
||||
return Constants.getNumberNotation(content);
|
||||
}
|
||||
return "B2C_convToUInt(" + parse(content) + ")";
|
||||
}
|
||||
|
@ -1121,6 +1254,30 @@ public class Parser {
|
|||
return parse(content, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the isString param, required for any function taking a string as argument.
|
||||
* If isString(content) returns true, this function returns "TRUE". Else it returns "FALSE".
|
||||
*/
|
||||
|
||||
public static String handleString(String content) {
|
||||
if (isString(content)) {
|
||||
return "TRUE";
|
||||
}
|
||||
return "FALSE";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff the content consists only of the Str function.
|
||||
* "Str 1 + StrRotate(Str 2)" will return false.
|
||||
* "Str 20" will return true.
|
||||
*/
|
||||
public static boolean isString(String content) {
|
||||
if (content.startsWith(new String(new char[]{0xF9, 0x3F})) && content.length() <= 4) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void incrementTabs() {
|
||||
tabs += "\t";
|
||||
}
|
||||
|
@ -1162,12 +1319,12 @@ public class Parser {
|
|||
if (list.length() == 1 && list.charAt(0) == 0xC0) {
|
||||
return "LIST_ANS";
|
||||
} else {
|
||||
return handleIntConversion(parse(list));
|
||||
return handleIntConversion(list);
|
||||
}
|
||||
}
|
||||
public static String getStr(String str) {
|
||||
if (str.length() > 2) {
|
||||
error("Invalid str " + str + "!");
|
||||
error("Invalid str " + printNonAscii(str) + "!");
|
||||
}
|
||||
try {
|
||||
int strno = Integer.valueOf(str);
|
||||
|
@ -1177,12 +1334,12 @@ public class Parser {
|
|||
} catch (NumberFormatException e) {
|
||||
error("Invalid str " + str + "!");
|
||||
}
|
||||
return "&str["+Integer.valueOf(str)+"]";
|
||||
return "STR_"+Integer.valueOf(str);
|
||||
|
||||
}
|
||||
|
||||
public static String addBCDBuffer() {return addBuffer(BCD_BUFFER);}
|
||||
public static String addStrBuffer() {return addBuffer(STR_BUFFER);}
|
||||
//public static String addStrBuffer() {return addBuffer(STR_BUFFER);}
|
||||
public static String addMatBuffer() {return addBuffer(MAT_BUFFER);}
|
||||
public static String addListBuffer() {return addBuffer(LIST_BUFFER);}
|
||||
|
||||
|
|
Loading…
Reference in New Issue