text:
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_BBOX_H

#include <time.h>    /* for clock() */

/* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include <sys/param.h> */
/* to get the HZ macro which is the equivalent.                         */
#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4)
#include <sys/param.h>
#define CLOCKS_PER_SEC HZ
#endif

  static long
  get_time( void )
  {
    return clock() * 10000L / CLOCKS_PER_SEC;
  }

  /* test bbox computations */

#define  XSCALE    65536
#define  XX(x)     ((FT_Pos)(x*XSCALE))
#define  XVEC(x,y)  { XX(x), XX(y) }
#define  XVAL(x)   ((x)/(1.0*XSCALE))

  /* dummy outline #1 */
  static FT_Vector  dummy_vec_1[4] =
  {
#if 1
    XVEC( 408.9111, 535.3164 ),
    XVEC( 455.8887, 634.396  ),
    XVEC( -37.8765, 786.2207 ),
    XVEC( 164.6074, 535.3164 )
#else
    { (FT_Int32)0x0198E93DL , (FT_Int32)0x021750FFL },  /* 408.9111, 535.3164 */
    { (FT_Int32)0x01C7E312L , (FT_Int32)0x027A6560L },  /* 455.8887, 634.3960 */
    { (FT_Int32)0xFFDA1F9EL , (FT_Int32)0x0312387FL },  /* -37.8765, 786.2207 */
    { (FT_Int32)0x00A49B7EL , (FT_Int32)0x021750FFL }   /* 164.6074, 535.3164 */
#endif
   };

  static char  dummy_tag_1[4] =
  {
    FT_CURVE_TAG_ON,
    FT_CURVE_TAG_CUBIC,
    FT_CURVE_TAG_CUBIC,
    FT_CURVE_TAG_ON
  };

  static short  dummy_contour_1[1] =
  {
    3
  };

  static FT_Outline  dummy_outline_1 =
  {
    1,
    4,
    dummy_vec_1,
    dummy_tag_1,
    dummy_contour_1,
    0
  };

  /* dummy outline #2 */
  static FT_Vector  dummy_vec_2[4] =
  {
    XVEC( 100.0, 100.0 ),
    XVEC( 100.0, 200.0 ),
    XVEC( 200.0, 200.0 ),
    XVEC( 200.0, 133.0 )
  };

  static FT_Outline  dummy_outline_2 =
  {
    1,
    4,
    dummy_vec_2,
    dummy_tag_1,
    dummy_contour_1,
    0
  };

  /* dummy outline #3 with bbox of [0 100 128 128] precisely */
  static FT_Vector  dummy_vec_3[4] =
  {
    XVEC( 100.0, 127.0 ),
    XVEC( 200.0, 127.0 ),
    XVEC(   0.0, 136.0 ),
    XVEC(   0.0, 100.0 )
  };

  static FT_Outline  dummy_outline_3 =
  {
    1,
    4,
    dummy_vec_3,
    dummy_tag_1,
    dummy_contour_1,
    0
  };

  static void
  dump_outline( FT_Outline*  outline )
  {
    FT_BBox  bbox;

    /* compute and display cbox */
    FT_Outline_Get_CBox( outline, &bbox );
    printf( "cbox = [%.2f %.2f %.2f %.2f]\n",
             XVAL( bbox.xMin ),
             XVAL( bbox.yMin ),
             XVAL( bbox.xMax ),
             XVAL( bbox.yMax ) );

    /* compute and display bbox */
    FT_Outline_Get_BBox( outline, &bbox );
    printf( "bbox = [%.2f %.2f %.2f %.2f]\n",
             XVAL( bbox.xMin ),
             XVAL( bbox.yMin ),
             XVAL( bbox.xMax ),
             XVAL( bbox.yMax ) );
  }

  static void
  profile_outline( FT_Outline*   outline,
                   long          repeat )
  {
    FT_BBox  bbox;
    long     count;
    long     time0;

    time0 = get_time();
    for ( count = repeat; count > 0; count-- )
      FT_Outline_Get_CBox( outline, &bbox );

    time0 = get_time() - time0;
    printf( "time = %6.3f cbox = [%8.4f %8.4f %8.4f %8.4f]\n",
             ((double)time0/10000.0),
             XVAL( bbox.xMin ),
             XVAL( bbox.yMin ),
             XVAL( bbox.xMax ),
             XVAL( bbox.yMax ) );
    printf( "cbox_hex = [%08X %08X %08X %08X]\n",
             bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax );

    time0 = get_time();
    for ( count = repeat; count > 0; count-- )
      FT_Outline_Get_BBox( outline, &bbox );

    time0 = get_time() - time0;
    printf( "time = %6.3f bbox = [%8.4f %8.4f %8.4f %8.4f]\n",
             ((double)time0/10000.0),
             XVAL( bbox.xMin ),
             XVAL( bbox.yMin ),
             XVAL( bbox.xMax ),
             XVAL( bbox.yMax ) );
    printf( "bbox_hex = [%08X %08X %08X %08X]\n",
             bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax );
  }

#define REPEAT  1000000L

  int  main( int  argc, char**  argv )
  {
    printf( "outline #1\n" );
    profile_outline( &dummy_outline_1, REPEAT );

    printf( "outline #2\n" );
    profile_outline( &dummy_outline_2, REPEAT );

    printf( "outline #3\n" );
    profile_outline( &dummy_outline_3, REPEAT );

    return 0;
  }


