Coverage Report

Created: 2026-01-25 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gettext-0.26/gettext-tools/src/read-catalog-special.c
Line
Count
Source
1
/* Parsing of special comments (#, and #= comments) in textual message catalogs.
2
   Copyright (C) 1995-2025 Free Software Foundation, Inc.
3
4
   This file was written by Peter Miller <millerp@canb.auug.org.au>
5
6
   This program is free software: you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program 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
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
18
19
20
#ifdef HAVE_CONFIG_H
21
# include "config.h"
22
#endif
23
24
/* Specification.  */
25
#include "read-catalog-special.h"
26
27
#include <limits.h>
28
#include <string.h>
29
30
31
/* Parse a special comment and put the result in *fuzzyp, formatp, *rangep,
32
   *wrapp, and, if scp != NULL, scp[0..NSYNTAXCHECKS-1].  */
33
void
34
parse_comment_special (const char *s,
35
                       bool *fuzzyp, enum is_format formatp[NFORMATS],
36
                       struct argument_range *rangep, enum is_wrap *wrapp,
37
                       enum is_syntax_check *scp)
38
57.7k
{
39
57.7k
  size_t i;
40
41
57.7k
  *fuzzyp = false;
42
2.13M
  for (i = 0; i < NFORMATS; i++)
43
2.07M
    formatp[i] = undecided;
44
57.7k
  rangep->min = -1;
45
57.7k
  rangep->max = -1;
46
57.7k
  *wrapp = undecided;
47
57.7k
  if (scp != NULL)
48
0
    {
49
0
      for (i = 0; i < NSYNTAXCHECKS; i++)
50
0
        scp[i] = undecided;
51
0
    }
52
53
136k
  while (*s != '\0')
54
78.3k
    {
55
78.3k
      const char *t;
56
57
      /* Skip whitespace.  */
58
178k
      while (*s != '\0' && strchr ("\n \t\r\f\v,", *s) != NULL)
59
100k
        s++;
60
61
      /* Collect a token.  */
62
78.3k
      t = s;
63
3.89M
      while (*s != '\0' && strchr ("\n \t\r\f\v,", *s) == NULL)
64
3.81M
        s++;
65
78.3k
      if (s != t)
66
76.9k
        {
67
76.9k
          size_t len = s - t;
68
69
          /* Accept fuzzy flag.  */
70
76.9k
          if (len == 5 && memcmp (t, "fuzzy", 5) == 0)
71
19.5k
            {
72
19.5k
              *fuzzyp = true;
73
19.5k
              continue;
74
19.5k
            }
75
76
          /* Accept format description.  */
77
57.4k
          if (len >= 7 && memcmp (t + len - 7, "-format", 7) == 0)
78
3.24k
            {
79
3.24k
              const char *p;
80
3.24k
              size_t n;
81
3.24k
              enum is_format value;
82
83
3.24k
              p = t;
84
3.24k
              n = len - 7;
85
86
3.24k
              if (n >= 3 && memcmp (p, "no-", 3) == 0)
87
115
                {
88
115
                  p += 3;
89
115
                  n -= 3;
90
115
                  value = no;
91
115
                }
92
3.13k
              else if (n >= 9 && memcmp (p, "possible-", 9) == 0)
93
90
                {
94
90
                  p += 9;
95
90
                  n -= 9;
96
90
                  value = possible;
97
90
                }
98
3.04k
              else if (n >= 11 && memcmp (p, "impossible-", 11) == 0)
99
100
                {
100
100
                  p += 11;
101
100
                  n -= 11;
102
100
                  value = impossible;
103
100
                }
104
2.94k
              else
105
2.94k
                value = yes;
106
107
115k
              for (i = 0; i < NFORMATS; i++)
108
112k
                if (strlen (format_language[i]) == n
109
6.45k
                    && memcmp (format_language[i], p, n) == 0)
110
262
                  {
111
262
                    formatp[i] = value;
112
262
                    break;
113
262
                  }
114
3.24k
              if (i < NFORMATS)
115
262
                continue;
116
3.24k
            }
117
118
          /* Accept range description "range: <min>..<max>".  */
119
57.1k
          if (len == 6 && memcmp (t, "range:", 6) == 0)
120
11.8k
            {
121
              /* Skip whitespace.  */
122
23.8k
              while (*s != '\0' && strchr ("\n \t\r\f\v,", *s) != NULL)
123
12.0k
                s++;
124
125
              /* Collect a token.  */
126
11.8k
              t = s;
127
404k
              while (*s != '\0' && strchr ("\n \t\r\f\v,", *s) == NULL)
128
392k
                s++;
129
              /* Parse it.  */
130
11.8k
              if (*t >= '0' && *t <= '9')
131
7.42k
                {
132
7.42k
                  unsigned int min = 0;
133
134
114k
                  for (; *t >= '0' && *t <= '9'; t++)
135
107k
                    {
136
107k
                      if (min <= INT_MAX / 10)
137
51.9k
                        {
138
51.9k
                          min = 10 * min + (*t - '0');
139
51.9k
                          if (min > INT_MAX)
140
489
                            min = INT_MAX;
141
51.9k
                        }
142
55.3k
                      else
143
                        /* Avoid integer overflow.  */
144
55.3k
                        min = INT_MAX;
145
107k
                    }
146
7.42k
                  if (*t++ == '.')
147
6.27k
                    if (*t++ == '.')
148
5.91k
                      if (*t >= '0' && *t <= '9')
149
4.57k
                        {
150
4.57k
                          unsigned int max = 0;
151
64.0k
                          for (; *t >= '0' && *t <= '9'; t++)
152
59.4k
                            {
153
59.4k
                              if (max <= INT_MAX / 10)
154
17.5k
                                {
155
17.5k
                                  max = 10 * max + (*t - '0');
156
17.5k
                                  if (max > INT_MAX)
157
43
                                    max = INT_MAX;
158
17.5k
                                }
159
41.8k
                              else
160
                                /* Avoid integer overflow.  */
161
41.8k
                                max = INT_MAX;
162
59.4k
                            }
163
4.57k
                          if (min <= max)
164
2.28k
                            {
165
2.28k
                              rangep->min = min;
166
2.28k
                              rangep->max = max;
167
2.28k
                              continue;
168
2.28k
                            }
169
4.57k
                        }
170
7.42k
                }
171
11.8k
            }
172
173
          /* Accept wrap description.  */
174
54.8k
          if (len == 4 && memcmp (t, "wrap", 4) == 0)
175
433
            {
176
433
              *wrapp = yes;
177
433
              continue;
178
433
            }
179
54.4k
          if (len == 7 && memcmp (t, "no-wrap", 7) == 0)
180
546
            {
181
546
              *wrapp = no;
182
546
              continue;
183
546
            }
184
185
          /* Accept syntax check description.  */
186
53.9k
          if (scp != NULL && len >= 6 && memcmp (t + len - 6, "-check", 6) == 0)
187
0
            {
188
0
              const char *p;
189
0
              size_t n;
190
0
              enum is_syntax_check value;
191
192
0
              p = t;
193
0
              n = len - 6;
194
195
0
              if (n >= 3 && memcmp (p, "no-", 3) == 0)
196
0
                {
197
0
                  p += 3;
198
0
                  n -= 3;
199
0
                  value = no;
200
0
                }
201
0
              else
202
0
                value = yes;
203
204
0
              for (i = 0; i < NSYNTAXCHECKS; i++)
205
0
                if (strlen (syntax_check_name[i]) == n
206
0
                    && memcmp (syntax_check_name[i], p, n) == 0)
207
0
                  {
208
0
                    scp[i] = value;
209
0
                    break;
210
0
                  }
211
0
              if (i < NSYNTAXCHECKS)
212
0
                continue;
213
0
            }
214
215
          /* Unknown special comment marker.  It may have been generated
216
             from a future xgettext version.  Ignore it.  */
217
53.9k
        }
218
78.3k
    }
219
57.7k
}