1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  cffparse.c                                                             */
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*    CFF token stream parser (body)                                       */
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  Copyright 1996-2004, 2007-2013 by                                      */
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  This file is part of the FreeType project, and may only be used,       */
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  modified, and distributed under the terms of the FreeType project      */
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  this file you indicate that you have read the license and              */
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  understand and accept it fully.                                        */
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/ft2build.h"
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cffparse.h"
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftstream.h"
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftdebug.h"
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cfferrs.h"
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cffpic.h"
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* messages during execution.                                            */
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  FT_COMPONENT
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT  trace_cffparse
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_LOCAL_DEF( void )
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parser_init( CFF_Parser  parser,
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   FT_UInt     code,
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   void*       object,
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   FT_Library  library)
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_MEM_ZERO( parser, sizeof ( *parser ) );
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->top         = parser->stack;
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->object_code = code;
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->object      = object;
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->library     = library;
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* read an integer */
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Long
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parse_integer( FT_Byte*  start,
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     FT_Byte*  limit )
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*  p   = start;
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int    v   = *p++;
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long   val = 0;
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( v == 28 )
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( p + 2 > limit )
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Bad;
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] );
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p  += 2;
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( v == 29 )
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( p + 4 > limit )
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Bad;
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      val = (FT_Long)( ( (FT_ULong)p[0] << 24 ) |
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       ( (FT_ULong)p[1] << 16 ) |
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       ( (FT_ULong)p[2] <<  8 ) |
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         (FT_ULong)p[3]         );
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p += 4;
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( v < 247 )
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      val = v - 139;
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( v < 251 )
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( p + 1 > limit )
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Bad;
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      val = ( v - 247 ) * 256 + p[0] + 108;
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p++;
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( p + 1 > limit )
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Bad;
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      val = -( v - 251 ) * 256 - p[0] - 108;
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p++;
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return val;
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Bad:
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    val = 0;
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_TRACE4(( "!!!END OF DATA:!!!" ));
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static const FT_Long power_tens[] =
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1L,
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    10L,
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    100L,
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1000L,
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    10000L,
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    100000L,
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1000000L,
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    10000000L,
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    100000000L,
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1000000000L
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  };
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* read a real */
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Fixed
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parse_real( FT_Byte*  start,
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Byte*  limit,
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Long   power_ten,
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Long*  scaling )
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*  p = start;
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt   nib;
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt   phase;
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long   result, number, exponent;
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int    sign = 0, exponent_sign = 0, have_overflow = 0;
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long   exponent_add, integer_length, fraction_length;
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( scaling )
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      *scaling = 0;
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    result = 0;
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    number   = 0;
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    exponent = 0;
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    exponent_add    = 0;
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    integer_length  = 0;
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    fraction_length = 0;
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* First of all, read the integer part. */
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    phase = 4;
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (;;)
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* If we entered this iteration with phase == 4, we need to */
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* read a new byte.  This also skips past the initial 0x1E. */
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( phase )
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p++;
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Make sure we don't read past the end. */
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( p >= limit )
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Bad;
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Get the nibble. */
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      nib   = ( p[0] >> phase ) & 0xF;
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      phase = 4 - phase;
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( nib == 0xE )
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        sign = 1;
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( nib > 9 )
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        break;
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Increase exponent if we can't add the digit. */
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( number >= 0xCCCCCCCL )
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          exponent_add++;
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Skip leading zeros. */
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else if ( nib || number )
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          integer_length++;
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          number = number * 10 + nib;
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Read fraction part, if any. */
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( nib == 0xa )
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for (;;)
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* If we entered this iteration with phase == 4, we need */
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* to read a new byte.                                   */
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( phase )
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          p++;
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          /* Make sure we don't read past the end. */
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( p >= limit )
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Bad;
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Get the nibble. */
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        nib   = ( p[0] >> phase ) & 0xF;
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        phase = 4 - phase;
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( nib >= 10 )
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          break;
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Skip leading zeros if possible. */
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( !nib && !number )
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          exponent_add--;
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Only add digit if we don't overflow. */
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else if ( number < 0xCCCCCCCL && fraction_length < 9 )
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          fraction_length++;
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          number = number * 10 + nib;
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Read exponent, if any. */
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( nib == 12 )
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      exponent_sign = 1;
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      nib           = 11;
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( nib == 11 )
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      for (;;)
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* If we entered this iteration with phase == 4, */
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* we need to read a new byte.                   */
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( phase )
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          p++;
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          /* Make sure we don't read past the end. */
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( p >= limit )
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Bad;
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Get the nibble. */
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        nib   = ( p[0] >> phase ) & 0xF;
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        phase = 4 - phase;
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( nib >= 10 )
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          break;
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Arbitrarily limit exponent. */
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( exponent > 1000 )
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          have_overflow = 1;
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          exponent = exponent * 10 + nib;
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( exponent_sign )
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        exponent = -exponent;
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !number )
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Exit;
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( have_overflow )
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( exponent_sign )
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Underflow;
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Overflow;
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* We don't check `power_ten' and `exponent_add'. */
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    exponent += power_ten + exponent_add;
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( scaling )
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Only use `fraction_length'. */
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      fraction_length += integer_length;
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      exponent        += integer_length;
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( fraction_length <= 5 )
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( number > 0x7FFFL )
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          result   = FT_DivFix( number, 10 );
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          *scaling = exponent - fraction_length + 1;
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( exponent > 0 )
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_Long  new_fraction_length, shift;
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* Make `scaling' as small as possible. */
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            new_fraction_length = FT_MIN( exponent, 5 );
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            shift               = new_fraction_length - fraction_length;
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if ( shift > 0 )
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            {
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              exponent -= new_fraction_length;
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              number   *= power_tens[shift];
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              if ( number > 0x7FFFL )
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              {
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                number   /= 10;
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                exponent += 1;
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              }
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            else
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              exponent -= fraction_length;
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          }
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          else
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            exponent -= fraction_length;
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          result   = (FT_Long)( (FT_ULong)number << 16 );
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          *scaling = exponent;
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( ( number / power_tens[fraction_length - 5] ) > 0x7FFFL )
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          result   = FT_DivFix( number, power_tens[fraction_length - 4] );
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          *scaling = exponent - 4;
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          result   = FT_DivFix( number, power_tens[fraction_length - 5] );
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          *scaling = exponent - 5;
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      integer_length  += exponent;
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      fraction_length -= exponent;
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( integer_length > 5 )
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Overflow;
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( integer_length < -5 )
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Underflow;
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Remove non-significant digits. */
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( integer_length < 0 )
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        number          /= power_tens[-integer_length];
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        fraction_length += integer_length;
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* this can only happen if exponent was non-zero */
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( fraction_length == 10 )
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        number          /= 10;
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        fraction_length -= 1;
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* Convert into 16.16 format. */
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( fraction_length > 0 )
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( ( number / power_tens[fraction_length] ) > 0x7FFFL )
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Exit;
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = FT_DivFix( number, power_tens[fraction_length] );
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        number *= power_tens[-fraction_length];
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( number > 0x7FFFL )
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Overflow;
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = (FT_Long)( (FT_ULong)number << 16 );
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( sign )
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      result = -result;
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return result;
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Overflow:
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    result = 0x7FFFFFFFL;
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_TRACE4(( "!!!OVERFLOW:!!!" ));
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Underflow:
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    result = 0;
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Bad:
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    result = 0;
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_TRACE4(( "!!!END OF DATA:!!!" ));
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* read a number, either integer or real */
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Long
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parse_num( FT_Byte**  d )
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return **d == 30 ? ( cff_parse_real( d[0], d[1], 0, NULL ) >> 16 )
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     :   cff_parse_integer( d[0], d[1] );
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* read a floating point number, either integer or real */
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Fixed
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  do_fixed( FT_Byte**  d,
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_Long    scaling )
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( **d == 30 )
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return cff_parse_real( d[0], d[1], scaling, NULL );
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Long  val = cff_parse_integer( d[0], d[1] );
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( scaling )
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val *= power_tens[scaling];
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( val > 0x7FFF )
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val = 0x7FFFFFFFL;
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Overflow;
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( val < -0x7FFF )
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        val = -0x7FFFFFFFL;
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Overflow;
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return (FT_Long)( (FT_ULong)val << 16 );
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Overflow:
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE4(( "!!!OVERFLOW:!!!" ));
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return val;
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* read a floating point number, either integer or real */
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Fixed
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parse_fixed( FT_Byte**  d )
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return do_fixed( d, 0 );
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* read a floating point number, either integer or real, */
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* but return `10^scaling' times the number read in      */
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Fixed
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parse_fixed_scaled( FT_Byte**  d,
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                          FT_Long    scaling )
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return do_fixed( d, scaling );
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* read a floating point number, either integer or real,     */
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* and return it as precise as possible -- `scaling' returns */
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* the scaling factor (as a power of 10)                     */
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Fixed
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parse_fixed_dynamic( FT_Byte**  d,
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FT_Long*   scaling )
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ASSERT( scaling );
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( **d == 30 )
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return cff_parse_real( d[0], d[1], 0, scaling );
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Long  number;
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int   integer_length;
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      number = cff_parse_integer( d[0], d[1] );
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( number > 0x7FFFL )
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for ( integer_length = 5; integer_length < 10; integer_length++ )
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( number < power_tens[integer_length] )
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( ( number / power_tens[integer_length - 5] ) > 0x7FFFL )
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          *scaling = integer_length - 4;
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          return FT_DivFix( number, power_tens[integer_length - 4] );
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          *scaling = integer_length - 5;
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          return FT_DivFix( number, power_tens[integer_length - 5] );
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *scaling = 0;
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return (FT_Long)( (FT_ULong)number << 16 );
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parse_font_matrix( CFF_Parser  parser )
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFF_FontRecDict  dict   = (CFF_FontRecDict)parser->object;
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Matrix*       matrix = &dict->font_matrix;
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Vector*       offset = &dict->font_offset;
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong*        upm    = &dict->units_per_em;
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte**        data   = parser->stack;
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error         error  = FT_ERR( Stack_Underflow );
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( parser->top >= parser->stack + 6 )
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Long  scaling;
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_Err_Ok;
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict->has_font_matrix = TRUE;
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* We expect a well-formed font matrix, this is, the matrix elements */
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* `xx' and `yy' are of approximately the same magnitude.  To avoid  */
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* loss of precision, we use the magnitude of element `xx' to scale  */
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* all other elements.  The scaling factor is then contained in the  */
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* `units_per_em' value.                                             */
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->xx = cff_parse_fixed_dynamic( data++, &scaling );
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      scaling = -scaling;
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( scaling < 0 || scaling > 9 )
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* Return default matrix in case of unlikely values. */
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_TRACE1(( "cff_parse_font_matrix:"
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    " strange scaling value for xx element (%d),\n"
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    "                      "
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    " using default matrix\n", scaling ));
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        matrix->xx = 0x10000L;
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        matrix->yx = 0;
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        matrix->xy = 0;
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        matrix->yy = 0x10000L;
553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offset->x  = 0;
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offset->y  = 0;
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *upm       = 1;
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Exit;
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->yx = cff_parse_fixed_scaled( data++, scaling );
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->xy = cff_parse_fixed_scaled( data++, scaling );
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      matrix->yy = cff_parse_fixed_scaled( data++, scaling );
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      offset->x  = cff_parse_fixed_scaled( data++, scaling );
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      offset->y  = cff_parse_fixed_scaled( data,   scaling );
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      *upm = power_tens[scaling];
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE4(( " [%f %f %f %f %f %f]\n",
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  (double)matrix->xx / *upm / 65536,
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  (double)matrix->xy / *upm / 65536,
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  (double)matrix->yx / *upm / 65536,
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  (double)matrix->yy / *upm / 65536,
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  (double)offset->x  / *upm / 65536,
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  (double)offset->y  / *upm / 65536 ));
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parse_font_bbox( CFF_Parser  parser )
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_BBox*         bbox = &dict->font_bbox;
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte**        data = parser->stack;
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error         error;
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = FT_ERR( Stack_Underflow );
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( parser->top >= parser->stack + 4 )
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) );
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      bbox->yMax = FT_RoundFix( cff_parse_fixed( data   ) );
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_Err_Ok;
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE4(( " [%d %d %d %d]\n",
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  bbox->xMin / 65536,
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  bbox->yMin / 65536,
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  bbox->xMax / 65536,
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  bbox->yMax / 65536 ));
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parse_private_dict( CFF_Parser  parser )
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte**        data = parser->stack;
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error         error;
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = FT_ERR( Stack_Underflow );
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( parser->top >= parser->stack + 2 )
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict->private_size   = cff_parse_num( data++ );
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict->private_offset = cff_parse_num( data   );
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE4(( " %lu %lu\n",
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  dict->private_size, dict->private_offset ));
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_Err_Ok;
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Error
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parse_cid_ros( CFF_Parser  parser )
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFF_FontRecDict  dict = (CFF_FontRecDict)parser->object;
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte**        data = parser->stack;
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error         error;
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = FT_ERR( Stack_Underflow );
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( parser->top >= parser->stack + 3 )
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict->cid_registry = (FT_UInt)cff_parse_num( data++ );
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict->cid_ordering = (FT_UInt)cff_parse_num( data++ );
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( **data == 30 )
651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_TRACE1(( "cff_parse_cid_ros: real supplement is rounded\n" ));
652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      dict->cid_supplement = cff_parse_num( data );
653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( dict->cid_supplement < 0 )
654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",
655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   dict->cid_supplement ));
656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      error = FT_Err_Ok;
657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_TRACE4(( " %d %d %d\n",
659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  dict->cid_registry,
660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  dict->cid_ordering,
661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  dict->cid_supplement ));
662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_NUM( code, name, id )             \
669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          CFF_FIELD( code, name, id, cff_kind_num )
670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_FIXED( code, name, id )             \
671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          CFF_FIELD( code, name, id, cff_kind_fixed )
672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_FIXED_1000( code, name, id )                 \
673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          CFF_FIELD( code, name, id, cff_kind_fixed_thousand )
674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_STRING( code, name, id )             \
675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          CFF_FIELD( code, name, id, cff_kind_string )
676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_BOOL( code, name, id )             \
677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          CFF_FIELD( code, name, id, cff_kind_bool )
678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFFCODE_TOPDICT  0x1000
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFFCODE_PRIVATE  0x2000
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_CONFIG_OPTION_PIC
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  CFF_FIELD
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  CFF_FIELD_DELTA
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_DEBUG_LEVEL_TRACE
691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_CALLBACK( code, name, id ) \
694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {                                  \
695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cff_kind_callback,               \
696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            code | CFFCODE,                  \
697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            0, 0,                            \
698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cff_parse_ ## name,              \
699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            0, 0                             \
700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          },
701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD( code, name, id, kind ) \
703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {                               \
704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            kind,                         \
705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            code | CFFCODE,               \
706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_FIELD_OFFSET( name ),      \
707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_FIELD_SIZE( name ),        \
708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            0, 0, 0                       \
709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          },
710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_DELTA( code, name, max, id ) \
712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {                                    \
713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cff_kind_delta,                    \
714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            code | CFFCODE,                    \
715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_FIELD_OFFSET( name ),           \
716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_FIELD_SIZE_DELTA( name ),       \
717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            0,                                 \
718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            max,                               \
719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_FIELD_OFFSET( num_ ## name )    \
720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          },
721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static const CFF_Field_Handler  cff_field_handlers[] =
723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cfftoken.h"
726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { 0, 0, 0, 0, 0, 0, 0 }
728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  };
729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* FT_DEBUG_LEVEL_TRACE */
732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_CALLBACK( code, name, id ) \
736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {                                  \
737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cff_kind_callback,               \
738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            code | CFFCODE,                  \
739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            0, 0,                            \
740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cff_parse_ ## name,              \
741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            0, 0,                            \
742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            id                               \
743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          },
744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD( code, name, id, kind ) \
746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {                               \
747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            kind,                         \
748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            code | CFFCODE,               \
749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_FIELD_OFFSET( name ),      \
750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_FIELD_SIZE( name ),        \
751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            0, 0, 0,                      \
752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            id                            \
753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          },
754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_DELTA( code, name, max, id ) \
756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {                                    \
757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cff_kind_delta,                    \
758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            code | CFFCODE,                    \
759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_FIELD_OFFSET( name ),           \
760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_FIELD_SIZE_DELTA( name ),       \
761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            0,                                 \
762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            max,                               \
763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_FIELD_OFFSET( num_ ## name ),   \
764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            id                                 \
765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          },
766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static const CFF_Field_Handler  cff_field_handlers[] =
768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cfftoken.h"
771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { 0, 0, 0, 0, 0, 0, 0, 0 }
773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  };
774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_DEBUG_LEVEL_TRACE */
777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* FT_CONFIG_OPTION_PIC */
780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  void
783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Destroy_Class_cff_field_handlers( FT_Library          library,
784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                       CFF_Field_Handler*  clazz )
785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Memory  memory = library->memory;
787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( clazz )
790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_FREE( clazz );
791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Error
795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Create_Class_cff_field_handlers( FT_Library           library,
796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      CFF_Field_Handler**  output_class )
797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFF_Field_Handler*  clazz  = NULL;
799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error            error;
800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Memory           memory = library->memory;
801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int  i = 0;
803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef CFF_FIELD
806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD( code, name, id, kind ) i++;
807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef CFF_FIELD_DELTA
808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_DELTA( code, name, max, id ) i++;
809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef CFF_FIELD_CALLBACK
810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_CALLBACK( code, name, id ) i++;
811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cfftoken.h"
813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    i++; /* { 0, 0, 0, 0, 0, 0, 0 } */
815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( FT_ALLOC( clazz, sizeof ( CFF_Field_Handler ) * i ) )
817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return error;
818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    i = 0;
820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_DEBUG_LEVEL_TRACE
823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef CFF_FIELD_CALLBACK
826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_CALLBACK( code_, name_, id_ )        \
827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].kind         = cff_kind_callback;   \
828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].code         = code_ | CFFCODE;     \
829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].offset       = 0;                   \
830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].size         = 0;                   \
831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].reader       = cff_parse_ ## name_; \
832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].array_max    = 0;                   \
833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].count_offset = 0;                   \
834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          i++;
835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  CFF_FIELD
837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD( code_, name_, id_, kind_ )               \
838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].kind         = kind_;                    \
839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].code         = code_ | CFFCODE;          \
840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].offset       = FT_FIELD_OFFSET( name_ ); \
841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].size         = FT_FIELD_SIZE( name_ );   \
842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].reader       = 0;                        \
843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].array_max    = 0;                        \
844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].count_offset = 0;                        \
845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          i++;                                              \
846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  CFF_FIELD_DELTA
848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_DELTA( code_, name_, max_, id_ )                  \
849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].kind         = cff_kind_delta;                   \
850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].code         = code_ | CFFCODE;                  \
851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].offset       = FT_FIELD_OFFSET( name_ );         \
852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].size         = FT_FIELD_SIZE_DELTA( name_ );     \
853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].reader       = 0;                                \
854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].array_max    = max_;                             \
855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \
856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          i++;
857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cfftoken.h"
859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].kind         = 0;
861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].code         = 0;
862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].offset       = 0;
863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].size         = 0;
864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].reader       = 0;
865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].array_max    = 0;
866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].count_offset = 0;
867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* FT_DEBUG_LEVEL_TRACE */
870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef CFF_FIELD_CALLBACK
873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_CALLBACK( code_, name_, id_ )        \
874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].kind         = cff_kind_callback;   \
875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].code         = code_ | CFFCODE;     \
876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].offset       = 0;                   \
877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].size         = 0;                   \
878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].reader       = cff_parse_ ## name_; \
879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].array_max    = 0;                   \
880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].count_offset = 0;                   \
881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].id           = id_;                 \
882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          i++;
883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  CFF_FIELD
885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD( code_, name_, id_, kind_ )               \
886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].kind         = kind_;                    \
887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].code         = code_ | CFFCODE;          \
888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].offset       = FT_FIELD_OFFSET( name_ ); \
889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].size         = FT_FIELD_SIZE( name_ );   \
890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].reader       = 0;                        \
891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].array_max    = 0;                        \
892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].count_offset = 0;                        \
893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].id           = id_;                      \
894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          i++;                                              \
895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  CFF_FIELD_DELTA
897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CFF_FIELD_DELTA( code_, name_, max_, id_ )                  \
898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].kind         = cff_kind_delta;                   \
899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].code         = code_ | CFFCODE;                  \
900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].offset       = FT_FIELD_OFFSET( name_ );         \
901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].size         = FT_FIELD_SIZE_DELTA( name_ );     \
902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].reader       = 0;                                \
903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].array_max    = max_;                             \
904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].count_offset = FT_FIELD_OFFSET( num_ ## name_ ); \
905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          clazz[i].id           = id_;                              \
906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          i++;
907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "cfftoken.h"
909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].kind         = 0;
911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].code         = 0;
912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].offset       = 0;
913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].size         = 0;
914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].reader       = 0;
915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].array_max    = 0;
916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].count_offset = 0;
917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clazz[i].id           = 0;
918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_DEBUG_LEVEL_TRACE */
921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *output_class = clazz;
924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_Err_Ok;
926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_CONFIG_OPTION_PIC */
930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_LOCAL_DEF( FT_Error )
933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  cff_parser_run( CFF_Parser  parser,
934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Byte*    start,
935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Byte*    limit )
936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Byte*    p       = start;
938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Error    error   = FT_Err_Ok;
939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Library  library = parser->library;
940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UNUSED( library );
941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->top    = parser->stack;
944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->start  = start;
945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->limit  = limit;
946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    parser->cursor = start;
947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ( p < limit )
949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_UInt  v = *p;
951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( v >= 27 && v != 31 )
954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* it's a number; we will push its position on the stack */
956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          goto Stack_Overflow;
958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *parser->top ++ = p;
960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* now, skip it */
962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( v == 30 )
963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          /* skip real number */
965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          p++;
966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          for (;;)
967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {
968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* An unterminated floating point number at the */
969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* end of a dictionary is invalid but harmless. */
970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if ( p >= limit )
971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              goto Exit;
972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            v = p[0] >> 4;
973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if ( v == 15 )
974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              break;
975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            v = p[0] & 0xF;
976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if ( v == 15 )
977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              break;
978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            p++;
979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          }
980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else if ( v == 28 )
982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          p += 2;
983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else if ( v == 29 )
984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          p += 4;
985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else if ( v > 246 )
986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          p += 1;
987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* This is not a number, hence it's an operator.  Compute its code */
991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* and look for it in our current list.                            */
992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_UInt                   code;
994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_UInt                   num_args = (FT_UInt)
995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             ( parser->top - parser->stack );
996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        const CFF_Field_Handler*  field;
997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *parser->top = p;
1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        code = v;
1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( v == 12 )
1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          /* two byte operator */
1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          p++;
1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( p >= limit )
1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Syntax_Error;
1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          code = 0x100 | p[0];
1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        code = code | parser->object_code;
1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for ( field = CFF_FIELD_HANDLERS_GET; field->kind; field++ )
1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if ( field->code == (FT_Int)code )
1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          {
1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* we found our field's handler; read it */
1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_Long   val;
1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_Byte*  q = (FT_Byte*)parser->object + field->offset;
1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE
1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_TRACE4(( "  %s", field->id ));
1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* check that we have enough arguments -- except for */
1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            /* delta encoded arrays, which can be empty          */
1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if ( field->kind != cff_kind_delta && num_args < 1 )
1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              goto Stack_Underflow;
1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            switch ( field->kind )
1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            {
1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cff_kind_bool:
1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cff_kind_string:
1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cff_kind_num:
1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              val = cff_parse_num( parser->stack );
1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              goto Store_Number;
1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cff_kind_fixed:
1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              val = cff_parse_fixed( parser->stack );
1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              goto Store_Number;
1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cff_kind_fixed_thousand:
1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              val = cff_parse_fixed_scaled( parser->stack, 3 );
1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Store_Number:
1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              switch ( field->size )
1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              {
1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              case (8 / FT_CHAR_BIT):
1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *(FT_Byte*)q = (FT_Byte)val;
1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              case (16 / FT_CHAR_BIT):
1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *(FT_Short*)q = (FT_Short)val;
1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              case (32 / FT_CHAR_BIT):
1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *(FT_Int32*)q = (FT_Int)val;
1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              default:  /* for 64-bit systems */
1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *(FT_Long*)q = val;
1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              }
1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE
1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              switch ( field->kind )
1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              {
1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              case cff_kind_bool:
1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_TRACE4(( " %s\n", val ? "true" : "false" ));
1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              case cff_kind_string:
1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_TRACE4(( " %ld (SID)\n", val ));
1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              case cff_kind_num:
1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_TRACE4(( " %ld\n", val ));
1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              case cff_kind_fixed:
1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_TRACE4(( " %f\n", (double)val / 65536 ));
1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              case cff_kind_fixed_thousand:
1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_TRACE4(( " %f\n", (double)val / 65536 / 1000 ));
1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              default:
1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                ; /* never reached */
1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              }
1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              break;
1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cff_kind_delta:
1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              {
1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_Byte*   qcount = (FT_Byte*)parser->object +
1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      field->count_offset;
1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_Byte**  data = parser->stack;
1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if ( num_args > field->array_max )
1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  num_args = field->array_max;
1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_TRACE4(( " [" ));
1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                /* store count */
1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *qcount = (FT_Byte)num_args;
1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                val = 0;
1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                while ( num_args > 0 )
1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                {
1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  val += cff_parse_num( data++ );
1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  switch ( field->size )
1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  {
1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  case (8 / FT_CHAR_BIT):
1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *(FT_Byte*)q = (FT_Byte)val;
1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    break;
1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  case (16 / FT_CHAR_BIT):
1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *(FT_Short*)q = (FT_Short)val;
1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    break;
1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  case (32 / FT_CHAR_BIT):
1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *(FT_Int32*)q = (FT_Int)val;
1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    break;
1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  default:  /* for 64-bit systems */
1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *(FT_Long*)q = val;
1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  }
1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_TRACE4(( " %ld", val ));
1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  q += field->size;
1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  num_args--;
1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_TRACE4(( "]\n" ));
1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              }
1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              break;
1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            default:  /* callback */
1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              error = field->reader( parser );
1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              if ( error )
1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                goto Exit;
1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Found;
1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          }
1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* this is an unknown operator, or it is unsupported; */
1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* we will ignore it for now.                         */
1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      Found:
1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        /* clear stack */
1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        parser->top = parser->stack;
1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      p++;
1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Exit:
1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return error;
1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Stack_Overflow:
1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = FT_THROW( Invalid_Argument );
1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Stack_Underflow:
1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = FT_THROW( Invalid_Argument );
1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  Syntax_Error:
1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    error = FT_THROW( Invalid_Argument );
1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    goto Exit;
1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */
1178