Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
profile_cmd.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
20// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/profile/profile_cmd.cpp $
21// $Author: mhoffe $
22// $Revision: #2 $
23// $DateTime: 2003/08/12 15:05:00 $
24//
25// ©2003 Electronic Arts
26//
27// Profile module command interface
29#include "_pch.h"
30
31unsigned ProfileCmdInterface::numResIf;
32ProfileCmdInterface::Factory *ProfileCmdInterface::resIf;
33
34void ProfileCmdInterface::AddResultFunction(ProfileResultInterface* (*func)(int, const char * const *),
35 const char *name, const char *arg)
36{
37 DFAIL_IF(!func) return;
38 DFAIL_IF(!name) return;
39 for (unsigned k=0;k<numResIf;k++)
40 if (!strcmp(resIf[k].name,name))
41 return;
42 ++numResIf;
43 resIf=(Factory *)ProfileReAllocMemory(resIf,numResIf*sizeof(Factory));
44 resIf[numResIf-1].func=func;
45 resIf[numResIf-1].name=name;
46 resIf[numResIf-1].arg=arg;
47}
48
50{
51 // no result functions registered?
52 if (!numResFunc)
53 Debug::Command("profile.result file_csv");
54
55 // process result interfaces
56 for (unsigned k=0;k<numResFunc;k++)
57 {
58 resFunc[k]->WriteResults();
59 resFunc[k]->Delete();
60 }
61}
62
63bool ProfileCmdInterface::Execute(class Debug& dbg, const char *cmd, CommandMode cmdmode,
64 unsigned argn, const char * const * argv)
65{
66 // just for convenience...
67 bool normalMode=cmdmode==CommandMode::Normal;
68
69 if (!strcmp(cmd,"help"))
70 {
71 if (!normalMode)
72 return true;
73
74 if (!argn)
75 {
76 dbg << "profile group help:\n"
77 " result, caller, clear, add, view\n";
78 return true;
79 }
80 else if (!strcmp(argv[0],"result"))
81 {
82 dbg << "result\n\n"
83 "Shows the list of available result functions and their\n"
84 "optional parameters.\n"
85 "\n"
86 "result <res_func_name> [ <arg1> .. <argN> ]\n\n"
87 "Adds the given result function to be executed on program\n"
88 "exit.\n";
89 }
90 else if (!strcmp(argv[0],"caller"))
91 {
92 dbg << "caller [ (+|-) ]\n\n"
93 "Enables/disables recording of caller information while\n"
94 "performing function level profiling. Turned off by default\n"
95 "since CPU hit is non-zero.\n";
96 }
97 else if (!strcmp(argv[0],"clear"))
98 {
99 dbg << "clear\n\n"
100 "Clears the profile inclusion/exclusion list.\n";
101 return true;
102 }
103 else if (!strcmp(argv[0],"add"))
104 {
105 dbg << "add (+|-) <pattern>\n"
106 "\n"
107 "Adds a pattern to the profile list. By default all\n"
108 "profile ranges are disabled. Each new range is then checked\n"
109 "against all pattern in this list. If a match is found the\n"
110 "active/inactive state is modified accordingly (+ for active,\n"
111 "- for inactive). The final state is always the last match.";
112 return true;
113 }
114 else if (!strcmp(argv[0],"view"))
115 {
116 dbg << "view\n\n"
117 "Shows the active pattern list.\n";
118 return true;
119 }
120 return false;
121 }
122
123 // command: result
124 if (!strcmp(cmd,"result"))
125 {
126 if (!argn)
127 {
128 for (unsigned k=0;k<numResIf;k++)
129 {
130 dbg << resIf[k].name;
131 if ((resIf[k].arg&&*resIf[k].arg)||!normalMode)
132 dbg << "\n " << resIf[k].arg;
133 dbg << "\n";
134 }
135 }
136 else
137 {
138 for (unsigned k=0;k<numResIf;k++)
139 if (!strcmp(argv[0],resIf[k].name))
140 break;
141 if (k==numResIf)
142 {
143 dbg << "Unknown result function\n";
144 return true;
145 }
146
147 ProfileResultInterface *newIf=resIf[k].func(argn-1,argv+1);
148 if (!newIf)
149 {
150 dbg << "Could not add result function\n";
151 return true;
152 }
153
154 ++numResFunc;
155 resFunc=(ProfileResultInterface **)ProfileReAllocMemory(resFunc,numResFunc*sizeof(ProfileResultInterface *));
156 resFunc[numResFunc-1]=newIf;
157 if (normalMode)
158 dbg << "Result function " << argv[0] << " added\n";
159 }
160
161 return true;
162 }
163
164 // command: caller
165 if (!strcmp(cmd,"caller"))
166 {
167#ifdef HAS_PROFILE
168 if (argn)
169 {
170 if (*argv[0]=='+')
171 ProfileFuncLevelTracer::recordCaller=true;
172 if (*argv[0]=='-')
173 ProfileFuncLevelTracer::recordCaller=false;
174 }
175 if (normalMode)
176 dbg << "Record caller: " << (ProfileFuncLevelTracer::recordCaller?"on":"off");
177 else
178 dbg << (ProfileFuncLevelTracer::recordCaller?"1":"0");
179#endif
180
181 return true;
182 }
183
184 // command: clear
185 if (!strcmp(cmd,"clear"))
186 {
187 // remove some (or all) pattern
188 const char *pattern=argn<1?"*":argv[0];
189 for (Profile::PatternListEntry **entryPtr=&Profile::firstPatternEntry;*entryPtr;)
190 {
191 if (Profile::SimpleMatch((*entryPtr)->pattern,pattern))
192 {
193 // remove this entry
194 Profile::PatternListEntry *cur=*entryPtr;
195 *entryPtr=cur->next;
196 ProfileFreeMemory(cur->pattern);
198 }
199 else
200 entryPtr=&((*entryPtr)->next);
201 }
202
203 // must fixup lastPatternEntry now
204 if (Profile::firstPatternEntry)
205 {
206 for (Profile::PatternListEntry *cur=Profile::firstPatternEntry;cur->next;cur=cur->next);
207 Profile::lastPatternEntry=cur;
208 }
209 else
210 Profile::lastPatternEntry=NULL;
211 return true;
212 }
213
214 // command: add
215 if (!strcmp(cmd,"add"))
216 {
217 // add a pattern
218 if (argn<2)
219 dbg << "Please specify mode and pattern";
220 else
221 {
222 // alloc new pattern entry
223 Profile::PatternListEntry *cur=(Profile::PatternListEntry *)
224 ProfileAllocMemory(sizeof(Profile::PatternListEntry));
225
226 // init
227 cur->next=NULL;
228 cur->isActive=*argv[0]=='+';
229 cur->pattern=(char *)ProfileAllocMemory(strlen(argv[1])+1);
230 strcpy(cur->pattern,argv[1]);
231
232 // add to list
233 if (Profile::lastPatternEntry)
234 Profile::lastPatternEntry->next=cur;
235 else
236 Profile::firstPatternEntry=cur;
237 Profile::lastPatternEntry=cur;
238 }
239 return true;
240 }
241
242 // command: view
243 if (!strcmp(cmd,"view"))
244 {
245 // show list of defined patterns
246 for (Profile::PatternListEntry *cur=Profile::firstPatternEntry;cur;cur=cur->next)
247 dbg << (cur->isActive?"+ ":"- ") << cur->pattern << "\n";
248 return true;
249 }
250
251 // unknown command
252 return false;
253}
#define NULL
Definition BaseType.h:92
CommandMode
possible command modes
Definition debug_cmd.h:67
@ Normal
normal command mode
Definition debug_cmd.h:69
Debug module main class (singleton).
Definition debug_debug.h:45
static void Command(const char *cmd)
Issues a debug command.
static void AddResultFunction(ProfileResultInterface *(*func)(int, const char *const *), const char *name, const char *arg)
void RunResultFunctions(void)
virtual bool Execute(class Debug &dbg, const char *cmd, CommandMode cmdmode, unsigned argn, const char *const *argv)
Execute the given command.
Result function class.
#define DFAIL_IF(cond)
void ProfileFreeMemory(void *ptr)
Definition profile.cpp:82
void * ProfileReAllocMemory(void *oldPtr, unsigned newSize)
Definition profile.cpp:52
void * ProfileAllocMemory(unsigned numBytes)
Definition profile.cpp:44