1 /***************************************************************************/
2 /*                                                                         */
3 /*  psconv.c                                                               */
4 /*                                                                         */
5 /*    Some convenience conversions (body).                                 */
6 /*                                                                         */
7 /*  Copyright 2006, 2008, 2009, 2012-2013 by                               */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
10 /*  This file is part of the FreeType project, and may only be used,       */
11 /*  modified, and distributed under the terms of the FreeType project      */
12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13 /*  this file you indicate that you have read the license and              */
14 /*  understand and accept it fully.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17 
18 
19 #include <ft2build.h>
20 #include FT_INTERNAL_POSTSCRIPT_AUX_H
21 #include FT_INTERNAL_DEBUG_H
22 
23 #include "psconv.h"
24 #include "psauxerr.h"
25 
26 
27   /*************************************************************************/
28   /*                                                                       */
29   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
30   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
31   /* messages during execution.                                            */
32   /*                                                                       */
33 #undef  FT_COMPONENT
34 #define FT_COMPONENT  trace_psconv
35 
36 
37   /* The following array is used by various functions to quickly convert */
38   /* digits (both decimal and non-decimal) into numbers.                 */
39 
40 #if 'A' == 65
41   /* ASCII */
42 
43   static const FT_Char  ft_char_table[128] =
44   {
45     /* 0x00 */
46     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
47     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
48     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
49      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
50     -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
51     25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
52     -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
53     25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
54   };
55 
56   /* no character >= 0x80 can represent a valid number */
57 #define OP  >=
58 
59 #endif /* 'A' == 65 */
60 
61 #if 'A' == 193
62   /* EBCDIC */
63 
64   static const FT_Char  ft_char_table[128] =
65   {
66     /* 0x80 */
67     -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
68     -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
69     -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
70     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
71     -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
72     -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
73     -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
74      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
75   };
76 
77   /* no character < 0x80 can represent a valid number */
78 #define OP  <
79 
80 #endif /* 'A' == 193 */
81 
82 
83   FT_LOCAL_DEF( FT_Long )
PS_Conv_Strtol(FT_Byte ** cursor,FT_Byte * limit,FT_Long base)84   PS_Conv_Strtol( FT_Byte**  cursor,
85                   FT_Byte*   limit,
86                   FT_Long    base )
87   {
88     FT_Byte*  p = *cursor;
89 
90     FT_Long   num           = 0;
91     FT_Bool   sign          = 0;
92     FT_Bool   have_overflow = 0;
93 
94     FT_Long   num_limit;
95     FT_Char   c_limit;
96 
97 
98     if ( p >= limit )
99       goto Bad;
100 
101     if ( base < 2 || base > 36 )
102     {
103       FT_TRACE4(( "!!!INVALID BASE:!!!" ));
104       return 0;
105     }
106 
107     if ( *p == '-' || *p == '+' )
108     {
109       sign = FT_BOOL( *p == '-' );
110 
111       p++;
112       if ( p == limit )
113         goto Bad;
114     }
115 
116     num_limit = 0x7FFFFFFFL / base;
117     c_limit   = (FT_Char)( 0x7FFFFFFFL % base );
118 
119     for ( ; p < limit; p++ )
120     {
121       FT_Char  c;
122 
123 
124       if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
125         break;
126 
127       c = ft_char_table[*p & 0x7f];
128 
129       if ( c < 0 || c >= base )
130         break;
131 
132       if ( num > num_limit || ( num == num_limit && c > c_limit ) )
133         have_overflow = 1;
134       else
135         num = num * base + c;
136     }
137 
138     *cursor = p;
139 
140     if ( have_overflow )
141     {
142       num = 0x7FFFFFFFL;
143       FT_TRACE4(( "!!!OVERFLOW:!!!" ));
144     }
145 
146     if ( sign )
147       num = -num;
148 
149     return num;
150 
151   Bad:
152     FT_TRACE4(( "!!!END OF DATA:!!!" ));
153     return 0;
154   }
155 
156 
157   FT_LOCAL_DEF( FT_Long )
PS_Conv_ToInt(FT_Byte ** cursor,FT_Byte * limit)158   PS_Conv_ToInt( FT_Byte**  cursor,
159                  FT_Byte*   limit )
160 
161   {
162     FT_Byte*  p = *cursor;
163     FT_Byte*  curp;
164 
165     FT_Long   num;
166 
167 
168     curp = p;
169     num  = PS_Conv_Strtol( &p, limit, 10 );
170 
171     if ( p == curp )
172       return 0;
173 
174     if ( p < limit && *p == '#' )
175     {
176       p++;
177 
178       curp = p;
179       num  = PS_Conv_Strtol( &p, limit, num );
180 
181       if ( p == curp )
182         return 0;
183     }
184 
185     *cursor = p;
186 
187     return num;
188   }
189 
190 
191   FT_LOCAL_DEF( FT_Fixed )
PS_Conv_ToFixed(FT_Byte ** cursor,FT_Byte * limit,FT_Long power_ten)192   PS_Conv_ToFixed( FT_Byte**  cursor,
193                    FT_Byte*   limit,
194                    FT_Long    power_ten )
195   {
196     FT_Byte*  p = *cursor;
197     FT_Byte*  curp;
198 
199     FT_Fixed  integral = 0;
200     FT_Long   decimal  = 0;
201     FT_Long   divider  = 1;
202 
203     FT_Bool   sign           = 0;
204     FT_Bool   have_overflow  = 0;
205     FT_Bool   have_underflow = 0;
206 
207 
208     if ( p >= limit )
209       goto Bad;
210 
211     if ( *p == '-' || *p == '+' )
212     {
213       sign = FT_BOOL( *p == '-' );
214 
215       p++;
216       if ( p == limit )
217         goto Bad;
218     }
219 
220     /* read the integer part */
221     if ( *p != '.' )
222     {
223       curp     = p;
224       integral = PS_Conv_ToInt( &p, limit );
225 
226       if ( p == curp )
227         return 0;
228 
229       if ( integral > 0x7FFF )
230         have_overflow = 1;
231       else
232         integral = (FT_Fixed)( (FT_UInt32)integral << 16 );
233     }
234 
235     /* read the decimal part */
236     if ( p < limit && *p == '.' )
237     {
238       p++;
239 
240       for ( ; p < limit; p++ )
241       {
242         FT_Char  c;
243 
244 
245         if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
246           break;
247 
248         c = ft_char_table[*p & 0x7f];
249 
250         if ( c < 0 || c >= 10 )
251           break;
252 
253         if ( decimal < 0xCCCCCCCL )
254         {
255           decimal = decimal * 10 + c;
256 
257           if ( !integral && power_ten > 0 )
258             power_ten--;
259           else
260             divider *= 10;
261         }
262       }
263     }
264 
265     /* read exponent, if any */
266     if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
267     {
268       FT_Long  exponent;
269 
270 
271       p++;
272 
273       curp     = p;
274       exponent = PS_Conv_ToInt( &p, limit );
275 
276       if ( curp == p )
277         return 0;
278 
279       /* arbitrarily limit exponent */
280       if ( exponent > 1000 )
281         have_overflow = 1;
282       else if ( exponent < -1000 )
283         have_underflow = 1;
284       else
285         power_ten += exponent;
286     }
287 
288     *cursor = p;
289 
290     if ( !integral && !decimal )
291       return 0;
292 
293     if ( have_overflow )
294       goto Overflow;
295     if ( have_underflow )
296       goto Underflow;
297 
298     while ( power_ten > 0 )
299     {
300       if ( integral >= 0xCCCCCCCL )
301         goto Overflow;
302       integral *= 10;
303 
304       if ( decimal >= 0xCCCCCCCL )
305       {
306         if ( divider == 1 )
307           goto Overflow;
308         divider /= 10;
309       }
310       else
311         decimal *= 10;
312 
313       power_ten--;
314     }
315 
316     while ( power_ten < 0 )
317     {
318       integral /= 10;
319       if ( divider < 0xCCCCCCCL )
320         divider *= 10;
321       else
322         decimal /= 10;
323 
324       if ( !integral && !decimal )
325         goto Underflow;
326 
327       power_ten++;
328     }
329 
330     if ( decimal )
331     {
332       decimal = FT_DivFix( decimal, divider );
333       /* it's not necessary to check this addition for overflow */
334       /* due to the structure of the real number representation */
335       integral += decimal;
336     }
337 
338   Exit:
339     if ( sign )
340       integral = -integral;
341 
342     return integral;
343 
344   Bad:
345     FT_TRACE4(( "!!!END OF DATA:!!!" ));
346     return 0;
347 
348   Overflow:
349     integral = 0x7FFFFFFFL;
350     FT_TRACE4(( "!!!OVERFLOW:!!!" ));
351     goto Exit;
352 
353   Underflow:
354     FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
355     return 0;
356   }
357 
358 
359 #if 0
360   FT_LOCAL_DEF( FT_UInt )
361   PS_Conv_StringDecode( FT_Byte**  cursor,
362                         FT_Byte*   limit,
363                         FT_Byte*   buffer,
364                         FT_Offset  n )
365   {
366     FT_Byte*  p;
367     FT_UInt   r = 0;
368 
369 
370     for ( p = *cursor; r < n && p < limit; p++ )
371     {
372       FT_Byte  b;
373 
374 
375       if ( *p != '\\' )
376       {
377         buffer[r++] = *p;
378 
379         continue;
380       }
381 
382       p++;
383 
384       switch ( *p )
385       {
386       case 'n':
387         b = '\n';
388         break;
389       case 'r':
390         b = '\r';
391         break;
392       case 't':
393         b = '\t';
394         break;
395       case 'b':
396         b = '\b';
397         break;
398       case 'f':
399         b = '\f';
400         break;
401       case '\r':
402         p++;
403         if ( *p != '\n' )
404         {
405           b = *p;
406 
407           break;
408         }
409         /* no break */
410       case '\n':
411         continue;
412         break;
413       default:
414         if ( IS_PS_DIGIT( *p ) )
415         {
416           b = *p - '0';
417 
418           p++;
419 
420           if ( IS_PS_DIGIT( *p ) )
421           {
422             b = b * 8 + *p - '0';
423 
424             p++;
425 
426             if ( IS_PS_DIGIT( *p ) )
427               b = b * 8 + *p - '0';
428             else
429             {
430               buffer[r++] = b;
431               b = *p;
432             }
433           }
434           else
435           {
436             buffer[r++] = b;
437             b = *p;
438           }
439         }
440         else
441           b = *p;
442         break;
443       }
444 
445       buffer[r++] = b;
446     }
447 
448     *cursor = p;
449 
450     return r;
451   }
452 #endif /* 0 */
453 
454 
455   FT_LOCAL_DEF( FT_UInt )
PS_Conv_ASCIIHexDecode(FT_Byte ** cursor,FT_Byte * limit,FT_Byte * buffer,FT_Offset n)456   PS_Conv_ASCIIHexDecode( FT_Byte**  cursor,
457                           FT_Byte*   limit,
458                           FT_Byte*   buffer,
459                           FT_Offset  n )
460   {
461     FT_Byte*  p;
462     FT_UInt   r   = 0;
463     FT_UInt   w   = 0;
464     FT_UInt   pad = 0x01;
465 
466 
467     n *= 2;
468 
469 #if 1
470 
471     p = *cursor;
472 
473     if ( p >= limit )
474       return 0;
475 
476     if ( n > (FT_UInt)( limit - p ) )
477       n = (FT_UInt)( limit - p );
478 
479     /* we try to process two nibbles at a time to be as fast as possible */
480     for ( ; r < n; r++ )
481     {
482       FT_UInt  c = p[r];
483 
484 
485       if ( IS_PS_SPACE( c ) )
486         continue;
487 
488       if ( c OP 0x80 )
489         break;
490 
491       c = ft_char_table[c & 0x7F];
492       if ( (unsigned)c >= 16 )
493         break;
494 
495       pad = ( pad << 4 ) | c;
496       if ( pad & 0x100 )
497       {
498         buffer[w++] = (FT_Byte)pad;
499         pad         = 0x01;
500       }
501     }
502 
503     if ( pad != 0x01 )
504       buffer[w++] = (FT_Byte)( pad << 4 );
505 
506     *cursor = p + r;
507 
508     return w;
509 
510 #else /* 0 */
511 
512     for ( r = 0; r < n; r++ )
513     {
514       FT_Char  c;
515 
516 
517       if ( IS_PS_SPACE( *p ) )
518         continue;
519 
520       if ( *p OP 0x80 )
521         break;
522 
523       c = ft_char_table[*p & 0x7f];
524 
525       if ( (unsigned)c >= 16 )
526         break;
527 
528       if ( r & 1 )
529       {
530         *buffer = (FT_Byte)(*buffer + c);
531         buffer++;
532       }
533       else
534         *buffer = (FT_Byte)(c << 4);
535 
536       r++;
537     }
538 
539     *cursor = p;
540 
541     return ( r + 1 ) / 2;
542 
543 #endif /* 0 */
544 
545   }
546 
547 
548   FT_LOCAL_DEF( FT_UInt )
PS_Conv_EexecDecode(FT_Byte ** cursor,FT_Byte * limit,FT_Byte * buffer,FT_Offset n,FT_UShort * seed)549   PS_Conv_EexecDecode( FT_Byte**   cursor,
550                        FT_Byte*    limit,
551                        FT_Byte*    buffer,
552                        FT_Offset   n,
553                        FT_UShort*  seed )
554   {
555     FT_Byte*  p;
556     FT_UInt   r;
557     FT_UInt   s = *seed;
558 
559 
560 #if 1
561 
562     p = *cursor;
563 
564     if ( p >= limit )
565       return 0;
566 
567     if ( n > (FT_UInt)(limit - p) )
568       n = (FT_UInt)(limit - p);
569 
570     for ( r = 0; r < n; r++ )
571     {
572       FT_UInt  val = p[r];
573       FT_UInt  b   = ( val ^ ( s >> 8 ) );
574 
575 
576       s         = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
577       buffer[r] = (FT_Byte) b;
578     }
579 
580     *cursor = p + n;
581     *seed   = (FT_UShort)s;
582 
583 #else /* 0 */
584 
585     for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
586     {
587       FT_Byte  b = (FT_Byte)( *p ^ ( s >> 8 ) );
588 
589 
590       s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
591       *buffer++ = b;
592     }
593     *cursor = p;
594     *seed   = s;
595 
596 #endif /* 0 */
597 
598     return r;
599   }
600 
601 
602 /* END */
603