Coverage report for bus/desktop-file.c.gcov

        -:    0:Source:desktop-file.c
        -:    0:Graph:desktop-file.gcno
        -:    0:Data:desktop-file.gcda
        -:    0:Runs:10118
        -:    0:Programs:2
        -:    1:/* -*- mode: C; c-file-style: "gnu" -*- */
        -:    2:/* desktop-file.c  .desktop file parser
        -:    3: *
        -:    4: * Copyright (C) 2003  CodeFactory AB
        -:    5: * Copyright (C) 2003  Red Hat Inc.
        -:    6: *
        -:    7: * Licensed under the Academic Free License version 2.1
        -:    8: * 
        -:    9: * This program is free software; you can redistribute it and/or modify
        -:   10: * it under the terms of the GNU General Public License as published by
        -:   11: * the Free Software Foundation; either version 2 of the License, or
        -:   12: * (at your option) any later version.
        -:   13: *
        -:   14: * This program is distributed in the hope that it will be useful,
        -:   15: * but WITHOUT ANY WARRANTY; without even the implied warranty of
        -:   16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        -:   17: * GNU General Public License for more details.
        -:   18: * 
        -:   19: * You should have received a copy of the GNU General Public License
        -:   20: * along with this program; if not, write to the Free Software
        -:   21: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
        -:   22: *
        -:   23: */
        -:   24:#include <dbus/dbus-sysdeps.h>
        -:   25:#include <dbus/dbus-internals.h>
        -:   26:#include "desktop-file.h"
        -:   27:#include "utils.h"
        -:   28:
        -:   29:typedef struct
        -:   30:{
        -:   31:  char *key;
        -:   32:  char *value;
        -:   33:} BusDesktopFileLine;
        -:   34:
        -:   35:typedef struct
        -:   36:{
        -:   37:  char *section_name;
        -:   38:  
        -:   39:  int n_lines;
        -:   40:  BusDesktopFileLine *lines;
        -:   41:  int n_allocated_lines;  
        -:   42:} BusDesktopFileSection;
        -:   43:
        -:   44:struct BusDesktopFile
        -:   45:{
        -:   46:  int n_sections;
        -:   47:  BusDesktopFileSection *sections;
        -:   48:  int n_allocated_sections;
        -:   49:};
        -:   50:
        -:   51:/**
        -:   52: * Parser for service files.
        -:   53: */
        -:   54:typedef struct
        -:   55:{
        -:   56:  DBusString data; /**< The data from the file */
        -:   57:
        -:   58:  BusDesktopFile *desktop_file; /**< The resulting object */
        -:   59:  int current_section;    /**< The current section being parsed */
        -:   60:  
        -:   61:  int pos;          /**< Current position */
        -:   62:  int len;          /**< Length */
        -:   63:  int line_num;     /**< Current line number */
        -:   64:  
        -:   65:} BusDesktopFileParser;
        -:   66:
        -:   67:#define VALID_KEY_CHAR 1
        -:   68:#define VALID_LOCALE_CHAR 2
        -:   69:unsigned char valid[256] = { 
        -:   70:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   71:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   72:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x3 , 0x2 , 0x0 , 
        -:   73:   0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   74:   0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 
        -:   75:   0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x2 , 
        -:   76:   0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 
        -:   77:   0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   78:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   79:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   80:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   81:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   82:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   83:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   84:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   85:   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
        -:   86:};
        -:   87:
        -:   88:static void report_error (BusDesktopFileParser *parser,
        -:   89:			  char                 *message,
        -:   90:			  const char           *error_name,
        -:   91:			  DBusError            *error);
        -:   92:
        -:   93:static void
        -:   94:parser_free (BusDesktopFileParser *parser)
function parser_free called 0 returned 0% blocks executed 0%
    #####:   95:{
    #####:   96:  bus_desktop_file_free (parser->desktop_file);
call    0 never executed
        -:   97:  
    #####:   98:  _dbus_string_free (&parser->data);
call    0 never executed
    #####:   99:}
        -:  100:
        -:  101:static void
        -:  102:bus_desktop_file_line_free (BusDesktopFileLine *line)
function bus_desktop_file_line_free called 48 returned 100% blocks executed 100%
       48:  103:{
       48:  104:  dbus_free (line->key);
call    0 returned 100%
       48:  105:  dbus_free (line->value);
call    0 returned 100%
       48:  106:}
        -:  107:
        -:  108:static void
        -:  109:bus_desktop_file_section_free (BusDesktopFileSection *section)
