+2024-09-15 Bruno Haible <bruno@clisp.org>
+
+ unilbrk: Fix bugs in implementation of Unicode rules (LB15a), (LB15b).
+ * lib/gen-uni-tables.c (output_lbrk_rules_as_tables): Fix typo in
+ comment.
+ * lib/unilbrk/u8-possible-linebreaks.c (u8_possible_linebreaks_loop):
+ Do the LBP_QU2 to LBP_QU1 mapping for (LB15a) after the table lookup but
+ before the assignment to last_prop. Do the LBP_QU3 to LBP_QU1 mapping
+ for (LB15b) in a way that does not influence prev_prop or last_prop.
+ * lib/unilbrk/u16-possible-linebreaks.c (u16_possible_linebreaks_loop):
+ Likewise.
+ * lib/unilbrk/u32-possible-linebreaks.c (u32_possible_linebreaks_loop):
+ Likewise.
+
2024-09-14 Bruno Haible <bruno@clisp.org>
unilbrk: Fix bug in implementation of Unicode rule (LB16).
set_table_cell (prohibited_with_sp, true);
}
- /* (LB15a) Do not break before an ambiguous quotation that is an initial
+ /* (LB15a) Do not break after an ambiguous quotation that is an initial
punctuation, even after spaces. */
for (after = 0; after < NLBP; after++)
{
/* This is arbitrary. */
prop = LBP_AL1;
break;
- case LBP_QU2:
- /* For (LB15a): Replace LBP_QU2 with LBP_QU1 if the previous
- character's line break property was not one of
- BK, CR, LF, OP, QU, GL, SP, ZW. */
- switch (prev_prop)
- {
- case LBP_BK:
- case LBP_CR:
- case LBP_LF:
- case LBP_OP1: case LBP_OP2:
- case LBP_QU1: case LBP_QU2: case LBP_QU3:
- case LBP_GL:
- case LBP_SP:
- case LBP_ZW:
- break;
- default:
- prop = LBP_QU1;
- break;
- }
- break;
- case LBP_QU3:
- /* For (LB15b): Replace LBP_QU3 with LBP_QU1 if the next
- character's line break property is not one of
- BK, CR, LF, SP, GL, WJ, CL, QU, CP, EX, IS, SY, ZW. */
- switch (PROP (lookahead1_prop_ea))
- {
- case LBP_BK:
- case LBP_CR:
- case LBP_LF:
- case LBP_SP:
- case LBP_GL:
- case LBP_WJ:
- case LBP_CL:
- case LBP_QU1: case LBP_QU2: case LBP_QU3:
- case LBP_CP1: case LBP_CP2:
- case LBP_EX:
- case LBP_IS:
- case LBP_SY:
- case LBP_ZW:
- break;
- default:
- prop = LBP_QU1;
- break;
- }
- break;
}
/* Deal with spaces and combining characters. */
}
else
{
- switch (unilbrk_table [last_prop] [prop])
+ int this_prop = prop;
+ if (prop == LBP_QU3)
+ {
+ /* For (LB15b): Replace LBP_QU3 with LBP_QU1 if the
+ next character's line break property is not one of
+ BK, CR, LF, SP, GL, WJ, CL, QU, CP, EX, IS, SY, ZW. */
+ switch (PROP (lookahead1_prop_ea))
+ {
+ case LBP_BK:
+ case LBP_CR:
+ case LBP_LF:
+ case LBP_SP:
+ case LBP_GL:
+ case LBP_WJ:
+ case LBP_CL:
+ case LBP_QU1: case LBP_QU2: case LBP_QU3:
+ case LBP_CP1: case LBP_CP2:
+ case LBP_EX:
+ case LBP_IS:
+ case LBP_SY:
+ case LBP_ZW:
+ break;
+ default:
+ this_prop = LBP_QU1;
+ break;
+ }
+ }
+
+ switch (unilbrk_table [last_prop] [this_prop])
{
case D:
*p = UC_BREAK_POSSIBLE;
abort ();
}
}
+
+ if (prop == LBP_QU2)
+ {
+ /* For (LB15a): Replace LBP_QU2 with LBP_QU1 if the
+ previous character's line break property was not one of
+ BK, CR, LF, OP, QU, GL, SP, ZW. */
+ switch (prev_prop)
+ {
+ case LBP_BK:
+ case LBP_CR:
+ case LBP_LF:
+ case LBP_OP1: case LBP_OP2:
+ case LBP_QU1: case LBP_QU2: case LBP_QU3:
+ case LBP_GL:
+ case LBP_SP:
+ case LBP_ZW:
+ break;
+ default:
+ prop = LBP_QU1;
+ break;
+ }
+ }
+
last_prop = prop;
seen_space = NULL;
}
/* This is arbitrary. */
prop = LBP_AL1;
break;
- case LBP_QU2:
- /* For (LB15a): Replace LBP_QU2 with LBP_QU1 if the previous
- character's line break property was not one of
- BK, CR, LF, OP, QU, GL, SP, ZW. */
- switch (prev_prop)
- {
- case LBP_BK:
- case LBP_CR:
- case LBP_LF:
- case LBP_OP1: case LBP_OP2:
- case LBP_QU1: case LBP_QU2: case LBP_QU3:
- case LBP_GL:
- case LBP_SP:
- case LBP_ZW:
- break;
- default:
- prop = LBP_QU1;
- break;
- }
- break;
- case LBP_QU3:
- /* For (LB15b): Replace LBP_QU3 with LBP_QU1 if the next
- character's line break property is not one of
- BK, CR, LF, SP, GL, WJ, CL, QU, CP, EX, IS, SY, ZW. */
- switch (PROP (lookahead1_prop_ea))
- {
- case LBP_BK:
- case LBP_CR:
- case LBP_LF:
- case LBP_SP:
- case LBP_GL:
- case LBP_WJ:
- case LBP_CL:
- case LBP_QU1: case LBP_QU2: case LBP_QU3:
- case LBP_CP1: case LBP_CP2:
- case LBP_EX:
- case LBP_IS:
- case LBP_SY:
- case LBP_ZW:
- break;
- default:
- prop = LBP_QU1;
- break;
- }
- break;
}
/* Deal with spaces and combining characters. */
}
else
{
- switch (unilbrk_table [last_prop] [prop])
+ int this_prop = prop;
+ if (prop == LBP_QU3)
+ {
+ /* For (LB15b): Replace LBP_QU3 with LBP_QU1 if the
+ next character's line break property is not one of
+ BK, CR, LF, SP, GL, WJ, CL, QU, CP, EX, IS, SY, ZW. */
+ switch (PROP (lookahead1_prop_ea))
+ {
+ case LBP_BK:
+ case LBP_CR:
+ case LBP_LF:
+ case LBP_SP:
+ case LBP_GL:
+ case LBP_WJ:
+ case LBP_CL:
+ case LBP_QU1: case LBP_QU2: case LBP_QU3:
+ case LBP_CP1: case LBP_CP2:
+ case LBP_EX:
+ case LBP_IS:
+ case LBP_SY:
+ case LBP_ZW:
+ break;
+ default:
+ this_prop = LBP_QU1;
+ break;
+ }
+ }
+
+ switch (unilbrk_table [last_prop] [this_prop])
{
case D:
*p = UC_BREAK_POSSIBLE;
abort ();
}
}
+
+ if (prop == LBP_QU2)
+ {
+ /* For (LB15a): Replace LBP_QU2 with LBP_QU1 if the
+ previous character's line break property was not one of
+ BK, CR, LF, OP, QU, GL, SP, ZW. */
+ switch (prev_prop)
+ {
+ case LBP_BK:
+ case LBP_CR:
+ case LBP_LF:
+ case LBP_OP1: case LBP_OP2:
+ case LBP_QU1: case LBP_QU2: case LBP_QU3:
+ case LBP_GL:
+ case LBP_SP:
+ case LBP_ZW:
+ break;
+ default:
+ prop = LBP_QU1;
+ break;
+ }
+ }
+
last_prop = prop;
seen_space = NULL;
}
/* This is arbitrary. */
prop = LBP_AL1;
break;
- case LBP_QU2:
- /* For (LB15a): Replace LBP_QU2 with LBP_QU1 if the previous
- character's line break property was not one of
- BK, CR, LF, OP, QU, GL, SP, ZW. */
- switch (prev_prop)
- {
- case LBP_BK:
- case LBP_CR:
- case LBP_LF:
- case LBP_OP1: case LBP_OP2:
- case LBP_QU1: case LBP_QU2: case LBP_QU3:
- case LBP_GL:
- case LBP_SP:
- case LBP_ZW:
- break;
- default:
- prop = LBP_QU1;
- break;
- }
- break;
- case LBP_QU3:
- /* For (LB15b): Replace LBP_QU3 with LBP_QU1 if the next
- character's line break property is not one of
- BK, CR, LF, SP, GL, WJ, CL, QU, CP, EX, IS, SY, ZW. */
- switch (PROP (lookahead1_prop_ea))
- {
- case LBP_BK:
- case LBP_CR:
- case LBP_LF:
- case LBP_SP:
- case LBP_GL:
- case LBP_WJ:
- case LBP_CL:
- case LBP_QU1: case LBP_QU2: case LBP_QU3:
- case LBP_CP1: case LBP_CP2:
- case LBP_EX:
- case LBP_IS:
- case LBP_SY:
- case LBP_ZW:
- break;
- default:
- prop = LBP_QU1;
- break;
- }
- break;
}
/* Deal with spaces and combining characters. */
}
else
{
- switch (unilbrk_table [last_prop] [prop])
+ int this_prop = prop;
+ if (prop == LBP_QU3)
+ {
+ /* For (LB15b): Replace LBP_QU3 with LBP_QU1 if the
+ next character's line break property is not one of
+ BK, CR, LF, SP, GL, WJ, CL, QU, CP, EX, IS, SY, ZW. */
+ switch (PROP (lookahead1_prop_ea))
+ {
+ case LBP_BK:
+ case LBP_CR:
+ case LBP_LF:
+ case LBP_SP:
+ case LBP_GL:
+ case LBP_WJ:
+ case LBP_CL:
+ case LBP_QU1: case LBP_QU2: case LBP_QU3:
+ case LBP_CP1: case LBP_CP2:
+ case LBP_EX:
+ case LBP_IS:
+ case LBP_SY:
+ case LBP_ZW:
+ break;
+ default:
+ this_prop = LBP_QU1;
+ break;
+ }
+ }
+
+ switch (unilbrk_table [last_prop] [this_prop])
{
case D:
*p = UC_BREAK_POSSIBLE;
abort ();
}
}
+
+ if (prop == LBP_QU2)
+ {
+ /* For (LB15a): Replace LBP_QU2 with LBP_QU1 if the
+ previous character's line break property was not one of
+ BK, CR, LF, OP, QU, GL, SP, ZW. */
+ switch (prev_prop)
+ {
+ case LBP_BK:
+ case LBP_CR:
+ case LBP_LF:
+ case LBP_OP1: case LBP_OP2:
+ case LBP_QU1: case LBP_QU2: case LBP_QU3:
+ case LBP_GL:
+ case LBP_SP:
+ case LBP_ZW:
+ break;
+ default:
+ prop = LBP_QU1;
+ break;
+ }
+ }
+
last_prop = prop;
seen_space = NULL;
}