@@ -519,12 +519,122 @@ NIAddAffix(IspellDict *Conf, int flag, char flagflags, const char *mask, const c
519
519
}
520
520
521
521
#define PAE_WAIT_MASK 0
522
- #define PAE_INMASK 1
522
+ #define PAE_INMASK 1
523
523
#define PAE_WAIT_FIND 2
524
- #define PAE_INFIND 3
524
+ #define PAE_INFIND 3
525
525
#define PAE_WAIT_REPL 4
526
- #define PAE_INREPL 5
526
+ #define PAE_INREPL 5
527
+ #define PAE_WAIT_TYPE 6
528
+ #define PAE_WAIT_FLAG 7
527
529
530
+ /*
531
+ * Used in parse_ooaffentry() to parse an .affix file entry.
532
+ */
533
+ static bool
534
+ get_nextentry (char * * str , char * next )
535
+ {
536
+ int state = PAE_WAIT_MASK ;
537
+ char * pnext = next ;
538
+
539
+ * next = '\0' ;
540
+
541
+ while (* * str )
542
+ {
543
+ if (state == PAE_WAIT_MASK )
544
+ {
545
+ if (t_iseq (* str , '#' ))
546
+ return false;
547
+ else if (!t_isspace (* str ))
548
+ {
549
+ COPYCHAR (pnext , * str );
550
+ pnext += pg_mblen (* str );
551
+ state = PAE_INMASK ;
552
+ }
553
+ }
554
+ else if (state == PAE_INMASK )
555
+ {
556
+ if (t_isspace (* str ))
557
+ {
558
+ * pnext = '\0' ;
559
+ return true;
560
+ }
561
+ else
562
+ {
563
+ COPYCHAR (pnext , * str );
564
+ pnext += pg_mblen (* str );
565
+ }
566
+ }
567
+ * str += pg_mblen (* str );
568
+ }
569
+
570
+ * pnext = '\0' ;
571
+
572
+ return * next ;
573
+ }
574
+
575
+ /*
576
+ * Parses entry of an .affix file of MySpell or Hunspell format.
577
+ *
578
+ * An .affix file entry has the following format:
579
+ * - header
580
+ * <type> <flag> <cross_flag> <flag_count>
581
+ * - fields after header:
582
+ * <type> <flag> <find> <replace> <mask>
583
+ */
584
+ static int
585
+ parse_ooaffentry (char * str , char * type , char * flag , char * find ,
586
+ char * repl , char * mask )
587
+ {
588
+ int state = PAE_WAIT_TYPE ,
589
+ next_state = PAE_WAIT_FLAG ;
590
+ int parse_read = 0 ;
591
+ bool valid = true;
592
+
593
+ * type = * flag = * find = * repl = * mask = '\0' ;
594
+
595
+ while (* str && valid )
596
+ {
597
+ switch (state )
598
+ {
599
+ case PAE_WAIT_TYPE :
600
+ valid = get_nextentry (& str , type );
601
+ break ;
602
+ case PAE_WAIT_FLAG :
603
+ valid = get_nextentry (& str , flag );
604
+ next_state = PAE_WAIT_FIND ;
605
+ break ;
606
+ case PAE_WAIT_FIND :
607
+ valid = get_nextentry (& str , find );
608
+ next_state = PAE_WAIT_REPL ;
609
+ break ;
610
+ case PAE_WAIT_REPL :
611
+ valid = get_nextentry (& str , repl );
612
+ next_state = PAE_WAIT_MASK ;
613
+ break ;
614
+ case PAE_WAIT_MASK :
615
+ get_nextentry (& str , mask );
616
+ /* break loop */
617
+ valid = false;
618
+ break ;
619
+ default :
620
+ elog (ERROR , "unrecognized state in parse_ooaffentry: %d" , state );
621
+ }
622
+ state = next_state ;
623
+ if (* str )
624
+ str += pg_mblen (str );
625
+
626
+ parse_read ++ ;
627
+ }
628
+
629
+ return parse_read ;
630
+ }
631
+
632
+ /*
633
+ * Parses entry of an .affix file of Ispell format
634
+ *
635
+ * An .affix file entry has the following format:
636
+ * <mask> > [-<find>,]<replace>
637
+ */
528
638
static bool
529
639
parse_affentry (char * str , char * mask , char * find , char * repl )
530
640
{
@@ -731,8 +841,7 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename)
731
841
sflaglen = 0 ;
732
842
char flagflags = 0 ;
733
843
tsearch_readline_state trst ;
734
- int scanread = 0 ;
735
- char scanbuf [BUFSIZ ];
844
+ int parseread = 0 ;
736
845
char * recoded ;
737
846
738
847
/* read file to find any flag */
@@ -804,8 +913,6 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename)
804
913
}
805
914
tsearch_readline_end (& trst );
806
915
807
- sprintf (scanbuf , "%%6s %%%ds %%%ds %%%ds %%%ds" , BUFSIZ / 5 , BUFSIZ / 5 , BUFSIZ / 5 , BUFSIZ / 5 );
808
-
809
916
if (!tsearch_readline_begin (& trst , filename ))
810
917
ereport (ERROR ,
811
918
(errcode (ERRCODE_CONFIG_FILE_ERROR ),
@@ -817,8 +924,7 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename)
817
924
if (* recoded == '\0' || t_isspace (recoded ) || t_iseq (recoded , '#' ))
818
925
goto nextline ;
819
926
820
- * find = * repl = * mask = '\0' ;
821
- scanread = sscanf (recoded , scanbuf , type , sflag , find , repl , mask );
927
+ parseread = parse_ooaffentry (recoded , type , sflag , find , repl , mask );
822
928
823
929
if (ptype )
824
930
pfree (ptype );
@@ -859,7 +965,7 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename)
859
965
goto nextline ;
860
966
}
861
967
/* Else try to parse prefixes and suffixes */
862
- if (scanread < 4 || (STRNCMP (ptype , "sfx" ) && STRNCMP (ptype , "pfx" )))
968
+ if (parseread < 4 || (STRNCMP (ptype , "sfx" ) && STRNCMP (ptype , "pfx" )))
863
969
goto nextline ;
864
970
865
971
sflaglen = strlen (sflag );
@@ -888,9 +994,13 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename)
888
994
if (flag == 0 )
889
995
goto nextline ;
890
996
prepl = lowerstr_ctx (Conf , repl );
891
- /* affix flag */
997
+ /* Find position of '/' in lowercased string "prepl" */
892
998
if ((ptr = strchr (prepl , '/' )) != NULL )
893
999
{
1000
+ /*
1001
+ * Here we use non-lowercased string "repl". We need position of
1002
+ * '/' in "repl".
1003
+ */
894
1004
* ptr = '\0' ;
895
1005
ptr = repl + (ptr - prepl ) + 1 ;
896
1006
aflg |= getFlagValues (Conf , getFlags (Conf , ptr ));
@@ -964,11 +1074,12 @@ NIImportAffixes(IspellDict *Conf, const char *filename)
964
1074
965
1075
if (STRNCMP (pstr , "compoundwords" ) == 0 )
966
1076
{
1077
+ /* Find position in lowercased string "pstr" */
967
1078
s = findchar (pstr , 'l' );
968
1079
if (s )
969
1080
{
970
- s = recoded + ( s - pstr ); /* we need non-lowercased
971
- * string */
1081
+ /* Here we use non-lowercased string "recoded" */
1082
+ s = recoded + ( s - pstr );
972
1083
while (* s && !t_isspace (s ))
973
1084
s += pg_mblen (s );
974
1085
while (* s && t_isspace (s ))
0 commit comments