function bus_desktop_file_section_free called 24 returned 100% blocks executed 100%
       24:  110:{
        -:  111:  int i;
        -:  112:
       72:  113:  for (i = 0; i < section->n_lines; i++)
branch  0 taken 67%
branch  1 taken 33% (fallthrough)
       48:  114:    bus_desktop_file_line_free (&section->lines[i]);
call    0 returned 100%
        -:  115:
       24:  116:  dbus_free (section->lines);
call    0 returned 100%
       24:  117:  dbus_free (section->section_name);
call    0 returned 100%
       24:  118:}
        -:  119:
        -:  120:void
        -:  121:bus_desktop_file_free (BusDesktopFile *desktop_file)
function bus_desktop_file_free called 24 returned 100% blocks executed 100%
       24:  122:{
        -:  123:  int i;
        -:  124:
       48:  125:  for (i = 0; i < desktop_file->n_sections; i++)
branch  0 taken 50%
branch  1 taken 50% (fallthrough)
       24:  126:    bus_desktop_file_section_free (&desktop_file->sections[i]);
call    0 returned 100%
       24:  127:  dbus_free (desktop_file->sections);
call    0 returned 100%
        -:  128:
       24:  129:  dbus_free (desktop_file);
call    0 returned 100%
       24:  130:}
        -:  131:
        -:  132:static dbus_bool_t
        -:  133:grow_lines_in_section (BusDesktopFileSection *section)
