1 2 /* 3 * Copyright (C) Texas Instruments - http://www.ti.com/ 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 #include "perf_config.h" 22 #include "perf_common.h" 23 #include <ctype.h> 24 25 #ifdef ANDROID 26 /* Log for Android system*/ 27 #include <utils/Log.h> 28 #endif 29 30 /* pre-declare helper functions */ 31 static int assign_string(char **psMember, char const *sValue); 32 static int assign_string_if_matches(char const *line, char const *argument, 33 char **psMember); 34 static int assign_long(unsigned long *piMember, char const *sValue); 35 static int assign_long_if_matches(char const *line, char const *argument, 36 unsigned long *piMember); 37 static void read_line(PERF_Config *sConfig, char const *line, char const *tag); 38 static char const *get_value_if_matches(char const *line, char const *argument); 39 40 /*----------------------------------------------------------------------------- 41 CONFIGURATION METHODS FUNCTIONS 42 -----------------------------------------------------------------------------*/ 43 /* default configuration */ 44 void PERF_Config_Init(PERF_Config *sConfig) 45 { 46 /* initialize default configuration */ 47 48 sConfig->mask = 0; 49 50 /* logging interface */ 51 sConfig->trace_file = NULL; 52 sConfig->delayed_open = 0; 53 sConfig->buffer_size = 65536; 54 55 /* debug interface */ 56 sConfig->debug = FALSE; 57 sConfig->detailed_debug = FALSE; 58 sConfig->csv = 1; 59 sConfig->log_file = NULL; 60 61 /* replay interface */ 62 sConfig->replay_file = strdup("STDOUT"); 63 64 /* real-time interface */ 65 sConfig->realtime = 0; 66 sConfig->rt_granularity = 1; 67 sConfig->rt_summary = 1; 68 sConfig->rt_debug = 0; 69 sConfig->rt_detailed = 0; 70 sConfig->rt_file = strdup("STDERR"); 71 } 72 73 /* release configuration memory */ 74 void PERF_Config_Release(PERF_Config *sConfig) 75 { 76 /* release all allocated members */ 77 if (sConfig->trace_file) 78 { 79 free(sConfig->trace_file); 80 sConfig->trace_file = NULL; 81 } 82 if (sConfig->log_file) 83 { 84 free(sConfig->log_file); 85 sConfig->log_file = NULL; 86 } 87 if (sConfig->replay_file) 88 { 89 free(sConfig->replay_file); 90 sConfig->replay_file = NULL; 91 } 92 if (sConfig->rt_file) 93 { 94 free(sConfig->rt_file); 95 sConfig->rt_file = NULL; 96 } 97 } 98 99 /** Method read_line 100 * 101 * Arg1 pointer to configuration 102 * 103 * Arg2 configuration line (trimmed of trailing white 104 * spaces) 105 * 106 * Arg3 tag - restrict matches to this tag or no-tag 107 * 108 * Effects compares configuration lines to assignments to each 109 * configuration variable. If tags are specified before the 110 * configuration variable, they are ignored unless they match 111 * the supplied tag. If it matches, the assignment is performed 112 * to the variable. Otherwise, an error message is printed. 113 * */ 114 115 static 116 void read_line(PERF_Config *cfg, char const *line, char const *tag) 117 { 118 char const *ptr; 119 120 /* skip leading spaces */ 121 while (*line && isspace(*line)) line++; 122 123 /* ignore comment lines and empty lines */ 124 if (!*line || *line == '#') return; 125 126 /* check to see if there is a tag prefix */ 127 128 /* find first white-space or . in the line */ 129 for (ptr = line; *ptr && !isspace(*ptr) && *ptr != '.' && *ptr != '='; ptr++); 130 131 if (*ptr == '.') 132 { 133 /* ignore lines where the tag does not match */ 134 if (!tag || strncmp(line, tag, ptr - line)) return; 135 136 /* otherwise, skip the tag for the match */ 137 line = ptr + 1; 138 } 139 140 /* check for known member names */ 141 142 if (!(assign_long_if_matches(line, "mask", &cfg->mask) || 143 /* logging configuration */ 144 assign_string_if_matches(line, "trace_file", &cfg->trace_file) || 145 assign_long_if_matches(line, "delayed_open", &cfg->delayed_open) || 146 assign_long_if_matches(line, "buffer_size", &cfg->buffer_size) || 147 /* debug configuration */ 148 assign_string_if_matches(line, "log_file", &cfg->log_file) || 149 assign_long_if_matches(line, "debug", &cfg->debug) || 150 assign_long_if_matches(line, "detailed_debug",&cfg->detailed_debug) || 151 assign_long_if_matches(line, "csv", &cfg->csv) || 152 /* replay configuration */ 153 assign_string_if_matches(line, "replay_file", &cfg->replay_file) || 154 /* real-time configuration */ 155 assign_long_if_matches(line, "realtime", &cfg->realtime) || 156 assign_long_if_matches(line, "rt_granularity", &cfg->rt_granularity) || 157 assign_long_if_matches(line, "rt_debug", &cfg->rt_debug) || 158 assign_long_if_matches(line, "rt_detailed", &cfg->rt_detailed) || 159 assign_long_if_matches(line, "rt_summary", &cfg->rt_summary) || 160 assign_string_if_matches(line, "rt_file", &cfg->rt_file) 161 )) 162 163 { 164 fprintf(stderr, 165 "warning: incorrect line in configuration file:\n%s\n", line); 166 } 167 } 168 169 /* 170 Effects: reads each line of the perf.ini file and processes configuration 171 assignments in linear order. Maximum line length is enforced, and all 172 lines longer than this are ignored. Also, all lines must end in new-line 173 If ulID is specified, lines starting with the fourCC ULID. will also be 174 read. Lines starting with # will be ignored. 175 */ 176 void PERF_Config_Read(PERF_Config *sConfig, char const *tag) 177 { 178 FILE *config_file = NULL; 179 char line[PERF_CONFIG_LINELENGTH]; 180 int ignore = FALSE; 181 182 if (sConfig) 183 { 184 /* open config file */ 185 config_file = fopen(PERF_CONFIG_FILE, "rt"); 186 if (config_file) 187 { 188 /* read each line */ 189 while (fgets(line, PERF_CONFIG_LINELENGTH, config_file)) 190 { 191 if (/* strlen(line) == PERF_CONFIG_LINELENGTH && */ 192 *line && line[strlen(line)-1] != '\n') 193 { 194 /* ignore lines that reach the max length */ 195 ignore = TRUE; 196 } 197 else if (!ignore) 198 { 199 /* remove new-line and trailing spaces from end of line */ 200 while (*line && isspace(line [strlen(line)-1])) 201 { 202 line[strlen(line)-1] = 0; 203 } 204 205 /* process un-ignored lines */ 206 read_line(sConfig, line, tag); 207 } 208 else 209 { 210 /* no longer ignore lines after they are completely read */ 211 ignore = FALSE; 212 } 213 } 214 215 /* done */ 216 fclose(config_file); 217 } 218 } 219 } 220 221 /*----------------------------------------------------------------------------- 222 HELPER FUNCTIONS 223 -----------------------------------------------------------------------------*/ 224 225 /** Method get_value_if_matches 226 * 227 * Arg1 configuration line 228 * 229 * Arg2 configuration variable name 230 * 231 * Effects if the configuration line is <variable name> = 232 * <value>, it returns the <value>. Otherwise, it returns NULL 233 * 234 * */ 235 static 236 char const *get_value_if_matches(char const *line, 237 char const *argument) 238 { 239 /* skip leading spaces */ 240 while (*line && isspace(*line)) line++; 241 242 /* return NULL if argument name does not match */ 243 if (strncasecmp(line, argument, strlen(argument))) return (NULL); 244 line += strlen(argument); 245 246 /* there must be an = after argument name */ 247 248 /* skip trailing spaces before = */ 249 while (*line && isspace(*line)) line++; 250 251 /* return NULL if = not found */ 252 if (*line != '=') return (NULL); 253 line++; 254 255 /* skip leading spaces before value */ 256 while (*line && isspace(*line)) line++; 257 258 /* if reached the end of line, return NULL; otherwise, return value */ 259 return(*line ? line : NULL); 260 } 261 262 /** Method assign_string 263 * 264 * Arg1 pointer to string configuration member 265 * 266 * Arg2 configuration value 267 * 268 * Effects Assigns the value to the configuration member. 269 * */ 270 271 static 272 int assign_string(char **psMember, char const *sValue) 273 { 274 /* delete any prior value */ 275 if (*psMember) 276 { 277 free(*psMember); 278 *psMember = NULL; 279 } 280 281 /* set new value unless it is NULL */ 282 if (strcasecmp(sValue, "NULL")) 283 { 284 *psMember = strdup(sValue); 285 } 286 287 return (1); 288 } 289 290 /** Method assign_long 291 * 292 * Arg1 pointer to configuration member 293 * 294 * Arg2 configuration value (string) 295 * 296 * Effects Assigns the integer value of the string to the 297 * configuration member. If value starts with '$' or '0x', it 298 * interprets the remaining digits as a hexadecimal number. If 299 * value starts with -, or with a digit, it is interpreted as a 300 * decimal (can be signed or unsigned). Otherwise, if it 301 * matches 'enabled', 'on' or 'true', the member is assigned 1. 302 * In all other cases, it is assigned 0. 303 * */ 304 305 static 306 int assign_long(unsigned long *piMember, char const *sValue) 307 { 308 /* set new value */ 309 310 /* hexadecimal value */ 311 if (!strncasecmp(sValue, "0x", 2)) sscanf(sValue + 2, "%lx", piMember); 312 else if (*sValue == '$') sscanf(sValue + 1, "%lx", piMember); 313 314 /* decimal value */ 315 else if (*sValue == '-') sscanf(sValue, "%ld", piMember); 316 else if (isdigit(*sValue)) sscanf(sValue, "%lu", piMember); 317 318 /* boolean value */ 319 else *piMember = (!strcasecmp(sValue, "enabled") || 320 !strcasecmp(sValue, "on") || 321 !strcasecmp(sValue, "true")); 322 323 return (1); 324 } 325 326 /** Method assign_string_if_matches 327 * 328 * Arg1 configuration line 329 * 330 * Arg2 configuration variable name 331 * 332 * Arg3 pointer to string configuration member 333 * 334 * Effects if the configuration line is <variable name> = 335 * <value>, it assigns the value to the configuration 336 * member. 337 * 338 * Returns 1, if assignment occured. 0 otherwise. 339 * */ 340 341 static 342 int assign_string_if_matches(char const *line, char const *argument, 343 char **target) 344 { 345 char const *value = get_value_if_matches(line, argument); 346 return (value ? (assign_string(target, value), 1) : 0); 347 } 348 349 /** Method assign_long_if_matches 350 * 351 * Arg1 configuration line 352 * 353 * Arg2 configuration variable name 354 * 355 * Arg3 pointer to string configuration member 356 * 357 * Effects if the configuration line is <variable name> = 358 * <value>, it assigns the integer value of the string to the 359 * configuration member in the following manner: If value 360 * starts with '$' or '0x', it interprets the remaining digits 361 * as a hexadecimal number. If value starts with -, or with a 362 * digit, it is interpreted as a decimal (can be signed or 363 * unsigned). Otherwise, if it matches 'enabled', 'on' or 364 * 'true', the member is assigned 1. In all other cases, it is 365 * assigned 0. 366 * 367 * Returns 1, if assignment occured. 0 otherwise (if config 368 * line was not an assignment to variable name). 369 * */ 370 371 static 372 int assign_long_if_matches(char const *line, char const *argument, 373 unsigned long *target) 374 { 375 char const *value = get_value_if_matches(line, argument); 376 return (value ? (assign_long(target, value), 1) : 0); 377 } 378 379 380