text:
eval '(exit $?0)' && eval 'exec perl -wS -i "$0" ${1+"$@"}'
  & eval 'exec perl -wS -i "$0" $argv:q'
    if 0;

# Copyright (C) 2015-2020 by
# Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used, modified,
# and distributed under the terms of the FreeType project license,
# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
# indicate that you have read the license and understand and accept it
# fully.

# [Note: This script is expected to be called by the shell, which in turn
#  calls perl automatically.  The nifty start-up code above is based on
#  gnulib's `update-copyright' script; it is a more portable replacement for
#  the shebang, using the first `perl' program in the shell's path instead.]

# Usage:
#
#   update-copyright-year file1 [file2 ...]

# This script handles copyright entries like
#
#   Copyright  2000   by
#   foobar
#
# or
#
#   /* Copyright 2000,  2001, 2004-2007 by    */
#   /* foobar                                 */
#
# and replaces them uniformly with
#
#   Copyright 2000-2015
#   foobar
#
# and
#
#   /* Copyright 2000-2015 by                 */
#   /* foobar                                 */
#
# (assuming that the current year is 2015).  As can be seen, the line length
# is retained if there is non-whitespace after the word `by' on the same
# line.

use strict;

my (undef, undef, undef,
    undef, undef, $year,
    undef, undef, undef) = localtime(time);
$year += 1900;

my $replaced = 0;

# Loop over all input files; option `-i' (issued at the very beginning of
# this script) makes perl edit them in-place.
while (<>)
{
  # Only handle the first copyright notice in a file.
  if (!$replaced)
  {
    # First try: Search multiple copyright years.
    s {
        (?<begin>.*)
        Copyright
        (?<space1>(\ +
                   | \ +\(C\)\ +))
        (?<first>[12][0-9][0-9][0-9])
        (?<middle>.+)
        (?<last>[12][0-9][0-9][0-9])
        (?<space2>\ +)
        by
        (?<space3>\ *)
        (?<end>.*)
      }
      {
        # Fill line to the same length (if appropriate); we skip the middle
        # part but insert `(C)', three spaces, and `-'.
        my $space = length($+{space1}) - 1
                    + length($+{middle}) - 1
                    + length($+{space2}) - 1
                    + length($+{space3})
                    - (length("(C)") + 1);

        print "$+{begin}";
        print "Copyright\ (C)\ $+{first}-$year\ by";
        print ' ' x $space if length($+{end});
        print "$+{end}\n";
        $replaced = 1;
      }ex
    ||
    # Second try: Search a single copyright year.
    s {
        (?<begin>.*)
        Copyright
        (?<space1>(\ +
                   | \ +\(C\)\ +))
        (?<first>[12][0-9][0-9][0-9])
        (?<space2>\ +)
        by
        (?<space3>\ *)
        (?<end>.*)
      }
      {
        # Fill line to the same length (if appropriate); we insert three
        # spaces, a `-', and the current year.
        my $space = length($+{space1}) - 1
                    + length($+{space2}) - 1
                    + length($+{space3})
                    - (length($year) + 1);

        print "$+{begin}";
        print "Copyright\ (C)\ $+{first}-$year\ by";
        # If $space is negative this inserts nothing.
        print ' ' x $space if length($+{end});
        print "$+{end}\n";
        $replaced = 1;
      }ex
    ||
    # Otherwise print line unaltered.
    print;
  }
  else
  {
    print;
  }
}
continue
{
  # Reset $replaced before processing the next file.
  $replaced = 0 if eof;
}

# EOF

repo_language: C

mime_type: text/x-c


text:
# compute arctangent table for CORDIC computations in fttrigon.c
import sys, math

#units  = 64*65536.0   # don't change !!
units  = 180 * 2**16
scale  = units/math.pi
shrink = 1.0
comma  = ""

print ""
print "table of arctan( 1/2^n ) for PI = " + repr(units/65536.0) + " units"

for n in range(1,32):

    x = 0.5**n                      # tangent value

    angle  = math.atan(x)           # arctangent
    angle2 = round(angle*scale)     # arctangent in FT_Angle units

    if angle2 <= 0:
        break

    sys.stdout.write( comma + repr( int(angle2) ) )
    comma = ", "

    shrink /= math.sqrt( 1 + x*x )

print
print "shrink factor    = " + repr( shrink )
print "shrink factor 2  = " + repr( int( shrink * (2**32) ) )
print "expansion factor = " + repr( 1/shrink )
print ""