function grow_lines_in_section called 48 returned 100% blocks executed 88%
       48:  134:{
        -:  135:  BusDesktopFileLine *lines;
        -:  136:  
        -:  137:  int new_n_lines;
        -:  138:
       48:  139:  if (section->n_allocated_lines == 0)
branch  0 taken 50% (fallthrough)
branch  1 taken 50%
       24:  140:    new_n_lines = 1;
        -:  141:  else
       24:  142:    new_n_lines = section->n_allocated_lines*2;
        -:  143:
       48:  144:  lines = dbus_realloc (section->lines,
call    0 returned 100%
        -:  145:                        sizeof (BusDesktopFileLine) * new_n_lines);
        -:  146:
       48:  147:  if (lines == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  148:    return FALSE;
        -:  149:  
       48:  150:  section->lines = lines;
       48:  151:  section->n_allocated_lines = new_n_lines;
        -:  152:
       48:  153:  return TRUE;
        -:  154:}
        -:  155:
        -:  156:static dbus_bool_t
        -:  157:grow_sections (BusDesktopFile *desktop_file)
function grow_sections called 24 returned 100% blocks executed 75%
       24:  158:{
        -:  159:  int new_n_sections;
        -:  160:  BusDesktopFileSection *sections;
        -:  161:  
       24:  162:  if (desktop_file->n_allocated_sections == 0)
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
       24:  163:    new_n_sections = 1;
        -:  164:  else
    #####:  165:    new_n_sections = desktop_file->n_allocated_sections*2;
        -:  166:
       24:  167:  sections = dbus_realloc (desktop_file->sections,
call    0 returned 100%
        -:  168:                           sizeof (BusDesktopFileSection) * new_n_sections);
       24:  169:  if (sections == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  170:    return FALSE;
        -:  171:  
       24:  172:  desktop_file->sections = sections;
        -:  173:  
       24:  174:  desktop_file->n_allocated_sections = new_n_sections;
        -:  175:
       24:  176:  return TRUE;
        -:  177:}
        -:  178:
        -:  179:static char *
        -:  180:unescape_string (BusDesktopFileParser *parser,
        -:  181:                 const DBusString     *str,
        -:  182:                 int                   pos,
        -:  183:                 int                   end_pos,
        -:  184:                 DBusError            *error)
function unescape_string called 72 returned 100% blocks executed 45%
       72:  185:{
        -:  186:  char *retval, *q;
        -:  187:
       72:  188:  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 100% (fallthrough)
branch  4 taken 0%
call    5 returned 100%
        -:  189:  
        -:  190:  /* len + 1 is enough, because unescaping never makes the
        -:  191:   * string longer
        -:  192:   */
       72:  193:  retval = dbus_malloc (end_pos - pos + 1);
call    0 returned 100%
       72:  194:  if (retval == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  195:    {
    #####:  196:      BUS_SET_OOM (error);
call    0 never executed
    #####:  197:      return NULL;
        -:  198:    }
        -:  199:
       72:  200:  q = retval;
        -:  201:  
     2670:  202:  while (pos < end_pos)
branch  0 taken 97%
branch  1 taken 3% (fallthrough)
        -:  203:    {
     2526:  204:      if (_dbus_string_get_byte (str, pos) == 0)
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  205:	{
        -:  206:	  /* Found an embedded null */
    #####:  207:	  dbus_free (retval);
call    0 never executed
    #####:  208:          report_error (parser, "Text to be unescaped contains embedded nul",
call    0 never executed
        -:  209:                        BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
    #####:  210:	  return NULL;
        -:  211:	}
        -:  212:
     2526:  213:      if (_dbus_string_get_byte (str, pos) == '\\')
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  214:	{
    #####:  215:	  pos ++;
        -:  216:
    #####:  217:	  if (pos >= end_pos)
branch  0 never executed
branch  1 never executed
        -:  218:	    {
        -:  219:	      /* Escape at end of string */
    #####:  220:	      dbus_free (retval);
call    0 never executed
    #####:  221:              report_error (parser, "Text to be unescaped ended in \\",
call    0 never executed
        -:  222:                            BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
    #####:  223:	      return NULL;
        -:  224:	    }
        -:  225:
    #####:  226:	  switch (_dbus_string_get_byte (str, pos))
call    0 never executed
branch  1 never executed
branch  2 never executed
branch  3 never executed
branch  4 never executed
branch  5 never executed
branch  6 never executed
        -:  227:	    {
        -:  228:	    case 's':
    #####:  229:              *q++ = ' ';
    #####:  230:              break;
        -:  231:           case 't':
    #####:  232:              *q++ = '\t';
    #####:  233:              break;
        -:  234:           case 'n':
    #####:  235:              *q++ = '\n';
    #####:  236:              break;
        -:  237:           case 'r':
    #####:  238:              *q++ = '\r';
    #####:  239:              break;
        -:  240:           case '\\':
    #####:  241:              *q++ = '\\';
    #####:  242:              break;
        -:  243:           default:
        -:  244:	     /* Invalid escape code */
    #####:  245:	     dbus_free (retval);
call    0 never executed
    #####:  246:             report_error (parser, "Text to be unescaped had invalid escape sequence",
call    0 never executed
        -:  247:                           BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
    #####:  248:             return NULL;
        -:  249:	    }
    #####:  250:	  pos++;
        -:  251:	}
        -:  252:      else
        -:  253:	{
     2526:  254:	  *q++ =_dbus_string_get_byte (str, pos);
call    0 returned 100%
        -:  255:
     2526:  256:	  pos++;
        -:  257:	}
        -:  258:    }
        -:  259:
       72:  260:  *q = 0;
        -:  261:
       72:  262:  return retval;
        -:  263:}
        -:  264:
        -:  265:static BusDesktopFileSection* 
        -:  266:new_section (BusDesktopFile *desktop_file,
        -:  267:             const char     *name)
function new_section called 24 returned 100% blocks executed 69%
       24:  268:{
        -:  269:  int n;
        -:  270:  char *name_copy;
        -:  271:  
       24:  272:  if (desktop_file->n_allocated_sections == desktop_file->n_sections)
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
        -:  273:    {
       24:  274:      if (!grow_sections (desktop_file))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  275:        return NULL;
        -:  276:    }
        -:  277:
       24:  278:  name_copy = _dbus_strdup (name);
call    0 returned 100%
       24:  279:  if (name_copy == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  280:    return NULL;
        -:  281:
       24:  282:  n = desktop_file->n_sections;
       24:  283:  desktop_file->sections[n].section_name = name_copy;
        -:  284:
       24:  285:  desktop_file->sections[n].n_lines = 0;
       24:  286:  desktop_file->sections[n].lines = NULL;
       24:  287:  desktop_file->sections[n].n_allocated_lines = 0;
        -:  288:
       24:  289:  if (!grow_lines_in_section (&desktop_file->sections[n]))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  290:    {
    #####:  291:      dbus_free (desktop_file->sections[n].section_name);
call    0 never executed
    #####:  292:      desktop_file->sections[n].section_name = NULL;
    #####:  293:      return NULL;
        -:  294:    }
        -:  295:
       24:  296:  desktop_file->n_sections += 1;
        -:  297:  
       24:  298:  return &desktop_file->sections[n];  
        -:  299:}
        -:  300:
        -:  301:static BusDesktopFileSection* 
        -:  302:open_section (BusDesktopFileParser *parser,
        -:  303:              char                 *name)
function open_section called 24 returned 100% blocks executed 83%
       24:  304:{  
        -:  305:  BusDesktopFileSection *section;
        -:  306:
       24:  307:  section = new_section (parser->desktop_file, name);
call    0 returned 100%
       24:  308:  if (section == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  309:    return NULL;
        -:  310:  
       24:  311:  parser->current_section = parser->desktop_file->n_sections - 1;
       24:  312:  _dbus_assert (&parser->desktop_file->sections[parser->current_section] == section);
call    0 returned 100%
        -:  313:  
       24:  314:  return section;
        -:  315:}
        -:  316:
        -:  317:static BusDesktopFileLine *
        -:  318:new_line (BusDesktopFileParser *parser)
function new_line called 48 returned 100% blocks executed 86%
       48:  319:{
        -:  320:  BusDesktopFileSection *section;
        -:  321:  BusDesktopFileLine *line;
        -:  322:  
       48:  323:  section = &parser->desktop_file->sections[parser->current_section];
        -:  324:
       48:  325:  if (section->n_allocated_lines == section->n_lines)
branch  0 taken 50% (fallthrough)
branch  1 taken 50%
        -:  326:    {
       24:  327:      if (!grow_lines_in_section (section))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  328:        return NULL;
        -:  329:    }
        -:  330:
       48:  331:  line = &section->lines[section->n_lines++];
        -:  332:
       48:  333:  memset (line, 0, sizeof (BusDesktopFileLine));
call    0 returned 100%
        -:  334:    
       48:  335:  return line;
        -:  336:}
        -:  337:
        -:  338:static dbus_bool_t
        -:  339:is_blank_line (BusDesktopFileParser *parser)
function is_blank_line called 51 returned 100% blocks executed 86%
       51:  340:{
        -:  341:  int p;
        -:  342:  char c;
        -:  343:  
       51:  344:  p = parser->pos;
        -:  345:
       51:  346:  c = _dbus_string_get_byte (&parser->data, p);
call    0 returned 100%
        -:  347:
      102:  348:  while (c && c != '\n')
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
branch  2 taken 94%
branch  3 taken 6% (fallthrough)
        -:  349:    {
       48:  350:      if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f'))
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
branch  2 taken 100% (fallthrough)
branch  3 taken 0%
branch  4 taken 100% (fallthrough)
branch  5 taken 0%
branch  6 taken 100% (fallthrough)
branch  7 taken 0%
branch  8 taken 100% (fallthrough)
branch  9 taken 0%
       48:  351:	return FALSE;
        -:  352:      
    #####:  353:      p++;
    #####:  354:      c = _dbus_string_get_byte (&parser->data, p);
call    0 never executed
        -:  355:    }
        -:  356:
        3:  357:  return TRUE;
        -:  358:}
        -:  359:
        -:  360:static void
        -:  361:parse_comment_or_blank (BusDesktopFileParser *parser)
function parse_comment_or_blank called 3 returned 100% blocks executed 71%
        3:  362:{
        -:  363:  int line_end;
        -:  364:  
        3:  365:  if (!_dbus_string_find (&parser->data, parser->pos, "\n", &line_end))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  366:    line_end = parser->len;
        -:  367:
        3:  368:  if (line_end == parser->len)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  369:    parser->pos = parser->len;
        -:  370:  else
        3:  371:    parser->pos = line_end + 1;
        -:  372:  
        3:  373:  parser->line_num += 1;
        3:  374:}
        -:  375:
        -:  376:static dbus_bool_t
        -:  377:is_valid_section_name (const char *name)
function is_valid_section_name called 24 returned 100% blocks executed 75%
       24:  378:{
        -:  379:  /* 5. Group names may contain all ASCII characters except for control characters and '[' and ']'. */
        -:  380:
      360:  381:  while (*name)
branch  0 taken 93%
branch  1 taken 7% (fallthrough)
        -:  382:    {
      312:  383:      if (!((*name >= 'A' && *name <= 'Z') || (*name >= 'a' || *name <= 'z') ||
branch  0 taken 85% (fallthrough)
branch  1 taken 15%
branch  2 taken 55% (fallthrough)
branch  3 taken 45%
branch  4 taken 25% (fallthrough)
branch  5 taken 75%
branch  6 taken 0% (fallthrough)
branch  7 taken 100%
branch  8 never executed
branch  9 never executed
branch 10 never executed
branch 11 never executed
        -:  384:	    *name == '\n' || *name == '\t'))
    #####:  385:	return FALSE;
        -:  386:      
      312:  387:      name++;
        -:  388:    }
        -:  389:
       24:  390:  return TRUE;
        -:  391:}
        -:  392:
        -:  393:static dbus_bool_t
        -:  394:parse_section_start (BusDesktopFileParser *parser, DBusError *error)
function parse_section_start called 24 returned 100% blocks executed 60%
       24:  395:{
        -:  396:  int line_end;
        -:  397:  char *section_name;
        -:  398:
       24:  399:  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 100% (fallthrough)
branch  4 taken 0%
call    5 returned 100%
        -:  400:  
       24:  401:  if (!_dbus_string_find (&parser->data, parser->pos, "\n", &line_end))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  402:    line_end = parser->len;
        -:  403:  
       24:  404:  if (line_end - parser->pos <= 2 ||
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 0% (fallthrough)
branch  4 taken 100%
        -:  405:      _dbus_string_get_byte (&parser->data, line_end - 1) != ']')
        -:  406:    {
    #####:  407:      report_error (parser, "Invalid syntax for section header", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
call    0 never executed
    #####:  408:      parser_free (parser);
call    0 never executed
    #####:  409:      return FALSE;
        -:  410:    }
        -:  411:
       24:  412:  section_name = unescape_string (parser,
call    0 returned 100%
        -:  413:                                  &parser->data, parser->pos + 1, line_end - 1,
        -:  414:                                  error);
        -:  415:
       24:  416:  if (section_name == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  417:    {
    #####:  418:      parser_free (parser);
call    0 never executed
    #####:  419:      return FALSE;
        -:  420:    }
        -:  421:
       24:  422:  if (!is_valid_section_name (section_name))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  423:    {
    #####:  424:      report_error (parser, "Invalid characters in section name", BUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error);
call    0 never executed
    #####:  425:      parser_free (parser);
call    0 never executed
    #####:  426:      dbus_free (section_name);
call    0 never executed
    #####:  427:      return FALSE;
        -:  428:    }
        -:  429:
       24:  430:  if (open_section (parser, section_name) == NULL)
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  431:    {
    #####:  432:      dbus_free (section_name);
call    0 never executed
    #####:  433:      return FALSE;
        -:  434:    }
        -:  435:
       24:  436:  if (line_end == parser->len)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  437:    parser->pos = parser->len;
        -:  438:  else
       24:  439:    parser->pos = line_end + 1;
        -:  440:  
       24:  441:  parser->line_num += 1;
        -:  442:
       24:  443:  dbus_free (section_name);
call    0 returned 100%
        -:  444:  
       24:  445:  return TRUE;
        -:  446:}
        -:  447:
        -:  448:static dbus_bool_t
        -:  449:parse_key_value (BusDesktopFileParser *parser, DBusError *error)
function parse_key_value called 48 returned 100% blocks executed 61%
       48:  450:{
        -:  451:  int line_end;
        -:  452:  int key_start, key_end;
        -:  453:  int value_start;
        -:  454:  int p;
        -:  455:  char *value, *tmp;
        -:  456:  DBusString key;
        -:  457:  BusDesktopFileLine *line;
        -:  458:
       48:  459:  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 100% (fallthrough)
branch  4 taken 0%
call    5 returned 100%
        -:  460:  
       48:  461:  if (!_dbus_string_find (&parser->data, parser->pos, "\n", &line_end))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  462:    line_end = parser->len;
        -:  463:  
       48:  464:  p = parser->pos;
       48:  465:  key_start = p;
      288:  466:  while (p < line_end &&
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 80%
branch  4 taken 20% (fallthrough)
        -:  467:	 (valid[_dbus_string_get_byte (&parser->data, p)] & VALID_KEY_CHAR))
      192:  468:    p++;
       48:  469:  key_end = p;
        -:  470:  
       48:  471:  if (key_start == key_end)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  472:    {
    #####:  473:      report_error (parser, "Empty key name", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
call    0 never executed
    #####:  474:      parser_free (parser);
call    0 never executed
    #####:  475:      return FALSE;
        -:  476:    }
        -:  477:
        -:  478:  /* We ignore locales for now */
       48:  479:  if (p < line_end && _dbus_string_get_byte (&parser->data, p) == '[')
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 0% (fallthrough)
branch  4 taken 100%
        -:  480:    {
    #####:  481:      if (line_end == parser->len)
branch  0 never executed
branch  1 never executed
    #####:  482:	parser->pos = parser->len;
        -:  483:      else
    #####:  484:	parser->pos = line_end + 1;
        -:  485:	  
    #####:  486:      parser->line_num += 1;
        -:  487:
    #####:  488:      return TRUE;
        -:  489:    }
        -:  490:  
        -:  491:  /* Skip space before '=' */
       96:  492:  while (p < line_end && _dbus_string_get_byte (&parser->data, p) == ' ')
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 0%
branch  4 taken 100% (fallthrough)
    #####:  493:    p++;
        -:  494:
       48:  495:  if (p < line_end && _dbus_string_get_byte (&parser->data, p) != '=')
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 0% (fallthrough)
branch  4 taken 100%
        -:  496:    {
    #####:  497:      report_error (parser, "Invalid characters in key name", BUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error);
call    0 never executed
    #####:  498:      parser_free (parser);
call    0 never executed
    #####:  499:      return FALSE;
        -:  500:    }
        -:  501:
       48:  502:  if (p == line_end)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  503:    {
    #####:  504:      report_error (parser, "No '=' in key/value pair", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
call    0 never executed
    #####:  505:      parser_free (parser);
call    0 never executed
    #####:  506:      return FALSE;
        -:  507:    }
        -:  508:
        -:  509:  /* Skip the '=' */
       48:  510:  p++;
        -:  511:
        -:  512:  /* Skip space after '=' */
       96:  513:  while (p < line_end && _dbus_string_get_byte (&parser->data, p) == ' ')
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 0%
branch  4 taken 100% (fallthrough)
    #####:  514:    p++;
        -:  515:
       48:  516:  value_start = p;
        -:  517:  
       48:  518:  value = unescape_string (parser, &parser->data, value_start, line_end, error);
call    0 returned 100%
       48:  519:  if (value == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  520:    {
    #####:  521:      parser_free (parser);
call    0 never executed
    #####:  522:      return FALSE;
        -:  523:    }
        -:  524:
       48:  525:  line = new_line (parser);
call    0 returned 100%
       48:  526:  if (line == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  527:    {
    #####:  528:      parser_free (parser);
call    0 never executed
    #####:  529:      return FALSE;
        -:  530:    }
        -:  531:  
       48:  532:  if (!_dbus_string_init (&key))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  533:    {
    #####:  534:      parser_free (parser);
call    0 never executed
    #####:  535:      return FALSE;
        -:  536:    }
        -:  537:  
       48:  538:  if (!_dbus_string_copy_len (&parser->data, key_start, key_end - key_start,
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  539:                              &key, 0))
        -:  540:    {
    #####:  541:      parser_free (parser);
call    0 never executed
    #####:  542:      return FALSE;
        -:  543:    }
        -:  544:  
       48:  545:  if (!_dbus_string_steal_data (&key, &tmp))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  546:    {
    #####:  547:      parser_free (parser);
call    0 never executed
    #####:  548:      return FALSE;
        -:  549:    }
        -:  550:  
       48:  551:  _dbus_string_free (&key);
call    0 returned 100%
        -:  552:  
       48:  553:  line->key = tmp;
       48:  554:  line->value = value;
        -:  555:
       48:  556:  if (line_end == parser->len)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  557:    parser->pos = parser->len;
        -:  558:  else
       48:  559:    parser->pos = line_end + 1;
        -:  560:  
       48:  561:  parser->line_num += 1;
        -:  562:
       48:  563:  return TRUE;
        -:  564:}
        -:  565:
        -:  566:static void
        -:  567:report_error (BusDesktopFileParser *parser,
        -:  568:	      char                 *message,
        -:  569:	      const char           *error_name,
        -:  570:	      DBusError            *error)
function report_error called 0 returned 0% blocks executed 0%
    #####:  571:{
    #####:  572:  const char *section_name = NULL;
        -:  573:
    #####:  574:  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
branch  0 never executed
branch  1 never executed
call    2 never executed
branch  3 never executed
branch  4 never executed
call    5 never executed
        -:  575:  
    #####:  576:  if (parser->current_section != -1)
branch  0 never executed
branch  1 never executed
    #####:  577:    section_name = parser->desktop_file->sections[parser->current_section].section_name;
        -:  578:
    #####:  579:  if (section_name)
branch  0 never executed
branch  1 never executed
    #####:  580:    dbus_set_error (error, error_name,
call    0 never executed
        -:  581:                    "Error in section %s at line %d: %s\n", section_name, parser->line_num, message);
        -:  582:  else
    #####:  583:    dbus_set_error (error, error_name,
call    0 never executed
        -:  584:                    "Error at line %d: %s\n", parser->line_num, message);
    #####:  585:}
        -:  586:
        -:  587:#if 0
        -:  588:static void
        -:  589:dump_desktop_file (BusDesktopFile *file)
        -:  590:{
        -:  591:  int i;
        -:  592:
        -:  593:  for (i = 0; i < file->n_sections; i++)
        -:  594:    {
        -:  595:      int j;
        -:  596:      
        -:  597:      printf ("[%s]\n", file->sections[i].section_name);
        -:  598:
        -:  599:      for (j = 0; j < file->sections[i].n_lines; j++)
        -:  600:	{
        -:  601:	  printf ("%s=%s\n", file->sections[i].lines[j].key,
        -:  602:		  file->sections[i].lines[j].value);
        -:  603:	}
        -:  604:    }
        -:  605:}
        -:  606:#endif
        -:  607:
        -:  608:BusDesktopFile*
        -:  609:bus_desktop_file_load (DBusString *filename,
        -:  610:		       DBusError  *error)
function bus_desktop_file_load called 24 returned 100% blocks executed 71%
       24:  611:{
        -:  612:  DBusString str;
        -:  613:  BusDesktopFileParser parser;
        -:  614:  DBusStat sb;
        -:  615:
       24:  616:  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
call    2 returned 100%
branch  3 taken 100% (fallthrough)
branch  4 taken 0%
call    5 returned 100%
        -:  617:  
        -:  618:  /* Clearly there's a race here, but it's just to make it unlikely
        -:  619:   * that we do something silly, we still handle doing it below.
        -:  620:   */
       24:  621:  if (!_dbus_stat (filename, &sb, error))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  622:    return NULL;
        -:  623:
       24:  624:  if (sb.size > _DBUS_ONE_KILOBYTE * 128)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  625:    {
    #####:  626:      dbus_set_error (error, DBUS_ERROR_FAILED,
call    0 never executed
        -:  627:                      "Desktop file size (%ld bytes) is too large", (long) sb.size);
    #####:  628:      return NULL;
        -:  629:    }
        -:  630:  
       24:  631:  if (!_dbus_string_init (&str))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  632:    return NULL;
        -:  633:  
       24:  634:  if (!_dbus_file_get_contents (&str, filename, error))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  635:    {
    #####:  636:      _dbus_string_free (&str);
call    0 never executed
    #####:  637:      return NULL;
        -:  638:    }
        -:  639:
       24:  640:  if (!_dbus_string_validate_utf8 (&str, 0, _dbus_string_get_length (&str)))
call    0 returned 100%
call    1 returned 100%
branch  2 taken 0% (fallthrough)
branch  3 taken 100%
        -:  641:    {
    #####:  642:      _dbus_string_free (&str);
call    0 never executed
    #####:  643:      dbus_set_error (error, DBUS_ERROR_FAILED,
call    0 never executed
        -:  644:                      "invalid UTF-8");   
    #####:  645:      return NULL;
        -:  646:    }
        -:  647:  
       24:  648:  parser.desktop_file = dbus_new0 (BusDesktopFile, 1);
call    0 returned 100%
       24:  649:  if (parser.desktop_file == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  650:    {
    #####:  651:      _dbus_string_free (&str);
call    0 never executed
    #####:  652:      BUS_SET_OOM (error);
call    0 never executed
    #####:  653:      return NULL;
        -:  654:    }
        -:  655:  
       24:  656:  parser.data = str;
       24:  657:  parser.line_num = 1;
       24:  658:  parser.pos = 0;
       24:  659:  parser.len = _dbus_string_get_length (&parser.data);
call    0 returned 100%
       24:  660:  parser.current_section = -1;
        -:  661:
      123:  662:  while (parser.pos < parser.len)
branch  0 taken 76%
branch  1 taken 24% (fallthrough)
        -:  663:    {
       75:  664:      if (_dbus_string_get_byte (&parser.data, parser.pos) == '[')
call    0 returned 100%
branch  1 taken 32% (fallthrough)
branch  2 taken 68%
        -:  665:	{
       24:  666:	  if (!parse_section_start (&parser, error))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  667:            {
    #####:  668:              return NULL;
        -:  669:            }
        -:  670:	}
       54:  671:      else if (is_blank_line (&parser) ||
call    0 returned 100%
branch  1 taken 94% (fallthrough)
branch  2 taken 6%
call    3 returned 100%
branch  4 taken 0% (fallthrough)
branch  5 taken 100%
        -:  672:	       _dbus_string_get_byte (&parser.data, parser.pos) == '#')
        3:  673:	parse_comment_or_blank (&parser);
call    0 returned 100%
        -:  674:      else
        -:  675:	{
       48:  676:	  if (!parse_key_value (&parser, error))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
        -:  677:            {
    #####:  678:              return NULL;
        -:  679:            }
        -:  680:	}
        -:  681:    }
        -:  682:
       24:  683:  _dbus_string_free (&parser.data);
call    0 returned 100%
        -:  684:
       24:  685:  return parser.desktop_file;
        -:  686:}
        -:  687:
        -:  688:static BusDesktopFileSection *
        -:  689:lookup_section (BusDesktopFile *desktop_file,
        -:  690:		const char     *section_name)
function lookup_section called 48 returned 100% blocks executed 70%
       48:  691:{
        -:  692:  BusDesktopFileSection *section;
        -:  693:  int i;
        -:  694:  
       48:  695:  if (section_name == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  696:    return NULL;
        -:  697:  
       48:  698:  for (i = 0; i < desktop_file->n_sections; i ++)
branch  0 taken 100%
branch  1 taken 0% (fallthrough)
        -:  699:    {
       48:  700:      section = &desktop_file->sections[i];
        -:  701:
       48:  702:      if (strcmp (section->section_name, section_name) == 0)
call    0 returned 100%
branch  1 taken 100% (fallthrough)
branch  2 taken 0%
       48:  703:	return section;
        -:  704:    }
        -:  705:  
    #####:  706:  return NULL;
        -:  707:}
        -:  708:
        -:  709:static BusDesktopFileLine *
        -:  710:lookup_line (BusDesktopFile        *desktop_file,
        -:  711:	     BusDesktopFileSection *section,
        -:  712:	     const char            *keyname)
function lookup_line called 48 returned 100% blocks executed 88%
       48:  713:{
        -:  714:  BusDesktopFileLine *line;
        -:  715:  int i;
        -:  716:
       72:  717:  for (i = 0; i < section->n_lines; i++)
branch  0 taken 100%
branch  1 taken 0% (fallthrough)
        -:  718:    {
       72:  719:      line = &section->lines[i];
        -:  720:      
       72:  721:      if (strcmp (line->key, keyname) == 0)
call    0 returned 100%
branch  1 taken 67% (fallthrough)
branch  2 taken 33%
       48:  722:	return line;
        -:  723:    }
        -:  724:  
    #####:  725:  return NULL;
        -:  726:}
        -:  727:
        -:  728:dbus_bool_t
        -:  729:bus_desktop_file_get_raw (BusDesktopFile  *desktop_file,
        -:  730:			  const char      *section_name,
        -:  731:			  const char      *keyname,
        -:  732:			  const char     **val)
function bus_desktop_file_get_raw called 48 returned 100% blocks executed 75%
       48:  733:{
        -:  734:  BusDesktopFileSection *section;
        -:  735:  BusDesktopFileLine *line;
        -:  736:
       48:  737:  *val = NULL;
        -:  738:
       48:  739:  section = lookup_section (desktop_file, section_name);
call    0 returned 100%
        -:  740:  
       48:  741:  if (!section)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  742:    return FALSE;
        -:  743:
       48:  744:  line = lookup_line (desktop_file,
call    0 returned 100%
        -:  745:		      section,
        -:  746:		      keyname);
        -:  747:
       48:  748:  if (!line)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  749:    return FALSE;
        -:  750:  
       48:  751:  *val = line->value;
        -:  752:  
       48:  753:  return TRUE;
        -:  754:}
        -:  755:
        -:  756:dbus_bool_t
        -:  757:bus_desktop_file_get_string (BusDesktopFile  *desktop_file,
        -:  758:			     const char      *section,
        -:  759:			     const char      *keyname,
        -:  760:			     char           **val)
function bus_desktop_file_get_string called 48 returned 100% blocks executed 75%
       48:  761:{
        -:  762:  const char *raw;
        -:  763:  
       48:  764:  *val = NULL;
        -:  765:  
       48:  766:  if (!bus_desktop_file_get_raw (desktop_file, section, keyname, &raw))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:  767:    return FALSE;
        -:  768:
       48:  769:  *val = _dbus_strdup (raw);
call    0 returned 100%
        -:  770:
        -:  771:  /* FIXME we don't distinguish "key not found" from "out of memory" here,
        -:  772:   * which is broken.
        -:  773:   */
       48:  774:  if (*val == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:  775:    return FALSE;
        -:  776:  
       48:  777:  return TRUE;
        -:  778:}