Coverage Report

Created: 2023-09-25 07:17

/src/neomutt/parse/rc.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file
3
 * Parse lines from a runtime configuration (rc) file
4
 *
5
 * @authors
6
 * Copyright (C) 2023 Richard Russon <rich@flatcap.org>
7
 *
8
 * @copyright
9
 * This program is free software: you can redistribute it and/or modify it under
10
 * the terms of the GNU General Public License as published by the Free Software
11
 * Foundation, either version 2 of the License, or (at your option) any later
12
 * version.
13
 *
14
 * This program is distributed in the hope that it will be useful, but WITHOUT
15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17
 * details.
18
 *
19
 * You should have received a copy of the GNU General Public License along with
20
 * this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
/**
24
 * @page parse_rc Parse lines from a config file
25
 *
26
 * Parse lines from a runtime configuration (rc) file
27
 */
28
29
#include "config.h"
30
#include <stdio.h>
31
#include "mutt/lib.h"
32
#include "core/lib.h"
33
#include "extract.h"
34
35
/**
36
 * parse_rc_buffer - Parse a line of user config
37
 * @param line  config line to read
38
 * @param token scratch buffer to be used by parser
39
 * @param err   where to write error messages
40
 * @retval #CommandResult Result e.g. #MUTT_CMD_SUCCESS
41
 *
42
 * The reason for `token` is to avoid having to allocate and deallocate a lot
43
 * of memory if we are parsing many lines.  the caller can pass in the memory
44
 * to use, which avoids having to create new space for every call to this function.
45
 */
46
enum CommandResult parse_rc_buffer(struct Buffer *line, struct Buffer *token,
47
                                   struct Buffer *err)
48
0
{
49
0
  if (buf_len(line) == 0)
50
0
    return 0;
51
52
0
  enum CommandResult rc = MUTT_CMD_SUCCESS;
53
54
0
  buf_reset(err);
55
56
  /* Read from the beginning of line->data */
57
0
  buf_seek(line, 0);
58
59
0
  SKIPWS(line->dptr);
60
0
  while (*line->dptr)
61
0
  {
62
0
    if (*line->dptr == '#')
63
0
      break; /* rest of line is a comment */
64
0
    if (*line->dptr == ';')
65
0
    {
66
0
      line->dptr++;
67
0
      continue;
68
0
    }
69
0
    parse_extract_token(token, line, TOKEN_NO_FLAGS);
70
71
0
    struct Command *cmd = NULL;
72
0
    size_t size = commands_array(&cmd);
73
0
    size_t i;
74
0
    for (i = 0; i < size; i++)
75
0
    {
76
0
      if (mutt_str_equal(token->data, cmd[i].name))
77
0
      {
78
0
        mutt_debug(LL_DEBUG1, "NT_COMMAND: %s\n", cmd[i].name);
79
0
        rc = cmd[i].parse(token, line, cmd[i].data, err);
80
0
        if ((rc == MUTT_CMD_WARNING) || (rc == MUTT_CMD_ERROR) || (rc == MUTT_CMD_FINISH))
81
0
          goto finish; /* Propagate return code */
82
83
0
        notify_send(NeoMutt->notify, NT_COMMAND, i, (void *) cmd);
84
0
        break; /* Continue with next command */
85
0
      }
86
0
    }
87
0
    if (i == size)
88
0
    {
89
0
      buf_printf(err, _("%s: unknown command"), buf_string(token));
90
0
      rc = MUTT_CMD_ERROR;
91
0
      break; /* Ignore the rest of the line */
92
0
    }
93
0
  }
94
0
finish:
95
0
  return rc;
96
0
}
97
98
/**
99
 * parse_rc_line - Parse a line of user config
100
 * @param line Config line to read
101
 * @param err  Where to write error messages
102
 * @retval #CommandResult Result e.g. #MUTT_CMD_SUCCESS
103
 */
104
enum CommandResult parse_rc_line(const char *line, struct Buffer *err)
105
0
{
106
0
  if (!line || (*line == '\0'))
107
0
    return MUTT_CMD_ERROR;
108
109
0
  struct Buffer *line_buffer = buf_pool_get();
110
0
  struct Buffer *token = buf_pool_get();
111
112
0
  buf_strcpy(line_buffer, line);
113
114
0
  enum CommandResult rc = parse_rc_buffer(line_buffer, token, err);
115
116
0
  buf_pool_release(&line_buffer);
117
0
  buf_pool_release(&token);
118
0
  return rc;
119
0
}