text:
/*
 * gcc -DFT2_BUILD_LIBRARY -I../../include -o test_afm test_afm.c \
 *     -L../../objs/.libs -lfreetype -lz -static
 */
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_POSTSCRIPT_AUX_H

  void dump_fontinfo( AFM_FontInfo  fi )
  {
    FT_UInt  i;

    printf( "This AFM is for %sCID font.\n\n",
            ( fi->IsCIDFont ) ? "" : "non-" );

    printf( "FontBBox: %.2f %.2f %.2f %.2f\n", fi->FontBBox.xMin / 65536.,
                                               fi->FontBBox.yMin / 65536.,
                                               fi->FontBBox.xMax / 65536.,
                                               fi->FontBBox.yMax / 65536. );
    printf( "Ascender: %.2f\n", fi->Ascender / 65536. );
    printf( "Descender: %.2f\n\n", fi->Descender / 65536. );

    if ( fi->NumTrackKern )
      printf( "There are %d sets of track kernings:\n",
              fi->NumTrackKern );
    else
      printf( "There is no track kerning.\n" );

    for ( i = 0; i < fi->NumTrackKern; i++ )
    {
      AFM_TrackKern  tk = fi->TrackKerns + i;

      printf( "\t%2d: %5.2f %5.2f %5.2f %5.2f\n", tk->degree,
                                                  tk->min_ptsize / 65536.,
                                                  tk->min_kern / 65536.,
                                                  tk->max_ptsize / 65536.,
                                                  tk->max_kern / 65536. );
    }

    printf( "\n" );

    if ( fi->NumKernPair )
      printf( "There are %d kerning pairs:\n",
              fi->NumKernPair );
    else
      printf( "There is no kerning pair.\n" );

    for ( i = 0; i < fi->NumKernPair; i++ )
    {
      AFM_KernPair  kp = fi->KernPairs + i;

      printf( "\t%3d + %3d => (%4d, %4d)\n", kp->index1,
                                             kp->index2,
                                             kp->x,
                                             kp->y );
    }

  }

  int
  dummy_get_index( const char*  name,
                   FT_Offset    len,
                   void*        user_data )
  {
    if ( len )
      return name[0];
    else
      return 0;
  }

  FT_Error
  parse_afm( FT_Library    library,
             FT_Stream     stream,
             AFM_FontInfo  fi )
  {
    PSAux_Service  psaux;
    AFM_ParserRec  parser;
    FT_Error       error = FT_Err_Ok;

    psaux = (PSAux_Service)FT_Get_Module_Interface( library, "psaux" );
    if ( !psaux || !psaux->afm_parser_funcs )
      return -1;

    error = FT_Stream_EnterFrame( stream, stream->size );
    if ( error )
      return error;

    error = psaux->afm_parser_funcs->init( &parser,
                                           library->memory,
                                           stream->cursor,
                                           stream->limit );
    if ( error )
      return error;

    parser.FontInfo = fi;
    parser.get_index = dummy_get_index;

    error = psaux->afm_parser_funcs->parse( &parser );

    psaux->afm_parser_funcs->done( &parser );

    return error;
  }

  int main( int    argc,
            char** argv )
  {
    FT_Library       library;
    FT_StreamRec     stream;
    FT_Error         error = FT_Err_Ok;
    AFM_FontInfoRec  fi;

    if ( argc < 2 )
      return FT_ERR( Invalid_Argument );

    error = FT_Init_FreeType( &library );
    if ( error )
      return error;

    FT_ZERO( &stream );
    error = FT_Stream_Open( &stream, argv[1] );
    if ( error )
      goto Exit;
    stream.memory = library->memory;

    FT_ZERO( &fi );
    error = parse_afm( library, &stream, &fi );

    if ( !error )
    {
      FT_Memory  memory = library->memory;

      dump_fontinfo( &fi );

      if ( fi.KernPairs )
        FT_FREE( fi.KernPairs );
      if ( fi.TrackKerns )
        FT_FREE( fi.TrackKerns );
    }
    else
      printf( "parse error\n" );

    FT_Stream_Close( &stream );

  Exit:
    FT_Done_FreeType( library );

    return error;
  }


text:
#! /usr/bin/perl -w
# -*- Perl -*-
#
# afblue.pl
#
# Process a blue zone character data file.
#
# Copyright (C) 2013-2020 by
# David Turner, Robert Wilhelm, and Werner Lemberg.
#
# This file is part of the FreeType project, and may only be used,
# modified, and distributed under the terms of the FreeType project
# license, LICENSE.TXT.  By continuing to use, modify, or distribute
# this file you indicate that you have read the license and
# understand and accept it fully.

use strict;
use warnings;
use English '-no_match_vars';
use open ':std', ':encoding(UTF-8)';

my $prog = $PROGRAM_NAME;
$prog =~ s| .* / ||x;      # Remove path.

die "usage: $prog datafile < infile > outfile\n" if $#ARGV != 0;

my $datafile = $ARGV[0];

my %diversions;        # The extracted and massaged data from `datafile'.
my @else_stack;        # Booleans to track else-clauses.
my @name_stack;        # Stack of integers used for names of aux. variables.

my $curr_enum;         # Name of the current enumeration.
my $curr_array;        # Name of the current array.
my $curr_max;          # Name of the current maximum value.

my $curr_enum_element; # Name of the current enumeration element.
my $curr_offset;       # The offset relative to current aux. variable.
my $curr_elem_size;    # The number of non-space characters in the current string or
                       # the number of elements in the current block.

my $have_sections = 0; # Boolean; set if start of a section has been seen.
my $have_strings;      # Boolean; set if current section contains strings.
my $have_blocks;       # Boolean; set if current section contains blocks.

my $have_enum_element; # Boolean; set if we have an enumeration element.
my $in_string;         # Boolean; set if a string has been parsed.

my $num_sections = 0;  # Number of sections seen so far.

my $last_aux;          # Name of last auxiliary variable.

# Regular expressions.

# [<ws>] <enum_name> <ws> <array_name> <ws> <max_name> [<ws>] ':' [<ws>] '\n'
my $section_re = qr/ ^ \s* (\S+) \s+ (\S+) \s+ (\S+) \s* : \s* $ /x;

# [<ws>] <enum_element_name> [<ws>] '\n'
my $enum_element_re = qr/ ^ \s* ( [A-Za-z0-9_]+ ) \s* $ /x;

# '#' <preprocessor directive> '\n'
my $preprocessor_re = qr/ ^ \# /x;

# [<ws>] '/' '/' <comment> '\n'
my $comment_re = qr| ^ \s* // |x;

