Fix syntax error.
[gnulib.git] / lib / unistr / u8-prev.c
1 /* Iterate over previous character in UTF-8 string.
2    Copyright (C) 2002, 2006-2007 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2002.
4
5    This program is free software; you can redistribute it and/or modify it
6    under the terms of the GNU Library General Public License as published
7    by the Free Software Foundation; either version 2, or (at your option)
8    any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18    USA.  */
19
20 #include <config.h>
21
22 /* Specification.  */
23 #include "unistr.h"
24
25 const uint8_t *
26 u8_prev (ucs4_t *puc, const uint8_t *s, const uint8_t *start)
27 {
28   /* Keep in sync with utf8-ucs4.h and utf8-ucs4.c.  */
29   if (s != start)
30     {
31       uint8_t c_1 = s[-1];
32
33       if (c_1 < 0x80)
34         {
35           *puc = c_1;
36           return s - 1;
37         }
38 #if CONFIG_UNICODE_SAFETY
39       if ((c_1 ^ 0x80) < 0x40)
40 #endif
41         if (s - 1 != start)
42           {
43             uint8_t c_2 = s[-2];
44
45             if (c_2 >= 0xc2 && c_2 < 0xe0)
46               {
47                 *puc = ((unsigned int) (c_2 & 0x1f) << 6)
48                        | (unsigned int) (c_1 ^ 0x80);
49                 return s - 2;
50               }
51 #if CONFIG_UNICODE_SAFETY
52             if ((c_2 ^ 0x80) < 0x40)
53 #endif
54               if (s - 2 != start)
55                 {
56                   uint8_t c_3 = s[-3];
57
58                   if (c_3 >= 0xe0 && c_3 < 0xf0
59 #if CONFIG_UNICODE_SAFETY
60                       && (c_3 >= 0xe1 || c_2 >= 0xa0)
61                       && (c_3 != 0xed || c_2 < 0xa0)
62 #endif
63                      )
64                     {
65                       *puc = ((unsigned int) (c_3 & 0x0f) << 12)
66                              | ((unsigned int) (c_2 ^ 0x80) << 6)
67                              | (unsigned int) (c_1 ^ 0x80);
68                       return s - 3;
69                     }
70 #if CONFIG_UNICODE_SAFETY
71                   if ((c_3 ^ 0x80) < 0x40)
72 #endif
73                     if (s - 3 != start)
74                       {
75                         uint8_t c_4 = s[-4];
76
77                         if (c_4 >= 0xf0 && c_4 < 0xf8
78 #if CONFIG_UNICODE_SAFETY
79                             && (c_4 >= 0xf1 || c_3 >= 0x90)
80                             && (c_4 < 0xf4 || (c_4 == 0xf4 && c_3 < 0x90))
81 #endif
82                            )
83                           {
84                             *puc = ((unsigned int) (c_4 & 0x07) << 18)
85                                    | ((unsigned int) (c_3 ^ 0x80) << 12)
86                                    | ((unsigned int) (c_2 ^ 0x80) << 6)
87                                    | (unsigned int) (c_1 ^ 0x80);
88                             return s - 4;
89                           }
90                       }
91                 }
92           }
93     }
94   return NULL;
95 }