2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2025-01-14 23:57:57 +03:00
metamod-r/trace_plugin/trace_api.cpp
2016-07-04 12:07:29 +06:00

301 lines
9.5 KiB
C++

// vi: set ts=4 sw=4 :
// vim: set tw=75 :
// trace_api.cpp - (main) implementation of HL API tracing operations
/*
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
*
* This file is part of Metamod.
*
* Metamod 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 2 of the License, or (at
* your option) any later version.
*
* Metamod 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 Metamod; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include <extdll.h> // always
#include <api_info.h> // api_info_t, etc
#include <sdk_util.h> // REG_SVR_COMMAND, etc
#include <meta_api.h> // Plugin_info, etc
#include "trace_api.h" // me
#include "log_plugin.h" // LOG_MSG, etc
#include "vers_meta.h" // OPT_TYPE
#include "vdate.h" // COMPILE_TIME
cvar_t init_dllapi_trace = {"trace_dllapi", "0", FCVAR_EXTDLL, 0, NULL};
cvar_t init_newapi_trace = {"trace_newapi", "0", FCVAR_EXTDLL, 0, NULL};
cvar_t init_engine_trace = {"trace_engine", "0", FCVAR_EXTDLL, 0, NULL};
cvar_t init_unlimit_trace = {"trace_unlimit", "0", FCVAR_EXTDLL, 0, NULL};
cvar_t *dllapi_trace = NULL;
cvar_t *newapi_trace = NULL;
cvar_t *engine_trace = NULL;
cvar_t *unlimit_trace = NULL;
const char *msg_dest_types[32];
time_t last_trace_log = 0;
// Plugin startup. Register commands and cvars.
void trace_init(void) {
CVAR_REGISTER(&init_dllapi_trace);
CVAR_REGISTER(&init_newapi_trace);
CVAR_REGISTER(&init_engine_trace);
CVAR_REGISTER(&init_unlimit_trace);
dllapi_trace=CVAR_GET_POINTER("trace_dllapi");
newapi_trace=CVAR_GET_POINTER("trace_newapi");
engine_trace=CVAR_GET_POINTER("trace_engine");
unlimit_trace=CVAR_GET_POINTER("trace_unlimit");
REG_SVR_COMMAND("trace", svr_trace);
memset(msg_dest_types, 0, sizeof(msg_dest_types));
msg_dest_types[MSG_BROADCAST]="all_unreliable";
msg_dest_types[MSG_ONE]="one_reliable";
msg_dest_types[MSG_ALL]="all_reliable";
msg_dest_types[MSG_INIT]="init";
msg_dest_types[MSG_PVS]="pvs_unreliable";
msg_dest_types[MSG_PAS]="pas_unreliable";
msg_dest_types[MSG_PVS_R]="pvs_reliable";
msg_dest_types[MSG_PAS_R]="pas_reliable";
msg_dest_types[MSG_ONE_UNRELIABLE]="one_unreliable";
}
// Parse "trace" console command.
void svr_trace(void) {
const char *cmd;
cmd=CMD_ARGV(1);
if(!strcasecmp(cmd, "version"))
cmd_trace_version();
else if(!strcasecmp(cmd, "show"))
cmd_trace_show();
else if(!strcasecmp(cmd, "set"))
cmd_trace_set();
else if(!strcasecmp(cmd, "unset"))
cmd_trace_unset();
else if(!strcasecmp(cmd, "list"))
cmd_trace_list();
else {
LOG_CONSOLE(PLID, "Unrecognized trace command: %s", cmd);
cmd_trace_usage();
return;
}
}
// Print usage for "trace" console command.
void cmd_trace_usage(void) {
LOG_CONSOLE(PLID, "usage: trace <command> [<arguments>]");
LOG_CONSOLE(PLID, "valid commands are:");
LOG_CONSOLE(PLID, " version - display plugin version info");
LOG_CONSOLE(PLID, " show - show currently traced api routines");
LOG_CONSOLE(PLID, " set <routine> - set tracing for given routine");
LOG_CONSOLE(PLID, " unset <routine> - unset tracing for given routine");
LOG_CONSOLE(PLID, " list dllapi - list all dllapi routines available for tracing");
LOG_CONSOLE(PLID, " list newapi - list all newapi routines available for tracing");
LOG_CONSOLE(PLID, " list engine - list all engine routines available for tracing");
LOG_CONSOLE(PLID, " list all - list dllapi, neapi, and engine");
}
// "trace version" console command.
void cmd_trace_version(void) {
LOG_CONSOLE(PLID, "%s v%s, %s", Plugin_info.name, Plugin_info.version, Plugin_info.date);
LOG_CONSOLE(PLID, "by %s", Plugin_info.author);
LOG_CONSOLE(PLID, " %s", Plugin_info.url);
LOG_CONSOLE(PLID, "compiled: %s Eastern (%s)", COMPILE_TIME, OPT_TYPE);
}
// "trace set" console command.
void cmd_trace_set(void) {
int i, argc;
const char *arg;
const char *api;
TRACE_RESULT ret;
argc=CMD_ARGC();
if(argc < 3) {
LOG_CONSOLE(PLID, "usage: trace set <routine> [<routine> ...]");
return;
}
for(i=2; i < argc; i++) {
arg=CMD_ARGV(i);
ret=trace_setflag(&arg, mTRUE, &api);
if(ret==TR_SUCCESS)
LOG_MESSAGE(PLID, "Tracing %s routine '%s'", api, arg);
else if(ret==TR_ALREADY)
LOG_CONSOLE(PLID, "Already tracing %s routine '%s'", api, arg);
else
LOG_CONSOLE(PLID, "Unrecognized API routine '%s'", arg);
}
}
// "trace unset" console command.
void cmd_trace_unset(void) {
int i, argc;
const char *arg;
const char *api;
TRACE_RESULT ret;
argc=CMD_ARGC();
if(argc < 3) {
LOG_CONSOLE(PLID, "usage: trace unset <routine>");
return;
}
for(i=1; i < argc; i++) {
arg=CMD_ARGV(i);
ret=trace_setflag(&arg, mFALSE, &api);
if(ret==TR_SUCCESS)
LOG_MESSAGE(PLID, "Un-Tracing %s routine '%s'", api, arg);
else if(ret==TR_ALREADY)
LOG_CONSOLE(PLID, "Already not tracing %s routine '%s'", api, arg);
else
LOG_CONSOLE(PLID, "Unrecognized API routine '%s'", arg);
}
}
// "trace show" console command.
void cmd_trace_show(void) {
api_info_t *routine;
int n=0;
LOG_CONSOLE(PLID, "Tracing routines:");
for(routine=(api_info_t *) &dllapi_info; routine->name; routine++) {
if(routine->trace==mTRUE) {
LOG_CONSOLE(PLID, " %s (dllapi)", routine->name);
n++;
}
}
for(routine=(api_info_t *) &newapi_info; routine->name; routine++) {
if(routine->trace==mTRUE) {
LOG_CONSOLE(PLID, " %s (newapi)", routine->name);
n++;
}
}
for(routine=(api_info_t *) &engine_info; routine->name; routine++) {
if(routine->trace==mTRUE) {
LOG_CONSOLE(PLID, " %s (engine)", routine->name);
n++;
}
}
LOG_CONSOLE(PLID, "%d routines", n);
}
// "trace list" console command.
void cmd_trace_list(void) {
api_info_t *routine;
mBOOL valid=mFALSE;
int n, t;
const char *arg;
arg=CMD_ARGV(2);
if(!strcasecmp(arg, "all") || !strcasecmp(arg, "dllapi")) {
valid=mTRUE;
n=0; t=0;
LOG_CONSOLE(PLID, "DLLAPI routines:");
for(routine=(api_info_t *) &dllapi_info; routine->name; routine++) {
LOG_CONSOLE(PLID, " %c %s",
routine->trace ? '+' : ' ',
routine->name);
n++;
if(routine->trace) t++;
}
LOG_CONSOLE(PLID, "%d DLLAPI routines, %d traced", n, t);
}
if(!strcasecmp(arg, "all") || !strcasecmp(arg, "newapi")) {
valid=mTRUE;
n=0; t=0;
LOG_CONSOLE(PLID, "NEWAPI routines:");
for(routine=(api_info_t *) &newapi_info; routine->name; routine++) {
LOG_CONSOLE(PLID, " %c %s",
routine->trace ? '+' : ' ',
routine->name);
n++;
if(routine->trace) t++;
}
LOG_CONSOLE(PLID, "%d NEWAPI routines, %d traced", n, t);
}
if(!strcasecmp(arg, "all") || !strcasecmp(arg, "engine")) {
valid=mTRUE;
n=0; t=0;
LOG_CONSOLE(PLID, "Engine routines:");
for(routine=(api_info_t *) &engine_info; routine->name; routine++) {
LOG_CONSOLE(PLID, " %c %s",
routine->trace ? '+' : ' ',
routine->name);
n++;
if(routine->trace) t++;
}
LOG_CONSOLE(PLID, "%d Engine routines, %d traced", n, t);
}
if(!valid) {
LOG_CONSOLE(PLID, "usage: trace list <type>");
LOG_CONSOLE(PLID, "where <type> is one of:");
LOG_CONSOLE(PLID, " dllapi - list all dllapi routines available for tracing");
LOG_CONSOLE(PLID, " newapi - list all newapi routines available for tracing");
LOG_CONSOLE(PLID, " engine - list all engine routines available for tracing");
LOG_CONSOLE(PLID, " all - list dllapi, newapi, engine");
}
}
// Set or unset tracing of a given api routine string. Searches all three
// API lists, in the order:
// dllapi
// newapi
// engine
// Returns API list in which the routine was found, as well as the
// "canonicalized" routine name/string.
TRACE_RESULT trace_setflag(const char **pfn_string, mBOOL flagval, const char **api) {
api_info_t *routine;
for(routine=(api_info_t *) &dllapi_info; routine->name; routine++) {
if(!strcasecmp(routine->name, *pfn_string)) {
*pfn_string=routine->name;
*api="DLLAPI";
if(routine->trace==flagval)
return(TR_ALREADY);
routine->trace=flagval;
return(TR_SUCCESS);
}
}
for(routine=(api_info_t *) &newapi_info; routine->name; routine++) {
if(!strcasecmp(routine->name, *pfn_string)) {
*pfn_string=routine->name;
*api="NEWAPI";
if(routine->trace==flagval)
return(TR_ALREADY);
routine->trace=flagval;
return(TR_SUCCESS);
}
}
for(routine=(api_info_t *) &engine_info; routine->name; routine++) {
if(!strcasecmp(routine->name, *pfn_string)) {
*pfn_string=routine->name;
*api="Engine";
if(routine->trace==flagval)
return(TR_ALREADY);
routine->trace=flagval;
return(TR_SUCCESS);
}
}
return(TR_FAILURE);
}