/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 | } |