| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /////////////////////////////////////////////////////////////////////////EA-V1
- // $File: //depot/GeneralsMD/Staging/code/Libraries/Source/profile/profile_cmd.cpp $
- // $Author: mhoffe $
- // $Revision: #2 $
- // $DateTime: 2003/08/12 15:05:00 $
- //
- // ©2003 Electronic Arts
- //
- // Profile module command interface
- //////////////////////////////////////////////////////////////////////////////
- #include "_pch.h"
- unsigned ProfileCmdInterface::numResIf;
- ProfileCmdInterface::Factory *ProfileCmdInterface::resIf;
- void ProfileCmdInterface::AddResultFunction(ProfileResultInterface* (*func)(int, const char * const *),
- const char *name, const char *arg)
- {
- DFAIL_IF(!func) return;
- DFAIL_IF(!name) return;
- for (unsigned k=0;k<numResIf;k++)
- if (!strcmp(resIf[k].name,name))
- return;
- ++numResIf;
- resIf=(Factory *)ProfileReAllocMemory(resIf,numResIf*sizeof(Factory));
- resIf[numResIf-1].func=func;
- resIf[numResIf-1].name=name;
- resIf[numResIf-1].arg=arg;
- }
- void ProfileCmdInterface::RunResultFunctions(void)
- {
- // no result functions registered?
- if (!numResFunc)
- Debug::Command("profile.result file_csv");
- // process result interfaces
- for (unsigned k=0;k<numResFunc;k++)
- {
- resFunc[k]->WriteResults();
- resFunc[k]->Delete();
- }
- }
- bool ProfileCmdInterface::Execute(class Debug& dbg, const char *cmd, CommandMode cmdmode,
- unsigned argn, const char * const * argv)
- {
- // just for convenience...
- bool normalMode=cmdmode==CommandMode::Normal;
- if (!strcmp(cmd,"help"))
- {
- if (!normalMode)
- return true;
-
- if (!argn)
- {
- dbg << "profile group help:\n"
- " result, caller, clear, add, view\n";
- return true;
- }
- else if (!strcmp(argv[0],"result"))
- {
- dbg << "result\n\n"
- "Shows the list of available result functions and their\n"
- "optional parameters.\n"
- "\n"
- "result <res_func_name> [ <arg1> .. <argN> ]\n\n"
- "Adds the given result function to be executed on program\n"
- "exit.\n";
- }
- else if (!strcmp(argv[0],"caller"))
- {
- dbg << "caller [ (+|-) ]\n\n"
- "Enables/disables recording of caller information while\n"
- "performing function level profiling. Turned off by default\n"
- "since CPU hit is non-zero.\n";
- }
- else if (!strcmp(argv[0],"clear"))
- {
- dbg << "clear\n\n"
- "Clears the profile inclusion/exclusion list.\n";
- return true;
- }
- else if (!strcmp(argv[0],"add"))
- {
- dbg << "add (+|-) <pattern>\n"
- "\n"
- "Adds a pattern to the profile list. By default all\n"
- "profile ranges are disabled. Each new range is then checked\n"
- "against all pattern in this list. If a match is found the\n"
- "active/inactive state is modified accordingly (+ for active,\n"
- "- for inactive). The final state is always the last match.";
- return true;
- }
- else if (!strcmp(argv[0],"view"))
- {
- dbg << "view\n\n"
- "Shows the active pattern list.\n";
- return true;
- }
- return false;
- }
- // command: result
- if (!strcmp(cmd,"result"))
- {
- if (!argn)
- {
- for (unsigned k=0;k<numResIf;k++)
- {
- dbg << resIf[k].name;
- if ((resIf[k].arg&&*resIf[k].arg)||!normalMode)
- dbg << "\n " << resIf[k].arg;
- dbg << "\n";
- }
- }
- else
- {
- for (unsigned k=0;k<numResIf;k++)
- if (!strcmp(argv[0],resIf[k].name))
- break;
- if (k==numResIf)
- {
- dbg << "Unknown result function\n";
- return true;
- }
- ProfileResultInterface *newIf=resIf[k].func(argn-1,argv+1);
- if (!newIf)
- {
- dbg << "Could not add result function\n";
- return true;
- }
-
- ++numResFunc;
- resFunc=(ProfileResultInterface **)ProfileReAllocMemory(resFunc,numResFunc*sizeof(ProfileResultInterface *));
- resFunc[numResFunc-1]=newIf;
- if (normalMode)
- dbg << "Result function " << argv[0] << " added\n";
- }
-
- return true;
- }
- // command: caller
- if (!strcmp(cmd,"caller"))
- {
- #ifdef HAS_PROFILE
- if (argn)
- {
- if (*argv[0]=='+')
- ProfileFuncLevelTracer::recordCaller=true;
- if (*argv[0]=='-')
- ProfileFuncLevelTracer::recordCaller=false;
- }
- if (normalMode)
- dbg << "Record caller: " << (ProfileFuncLevelTracer::recordCaller?"on":"off");
- else
- dbg << (ProfileFuncLevelTracer::recordCaller?"1":"0");
- #endif
- return true;
- }
- // command: clear
- if (!strcmp(cmd,"clear"))
- {
- // remove some (or all) pattern
- const char *pattern=argn<1?"*":argv[0];
- for (Profile::PatternListEntry **entryPtr=&Profile::firstPatternEntry;*entryPtr;)
- {
- if (Profile::SimpleMatch((*entryPtr)->pattern,pattern))
- {
- // remove this entry
- Profile::PatternListEntry *cur=*entryPtr;
- *entryPtr=cur->next;
- ProfileFreeMemory(cur->pattern);
- ProfileFreeMemory(cur);
- }
- else
- entryPtr=&((*entryPtr)->next);
- }
- // must fixup lastPatternEntry now
- if (Profile::firstPatternEntry)
- {
- for (Profile::PatternListEntry *cur=Profile::firstPatternEntry;cur->next;cur=cur->next);
- Profile::lastPatternEntry=cur;
- }
- else
- Profile::lastPatternEntry=NULL;
- return true;
- }
- // command: add
- if (!strcmp(cmd,"add"))
- {
- // add a pattern
- if (argn<2)
- dbg << "Please specify mode and pattern";
- else
- {
- // alloc new pattern entry
- Profile::PatternListEntry *cur=(Profile::PatternListEntry *)
- ProfileAllocMemory(sizeof(Profile::PatternListEntry));
- // init
- cur->next=NULL;
- cur->isActive=*argv[0]=='+';
- cur->pattern=(char *)ProfileAllocMemory(strlen(argv[1])+1);
- strcpy(cur->pattern,argv[1]);
- // add to list
- if (Profile::lastPatternEntry)
- Profile::lastPatternEntry->next=cur;
- else
- Profile::firstPatternEntry=cur;
- Profile::lastPatternEntry=cur;
- }
- return true;
- }
- // command: view
- if (!strcmp(cmd,"view"))
- {
- // show list of defined patterns
- for (Profile::PatternListEntry *cur=Profile::firstPatternEntry;cur;cur=cur->next)
- dbg << (cur->isActive?"+ ":"- ") << cur->pattern << "\n";
- return true;
- }
- // unknown command
- return false;
- }
|