1151497Sru// -*- C++ -*-
2151497Sru/* Copyright (C) 2002
3151497Sru   Free Software Foundation, Inc.
4151497Sru     Written by Werner Lemberg <wl@gnu.org>
5151497Sru
6151497SruThis file is part of groff.
7151497Sru
8151497Srugroff is free software; you can redistribute it and/or modify it under
9151497Sruthe terms of the GNU General Public License as published by the Free
10151497SruSoftware Foundation; either version 2, or (at your option) any later
11151497Sruversion.
12151497Sru
13151497Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY
14151497SruWARRANTY; without even the implied warranty of MERCHANTABILITY or
15151497SruFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16151497Srufor more details.
17151497Sru
18151497SruYou should have received a copy of the GNU General Public License along
19151497Sruwith groff; see the file COPYING.  If not, write to the Free Software
20151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
21151497Sru
22151497Sru#include "lib.h"
23151497Sru#include "cset.h"
24151497Sru#include "stringclass.h"
25151497Sru
26151497Sru#include "unicode.h"
27151497Sru
28151497Sruconst char *check_unicode_name(const char *u)
29151497Sru{
30151497Sru  if (*u != 'u')
31151497Sru    return 0;
32151497Sru  const char *p = ++u;
33151497Sru  for (;;) {
34151497Sru    int val = 0;
35151497Sru    const char *start = p;
36151497Sru    for (;;) {
37151497Sru      // only uppercase hex digits allowed
38151497Sru      if (!csxdigit(*p))
39151497Sru	return 0;
40151497Sru      if (csdigit(*p))
41151497Sru	val = val*0x10 + (*p-'0');
42151497Sru      else if (csupper(*p))
43151497Sru	val = val*0x10 + (*p-'A'+10);
44151497Sru      else
45151497Sru	return 0;
46151497Sru      // biggest Unicode value is U+10FFFF
47151497Sru      if (val > 0x10FFFF)
48151497Sru	return 0;
49151497Sru      p++;
50151497Sru      if (*p == '\0' || *p == '_')
51151497Sru	break;
52151497Sru    }
53151497Sru    // surrogates not allowed
54151497Sru    if ((val >= 0xD800 && val <= 0xDBFF) || (val >= 0xDC00 && val <= 0xDFFF))
55151497Sru      return 0;
56151497Sru    if (val > 0xFFFF) {
57151497Sru      if (*start == '0')	// no leading zeros allowed if > 0xFFFF
58151497Sru	return 0;
59151497Sru    }
60151497Sru    else if (p - start != 4)	// otherwise, check for exactly 4 hex digits
61151497Sru      return 0;
62151497Sru    if (*p == '\0')
63151497Sru      break;
64151497Sru    p++;
65151497Sru  }
66151497Sru  return u;
67151497Sru}
68