# empty line
my $whitespace_only_re = qr/ ^ \s* $ /x;

# [<ws>] '"' <string> '"' [<ws>] '\n'  (<string> doesn't contain newlines)
my $string_re = qr/ ^ \s*
                       " ( (?> (?: (?> [^"\\]+ ) | \\. )* ) ) "
                       \s* $ /x;

# [<ws>] '{' <block> '}' [<ws>] '\n'  (<block> can contain newlines)
my $block_start_re = qr/ ^ \s* \{ /x;

# We need the capturing group for `split' to make it return the separator
# tokens (i.e., the opening and closing brace) also.
my $brace_re = qr/ ( [{}] ) /x;

sub Warn
{
  my $message = shift;
  warn "$datafile:$INPUT_LINE_NUMBER: warning: $message\n";
}

sub Die
{
  my $message = shift;
  die "$datafile:$INPUT_LINE_NUMBER: error: $message\n";
}

my $warned_before = 0;

sub warn_before
{
  Warn("data before first section gets ignored") unless $warned_before;
  $warned_before = 1;
}

sub strip_newline
{
  chomp;
  s/ \x0D $ //x;
}

sub end_curr_string
{
  # Append final null byte to string.
  if ($have_strings)
  {
    push @{$diversions{$curr_array}}, "    '\\0',\n" if $in_string;

    $curr_offset++;
    $in_string = 0;
  }
}

sub update_max_elem_size
{
  if ($curr_elem_size)
  {
    my $max = pop @{$diversions{$curr_max}};
    $max = $curr_elem_size if $curr_elem_size > $max;
    push @{$diversions{$curr_max}}, $max;
  }
}

sub convert_non_ascii_char
{
  # A UTF-8 character outside of the printable ASCII range, with possibly a
  # leading backslash character.
  my $s = shift;

  # Here we count characters, not bytes.
  $curr_elem_size += length $s;

  utf8::encode($s);
  $s = uc unpack 'H*', $s;

  $curr_offset += $s =~ s/\G(..)/'\\x$1', /sg;

  return $s;
}

sub convert_ascii_chars
{
  # A series of ASCII characters in the printable range.
  my $s = shift;

  # We reduce multiple space characters to a single one.
  $s =~ s/ +/ /g;

  # Count all non-space characters.  Note that `()' applies a list context
  # to the capture that is used to count the elements.
  $curr_elem_size += () = $s =~ /[^ ]/g;

  $curr_offset += $s =~ s/\G(.)/'$1', /g;

  return $s;
}

sub convert_literal
{
  my $s = shift;
  my $orig = $s;

  # ASCII printables and space
  my $safe_re = '\x20-\x7E';
  # ASCII printables and space, no backslash
  my $safe_no_backslash_re = '\x20-\x5B\x5D-\x7E';

  $s =~ s{
           (?: \\? ( [^$safe_re] )
               | ( (?: [$safe_no_backslash_re]
                       | \\ [$safe_re] )+ ) )
         }
         {
           defined($1) ? convert_non_ascii_char($1)
                       : convert_ascii_chars($2)
         }egx;

   # We assume that `$orig' doesn't contain `*/'
   return $s . " /* $orig */";
}

sub aux_name
{
  return "af_blue_" . $num_sections. "_" . join('_', @name_stack);
}

sub aux_name_next
{
  $name_stack[$#name_stack]++;
  my $name = aux_name();
  $name_stack[$#name_stack]--;

  return $name;
}

sub enum_val_string
{
  # Build string that holds code to save the current offset in an
  # enumeration element.
  my $aux = shift;

  my $add = ($last_aux eq "af_blue_" . $num_sections . "_0" )
              ? ""
              : "$last_aux + ";

  return "    $aux = $add$curr_offset,\n";
}

# Process data file.

open(DATA, $datafile) || die "$prog: can't open \`$datafile': $OS_ERROR\n";

while (<DATA>)
{
  strip_newline();

  next if /$comment_re/;
  next if /$whitespace_only_re/;

  if (/$section_re/)
  {
    Warn("previous section is empty") if ($have_sections
                                          && !$have_strings
                                          && !$have_blocks);

    end_curr_string();
    update_max_elem_size();

    # Save captured groups from `section_re'.
    $curr_enum = $1;
    $curr_array = $2;
    $curr_max = $3;

    $curr_enum_element = "";
    $curr_offset = 0;

    Warn("overwriting already defined enumeration \`$curr_enum'")
      if exists($diversions{$curr_enum});
    Warn("overwriting already defined array \`$curr_array'")
      if exists($diversions{$curr_array});
    Warn("overwriting already defined maximum value \`$curr_max'")
      if exists($diversions{$curr_max});

    $diversions{$curr_enum} = [];
    $diversions{$curr_array} = [];
    $diversions{$curr_max} = [];

    push @{$diversions{$curr_max}}, 0;

    @name_stack = ();
    push @name_stack, 0;

    $have_sections = 1;
    $have_strings = 0;
    $have_blocks = 0;

    $have_enum_element = 0;
    $in_string = 0;

    $num_sections++;
    $curr_elem_size = 0;

    $last_aux = aux_name();

    next;
  }

  if (/$preprocessor_re/)
  {
    if ($have_sections)
    {
      # Having preprocessor conditionals complicates the computation of
      # correct offset values.  We have to introduce auxiliary enumeration
      # elements with the name `af_blue_<s>_<n1>_<n2>_...' that store
      # offsets to be used in conditional clauses.  `<s>' is the number of
      # sections seen so far, `<n1>' is the number of `#if' and `#endif'
      # conditionals seen so far in the topmost level, `<n2>' the number of
      # `#if' and `#endif' conditionals seen so far one level deeper, etc.
      # As a consequence, uneven values are used within a clause, and even
      # values after a clause, since the C standard doesn't allow the
      # redefinition of an enumeration value.  For example, the name
      # `af_blue_5_1_6' is used to construct enumeration values in the fifth
      # section after the third (second-level) if-clause within the first
      # (top-level) if-clause.  After the first top-level clause has
      # finished, `af_blue_5_2' is used.  The current offset is then
      # relative to the value stored in the current auxiliary element.

      if (/ ^ \# \s* if /x)
      {
        push @else_stack, 0;

        $name_stack[$#name_stack]++;

        push @{$diversions{$curr_enum}}, enum_val_string(aux_name());
        $last_aux = aux_name();

        push @name_stack, 0;

        $curr_offset = 0;
      }
      elsif (/ ^ \# \s* elif /x)
      {
        Die("unbalanced #elif") unless @else_stack;

        pop @name_stack;

        push @{$diversions{$curr_enum}}, enum_val_string(aux_name_next());
        $last_aux = aux_name();

        push @name_stack, 0;

        $curr_offset = 0;
      }
      elsif (/ ^ \# \s* else /x)
      {
        my $prev_else = pop @else_stack;
        Die("unbalanced #else") unless defined($prev_else);
        Die("#else already seen") if $prev_else;
        push @else_stack, 1;

        pop @name_stack;

        push @{$diversions{$curr_enum}}, enum_val_string(aux_name_next());
        $last_aux = aux_name();

        push @name_stack, 0;

        $curr_offset = 0;
      }
      elsif (/ ^ (\# \s*) endif /x)
      {
        my $prev_else = pop @else_stack;
        Die("unbalanced #endif") unless defined($prev_else);

        pop @name_stack;

        # If there is no else-clause for an if-clause, we add one.  This is
        # necessary to have correct offsets.
        if (!$prev_else)
        {
          # Use amount of whitespace from `endif'.
          push @{$diversions{$curr_enum}}, enum_val_string(aux_name_next())
                                           . $1 . "else\n";
          $last_aux = aux_name();

          $curr_offset = 0;
        }

        $name_stack[$#name_stack]++;

        push @{$diversions{$curr_enum}}, enum_val_string(aux_name());
        $last_aux = aux_name();

        $curr_offset = 0;
      }

      # Handle (probably continued) preprocessor lines.
    CONTINUED_LOOP:
      {
        do
        {
          strip_newline();

          push @{$diversions{$curr_enum}}, $ARG . "\n";
          push @{$diversions{$curr_array}}, $ARG . "\n";

          last CONTINUED_LOOP unless / \\ $ /x;

        } while (<DATA>);
      }
    }
    else
    {
      warn_before();
    }

    next;
  }

  if (/$enum_element_re/)
  {
    end_curr_string();
    update_max_elem_size();

    $curr_enum_element = $1;
    $have_enum_element = 1;
    $curr_elem_size = 0;

    next;
  }

  if (/$string_re/)
  {
    if ($have_sections)
    {
      Die("strings and blocks can't be mixed in a section") if $have_blocks;

      # Save captured group from `string_re'.
      my $string = $1;

      if ($have_enum_element)
      {
        push @{$diversions{$curr_enum}}, enum_val_string($curr_enum_element);
        $have_enum_element = 0;
      }

      $string = convert_literal($string);

      push @{$diversions{$curr_array}}, "    $string\n";

      $have_strings = 1;
      $in_string = 1;
    }
    else
    {
      warn_before();
    }

    next;
  }

  if (/$block_start_re/)
  {
    if ($have_sections)
    {
      Die("strings and blocks can't be mixed in a section") if $have_strings;

      my $depth = 0;
      my $block = "";
      my $block_end = 0;

      # Count braces while getting the block.
    BRACE_LOOP:
      {
        do
        {
          strip_newline();

          foreach my $substring (split(/$brace_re/))
          {
            if ($block_end)
            {
              Die("invalid data after last matching closing brace")
                if $substring !~ /$whitespace_only_re/;
            }

            $block .= $substring;

            if ($substring eq '{')
            {
              $depth++;
            }
            elsif ($substring eq '}')
            {
              $depth--;

              $block_end = 1 if $depth == 0;
            }
          }

          # If we are here, we have run out of substrings, so get next line
          # or exit.
          last BRACE_LOOP if $block_end;

          $block .= "\n";

        } while (<DATA>);
      }

      if ($have_enum_element)
      {
        push @{$diversions{$curr_enum}}, enum_val_string($curr_enum_element);
        $have_enum_element = 0;
      }

      push @{$diversions{$curr_array}}, $block . ",\n";

      $curr_offset++;
      $curr_elem_size++;

      $have_blocks = 1;
    }
    else
    {
      warn_before();
    }

    next;
  }

  # Garbage.  We weren't able to parse the data.
  Die("syntax error");
}

# Finalize data.
end_curr_string();
update_max_elem_size();

# Filter stdin to stdout, replacing `@...@' templates.

sub emit_diversion
{
  my $diversion_name = shift;
  return (exists($diversions{$1})) ? "@{$diversions{$1}}"
                                   : "@" . $diversion_name . "@";
}

$LIST_SEPARATOR = '';

my $s1 = "This file has been generated by the Perl script \`$prog',";
my $s1len = length $s1;
my $s2 = "using data from file \`$datafile'.";
my $s2len = length $s2;
my $slen = ($s1len > $s2len) ? $s1len : $s2len;

print "/* " . $s1 . " " x ($slen - $s1len) . " */\n"
      . "/* " . $s2 . " " x ($slen - $s2len) . " */\n"
      . "\n";

while (<STDIN>)
{
  s/ @ ( [A-Za-z0-9_]+? ) @ / emit_diversion($1) /egx;
  print;
}

# EOF


text:
#!/usr/bin/env python
#
# Check trace components in FreeType 2 source.
# Author: suzuki toshiya, 2009, 2013
#
# This code is explicitly into the public domain.

import sys
import os
import re

SRC_FILE_LIST   = []
USED_COMPONENT  = {}
KNOWN_COMPONENT = {}

SRC_FILE_DIRS   = [ "src" ]
TRACE_DEF_FILES = [ "include/freetype/internal/fttrace.h" ]

# --------------------------------------------------------------
# Parse command line options
#

for i in range( 1, len( sys.argv ) ):
  if sys.argv[i].startswith( "--help" ):
    print "Usage: %s [option]" % sys.argv[0]
    print "Search used-but-defined and defined-but-not-used trace_XXX macros"
    print ""
    print "  --help:"
    print "        Show this help"
    print ""
    print "  --src-dirs=dir1:dir2:..."
    print "        Specify the directories of C source files to be checked"
    print "        Default is %s" % ":".join( SRC_FILE_DIRS )
    print ""
    print "  --def-files=file1:file2:..."
    print "        Specify the header files including FT_TRACE_DEF()"
    print "        Default is %s" % ":".join( TRACE_DEF_FILES )
    print ""
    exit(0)
  if sys.argv[i].startswith( "--src-dirs=" ):
    SRC_FILE_DIRS = sys.argv[i].replace( "--src-dirs=", "", 1 ).split( ":" )
  elif sys.argv[i].startswith( "--def-files=" ):
    TRACE_DEF_FILES = sys.argv[i].replace( "--def-files=", "", 1 ).split( ":" )

# --------------------------------------------------------------
# Scan C source and header files using trace macros.
#

c_pathname_pat = re.compile( '^.*\.[ch]$', re.IGNORECASE )
trace_use_pat  = re.compile( '^[ \t]*#define[ \t]+FT_COMPONENT[ \t]+trace_' )

for d in SRC_FILE_DIRS:
  for ( p, dlst, flst ) in os.walk( d ):
    for f in flst:
      if c_pathname_pat.match( f ) != None:
        src_pathname = os.path.join( p, f )

        line_num = 0
        for src_line in open( src_pathname, 'r' ):
          line_num = line_num + 1
          src_line = src_line.strip()
          if trace_use_pat.match( src_line ) != None:
            component_name = trace_use_pat.sub( '', src_line )
            if component_name in USED_COMPONENT:
              USED_COMPONENT[component_name].append( "%s:%d" % ( src_pathname, line_num ) )
            else:
              USED_COMPONENT[component_name] = [ "%s:%d" % ( src_pathname, line_num ) ]

# --------------------------------------------------------------
# Scan header file(s) defining trace macros.
#

trace_def_pat_opn = re.compile( '^.*FT_TRACE_DEF[ \t]*\([ \t]*' )
trace_def_pat_cls = re.compile( '[ \t\)].*$' )

for f in TRACE_DEF_FILES:
  line_num = 0
  for hdr_line in open( f, 'r' ):
    line_num = line_num + 1
    hdr_line = hdr_line.strip()
    if trace_def_pat_opn.match( hdr_line ) != None:
      component_name = trace_def_pat_opn.sub( '', hdr_line )
      component_name = trace_def_pat_cls.sub( '', component_name )
      if component_name in KNOWN_COMPONENT:
        print "trace component %s is defined twice, see %s and fttrace.h:%d" % \
          ( component_name, KNOWN_COMPONENT[component_name], line_num )
      else:
        KNOWN_COMPONENT[component_name] = "%s:%d" % \
          ( os.path.basename( f ), line_num )

# --------------------------------------------------------------
# Compare the used and defined trace macros.
#

print "# Trace component used in the implementations but not defined in fttrace.h."
cmpnt = USED_COMPONENT.keys()
cmpnt.sort()
for c in cmpnt:
  if c not in KNOWN_COMPONENT:
    print "Trace component %s (used in %s) is not defined." % ( c, ", ".join( USED_COMPONENT[c] ) )

print "# Trace component is defined but not used in the implementations."
cmpnt = KNOWN_COMPONENT.keys()
cmpnt.sort()
for c in cmpnt:
  if c not in USED_COMPONENT:
    if c != "any":
      print "Trace component %s (defined in %s) is not used." % ( c, KNOWN_COMPONENT[c] )


text:
# Jamfile for src/tools
#
SubDir FT2_TOP src tools ;

Main  apinames : apinames.c ;


text:
/*
 * This little program is used to parse the FreeType headers and
 * find the declaration of all public APIs.  This is easy, because
 * they all look like the following:
 *
 *   FT_EXPORT( return_type )
 *   function_name( function arguments );
 *
 * You must pass the list of header files as arguments.  Wildcards are
 * accepted if you are using GCC for compilation (and probably by
 * other compilers too).
 *
 * Author: FreeType team, 2005-2019
 *
 * This code is explicitly placed into the public domain.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define  PROGRAM_NAME     "apinames"
#define  PROGRAM_VERSION  "0.3"

#define  LINEBUFF_SIZE  1024

typedef enum  OutputFormat_
{
  OUTPUT_LIST = 0,      /* output the list of names, one per line             */
  OUTPUT_WINDOWS_DEF,   /* output a Windows .DEF file for Visual C++ or Mingw */
  OUTPUT_BORLAND_DEF,   /* output a Windows .DEF file for Borland C++         */
  OUTPUT_WATCOM_LBC,    /* output a Watcom Linker Command File                */
  OUTPUT_NETWARE_IMP,   /* output a NetWare ImportFile                        */
  OUTPUT_GNU_VERMAP     /* output a version map for GNU or Solaris linker     */

} OutputFormat;

static void
panic( const char*  message )
{
  fprintf( stderr, "PANIC: %s\n", message );
  exit(2);
}

typedef struct  NameRec_
{
  char*         name;
  unsigned int  hash;

} NameRec, *Name;

static Name  the_names;
static int   num_names;
static int   max_names;

static void
names_add( const char*  name,
           const char*  end )
{
  unsigned int  h;
  int           nn, len;
  Name          nm;

  if ( end <= name )
    return;

  /* compute hash value */
  len = (int)( end - name );
  h   = 0;

  for ( nn = 0; nn < len; nn++ )
    h = h * 33 + name[nn];

  /* check for an pre-existing name */
  for ( nn = 0; nn < num_names; nn++ )
  {
    nm = the_names + nn;

    if ( (int)nm->hash                 == h &&
         memcmp( name, nm->name, len ) == 0 &&
         nm->name[len]                 == 0 )
      return;
  }

  /* add new name */
  if ( num_names >= max_names )
  {
    max_names += ( max_names >> 1 ) + 4;
    the_names  = (NameRec*)realloc( the_names,
                                    sizeof ( the_names[0] ) * max_names );
    if ( !the_names )
      panic( "not enough memory" );
  }
  nm = &the_names[num_names++];

  nm->hash = h;
  nm->name = (char*)malloc( len + 1 );
  if ( !nm->name )
    panic( "not enough memory" );

  memcpy( nm->name, name, len );
  nm->name[len] = 0;
}

static int
name_compare( const void*  name1,
              const void*  name2 )
{
  Name  n1 = (Name)name1;
  Name  n2 = (Name)name2;

  return strcmp( n1->name, n2->name );
}

static void
names_sort( void )
{
  qsort( the_names, (size_t)num_names,
         sizeof ( the_names[0] ), name_compare );
}

static void
names_dump( FILE*         out,
            OutputFormat  format,
            const char*   dll_name )
{
  int  nn;

  switch ( format )
  {
  case OUTPUT_WINDOWS_DEF:
    if ( dll_name )
      fprintf( out, "LIBRARY %s\n", dll_name );

    fprintf( out, "DESCRIPTION  FreeType 2 DLL\n" );
    fprintf( out, "EXPORTS\n" );

    for ( nn = 0; nn < num_names; nn++ )
      fprintf( out, "  %s\n", the_names[nn].name );

    break;

  case OUTPUT_BORLAND_DEF:
    if ( dll_name )
      fprintf( out, "LIBRARY %s\n", dll_name );

    fprintf( out, "DESCRIPTION  FreeType 2 DLL\n" );
    fprintf( out, "EXPORTS\n" );

    for ( nn = 0; nn < num_names; nn++ )
      fprintf( out, "  _%s\n", the_names[nn].name );

    break;

  case OUTPUT_WATCOM_LBC:
    {
      const char*  dot;
      char         temp[512];

      if ( !dll_name )
      {
        fprintf( stderr,
                 "you must provide a DLL name with the -d option!\n" );
        exit( 4 );
      }

      /* we must omit the `.dll' suffix from the library name */
      dot = strchr( dll_name, '.' );
      if ( dot )
      {
        int  len = dot - dll_name;

        if ( len > (int)( sizeof ( temp ) - 1 ) )
          len = sizeof ( temp ) - 1;

        memcpy( temp, dll_name, len );
        temp[len] = 0;

        dll_name = (const char*)temp;
      }

      for ( nn = 0; nn < num_names; nn++ )
        fprintf( out, "++_%s.%s.%s\n",
                      the_names[nn].name, dll_name, the_names[nn].name );
    }

    break;

  case OUTPUT_NETWARE_IMP:
    if ( dll_name )
      fprintf( out, "  (%s)\n", dll_name );

    for ( nn = 0; nn < num_names - 1; nn++ )
      fprintf( out, "  %s,\n", the_names[nn].name );
    fprintf( out, "  %s\n", the_names[num_names - 1].name );

    break;

  case OUTPUT_GNU_VERMAP:
    fprintf( out, "{\n\tglobal:\n" );

    for ( nn = 0; nn < num_names; nn++ )
      fprintf( out, "\t\t%s;\n", the_names[nn].name );

    fprintf( out, "\tlocal:\n\t\t*;\n};\n" );

    break;

  default:  /* LIST */
    for ( nn = 0; nn < num_names; nn++ )
      fprintf( out, "%s\n", the_names[nn].name );

    break;
  }
}

/* states of the line parser */

typedef enum  State_
{
  STATE_START = 0,  /* waiting for FT_EXPORT keyword and return type */
  STATE_TYPE        /* type was read, waiting for function name      */

} State;

static int
read_header_file( FILE*  file,
                  int    verbose )
{
  static char  buff[LINEBUFF_SIZE + 1];
  State        state = STATE_START;

  while ( !feof( file ) )
  {
    char*  p;

    if ( !fgets( buff, LINEBUFF_SIZE, file ) )
      break;

    p = buff;

    /* skip leading whitespace */
    while ( *p && ( *p == ' ' || *p == '\\' ) )
      p++;

    /* skip empty lines */
    if ( *p == '\n' || *p == '\r' )
      continue;

    switch ( state )
    {
    case STATE_START:
      if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 )
        break;

      p += 10;
      for (;;)
      {
        if ( *p == 0 || *p == '\n' || *p == '\r' )
          goto NextLine;

        if ( *p == ')' )
        {
          p++;
          break;
        }

        p++;
      }

      state = STATE_TYPE;

      /*
       * Sometimes, the name is just after `FT_EXPORT(...)', so skip
       * whitespace and fall-through if we find an alphanumeric character.
       */
      while ( *p == ' ' || *p == '\t' )
        p++;

      if ( !isalpha( *p ) )
        break;

      /* fall-through */

    case STATE_TYPE:
      {
        char*   name = p;

        while ( isalnum( *p ) || *p == '_' )
          p++;

        if ( p > name )
        {
          if ( verbose )
            fprintf( stderr, ">>> %.*s\n", (int)( p - name ), name );

          names_add( name, p );
        }

        state = STATE_START;
      }

      break;

    default:
      ;
    }

NextLine:
    ;
  } /* end of while loop */

  return 0;
}

static void
usage( void )
{
  static const char* const  format =
    "%s %s: extract FreeType API names from header files\n"
    "\n"
    "This program extracts the list of public FreeType API functions.\n"
    "It receives a list of header files as an argument and\n"
    "generates a sorted list of unique identifiers in various formats.\n"
    "\n"
    "usage: %s header1 [options] [header2 ...]\n"
    "\n"
    "options:   -       parse the contents of stdin, ignore arguments\n"
    "           -v      verbose mode, output sent to standard error\n"
    "           -oFILE  write output to FILE instead of standard output\n"
    "           -dNAME  indicate DLL file name, 'freetype.dll' by default\n"
    "           -w      output .DEF file for Visual C++ and Mingw\n"
    "           -wB     output .DEF file for Borland C++\n"
    "           -wW     output Watcom Linker Response File\n"
    "           -wN     output NetWare Import File\n"
    "           -wL     output version map for GNU or Solaris linker\n"
    "\n";

  fprintf( stderr,
           format,
           PROGRAM_NAME,
           PROGRAM_VERSION,
           PROGRAM_NAME );

  exit( 1 );
}

int
main( int                 argc,
      const char* const*  argv )
{
  int           from_stdin   = 0;
  int           verbose      = 0;
  OutputFormat  format       = OUTPUT_LIST;  /* the default */
  FILE*         out          = stdout;
  const char*   library_name = NULL;

  if ( argc < 2 )
    usage();

  /* `-' used as a single argument means read source file from stdin */
  while ( argc > 1 && argv[1][0] == '-' )
  {
    const char*  arg = argv[1];

    switch ( arg[1] )
    {
    case 'v':
      verbose = 1;

      break;

    case 'o':
      if ( arg[2] == 0 )
      {
        if ( argc < 2 )
          usage();

        arg = argv[2];
        argv++;
        argc--;
      }
      else
        arg += 2;

      out = fopen( arg, "wt" );
      if ( !out )
      {
        fprintf( stderr, "could not open '%s' for writing\n", arg );
        exit( 3 );
      }

      break;

    case 'd':
      if ( arg[2] == 0 )
      {
        if ( argc < 2 )
          usage();

        arg = argv[2];
        argv++;
        argc--;
      }
      else
        arg += 2;

      library_name = arg;

      break;

    case 'w':
      format = OUTPUT_WINDOWS_DEF;

      switch ( arg[2] )
      {
      case 'B':
        format = OUTPUT_BORLAND_DEF;
        break;

      case 'W':
        format = OUTPUT_WATCOM_LBC;
        break;

      case 'N':
        format = OUTPUT_NETWARE_IMP;
        break;

      case 'L':
        format = OUTPUT_GNU_VERMAP;
        break;

      case 0:
        break;

      default:
        usage();
      }

      break;

    case 0:
      from_stdin = 1;

      break;

    default:
      usage();
    }

    argc--;
    argv++;

  } /* end of while loop */

  if ( from_stdin )
    read_header_file( stdin, verbose );
  else
  {
    for ( --argc, argv++; argc > 0; argc--, argv++ )
    {
      FILE*  file = fopen( argv[0], "rb" );

      if ( !file )
        fprintf( stderr, "unable to open '%s'\n", argv[0] );
      else
      {
        if ( verbose )
          fprintf( stderr, "opening '%s'\n", argv[0] );

        read_header_file( file, verbose );
        fclose( file );
      }
    }
  }

  if ( num_names == 0 )
    panic( "could not find exported functions\n" );

  names_sort();
  names_dump( out, format, library_name );

  if ( out != stdout )
    fclose( out );

  return 0;
}

/* END */


text:
#!/bin/sh

# Run the `update-copyright-year' script on all files in the git repository,
# taking care of exceptions stored in file `no-copyright'.

topdir=`git rev-parse --show-toplevel`
toolsdir=$topdir/src/tools

git ls-files --full-name $topdir        \
| sed 's|^|../../|'                     \
| grep -vFf $toolsdir/no-copyright      \
| xargs $toolsdir/update-copyright-year

# EOF