home *** CD-ROM | disk | FTP | other *** search
- #include "Console.h"
- #include "CVar.h"
- #include "CCmd.h"
- #include "CAlias.h"
- #include "Tokenizer.h"
-
- #include <stdarg.h>
-
- #include "log.h"
-
- Console* console = NULL;
-
-
-
- /*
- Creates a new (empty) console
- */
- Console::Console(){
- int i;
-
- for(i=0;i<CON_MAX_CVARS;i++)
- cVars[i]=NULL;
- for(i=0;i<CON_MAX_CCMDS;i++)
- cCmds[i]=NULL;
- for(i=0;i<CON_MAX_ALIASES;i++)
- aliases[i]=NULL;
- for(i=0;i<CON_MAX_LINES;i++)
- lines[i]=NULL;
- // for(i=0;i<CON_MAX_HISTORY_LINES;i++)
- // historyLines[i]=NULL;
-
- accessFlags=CON_FLAG_NONE_SET;
-
- logFile=NULL;
- logOutput=false;
- }
-
- Console::~Console(){
- int i;
-
- for(i=0;i<CON_MAX_LINES;i++){
- if(lines[i]!=NULL){
- delete[] lines[i];
- lines[i]=NULL;
- }
- }
-
- // for(i=0;i<CON_MAX_HISTORY_LINES;i++){
- // if(historyLines[i]!=NULL){
- // delete[] historyLines[i];
- // historyLines[i]=NULL;
- // }
- // }
-
- for(i=0;i<CON_MAX_CCMDS;i++){
- if(cCmds[i]!=NULL){
- cCmds[i]->setConsole(NULL);
- cCmds[i]=NULL;
- }
- }
-
- if(logOutput)
- endLog();
-
- // THINKABOUTME: cvars l÷schen?? Und aliases???
- }
-
- /*
- The console recieves input through this function.
- The input string is printed in the console window and then parsed.
- */
- void Console::input(const char* inputStr){
- print("> %s\n", inputStr);
- // appendHistoryLine(inputStr);
- parse(inputStr);
- }
-
- /*
- This function prints a printf-format-string in the console window
- */
- void Console::print(const char* formatString,...){
- char buff[CON_MAX_STRING_LENGTH];
- va_list ap;
- int count;
-
- va_start (ap, formatString);
- #ifdef WIN32
- count = _vsnprintf(buff, CON_MAX_STRING_LENGTH, formatString, ap);
- #else
- count = vsnprintf(buff, CON_MAX_STRING_LENGTH, formatString, ap);
- #endif
- va_end(ap);
-
- if(count == -1){
- print("\n## ERROR: (in console.print): formatString too long.\n\n");
- return;
- }
- appendLine(buff);
-
- if(logOutput && logFile!=NULL){
- fprintf(logFile, buff);
- }
- }
-
- /*
- adds a line to the consoles output
- */
- void Console::appendLine(const char *line){
- int i;
-
- if(lines[CON_MAX_LINES-1]!=NULL) // delete last line
- delete[] lines[CON_MAX_LINES-1];
-
- for(i=CON_MAX_LINES-1; i>0; i--){ // move all one position up
- lines[i]=lines[i-1];
- }
-
- // int t=strlen(line);
- lines[0]=new char[strlen(line)+1];
- lines[0]=strncpy(lines[0], line, strlen(line)+1);
- }
-
-
- /*
- adds a line to the consoles input history
- */
- /*
- void Console::appendHistoryLine(const char *line){
- int i;
-
- if(lines[CON_MAX_HISTORY_LINES-1]!=NULL) // delete last line
- delete[] historyLines[CON_MAX_HISTORY_LINES-1];
-
- for(i=CON_MAX_HISTORY_LINES-1; i>0; i--){ // move all one position up
- historyLines[i]=historyLines[i-1];
- }
-
- // int t=strlen(line);
- historyLines[0]=new char[strlen(line)+1];
- historyLines[0]=strncpy(historyLines[0], line, strlen(line)+1);
- }
- */
-
- /*
- This function parses a string and executes the corresponding commands.
- This is the heart of the conosle.
- It return true if ALL commands in parseStr were executed without failure and false if an error occured.
- */
- bool Console::parse(const char* parseStr){
- if(parseStr==NULL)
- return false;
-
- // printf("console::parse(): %s\n", parseStr);
-
- if(*parseStr=='\0')
- return true;
-
- int i;
-
- char* p=(char*)parseStr;
- char* start=NULL;
- char* tokens[CON_MAX_STRING_LENGTH]; // can't have more tokens than chars in the string...
- int numTokens=0;
-
- for(i=0;i<CON_MAX_STRING_LENGTH;i++){
- tokens[i]=NULL;
- }
-
- while(*p!='\0' && *p!=';' && *p!='\n' && *p!='\r'){ // THINKABOUTME: how to treat '\n' and '\r'?
- if(numTokens>=CON_MAX_STRING_LENGTH){
- print("by far too many tokens!!");
- return false;
- }
- if(*p==' ' || *p=='\t'){
- if(start!=NULL){ // end the token
- tokens[numTokens]=newString(start, p-start);
- numTokens++;
- start=NULL;
- }
- p++;
- }else if(*p=='\"'){
- if(start!=NULL){ // end the token
- tokens[numTokens]=newString(start, p-start);
- numTokens++;
- start=NULL;
- }
- p++; // skip the '\"' itself
- start=p;
- while(*p!='\"' && *p!='\0'){
- p++;
- }
- if(*p=='\0'){
- print("error...");
- return false;
- }
- if(*p=='\"'){ // this is certain at this point...
- tokens[numTokens]=newString(start, p-start);
- numTokens++;
- start=NULL;
- }
- p++; // skip the closing '\"'
- }else if(*p=='{'){
- if(start!=NULL){ // end the token
- tokens[numTokens]=newString(start, p-start);
- numTokens++;
- start=NULL;
- }
- p++; // skip the '{' itself
- start=p;
- int numBracketsOpened=1;
- while(numBracketsOpened!=0 && *p!='\0'){
- if(*p=='{') // FIXME: do not count brackets in '\"'
- numBracketsOpened++;
- if(*p=='}')
- numBracketsOpened--;
- p++;
- }
- if(*p=='\0' && numBracketsOpened!=0){
- print("error...");
- return false;
- }
- p--; // substract the last p++ of the while-loop
- if(*p=='}'){ // this is certain at this point...
- tokens[numTokens]=newString(start, p-start);
- numTokens++;
- start=NULL;
- }
- p++; // skip the closing '}'
- }else if(*p=='}'){
- // THINKABOUTME: fehler ausgeben oder nicht?
- }else{ // any other character
- if(start==NULL) // start new token if not already one in progress
- start=p;
- p++;
- }
- } //while
-
- if(start!=NULL && numTokens<CON_MAX_STRING_LENGTH-1){
- tokens[numTokens]=newString(start, p-start);
- numTokens++;
- start=NULL;
- }
-
- /*
- printf("tokens: %i\n", numTokens);
- for(i=0;i<numTokens;i++){
- printf("%s\n",tokens[i]);
- }
- */
-
- bool retVal=true;
- char val[CON_MAX_STRING_LENGTH];
- char varVal[CON_MAX_STRING_LENGTH];
-
- CCmd* cCmd=NULL;
- CVar* cVar=NULL;
- CAlias* alias=NULL;
-
-
- if(numTokens==0)
- return true;
-
- aliasFound: // FIXME: ordentlich machen!!
- cCmd=getCCmd(tokens[0]);
- if(cCmd!=NULL){
- if( true /*hasAccessToCCmd(cCmd, CON_FLAG_EXECUTE)*/){
- if(!cCmd->exec(numTokens-1, &tokens[1]))
- retVal=false; // we return only false on parse errors
- }else{
- print("'%s': exec access denied\n", cCmd->name);
- retVal=false;
- }
- }else{ // cCmd is NULL -> search for a cVar
- cVar=getCVar(tokens[0]);
- if(cVar!=NULL){
- if(numTokens==1){
- if(true /*hasAccessToCVar(cVar, CON_FLAG_READ)*/){
- cVar->getValStr(val);
- cVar->getVarValStr(varVal);
- if(streq(val, varVal))
- print("value of '%s': %s\n", cVar->name, val);
- else
- print("value of '%s': %s (internal value: %s)\n", cVar->name, val, varVal);
- }else{
- print("'%s': read access denied\n", cVar->name);
- retVal=false;
- }
- }else if(numTokens==2){
- if( (cVar->flags & CON_FLAG_READ_ONLY) != CON_FLAG_READ_ONLY){
- if(cVar->valStrIsValid(tokens[1])){
- cVar->setValStr(tokens[1]);
- print("'%s' set to %s %s\n", cVar->name, cVar->getValStr(val), cVar->changeStr);
- }else{
- print("'%s' is not a valid value for '%s'\n", tokens[1], cVar->name);
- retVal=false;
- }
- }else{
- print("'%s' is read-only.\n", cVar->name);
- retVal=false;
- }
- }else{
- print("Syntax error: '%s' (to many tokens: %i)\n", tokens[0], numTokens);
- retVal=false;
- }
- }else{ // no cvar found -> search for alias
- alias=getAlias(tokens[0]);
- if(alias!=NULL){
- delete[] tokens[0];
- tokens[0]=newString(alias->string);
- goto aliasFound;
- }else{
- print("Unknown command or variable: '%s'\n", tokens[0]);
- retVal=false;
- }
- }
- }// else (CCmd==NULL)
-
- for(i=0;i<numTokens;i++){
- delete[] tokens[i];
- }
-
- if(*p==';')
- return (parse(p+1) && retVal); // return only true if ALL ccmds are executed without errors
- else
- return retVal;
-
- }
-
- /*
- clears all output lines
- */
- void Console::clear(){
- int i;
-
- for(i=0;i<CON_MAX_LINES;i++){
- if(lines[i]!=NULL){
- delete[] lines[i];
- lines[i]=NULL;
- }
- }
- }
-
-
- /*
- clears input history
- */
- /*
- void Console::clearHistory(){
- int i;
-
- for(i=0;i<CON_MAX_HISTORY_LINES;i++){
- if(historyLines[i]!=NULL){
- delete[] historyLines[i];
- historyLines[i]=NULL;
- }
- }
- }
- */
-
- /*
- registers a new cvar, so that the console can work on it
- */
- bool Console::registerCVar(CVar* cVar){
- int i;
-
- for(i=0;i<CON_MAX_CVARS;i++){
- if(cVars[i]!=NULL && streq(cVars[i]->name, cVar->name)){
-
- print("\n##ERROR: couldn't register cvar '%s'. Another cvar with that name already exists!\n\n", cVar->name);
- return false; // cvar with name already exists
- }
- }
-
- for(i=0;i<CON_MAX_CVARS;i++){
- if(cVars[i]==NULL){
- cVars[i]=cVar; // register the cvar
- print("cvar '%s' successfully registered.\n", cVar->name);
- return true;
- }
- }
-
- print("\n##ERROR: couldn't register cvar '%s'. CON_MAX_CVARS reached\n\n", cVar->name);
- return false; // there was no free slot
- }
-
- /*
-
- unregisters a cvar (but does NOT delete it)
- */
- bool Console::unregisterCVar(CVar* cVar){
- int i;
-
- for(i=0;i<CON_MAX_CVARS;i++){
- if(cVars[i]==cVar){
- cVars[i]=NULL; // THIS DOES NOT DELETE THE CVAR!!!
- print("cvar '%s' successfully unregistered.\n", cVar->name);
- return true;
- }
- }
-
- print("\n##ERROR: couldn't unregister cvar '%s'.\n\n", cVar->name);
- return false; // no cvar with name 'name' found
- }
-
- /*
- THIS really DELETES a cvar
- */
- bool Console::deleteCVar(CVar* cVar){
- int i;
-
-
- for(i=0;i<CON_MAX_CVARS;i++){
- if(cVars[i]==cVar && cVars[i]!=NULL){
- delete cVars[i]; // THINKABOUTME: wirklich l÷schen???
- cVars[i]=NULL;
- print("cvar '%s' successfully deleted.\n", cVar->name);
- return true; // delete cvar
- }
- }
-
- print("\n##ERROR: couldn't delete cvar '%s'.\n\n", cVar->name);
- return false; // no cvar with name 'name' found
- }
-
-
- /*
- returns a pointer to the cvar called 'name'
- */
- CVar* Console::getCVar(const char* name){
- int i;
-
- for(i=0;i<CON_MAX_CVARS;i++)
- if(cVars[i]!=NULL && streq(cVars[i]->name, name))
- return cVars[i];
-
- return NULL; // no cvar with name 'name' found
- }
-
-
- /*
- Same as for cvars
- */
- bool Console::registerCCmd(CCmd* cCmd){
- int i;
-
- for(i=0;i<CON_MAX_CCMDS;i++){
- if(cCmds[i]!=NULL && streq(cCmds[i]->name, cCmd->name)){
- print("\n##ERROR: couldn't register ccmd '%s'. Another ccmd with that name already exists!\n\n", cCmd->name);
- return false; // cvar with name already exists
- }
- }
-
- for(i=0;i<CON_MAX_CCMDS;i++){
- if(cCmds[i]==NULL){
- cCmds[i]=cCmd; // register the ccmd
- cCmds[i]->setConsole(this);
- print("ccmd '%s' successfully registered.\n", cCmd->name);
- return true;
- }
- }
-
- print("\n##ERROR: couldn't register ccmd '%s'. CON_MAX_CCMDS reached\n\n", cCmd->name);
- return false; // there was no free slot
- }
-
- bool Console::unregisterCCmd(CCmd* cCmd){
- int i;
-
- for(i=0;i<CON_MAX_CCMDS;i++){
- if(cCmds[i]!=NULL && cCmds[i]==cCmd){
- cCmds[i]->setConsole(NULL);
- cCmds[i]=NULL;
- print("ccmd '%s' successfully unregistered.\n", cCmd->name);
- return true;
- }
- }
- print("\n##ERROR: couldn't unregister ccmd '%s'. No ccmd with that name found!\n\n", cCmd->name);
- return false; // no ccmd with name 'name' found
- }
-
- bool Console::deleteCCmd(CCmd* cCmd){
- int i;
-
- for(i=0;i<CON_MAX_CCMDS;i++){
- if(cCmds[i]!=NULL && cCmds[i]==cCmd){
- delete cCmds[i]; // THINKABOUTME: wirklich l÷schen???
- cCmds[i]=NULL;
- print("ccmd '%s' successfully deleted.\n", cCmd->name);
- return true;
- }
- }
-
- print("\n##ERROR: couldn't delete ccmd '%s'. No ccmd with that name found!\n\n", cCmd->name);
- return false; // no cvar with name 'name' found
- }
-
- CCmd* Console::getCCmd(const char* name){
- int i;
-
- for(i=0;i<CON_MAX_CCMDS;i++)
- if(cCmds[i]!=NULL && streq(cCmds[i]->name,name))
- return cCmds[i];
-
- return NULL; // no ccmd with name 'name' found
- }
-
- /*
- returns true if the console has 'desiredAccess' to 'cVar' (e.g. read, write, ...)
- */
- bool Console::hasAccessToCVar(CVar* cVar, unsigned int desiredAccess){
- return true;
- }
-
- /*
- returns true if the console has 'desiredAccess' to 'cCmd' (e.g. execute, ...)
- */
- bool Console::hasAccessToCCmd(CCmd* cCmd, unsigned int desiredAccess){
- return true;//(accessFlags & cCmd->flags) == desiredAccess;
- }
-
-
-
- /*
- Same as for cvars
- */
- bool Console::registerAlias(CAlias* alias){
- int i;
-
- CCmd* test=getCCmd(alias->name);
- if(test!=NULL){
- printf("A ccmd with name '%s' already exists! Overwriting ccmds with aliases is forbidden.\n", alias->name);
- return false;
- }
- CVar* test2=getCVar(alias->name);
- if(test2!=NULL){
- printf("A cvar with name '%s' already exists! Overwriting cvars with aliases is forbidden.\n", alias->name);
- return false;
- }
- if(streq(alias->name, alias->string)){
- printf("alias '%s': name and string are identical. This is forbidden.\n", alias->name);
- return false;
- }
-
- for(i=0;i<CON_MAX_ALIASES;i++){
- if(aliases[i]!=NULL && streq(aliases[i]->name, alias->name)){
- print("\n##WARNING: Another alias with name '%s' already exists! Overwriting it.\n\n", alias->name);
- delete aliases[i]; // THINKABOUTME
- aliases[i]=alias;
- return true; // alias with name already exists
- }
- }
-
- for(i=0;i<CON_MAX_ALIASES;i++){
- if(aliases[i]==NULL){
- aliases[i]=alias; // register the alias
- //aliass[i]->setConsole(this);
- print("alias '%s' successfully registered.\n", alias->name);
- return true;
- }
- }
-
- print("\n##ERROR: couldn't register alias '%s'. CON_MAX_ALIASES reached\n\n", alias->name);
- return false; // there was no free slot
- }
-
- bool Console::unregisterAlias(CAlias* alias){
- int i;
-
- for(i=0;i<CON_MAX_ALIASES;i++){
- if(aliases[i]!=NULL && aliases[i]==alias){
- //aliass[i]->setConsole(NULL);
- aliases[i]=NULL; // THIS DOES NOT DELETE THE Alias!!!
- print("alias '%s' successfully unregistered.\n", alias->name);
- return true;
- }
- }
- print("\n##ERROR: couldn't unregister alias '%s'. No alias with that name found!\n\n", alias->name);
- return false; // no alias with name 'name' found
- }
-
- bool Console::deleteAlias(CAlias* alias){
- int i;
-
- for(i=0;i<CON_MAX_ALIASES;i++){
- if(aliases[i]!=NULL && aliases[i]==alias){
- delete aliases[i]; // THINKABOUTME: wirklich l÷schen???
- aliases[i]=NULL;
- print("alias '%s' successfully deleted.\n", alias->name);
- return true;
- }
- }
-
- print("\n##ERROR: couldn't delete alias '%s'. No alias with that name found!\n\n", alias->name);
- return false; // no alias with name 'name' found
- }
-
- CAlias* Console::getAlias(const char* name){
- int i;
-
- for(i=0;i<CON_MAX_ALIASES;i++)
- if(aliases[i]!=NULL && streq(aliases[i]->name,name))
- return aliases[i];
-
- return NULL; // no CAlias with name 'name' found
- }
-
-
-
-
-
- void Console::startLog(const char* filename){
- if(logOutput){
- print("There is already a session in progress. I am closing it first...\n");
- endLog();
- }
-
- print("logging console output to file '%s'...\n", filename);
-
- logFile=fopen(filename, "wt");
- if(logFile==NULL){
- print("Couln't open file '%s'...\n");
-
- return;
- }
-
- fprintf(logFile, "*** starting console log ***\n");
-
- logOutput=true;
- }
- void Console::endLog(){
- if(logOutput){
- print("closing console log...\n");
- fclose(logFile);
- logFile=NULL;
- logOutput=false;
- }else{
- print("no log in progress.\n");
- }
- }
-