Home | History | Annotate | Download | only in src
      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