Put into CHS, which currently contains *PNCHS bytes containing NUL-terminated abbreviations none of which are suffixes of another, the abbreviation ABBR including its trailing NUL. If ABBR does not already appear in CHS, possibly as a suffix of an existing abbreviation, add ABBR to CHS, remove from CHS any abbreviation that is a suffix of ABBR, and increment *PNCHS accordingly.
| 4221 | Return the index of ABBR after any modifications to CHS are made. |
| 4222 | |
| 4223 | If all abbreviations have already been added, this function |
| 4224 | lets the caller look up the index of an existing abbreviation. */ |
| 4225 | static int |
| 4226 | addabbr(char chs[TZ_MAX_CHARS], int *pnchs, char const *abbr) |
| 4227 | { |
| 4228 | int nchs = *pnchs; |
| 4229 | int alen = strlen(abbr), nchs_incr = alen + 1; |
| 4230 | int i; |
| 4231 | for (i = 0; i < nchs; ) { |
| 4232 | int clen = strlen(&chs[i]); |
| 4233 | if (alen <= clen) { |
| 4234 | /* If ABBR is a suffix of an abbreviation in CHS, |
| 4235 | return the index of ABBR in CHS. */ |
| 4236 | int isuff = i + (clen - alen); |
| 4237 | if (memcmp(&chs[isuff], abbr, alen) == 0) |
| 4238 | return isuff; |
| 4239 | } else if (memcmp(&chs[i], &abbr[alen - clen], clen) == 0) { |
| 4240 | /* An abbreviation in CHS is a substring of ABBR. |
| 4241 | Replace it with ABBR, instead of the more-common |
| 4242 | actions of appending ABBR or doing nothing. */ |
| 4243 | nchs_incr = alen - clen; |
| 4244 | break; |
| 4245 | } |
| 4246 | i += clen + 1; |
| 4247 | } |
| 4248 | if (TZ_MAX_CHARS < nchs + nchs_incr) { |
| 4249 | error(N_("too many, or too long, time zone abbreviations")); |
| 4250 | exit(EXIT_FAILURE); |
| 4251 | } |
| 4252 | memmove(&chs[i + nchs_incr], &chs[i], nchs - i); |
| 4253 | memcpy(&chs[i], abbr, nchs_incr); |
| 4254 | *pnchs = nchs + nchs_incr; |
| 4255 | return i; |
| 4256 | } |
| 4257 |