blob: 0a2fd3707e9b9f23695ef7c8df8a07aeafa81f21 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
// //
// 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