📄 script.c
字号:
add_scriptb(a&0x3f);
}
/*==========================================
* 僗僋儕僾僩僶僢僼傽偵惍悢傪彂偒崬傓
*------------------------------------------
*/
static void add_scripti(int a)
{
while(a>=0x40){
add_scriptb(a|0xc0);
a=(a-0x40)>>6;
}
add_scriptb(a|0x80);
}
/*==========================================
* 僗僋儕僾僩僶僢僼傽偵儔儀儖/曄悢/娭悢傪彂偒崬傓
*------------------------------------------
*/
// 嵟戝16M傑偱
static void add_scriptl(int l)
{
int backpatch = str_data[l].backpatch;
switch(str_data[l].type){
case C_POS:
add_scriptc(C_POS);
add_scriptb(str_data[l].label);
add_scriptb(str_data[l].label>>8);
add_scriptb(str_data[l].label>>16);
break;
case C_NOP:
// 儔儀儖偺壜擻惈偑偁傞偺偱backpatch梡僨乕僞杽傔崬傒
add_scriptc(C_NAME);
str_data[l].backpatch=script_pos;
add_scriptb(backpatch);
add_scriptb(backpatch>>8);
add_scriptb(backpatch>>16);
break;
case C_INT:
add_scripti(str_data[l].val);
break;
default:
// 傕偆懠偺梡搑偲妋掕偟偰傞偺偱悢帤傪偦偺傑傑
add_scriptc(C_NAME);
add_scriptb(l);
add_scriptb(l>>8);
add_scriptb(l>>16);
break;
}
}
/*==========================================
* 儔儀儖傪夝寛偡傞
*------------------------------------------
*/
void set_label(int l,int pos)
{
int i,next;
str_data[l].type=C_POS;
str_data[l].label=pos;
for(i=str_data[l].backpatch;i>=0 && i!=0x00ffffff;){
next=(*(int*)(script_buf+i)) & 0x00ffffff;
script_buf[i-1]=C_POS;
script_buf[i]=pos;
script_buf[i+1]=pos>>8;
script_buf[i+2]=pos>>16;
i=next;
}
}
/*==========================================
* 僗儁乕僗/僐儊儞僩撉傒旘偽偟
*------------------------------------------
*/
static unsigned char *skip_space(unsigned char *p)
{
while(1){
while(isspace(*p))
p++;
if(p[0]=='/' && p[1]=='/'){
while(*p && *p!='\n')
p++;
} else if(p[0]=='/' && p[1]=='*'){
p++;
while(*p && (p[-1]!='*' || p[0]!='/'))
p++;
if(*p) p++;
} else
break;
}
return p;
}
/*==========================================
* 侾扨岅僗僉僢僾
*------------------------------------------
*/
static unsigned char *skip_word(unsigned char *p)
{
// prefix
if(*p=='$') p++; // MAP嶪撪嫟桳曄悢梡
if(*p=='@') p++; // 堦帪揑曄悢梡(like weiss)
if(*p=='#') p++; // account曄悢梡
if(*p=='#') p++; // 儚乕儖僪account曄悢梡
while(isalnum(*p)||*p=='_'|| *p>=0x81)
if(*p>=0x81 && p[1]){
p+=2;
} else
p++;
// postfix
if(*p=='$') p++; // 暥帤楍曄悢
return p;
}
static unsigned char *startptr;
static int startline;
/*==========================================
* 僄儔乕儊僢僙乕僕弌椡
*------------------------------------------
*/
static void disp_error_message(const char *mes,const unsigned char *pos)
{
int line,c=0,i;
unsigned char *p,*linestart,*lineend;
for(line=startline,p=startptr;p && *p;line++){
linestart=p;
lineend=strchr(p,'\n');
if(lineend){
c=*lineend;
*lineend=0;
}
if(lineend==NULL || pos<lineend){
printf("%s line %d : ",mes,line);
for(i=0;linestart[i];i++){
if(linestart+i!=pos)
printf("%c",linestart[i]);
else
printf("\'%c\'",linestart[i]);
}
printf("\n");
if(lineend)
*lineend=c;
return;
}
*lineend=c;
p=lineend+1;
}
}
/*==========================================
* 崁偺夝愅
*------------------------------------------
*/
unsigned char* parse_simpleexpr(unsigned char *p)
{
int i;
p=skip_space(p);
#ifdef DEBUG_FUNCIN
if(battle_config.etc_log)
printf("parse_simpleexpr %s\n",p);
#endif
if(*p==';' || *p==','){
disp_error_message("unexpected expr end",p);
exit(1);
}
if(*p=='('){
p=parse_subexpr(p+1,-1);
p=skip_space(p);
if((*p++)!=')'){
disp_error_message("unmatch ')'",p);
exit(1);
}
} else if(isdigit(*p) || ((*p=='-' || *p=='+') && isdigit(p[1]))){
char *np;
i=strtoul(p,&np,0);
add_scripti(i);
p=np;
} else if(*p=='"'){
add_scriptc(C_STR);
p++;
while(*p && *p!='"'){
if(p[-1]<=0x7e && *p=='\\')
p++;
else if(*p=='\n'){
disp_error_message("unexpected newline @ string",p);
exit(1);
}
add_scriptb(*p++);
}
if(!*p){
disp_error_message("unexpected eof @ string",p);
exit(1);
}
add_scriptb(0);
p++; //'"'
} else {
int c,l;
char *p2;
// label , register , function etc
if(skip_word(p)==p){
disp_error_message("unexpected charactor",p);
exit(1);
}
p2=skip_word(p);
c=*p2; *p2=0; // 柤慜傪add_str偡傞
l=add_str(p);
parse_cmd=l; // warn_*_mismatch_paramnum偺偨傔偵昁梫
if(l==search_str("if")) // warn_cmd_no_comma偺偨傔偵昁梫
parse_cmd_if++;
// 攑巭梊掕偺l14/l15,偍傛傃僾儗僼傿僢僋僗倢偺寈崘
if( strcmp(str_buf+str_data[l].str,"l14")==0 ||
strcmp(str_buf+str_data[l].str,"l15")==0 ){
disp_error_message("l14 and l15 is DEPRECATED. use @menu instead of l15.",p);
}else if(str_buf[str_data[l].str]=='l'){
disp_error_message("prefix 'l' is DEPRECATED. use prefix '@' instead.",p2);
}
*p2=c; p=p2;
if(str_data[l].type!=C_FUNC && c=='['){
// array(name[i] => getelementofarray(name,i) )
add_scriptl(search_str("getelementofarray"));
add_scriptc(C_ARG);
add_scriptl(l);
p=parse_subexpr(p+1,-1);
p=skip_space(p);
if((*p++)!=']'){
disp_error_message("unmatch ']'",p);
exit(1);
}
add_scriptc(C_FUNC);
}else
add_scriptl(l);
}
#ifdef DEBUG_FUNCIN
if(battle_config.etc_log)
printf("parse_simpleexpr end %s\n",p);
#endif
return p;
}
/*==========================================
* 幃偺夝愅
*------------------------------------------
*/
unsigned char* parse_subexpr(unsigned char *p,int limit)
{
int op,opl,len;
char *tmpp;
#ifdef DEBUG_FUNCIN
if(battle_config.etc_log)
printf("parse_subexpr %s\n",p);
#endif
p=skip_space(p);
if(*p=='-'){
tmpp=skip_space(p+1);
if(*tmpp==';' || *tmpp==','){
add_scriptl(LABEL_NEXTLINE);
p++;
return p;
}
}
tmpp=p;
if((op=C_NEG,*p=='-') || (op=C_LNOT,*p=='!') || (op=C_NOT,*p=='~')){
p=parse_subexpr(p+1,100);
add_scriptc(op);
} else
p=parse_simpleexpr(p);
p=skip_space(p);
while(((op=C_ADD,opl=6,len=1,*p=='+') ||
(op=C_SUB,opl=6,len=1,*p=='-') ||
(op=C_MUL,opl=7,len=1,*p=='*') ||
(op=C_DIV,opl=7,len=1,*p=='/') ||
(op=C_MOD,opl=7,len=1,*p=='%') ||
(op=C_FUNC,opl=8,len=1,*p=='(') ||
(op=C_LAND,opl=1,len=2,*p=='&' && p[1]=='&') ||
(op=C_AND,opl=5,len=1,*p=='&') ||
(op=C_LOR,opl=0,len=2,*p=='|' && p[1]=='|') ||
(op=C_OR,opl=4,len=1,*p=='|') ||
(op=C_XOR,opl=3,len=1,*p=='^') ||
(op=C_EQ,opl=2,len=2,*p=='=' && p[1]=='=') ||
(op=C_NE,opl=2,len=2,*p=='!' && p[1]=='=') ||
(op=C_GE,opl=2,len=2,*p=='>' && p[1]=='=') ||
(op=C_GT,opl=2,len=1,*p=='>') ||
(op=C_LE,opl=2,len=2,*p=='<' && p[1]=='=') ||
(op=C_LT,opl=2,len=1,*p=='<')) && opl>limit){
p+=len;
if(op==C_FUNC){
int i=0,func=parse_cmd;
const char *plist[128];
if( str_data[func].type!=C_FUNC ){
disp_error_message("expect function",tmpp);
exit(0);
}
add_scriptc(C_ARG);
do {
plist[i]=p;
p=parse_subexpr(p,-1);
p=skip_space(p);
if(*p==',') p++;
else if(*p!=')' && script_config.warn_func_no_comma){
disp_error_message("expect ',' or ')' at func params",p);
}
p=skip_space(p);
i++;
} while(*p && *p!=')' && i<128);
plist[i]=p;
if(*(p++)!=')'){
disp_error_message("func request '(' ')'",p);
exit(1);
}
if( str_data[func].type==C_FUNC && script_config.warn_func_mismatch_paramnum){
const char *arg=buildin_func[str_data[func].val].arg;
int j=0;
for(j=0;arg[j];j++) if(arg[j]=='*')break;
if( (arg[j]==0 && i!=j) || (arg[j]=='*' && i<j) ){
disp_error_message("illeagal number of parameters",plist[(i<j)?i:j]);
}
}
} else {
p=parse_subexpr(p,opl);
}
add_scriptc(op);
p=skip_space(p);
}
#ifdef DEBUG_FUNCIN
if(battle_config.etc_log)
printf("parse_subexpr end %s\n",p);
#endif
return p; /* return first untreated operator */
}
/*==========================================
* 幃偺昡壙
*------------------------------------------
*/
unsigned char* parse_expr(unsigned char *p)
{
#ifdef DEBUG_FUNCIN
if(battle_config.etc_log)
printf("parse_expr %s\n",p);
#endif
switch(*p){
case ')': case ';': case ':': case '[': case ']':
case '}':
disp_error_message("unexpected char",p);
exit(1);
}
p=parse_subexpr(p,-1);
#ifdef DEBUG_FUNCIN
if(battle_config.etc_log)
printf("parse_expr end %s\n",p);
#endif
return p;
}
/*==========================================
* 峴偺夝愅
*------------------------------------------
*/
unsigned char* parse_line(unsigned char *p)
{
int i=0,cmd;
const char *plist[128];
char *p2;
p=skip_space(p);
if(*p==';')
return p;
parse_cmd_if=0; // warn_cmd_no_comma偺偨傔偵昁梫
// 嵟弶偼娭悢柤
p2=p;
p=parse_simpleexpr(p);
p=skip_space(p);
cmd=parse_cmd;
if( str_data[cmd].type!=C_FUNC ){
disp_error_message("expect command",p2);
exit(0);
}
add_scriptc(C_ARG);
while(p && *p && *p!=';' && i<128){
plist[i]=p;
p=parse_expr(p);
p=skip_space(p);
// 堷悢嬫愗傝偺,張棟
if(*p==',') p++;
else if(*p!=';' && script_config.warn_cmd_no_comma && parse_cmd_if*2<=i ){
disp_error_message("expect ',' or ';' at cmd params",p);
}
p=skip_space(p);
i++;
}
plist[i]=p;
if(!p || *(p++)!=';'){
disp_error_message("need ';'",p);
exit(1);
}
add_scriptc(C_FUNC);
if( str_data[cmd].type==C_FUNC && script_config.warn_cmd_mismatch_paramnum){
const char *arg=buildin_func[str_data[cmd].val].arg;
int j=0;
for(j=0;arg[j];j++) if(arg[j]=='*')break;
if( (arg[j]==0 && i!=j) || (arg[j]=='*' && i<j) ){
disp_error_message("illeagal number of parameters",plist[(i<j)?i:j]);
}
}
return p;
}
/*==========================================
* 慻傒崬傒娭悢偺捛壛
*------------------------------------------
*/
static void add_buildin_func(void)
{
int i,n;
for(i=0;buildin_func[i].func;i++){
n=add_str(buildin_func[i].name);
str_data[n].type=C_FUNC;
str_data[n].val=i;
str_data[n].func=buildin_func[i].func;
}
}
/*==========================================
* 掕悢僨乕僞儀乕僗偺撉傒崬傒
*------------------------------------------
*/
static void read_constdb(void)
{
FILE *fp;
char line[1024],name[1024];
int val,n,i,type;
fp=fopen("db/const.txt","r");
if(fp==NULL){
printf("can't read db/const.txt\n");
return ;
}
while(fgets(line,1020,fp)){
if(line[0]=='/' && line[1]=='/')
continue;
type=0;
if(sscanf(line,"%[A-Za-z0-9_],%d,%d",name,&val,&type)>=2 ||
sscanf(line,"%[A-Za-z0-9_] %d %d",name,&val,&type)>=2){
for(i=0;name[i];i++)
name[i]=tolower(name[i]);
n=add_str(name);
if(type==0)
str_data[n].type=C_INT;
else
str_data[n].type=C_PARAM;
str_data[n].val=val;
}
}
fclose(fp);
}
/*==========================================
* 僗僋儕僾僩偺夝愅
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -