457
470
Conf->naffixes++;
474
/* Parsing states for parse_affentry() and friends */
460
475
#define PAE_WAIT_MASK 0
462
477
#define PAE_WAIT_FIND 2
464
479
#define PAE_WAIT_REPL 4
481
#define PAE_WAIT_TYPE 6
482
#define PAE_WAIT_FLAG 7
485
* Parse next space-separated field of an .affix file line.
487
* *str is the input pointer (will be advanced past field)
488
* next is where to copy the field value to, with null termination
490
* The buffer at "next" must be of size BUFSIZ; we truncate the input to fit.
492
* Returns TRUE if we found a field, FALSE if not.
495
get_nextfield(char **str, char *next)
497
int state = PAE_WAIT_MASK;
502
if (state == PAE_WAIT_MASK)
504
if (t_iseq(*str, '#'))
506
else if (!t_isspace(*str))
508
int clen = pg_mblen(*str);
512
COPYCHAR(next, *str);
519
else /* state == PAE_INMASK */
528
int clen = pg_mblen(*str);
532
COPYCHAR(next, *str);
538
*str += pg_mblen(*str);
543
return (state == PAE_INMASK); /* OK if we got a nonempty field */
547
* Parses entry of an .affix file of MySpell or Hunspell format.
549
* An .affix file entry has the following format:
551
* <type> <flag> <cross_flag> <flag_count>
552
* - fields after header:
553
* <type> <flag> <find> <replace> <mask>
555
* str is the input line
556
* field values are returned to type etc, which must be buffers of size BUFSIZ.
558
* Returns number of fields found; any omitted fields are set to empty strings.
561
parse_ooaffentry(char *str, char *type, char *flag, char *find,
562
char *repl, char *mask)
564
int state = PAE_WAIT_TYPE;
568
*type = *flag = *find = *repl = *mask = '\0';
575
valid = get_nextfield(&str, type);
576
state = PAE_WAIT_FLAG;
579
valid = get_nextfield(&str, flag);
580
state = PAE_WAIT_FIND;
583
valid = get_nextfield(&str, find);
584
state = PAE_WAIT_REPL;
587
valid = get_nextfield(&str, repl);
588
state = PAE_WAIT_MASK;
591
valid = get_nextfield(&str, mask);
592
state = -1; /* force loop exit */
595
elog(ERROR, "unrecognized state in parse_ooaffentry: %d",
602
break; /* early EOL */
604
break; /* got all fields */
611
* Parses entry of an .affix file of Ispell format
613
* An .affix file entry has the following format:
614
* <mask> > [-<find>,]<replace>
468
617
parse_affentry(char *str, char *mask, char *find, char *repl)
683
830
tsearch_readline_end(&trst);
685
sprintf(scanbuf, "%%6s %%%ds %%%ds %%%ds %%%ds", BUFSIZ / 5, BUFSIZ / 5, BUFSIZ / 5, BUFSIZ / 5);
687
832
if (!tsearch_readline_begin(&trst, filename))
689
834
(errcode(ERRCODE_CONFIG_FILE_ERROR),
693
838
while ((recoded = tsearch_readline(&trst)) != NULL)
695
842
if (*recoded == '\0' || t_isspace(recoded) || t_iseq(recoded, '#'))
698
scanread = sscanf(recoded, scanbuf, type, sflag, find, repl, mask);
845
fields_read = parse_ooaffentry(recoded, type, sflag, find, repl, mask);
702
849
ptype = lowerstr_ctx(Conf, type);
703
if (scanread < 4 || (STRNCMP(ptype, "sfx") && STRNCMP(ptype, "pfx")))
850
if (fields_read < 4 ||
851
(STRNCMP(ptype, "sfx") != 0 && STRNCMP(ptype, "pfx") != 0))
854
if (fields_read == 4)
708
856
if (strlen(sflag) != 1)
722
870
if (strlen(sflag) != 1 || flag != *sflag || flag == 0)
872
/* Get flags after '/' (flags are case sensitive) */
873
if ((ptr = strchr(repl, '/')) != NULL)
878
aflg |= Conf->flagval[*(unsigned char *) ptr];
882
/* Get lowercased version of string before '/' */
724
883
prepl = lowerstr_ctx(Conf, repl);
726
884
if ((ptr = strchr(prepl, '/')) != NULL)
729
ptr = repl + (ptr - prepl) + 1;
732
aflg |= Conf->flagval[*(unsigned char *) ptr];
736
886
pfind = lowerstr_ctx(Conf, find);
737
887
pmask = lowerstr_ctx(Conf, mask);
738
888
if (t_iseq(find, '0'))
801
951
if (STRNCMP(pstr, "compoundwords") == 0)
803
s = findchar(pstr, 'l');
953
/* Find case-insensitive L flag in non-lowercased string */
954
s = findchar2(recoded, 'l', 'L');
806
s = recoded + (s - pstr); /* we need non-lowercased
808
957
while (*s && !t_isspace(s))
809
958
s += pg_mblen(s);
810
959
while (*s && t_isspace(s))