Enhance buildrom.pm to enable final OBY file to be converted into acceptable input for buildrom (Bug 3862)
/*
* Copyright (c) 2009 - 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
* @internalComponent * @released
* configpaging mainfile to do configpaging in buildrom.
*
*/
#include <boost/regex.hpp>
#include <string>
#include <iostream>
#include <map>
#include <vector>
#include <fstream>
#include <malloc.h>
using namespace std;
using namespace boost ;
typedef const char* const_str ;
static const string NULL_STRING("");
static const char CONSTANT_UNPAGED[] = "unpaged";
static const char CONSTANT_PAGED[] = "paged";
static const char CONSTANT_UNPAGEDCODE[] = "unpagedcode";
static const char CONSTANT_PAGEDCODE[] = "pagedcode";
static const char CONSTANT_UNPAGEDDATA[] = "unpageddata";
static const char CONSTANT_PAGEDDATA[] = "pageddata";
#ifdef WIN32
static const char CONSTANT_CONFIG_PATH[] = "epoc32\\rom\\configpaging\\";
static string epocroot("\\");
static const char SLASH_CHAR = '\\';
#else
#include <strings.h>
#define strnicmp strncasecmp
#define _alloca alloca
static const char CONSTANT_CONFIG_PATH[] = "epoc32/rom/configpaging/";
static string epocroot("/");
static const char SLASH_CHAR = '/';
#endif
static const char CONSTANT_CONFIG_FILE[] = "configpaging.cfg" ;
#define is_undef(s) (0 == s.length())
static const int MAJOR_VERSION = 1;
static const int MINOR_VERSION = 2;
static const int BUILD_NUMBER = 0;
static const char COPYRIGHT[]="Copyright (c) 2010 Nokia Corporation.";
struct ListElement{
const_str code ;
const_str data ;
};
static string configlist ;
static regex e0("^(file|data|dll|secondary)(=|\\s+)",regex::perl|regex::icase);
static regex e1("^(code|data)?pagingoverride=(.*)\\s*",regex::perl);
static regex e2("^(un)?paged(code|data)?(\\s+(un)?paged(code|data)?)?:",regex::perl);
static regex e3("^include\\s*\"(.*)\"",regex::perl);
static regex e4("(\\S+)(\\s+(un)?paged(code|data)?(\\s+(un)?paged(code|data)?)?)?",regex::perl);
static regex e5("\\b(un)?paged(data)?\\b\\s*$",regex::perl|regex::icase);
static regex e6("\\b(un)?paged(code)?\\b\\s*$",regex::perl|regex::icase);
static regex e7("\\b(un)?paged(code|data)?\\b",regex::perl|regex::icase);
//static regex e8("tool=|\\s+)",regex::perl|regex::icase);
static bool is_obystatement(const char* aLine) {
if(!strnicmp(aLine,"file",4)|| !strnicmp(aLine,"data",4))
aLine += 4 ;
else if(!strnicmp(aLine,"dll",3))
aLine += 3;
else if(!strnicmp(aLine,"secondary",9))
aLine += 9 ;
else
return false ;
return (*aLine =='=' || *aLine == ' '|| *aLine == '\t');
}
static void trim(string& aStr){
char* data = const_cast<char*>(aStr.data());
int length = aStr.length();
int firstIndex = 0 ;
int lastIndex = length - 1;
// remove ending blanks
while(lastIndex >= 0 && (data[lastIndex] == ' ' || data[lastIndex] == '\t')){
lastIndex -- ;
}
// remove heading blanks
while((firstIndex < lastIndex ) && (data[firstIndex] == ' ' || data[firstIndex] == '\t')){
firstIndex ++ ;
}
lastIndex++ ;
if(lastIndex < length){
aStr.erase(lastIndex,length - lastIndex);
}
if(firstIndex > 0){
aStr.erase(0,firstIndex);
}
}
static void make_lower(char* aStr,size_t aLength){
for(size_t i = 0 ; i < aLength ; i++){
if(aStr[i] >= 'A' && aStr[i] <= 'Z')
aStr[i] |= 0x20 ;
}
}
static bool readConfigFile(const_str& aCodePagingRef, const_str& aDataPagingRef,
map<string,ListElement>& aListRef, const_str aFileName ) {
ifstream is(aFileName, ios_base::binary | ios_base::in);
if(!is.is_open()){
cerr<< "Can not open \""<< aFileName << "\" for reading.\n";
return false ;
}
const_str filecodepaging = "";
const_str filedatapaging = "";
match_results<string::const_iterator> what;
is.seekg(0,ios::end);
size_t size = is.tellg();
is.seekg(0,ios::beg);
char *buf = new char[size + 1];
is.read(buf,size);
buf[size] = '\n' ;
char* end = buf + size ;
char* lineStart = buf ;
int lfcr ;
string line ;
while(lineStart < end ){
// trim left ;
while(*lineStart == ' ' || *lineStart == '\t' ){
lineStart++ ;
}
char* lineEnd = lineStart;
while(*lineEnd != '\r' && *lineEnd != '\n'){
lineEnd++ ;
}
if(*lineEnd == '\r' && lineEnd[1] == '\n')
lfcr = 2 ;
else
lfcr = 1 ;
*lineEnd = 0 ;
// empty line or comment
if(lineEnd == lineStart || *lineStart == '#' ){
lineStart = lineEnd + lfcr ;
continue ;
}
size_t lenOfLine = lineEnd - lineStart;
make_lower(lineStart,lenOfLine);
line.assign(lineStart,lenOfLine);
if(regex_search(line, what, e1)){
string r1 = what[1].str();
string r2 = what[2].str();
if(is_undef(r1)){ //if ($1 eq undef)
if(r2 == "defaultpaged"){
aCodePagingRef = CONSTANT_PAGED ;
} else if(r2 == "defaultunpaged"){
aCodePagingRef = CONSTANT_UNPAGED ;
aDataPagingRef = CONSTANT_UNPAGED;
}else{
cerr << "Configpaging Warning: invalid pagingoverride setting: "<< r2 <<"\n" ;
}
}else if(r1 == "code"){
if(r2 == "defaultpaged"){
aCodePagingRef = CONSTANT_PAGED ;
} else if(r2 == "defaultunpaged"){
aCodePagingRef = CONSTANT_UNPAGED ;
}else{
cerr << "Configpaging Warning: invalid codepagingoverride setting: "<< r2 <<"\n" ;
}
}
else if(r1 == "data" ){
if(r2 == "defaultpaged"){
aDataPagingRef = CONSTANT_PAGED ;
} else if(r2 == "defaultunpaged"){
aDataPagingRef = CONSTANT_UNPAGED ;
}else{
cerr << "Configpaging Warning: invalid datapagingoverride setting: "<< r2 <<"\n" ;
}
}
}// check e1
else if(regex_search(line, what, e2)){
string r1 = what[1].str();
string r2 = what[2].str();
string r3 = what[3].str();
string r4 = what[4].str();
string r5 = what[5].str();
filecodepaging = "";
filedatapaging = "";
if (is_undef(r1)) {
if (is_undef(r2)) {
filecodepaging = CONSTANT_PAGED;
}else if (r2 == "code") {
filecodepaging = CONSTANT_PAGED;
} else if(r2 == "data") {
filedatapaging = CONSTANT_PAGED;
} else {
cerr << "Configpaging Warning: unrecognized line: "<< lineStart << "\n";
}
} else if (r1 == "un"){
if (is_undef(r2)) { //$2 eq undef
filecodepaging = CONSTANT_UNPAGED;
filedatapaging = CONSTANT_UNPAGED;
}else if (r2 == "code") {
filecodepaging = CONSTANT_UNPAGED;
} else if(r2 == "data") {
filedatapaging = CONSTANT_UNPAGED;
} else {
cerr << "Configpaging Warning: unrecognized line: "<< lineStart << "\n";
}
} else {
cerr << "Configpaging Warning: unrecognized line: "<< lineStart << "\n";
}
if (r3.length() > 0){ //$3 ne undef
if (is_undef(r4)) {
if (is_undef(r5)) {
filecodepaging = CONSTANT_PAGED;
}else if (r5 == "code") {
filecodepaging = CONSTANT_PAGED;
} else if(r5 == "data") {
filedatapaging = CONSTANT_PAGED;
} else {
cerr << "Configpaging Warning: unrecognized line: "<< lineStart << "\n";
}
} else if (r4 == "un") {
if (is_undef(r5)) {
filecodepaging = CONSTANT_UNPAGED;
filedatapaging = CONSTANT_UNPAGED;
}else if (r5 == "code") {
filecodepaging = CONSTANT_UNPAGED;
} else if(r5 == "data") {
filedatapaging = CONSTANT_UNPAGED;
} else {
cerr << "Configpaging Warning: unrecognized line: "<< lineStart << "\n";
}
} else {
cerr << "Configpaging Warning: unrecognized line: "<< lineStart << "\n";
}
}
}
else if(regex_search(line, what, e3)){
string filename = epocroot + CONSTANT_CONFIG_PATH;
filename += what[1].str();
readConfigFile(aCodePagingRef, aDataPagingRef, aListRef, filename.c_str());
}
else if(regex_search(line, what, e4)){
string r1 = what[1].str();
string r2 = what[2].str();
string r3 = what[3].str();
string r4 = what[4].str();
string r5 = what[5].str();
string r6 = what[6].str();
string r7 = what[7].str();
ListElement element = {aCodePagingRef, aDataPagingRef};
if (is_undef(r2)){ //($2 eq undef){
if (0 != *filecodepaging){//filecodepaging ne "")
element.code = filecodepaging; //$element{code} = $filecodepaging;
}
if ( 0 != *filedatapaging){//$filedatapaging ne "")
element.data = filedatapaging ;//element.data = $filedatapaging;
}
} else {
if (is_undef(r4)){//$4 eq undef
if (is_undef(r3)) {//$3 eq undef
element.code = CONSTANT_PAGED;
} else if (r3 == "un") {
element.code = CONSTANT_UNPAGED;
element.data = CONSTANT_UNPAGED;
}
} else if (r4 == "code") {
if (is_undef(r3)) {
element.code = CONSTANT_PAGED;
} else if (r3 == "un") {
element.code = CONSTANT_UNPAGED;
}
} else if (r4 == "data") {
if (is_undef(r3)) {
element.data = CONSTANT_PAGED;
} else if (r3 == "un") {
element.data = CONSTANT_UNPAGED;
}
} else {
cerr << "Configpaging Warning: unrecognized attribute in line: "<< lineStart << "\n";
}
if (r5.length() > 0){//$5 ne undef
if (is_undef(r7)){ //$7 eq undef
if (is_undef(r6)) { //$6 eq undef
element.code = CONSTANT_PAGED;
} else if (r6 == "un") {
element.code = CONSTANT_UNPAGED;
element.data = CONSTANT_UNPAGED;
}
} else if (r7 == "code") {
if (is_undef(r6)) {
element.code = CONSTANT_PAGED;
} else if (r6 == "un") {
element.code = CONSTANT_UNPAGED;
}
} else if (r7 == "data") {
if (is_undef(r6)) {
element.data = CONSTANT_PAGED;
} else if (r6 == "un") {
element.data = CONSTANT_UNPAGED;
}
} else {
cerr << "Configpaging Warning: unrecognized attribute in line: "<< lineStart << "\n";
}
}
}
//$$listref{$1} = \%element;
aListRef.insert(pair<string,ListElement>(r1,element));
}
lineStart = lineEnd + lfcr ;
}
delete []buf ;
is.close();
return true ;
}
static bool match_icase(const string& a, const string& b){
int la = a.length();
int lb = b.length();
char *copyOfA = (char*)_alloca(la+2);
*copyOfA = ' ';
copyOfA++ ;
memcpy(copyOfA ,a.c_str(),la);
copyOfA[la] = 0;
char* end = ©OfA[la];
make_lower(copyOfA,la);
while(copyOfA < end){
char *found = strstr(copyOfA,b.c_str());
if(0 == found)
return false ;
if((found[-1] == ' ' || found[-1] == '\\'|| found[-1] == '/'|| found[-1] == '\t' || found[-1] == '"'|| found[-1] == '=') &&
( found[lb] == ' '|| found[lb] == '\t' || found[lb] == '"'|| found[lb] == '\0'))
return true ;
copyOfA = found + lb ;
}
return false ;
}
static void configpaging_single(){
const_str codepaging="";
const_str datapaging="";
map<string, ListElement> list ;
vector<string> keys ;//my @keys;
string line ;
cerr << "configpaging.exe: Modifying demand paging configuration using "<< configlist <<"\n";
readConfigFile(codepaging, datapaging, list, configlist.c_str());
match_results<string::const_iterator> what;
string codepagingadd ,datapagingadd ;
while(true){
getline(cin,line);
if(cin.eof()) break ;
if(line == ":q") break ;
trim(line);
const char* lineData = line.data();
if(*lineData == '#' ){
cout << lineData << "\n" ;
continue ;
}
int length = line.length();
if( length > 2){
//check rem
if((lineData[0] == 'R' || lineData[0] == 'r' ) && (lineData[1] == 'E' || lineData[1] == 'e' ) && (lineData[2] == 'M' || lineData[2] == 'm' )){
cout << lineData << "\n" ;
continue ;
}
}
codepagingadd = "";
datapagingadd = "";
if(is_obystatement(lineData)){
for( map<string,ListElement>::iterator it = list.begin() ; it != list.end() ; it++){
if(match_icase(line,it->first) ){
if (it->second.code == CONSTANT_PAGED ){
codepagingadd += " " ;
codepagingadd += CONSTANT_PAGEDCODE;
} else if (it->second.code == CONSTANT_UNPAGED) {
codepagingadd += " " ;
codepagingadd += CONSTANT_UNPAGEDCODE;
}
if (it->second.data == CONSTANT_PAGED) {
datapagingadd += " " ;
datapagingadd += CONSTANT_PAGEDDATA;
} else if (it->second.data == CONSTANT_UNPAGED) {
datapagingadd += " " ;
datapagingadd += CONSTANT_UNPAGEDDATA;
}
break ;
}
}//for
if (codepagingadd.length() == 0 && 0 != *codepaging) {//!$codepagingadd and $codepaging
codepagingadd = " " ;
codepagingadd += codepaging ;
codepagingadd += "code";
}
if (datapagingadd.length() == 0 && 0 != *datapaging) { //!$datapagingadd and $datapaging
datapagingadd = " " ;
datapagingadd += datapaging ;
datapagingadd += "data";
}
if (codepagingadd.length() > 0 && datapagingadd.length() == 0){ //$codepagingadd and !$datapagingadd
if (regex_search(line,what,e5)){ //$line =~ /\b(un)?paged(data)?\b\s*$/) { //$line =~ /\b(un)?paged(data)?\b\s*$/
datapagingadd = " " ;
if(what[1].length() > 0)
{
datapagingadd += what[1].str();
datapagingadd += "pageddata";
}
}
} else if (datapagingadd.length() > 0 && codepagingadd.length() == 0) {//$datapagingadd and !$codepagingadd
if (regex_search(line,what,e6)){
codepagingadd = " " ;
codepagingadd += what[1].str();
codepagingadd += "pagedcode";
}
}
if (datapagingadd.length() > 0 || datapagingadd.length() > 0) { // $datapagingadd or $datapagingadd
line = regex_replace(line,e7,NULL_STRING);
}
}
cout << line << codepagingadd << datapagingadd << "\n";
}
}
//
int main(int argc , char* argv[]) {
char* tmp = getenv("EPOCROOT");
if(tmp && *tmp)
epocroot = string(tmp);
char ch = epocroot.at(epocroot.length() - 1);
if(ch != '\\' && ch != '/')
epocroot += SLASH_CHAR;
if(argc > 1 ){
char* arg = argv[1];
if('-' == *arg && (arg[1] | 0x20) == 'v'){
cout << "configpaging - The paging configuration plugin for BUILDROM V" ;
cout << MAJOR_VERSION << "."<< MINOR_VERSION << "." << BUILD_NUMBER<< endl;
cout << COPYRIGHT << endl << endl;
return 0;
}
configlist = epocroot + CONSTANT_CONFIG_PATH;
configlist += string(arg);
}
else{
configlist = epocroot + CONSTANT_CONFIG_PATH;
configlist += CONSTANT_CONFIG_FILE;
}
configpaging_single();
return 0;
}