| /////////////////////////////////////////////////////////////////////////////// |
| // // |
| // Copyright (c) 2000-2019 Ericsson Telecom AB // |
| // // |
| // All rights reserved. This program and the accompanying materials // |
| // are made available under the terms of the Eclipse Public License v2.0 // |
| // which accompanies this distribution, and is available at // |
| // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html // |
| // // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| #include "EPTF_CLL_SMacro_Functions.hh" |
| #include <ctype.h> |
| |
| namespace EPTF__CLL__SMacro__Functions |
| { |
| |
| ///////////////////////////////////////////// |
| // |
| // checks whether the macro name is valid |
| // |
| ///////////////////////////////////////////// |
| |
| INTEGER f__EPTF__SMacro__checkName( |
| const CHARSTRING& pl__macro__name){ |
| |
| const char* str=pl__macro__name; |
| int str_len = pl__macro__name.lengthof(); |
| int pos=0; |
| |
| if(str_len ==0) return 1; // empty macro name not accepted |
| |
| while(isalnum(str[pos]) || str[pos]=='_') pos++; // alphanumeric and "_" characters |
| |
| if(pos != str_len){ |
| return 1; |
| } |
| |
| return 0; // macro name accepted |
| } |
| |
| ///////////////////////////////////////////// |
| // |
| // only for syntax $macro_name |
| // |
| ///////////////////////////////////////////// |
| CHARSTRING f__EPTF__SMacro__getSimpleMacroName( |
| const CHARSTRING& pl__stringTemplate, |
| const INTEGER& pl__macroBeginOffset){ |
| |
| if(pl__stringTemplate.lengthof()==0) return ""; |
| |
| const char* str=(const char*)pl__stringTemplate+pl__macroBeginOffset+(int)1; // +1: remove "$" from the begining |
| int pos=0; |
| while(isalnum(str[pos]) || str[pos]=='_') pos++; // alphanumeric and "_" characters |
| |
| return CHARSTRING (pos,str); |
| } |
| |
| ///////////////////////////////////////////// |
| // |
| // only for syntax $(macro_name) |
| // |
| ///////////////////////////////////////////// |
| CHARSTRING f__EPTF__SMacro__getMacroName( |
| const CHARSTRING& pl__stringTemplate, |
| const INTEGER& pl__macroBeginOffset){ |
| |
| if(pl__stringTemplate.lengthof()==0) return ""; |
| |
| const char* str=(const char*)pl__stringTemplate+pl__macroBeginOffset+(int)1; // remove "$" from the begining |
| int pos=0; |
| |
| if(str[pos] != '('){ // must start with "(" character |
| return ""; |
| } |
| str=str+1; // "(" // skip "(" |
| |
| while(isalnum(str[pos]) || str[pos]=='_') pos++; // alphanumeric and "_" characters |
| |
| if(str[pos]!=')'){ // ")" character not found at the end |
| return ""; |
| } |
| |
| return CHARSTRING (pos,str); |
| } |
| |
| ///////////////////////////////////////////// |
| // |
| // only for syntax $(macro,"par","par2"...) |
| // |
| ///////////////////////////////////////////// |
| CHARSTRING f__EPTF__SMacro__getMacroWithPar( |
| const CHARSTRING& pl__stringTemplate, |
| const INTEGER& pl__macroBeginOffset, |
| CHARSTRING& pl__macro__name, |
| CHARSTRING& pl__parString |
| ){ |
| |
| CHARSTRING retVal=""; |
| pl__macro__name=""; |
| pl__parString=""; |
| |
| if(pl__stringTemplate.lengthof() ==0 ) return retVal; |
| |
| const char* str=(const char*)pl__stringTemplate+pl__macroBeginOffset+(int)1; // remove "$" from the begining |
| |
| int pos=0; |
| int pos1=0; // end of macro name |
| int len= pl__stringTemplate.lengthof()-pl__macroBeginOffset-1; // length without "$" |
| bool found=false; |
| int posTemp=0; // searching backward |
| |
| if(str[0] != '('){ // does not match with the syntax |
| return retVal; |
| } |
| str=str+1; // skip "(" |
| |
| while(isalnum(str[pos]) || str[pos]=='_' && pos<len) pos++; // alphanumeric and "_" characters for macro name |
| pos1=pos; // end of macro name |
| |
| if(pos1==0){ // macro name not found |
| return retVal; |
| } |
| |
| while(isblank(str[pos]) && pos<len) pos++; // "/t" and " " characters are accepted |
| |
| while(str[pos] != ')' && pos<len){ |
| |
| if(str[pos] != ','){ // must be one comma |
| return retVal; |
| } |
| pos=pos+1; // skip "," |
| |
| while(isblank(str[pos]) && pos<len) pos++; // "/t" and " " characters are accepted |
| |
| if(str[pos] != '"'){ // open quotation mark |
| return retVal; |
| } |
| pos=pos+1; // skip open quotation mark |
| |
| while(found!=true && pos<len){ |
| pos++; |
| while(str[pos] != '"' && pos<len) pos++; // go until end quotation mark, escape level is considered |
| |
| posTemp=pos-1; |
| while(str[posTemp] == '\\' && posTemp-1 >pos1) posTemp--; // search backward for escape characters |
| if((pos-posTemp+1)%2 ==0) { // even number of escape character found so this is the end of parameter string |
| found=true; |
| } |
| } |
| found=false; |
| |
| if(str[pos] != '"'){ |
| return retVal; |
| } |
| pos=pos+1; // skip end quotation mark |
| |
| while(isblank(str[pos]) && pos<len) pos++; // "/t" and " " characters are accepted |
| } |
| |
| pl__macro__name=CHARSTRING(pos1,str); |
| pl__parString=CHARSTRING(pos-pos1,str+pos1); |
| retVal=CHARSTRING(pos,str); |
| |
| return retVal; |
| } |
| |
| ///////////////////////////////////////////// |
| // |
| // to get macro param |
| // |
| ///////////////////////////////////////////// |
| CHARSTRING f__EPTF__SMacro__getMacroParam( |
| CHARSTRING& pl__parString |
| ){ |
| |
| int pos=0; |
| int pos1=0; // open quotation mark |
| int pos2=0; // end quotation mark |
| int posTemp=0; // searching backward |
| int len= pl__parString.lengthof(); |
| const char* str=pl__parString; |
| bool found=false; |
| CHARSTRING retVal=""; |
| |
| while(str[pos] != '"' && pos<len) pos++; // open quotation mark |
| pos1=pos; |
| |
| while(found!=true && pos<len){ |
| pos++; |
| while(str[pos] != '"' && pos<len) pos++; // go until end quotation mark, escape level is considered |
| |
| posTemp=pos-1; |
| while(str[posTemp] == '\\' && posTemp-1 >pos1) posTemp--; // search backward for escape characters |
| if((pos-posTemp+1)%2 ==0) { // even number of escape character found so this is the end of parameter string |
| found=true; |
| } |
| } |
| |
| pos2=pos; |
| pos=pos+1; // skip end quotation mark |
| |
| while(isblank(str[pos]) && pos<len) pos++; // "/t" and " " characters are accepted |
| |
| retVal=CHARSTRING(pos2-pos1+1,str+pos1); // +1: end quotation is needed |
| pl__parString=CHARSTRING(len-pos,str+pos); |
| |
| return retVal; |
| } |
| |
| ///////////////////////////////////////////// |
| // |
| // to get expression for EVAL |
| // |
| ///////////////////////////////////////////// |
| |
| void f__EPTF__SMacro__getExpression( |
| const CHARSTRING& pl__inputStr, |
| CHARSTRING& pl__firstArgSignStr, |
| CHARSTRING& pl__firstArg, |
| CHARSTRING& pl__operator, |
| CHARSTRING& pl__secondArgSignStr, |
| CHARSTRING& pl__secondArg, |
| CHARSTRING& pl__firstIntStr, |
| CHARSTRING& pl__secondIntStr){ |
| |
| pl__firstArgSignStr=""; |
| pl__firstArg=""; |
| pl__operator=""; |
| pl__secondArgSignStr=""; |
| pl__secondArg=""; |
| pl__firstIntStr=""; |
| pl__secondIntStr=""; |
| |
| const char* str=pl__inputStr; |
| int len= pl__inputStr.lengthof(); |
| if(len==0 ) return; |
| int pos=0; |
| int pos1=0; // end of first arg signum |
| int pos2=0; // end of first arg |
| int pos3=0; // pos of operator |
| int pos4=0; // end of second arg signum |
| int pos5=0; // end of second arg |
| int pos6=0; // end of first integer arg quess |
| int pos7=0; // end of second integer arg quess |
| bool dotFound=false; |
| bool eFound=false; |
| bool eSignFound=false; |
| |
| while(pos<len) { |
| |
| dotFound=false; |
| eFound=false; |
| eSignFound=false; |
| |
| while((str[pos]== '+' || str[pos]== '-') && pos<len) pos++; // signum could be: + - |
| |
| if(pos1 == 0 && pos3==0){ |
| pos1=pos; |
| }else if (pos4 ==0){ |
| pos4=pos; |
| } |
| |
| while(isdigit(str[pos]) && pos<len) pos++; // any digits |
| |
| if(str[pos] == '.'){ |
| dotFound=true; |
| pos++; // skip dot |
| } |
| else if(pos6==0){ |
| pos6=pos; |
| }else if(pos7==0){ |
| pos7=pos; |
| } |
| |
| if(not isdigit(str[pos]) && dotFound){ // at least one digit after dot |
| return; // there is no digit after dot |
| } |
| |
| if(str[pos] == 'e'){ // for example: 2.0e-1 |
| eFound=true; |
| pos++; |
| if(str[pos] == '+' || str[pos] == '-'){ |
| eSignFound=true; |
| pos++; |
| } |
| } |
| |
| if(not isdigit(str[pos]) && eFound){ // at least one digit after exponent |
| return; |
| } |
| |
| while(isdigit(str[pos]) && pos<len) pos++; // then any digits |
| |
| if(pos2 == 0){ |
| pos2=pos; |
| }else if (pos5==0){ |
| pos5=pos; |
| } |
| |
| if(pos3== 0 && (str[pos] == '*' || str[pos] == '/' || str[pos] == '%' || str[pos] == '+' || str[pos] == '-')){ |
| pos++; |
| pos3=pos; |
| } |
| } |
| |
| pl__firstArgSignStr=CHARSTRING(pos1,str); |
| pl__firstArg=CHARSTRING(pos2-pos1,str+pos1); |
| pl__operator=CHARSTRING(1,str+pos2); |
| pl__secondArgSignStr=CHARSTRING(pos4-pos3,str+pos3); |
| pl__secondArg=CHARSTRING(pos5-pos4,str+pos4); |
| |
| if(pos6==pos2){ |
| pl__firstIntStr=pl__firstArg; |
| } |
| if(pos7==pos5){ |
| pl__secondIntStr=pl__secondArg; |
| } |
| } |
| |
| ///////////////////////////////////////////// |
| // |
| // checks whether the string is float number |
| // |
| ///////////////////////////////////////////// |
| |
| CHARSTRING f__EPTF__SMacro__isFloat( |
| const CHARSTRING& pl__inputStr){ |
| |
| const char* str=pl__inputStr; |
| int len= pl__inputStr.lengthof(); |
| CHARSTRING retVal=""; |
| if(len==0 ) return retVal; |
| int pos=0; |
| bool dotFound=false; |
| bool eFound=false; |
| bool eSignFound=false; |
| |
| if(str[pos] == '-' || str[pos] == '+'){ // skip signum |
| pos++; |
| } |
| |
| if(not isdigit(str[pos])){ // should start with one digit |
| return retVal; |
| } |
| pos++; // skip digit |
| |
| while(pos<len) { |
| while(isdigit(str[pos]) && pos<len) pos++; // any digits |
| |
| if(str[pos] == '.'){ |
| dotFound=true; |
| pos++; // skip dot |
| } |
| |
| if(not isdigit(str[pos]) && dotFound){ // at least one digit after dot |
| pos--; // there is no digit after dot |
| break; |
| } |
| |
| while(isdigit(str[pos]) && pos<len) pos++; // then any digits |
| |
| if(str[pos] == 'e'){ // for example: 2.0e-1 |
| eFound=true; |
| pos++; |
| if(str[pos] == '+' || str[pos] == '-'){ |
| eSignFound=true; |
| pos++; |
| } |
| } |
| |
| if(not isdigit(str[pos]) && eFound){ // at least one digit after exponent |
| pos--; |
| if(eSignFound){ |
| pos--; |
| } |
| break; |
| } |
| while(isdigit(str[pos]) && pos<len) pos++; // then any digits |
| |
| break; |
| } |
| |
| retVal=CHARSTRING(pos,str); |
| return retVal; |
| } |
| |
| |
| ///////////////////////////////////////////// |
| // |
| // to get first expression |
| // |
| ///////////////////////////////////////////// |
| |
| CHARSTRING f__EPTF__SMacro__getFirstExpression( |
| const CHARSTRING& pl__inputStr, |
| const CHARSTRING& pl__ops, |
| CHARSTRING& pl__prefix, |
| CHARSTRING& pl__postfix |
| ){ |
| |
| pl__prefix=""; |
| pl__postfix=pl__inputStr; |
| CHARSTRING retVal=""; // expression |
| |
| int pos=0; |
| int pos1=0; // pos of first arg start |
| int pos2=0; // pos of second arg end |
| int posTemp=0; // searching backward |
| |
| bool firstArgFound=false; |
| bool secondArgFound=false; |
| bool opFound=false; |
| bool bracketFound=false; |
| CHARSTRING tmp=""; |
| CHARSTRING tmp2=""; |
| |
| const char* str=pl__inputStr; |
| int len= pl__inputStr.lengthof(); |
| |
| if(pl__ops == "("){ // "(" precedence |
| |
| while(pos<len){ |
| |
| while(str[pos] != '(' && pos<len) pos++; // go until open bracket |
| |
| if(str[pos] == '('){ |
| pos1=pos; |
| pos++; // skip open bracket |
| |
| while((str[pos] == '+' || str[pos] == '-') && pos <len) pos++; // further signums |
| |
| tmp2=f__EPTF__SMacro__isFloat(str+pos); // float number with only one signum |
| if(tmp2.lengthof() !=0){ |
| pos=pos+tmp2.lengthof(); |
| } |
| |
| if(str[pos] == ')'){ |
| if(pos > pos1+1){ // there is a float between brackets |
| bracketFound=true; |
| pos2=pos+1; // skip end bracket |
| } |
| break; |
| } |
| }else pos++; |
| } |
| } |
| else if(pl__ops=="*/%"){ // "*" precedence |
| |
| while(not firstArgFound && not secondArgFound && not opFound && pos <len){ |
| |
| while(not isdigit(str[pos]) && pos<len) pos++; // go until the first digit |
| |
| posTemp=pos; |
| while((str[posTemp-1] == '+' || str[posTemp-1] == '-') && posTemp >0) posTemp--; // go backward for multiple signums |
| |
| if(isdigit(str[posTemp-1])){ // there is a number before signum, which is the oprator itself |
| pos1=posTemp+1; // skip the operator |
| } |
| else{ // considering all signum digit |
| pos1=posTemp; |
| } |
| |
| tmp=f__EPTF__SMacro__isFloat(str+pos); |
| if(tmp.lengthof() !=0){ // float found |
| pos=pos+tmp.lengthof(); |
| |
| if(str[pos] == '*' || str[pos] == '/' || str[pos] == '%'){ // first arg + operator found |
| opFound=true; |
| firstArgFound=true; |
| pos++; |
| } |
| |
| tmp=""; |
| if(firstArgFound && opFound){ |
| while((str[pos] == '+' || str[pos] == '-') && pos < len) pos++; // skip multiple signums for second arg |
| tmp=f__EPTF__SMacro__isFloat(str+pos); // searching for second arg |
| } |
| |
| if(tmp.lengthof() !=0){ // second arg found |
| secondArgFound=true; |
| pos=pos+tmp.lengthof(); |
| pos2=pos; |
| } |
| else{ // second arg not found recheck from next char |
| pos++; |
| firstArgFound=false; |
| opFound=false; |
| } |
| } |
| else{ // first arg not found recheck from next char |
| pos++; |
| } |
| } |
| } |
| else if(pl__ops=="+-"){ // "+" precedence |
| |
| while(not firstArgFound && not secondArgFound && not opFound && pos <len){ |
| |
| while(not isdigit(str[pos]) && pos<len) pos++; // go until the first digit |
| |
| posTemp=pos; |
| while((str[posTemp-1] == '+' || str[posTemp-1] == '-') && posTemp>0) posTemp--; // go backward for further signums |
| |
| tmp=f__EPTF__SMacro__isFloat(str+pos); |
| if(tmp.lengthof() !=0){ // first arg found |
| pos1=posTemp; |
| pos=pos+tmp.lengthof(); |
| |
| while((str[pos] == '+' || str[pos] == '-') && pos<len){ // any signum including the operator |
| opFound=true; |
| firstArgFound=true; |
| pos++; |
| } |
| |
| tmp=""; |
| if(firstArgFound && opFound){ |
| tmp=f__EPTF__SMacro__isFloat(str+pos); // searching for second arg |
| } |
| |
| if(tmp.lengthof() !=0){ // second arg found |
| secondArgFound=true; |
| pos=pos+tmp.lengthof(); |
| pos2=pos; |
| |
| } |
| else{ // second arg not found recheck from next char |
| pos++; |
| firstArgFound=false; |
| opFound=false; |
| } |
| } |
| else{ // first arg not found recheck from next char |
| pos++; |
| } |
| } |
| } |
| |
| if((firstArgFound && secondArgFound && opFound) || bracketFound){ |
| pl__prefix=CHARSTRING(len-(len-pos1),str); |
| pl__postfix=CHARSTRING(len-pos2,str+pos2); |
| retVal=CHARSTRING(len-pos1-(len-pos2),str+pos1); |
| } |
| |
| return retVal; |
| } |
| |
| |
| ///////////////////////////////////////////// |
| // |
| // to calculate signum bits at the begining of the string |
| // |
| ///////////////////////////////////////////// |
| |
| CHARSTRING f__EPTF__SMacro__calcSignum( |
| const CHARSTRING& pl__inputStr){ |
| |
| const char* str=pl__inputStr; |
| int len= pl__inputStr.lengthof(); |
| int pos=0; |
| int num=0; |
| CHARSTRING retVal=""; // expression |
| |
| while((str[pos] == '+' || str[pos] == '-') && pos<len){ |
| if(str[pos] == '-'){ |
| num++; |
| } |
| pos++; |
| } |
| |
| retVal=CHARSTRING(len-pos,str+pos); |
| |
| if(num%2 !=0){ |
| retVal="-"+retVal; |
| } |
| |
| return retVal; |
| } |
| |
| |
| ///////////////////////////////////////////// |
| // |
| // to get last float of a syntactically valid expression |
| // |
| ///////////////////////////////////////////// |
| CHARSTRING f__EPTF__SMacro__getLastFloat( |
| CHARSTRING& pl__valueStr |
| ){ |
| |
| const char* str=pl__valueStr; |
| int len= pl__valueStr.lengthof(); |
| int pos=0; |
| int pos1=0; // pos of last float |
| CHARSTRING retVal=""; // last float |
| CHARSTRING tmp=""; |
| |
| while((str[pos]!= '*' && str[pos]!= '/' && str[pos]!= '%' && str[pos]!= '+' && str[pos]!= '-') && pos<len) pos++; // go until operator |
| |
| if(str[pos] != '*' && str[pos] != '/' && str[pos] != '%' && str[pos] != '+' && str[pos] != '-') { // operator not found |
| return retVal; |
| } |
| |
| pos++; // skip operator |
| pos1=pos; |
| |
| tmp=f__EPTF__SMacro__isFloat(str+pos); |
| |
| if(tmp.lengthof()==0){ // float not found |
| return retVal; |
| } |
| |
| retVal=CHARSTRING(len-pos1,str+pos1); // last float |
| pl__valueStr=CHARSTRING(pos1,str); // rest of the input string |
| return retVal; |
| } |
| |
| |
| } // end of namespace |