static Image *ReadTIFFImage(const ImageInfo *image_info,
  ExceptionInfo *exception)
{
  const char
    *option;

  float
    *chromaticity,
    x_position,
    y_position,
    x_resolution,
    y_resolution;

  Image
    *image;

  int
    tiff_status;

  MagickBooleanType
    status;

  MagickSizeType
    number_pixels;

  QuantumInfo
    *quantum_info;

  QuantumType
    quantum_type;

  register ssize_t
    i;

  size_t
    pad;

  ssize_t
    y;

  TIFF
    *tiff;

  TIFFMethodType
    method;

  uint16
    compress_tag,
    bits_per_sample,
    endian,
    extra_samples,
    interlace,
    max_sample_value,
    min_sample_value,
    orientation,
    pages,
    photometric,
    *sample_info,
    sample_format,
    samples_per_pixel,
    units,
    value;

  uint32
    height,
    rows_per_strip,
    width;

  unsigned char
    *tiff_pixels;

  /*
    Open image.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  if (image_info->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickCoreSignature);
  image=AcquireImage(image_info,exception);
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
  if (status == MagickFalse)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  (void) SetMagickThreadValue(tiff_exception,exception);
  tiff=TIFFClientOpen(image->filename,"rb",(thandle_t) image,TIFFReadBlob,
    TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
    TIFFUnmapBlob);
  if (tiff == (TIFF *) NULL)
    {
      image=DestroyImageList(image);
      return((Image *) NULL);
    }
  if (image_info->number_scenes != 0)
    {
      /*
        Generate blank images for subimage specification (e.g. image.tif[4].
        We need to check the number of directores because it is possible that
        the subimage(s) are stored in the photoshop profile.
      */
      if (image_info->scene < (size_t) TIFFNumberOfDirectories(tiff))
        {
          for (i=0; i < (ssize_t) image_info->scene; i++)
          {
            status=TIFFReadDirectory(tiff) != 0 ? MagickTrue : MagickFalse;
            if (status == MagickFalse)
              {
                TIFFClose(tiff);
                image=DestroyImageList(image);
                return((Image *) NULL);
              }
            AcquireNextImage(image_info,image,exception);
            if (GetNextImageInList(image) == (Image *) NULL)
              {
                TIFFClose(tiff);
                image=DestroyImageList(image);
                return((Image *) NULL);
              }
            image=SyncNextImageInList(image);
          }
      }
  }
  do
  {
DisableMSCWarning(4127)
    if (0 && (image_info->verbose != MagickFalse))
      TIFFPrintDirectory(tiff,stdout,MagickFalse);
RestoreMSCWarning
    if ((TIFFGetField(tiff,TIFFTAG_IMAGEWIDTH,&width) != 1) ||
        (TIFFGetField(tiff,TIFFTAG_IMAGELENGTH,&height) != 1) ||
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_COMPRESSION,&compress_tag) != 1) ||
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&endian) != 1) ||
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_PLANARCONFIG,&interlace) != 1) ||
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,&samples_per_pixel) != 1) ||
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,&bits_per_sample) != 1) ||
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLEFORMAT,&sample_format) != 1) ||
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_MINSAMPLEVALUE,&min_sample_value) != 1) ||
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_MAXSAMPLEVALUE,&max_sample_value) != 1) ||
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_PHOTOMETRIC,&photometric) != 1))
      {
        TIFFClose(tiff);
        ThrowReaderException(CorruptImageError,"ImproperImageHeader");
      }
    if (sample_format == SAMPLEFORMAT_IEEEFP)
      (void) SetImageProperty(image,"quantum:format","floating-point",
        exception);
    switch (photometric)
    {
      case PHOTOMETRIC_MINISBLACK:
      {
        (void) SetImageProperty(image,"tiff:photometric","min-is-black",
          exception);
        break;
      }
      case PHOTOMETRIC_MINISWHITE:
      {
        (void) SetImageProperty(image,"tiff:photometric","min-is-white",
          exception);
        break;
      }
      case PHOTOMETRIC_PALETTE:
      {
        (void) SetImageProperty(image,"tiff:photometric","palette",exception);
        break;
      }
      case PHOTOMETRIC_RGB:
      {
        (void) SetImageProperty(image,"tiff:photometric","RGB",exception);
        break;
      }
      case PHOTOMETRIC_CIELAB:
      {
        (void) SetImageProperty(image,"tiff:photometric","CIELAB",exception);
        break;
      }
      case PHOTOMETRIC_LOGL:
      {
        (void) SetImageProperty(image,"tiff:photometric","CIE Log2(L)",
          exception);
        break;
      }
      case PHOTOMETRIC_LOGLUV:
      {
        (void) SetImageProperty(image,"tiff:photometric","LOGLUV",exception);
        break;
      }
#if defined(PHOTOMETRIC_MASK)
      case PHOTOMETRIC_MASK:
      {
        (void) SetImageProperty(image,"tiff:photometric","MASK",exception);
        break;
      }
#endif
      case PHOTOMETRIC_SEPARATED:
      {
        (void) SetImageProperty(image,"tiff:photometric","separated",exception);
        break;
      }
      case PHOTOMETRIC_YCBCR:
      {
        (void) SetImageProperty(image,"tiff:photometric","YCBCR",exception);
        break;
      }
      default:
      {
        (void) SetImageProperty(image,"tiff:photometric","unknown",exception);
        break;
      }
    }
    if (image->debug != MagickFalse)
      {
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Geometry: %ux%u",
          (unsigned int) width,(unsigned int) height);
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Interlace: %u",
          interlace);
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
          "Bits per sample: %u",bits_per_sample);
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
          "Min sample value: %u",min_sample_value);
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
          "Max sample value: %u",max_sample_value);
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Photometric "
          "interpretation: %s",GetImageProperty(image,"tiff:photometric",
          exception));
      }
    image->columns=(size_t) width;
    image->rows=(size_t) height;
    image->depth=(size_t) bits_per_sample;
    if (image->debug != MagickFalse)
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Image depth: %.20g",
        (double) image->depth);
    image->endian=MSBEndian;
    if (endian == FILLORDER_LSB2MSB)
      image->endian=LSBEndian;
#if defined(MAGICKCORE_HAVE_TIFFISBIGENDIAN)
    if (TIFFIsBigEndian(tiff) == 0)
      {
        (void) SetImageProperty(image,"tiff:endian","lsb",exception);
        image->endian=LSBEndian;
      }
    else
      {
        (void) SetImageProperty(image,"tiff:endian","msb",exception);
        image->endian=MSBEndian;
      }
#endif
    if ((photometric == PHOTOMETRIC_MINISBLACK) ||
        (photometric == PHOTOMETRIC_MINISWHITE))
      SetImageColorspace(image,GRAYColorspace,exception);
    if (photometric == PHOTOMETRIC_SEPARATED)
      SetImageColorspace(image,CMYKColorspace,exception);
    if (photometric == PHOTOMETRIC_CIELAB)
      SetImageColorspace(image,LabColorspace,exception);
    TIFFGetProfiles(tiff,image,exception);
    TIFFGetProperties(tiff,image,exception);
    option=GetImageOption(image_info,"tiff:exif-properties");
    if (IsStringFalse(option) == MagickFalse) /* enabled by default */
      TIFFGetEXIFProperties(tiff,image,exception);
    (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,
      &samples_per_pixel);
    if ((TIFFGetFieldDefaulted(tiff,TIFFTAG_XRESOLUTION,&x_resolution) == 1) &&
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_YRESOLUTION,&y_resolution) == 1))
      {
        image->resolution.x=x_resolution;
        image->resolution.y=y_resolution;
      }
    if (TIFFGetFieldDefaulted(tiff,TIFFTAG_RESOLUTIONUNIT,&units) == 1)
      {
        if (units == RESUNIT_INCH)
          image->units=PixelsPerInchResolution;
        if (units == RESUNIT_CENTIMETER)
          image->units=PixelsPerCentimeterResolution;
      }
    if ((TIFFGetFieldDefaulted(tiff,TIFFTAG_XPOSITION,&x_position) == 1) &&
        (TIFFGetFieldDefaulted(tiff,TIFFTAG_YPOSITION,&y_position) == 1))
      {
        image->page.x=(ssize_t) ceil(x_position*image->resolution.x-0.5);
        image->page.y=(ssize_t) ceil(y_position*image->resolution.y-0.5);
      }
    if (TIFFGetFieldDefaulted(tiff,TIFFTAG_ORIENTATION,&orientation) == 1)
      image->orientation=(OrientationType) orientation;
    if (TIFFGetField(tiff,TIFFTAG_WHITEPOINT,&chromaticity) == 1)
      {
        if (chromaticity != (float *) NULL)
          {
            image->chromaticity.white_point.x=chromaticity[0];
            image->chromaticity.white_point.y=chromaticity[1];
          }
      }
    if (TIFFGetField(tiff,TIFFTAG_PRIMARYCHROMATICITIES,&chromaticity) == 1)
      {
        if (chromaticity != (float *) NULL)
          {
            image->chromaticity.red_primary.x=chromaticity[0];
            image->chromaticity.red_primary.y=chromaticity[1];
            image->chromaticity.green_primary.x=chromaticity[2];
            image->chromaticity.green_primary.y=chromaticity[3];
            image->chromaticity.blue_primary.x=chromaticity[4];
            image->chromaticity.blue_primary.y=chromaticity[5];
          }
      }
#if defined(MAGICKCORE_HAVE_TIFFISCODECCONFIGURED) || (TIFFLIB_VERSION > 20040919)
    if ((compress_tag != COMPRESSION_NONE) &&
        (TIFFIsCODECConfigured(compress_tag) == 0))
      {
        TIFFClose(tiff);
        ThrowReaderException(CoderError,"CompressNotSupported");
      }
#endif
    switch (compress_tag)
    {
      case COMPRESSION_NONE: image->compression=NoCompression; break;
      case COMPRESSION_CCITTFAX3: image->compression=FaxCompression; break;
      case COMPRESSION_CCITTFAX4: image->compression=Group4Compression; break;
      case COMPRESSION_JPEG:
      {
         image->compression=JPEGCompression;
#if defined(JPEG_SUPPORT)
         {
           char
             sampling_factor[MagickPathExtent];

           int
             tiff_status;

           uint16
             horizontal,
             vertical;

           tiff_status=TIFFGetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,&horizontal,
             &vertical);
           if (tiff_status == 1)
             {
               (void) FormatLocaleString(sampling_factor,MagickPathExtent,
                 "%dx%d",horizontal,vertical);
               (void) SetImageProperty(image,"jpeg:sampling-factor",
                 sampling_factor,exception);
               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                 "Sampling Factors: %s",sampling_factor);
             }
         }
#endif
        break;
      }
      case COMPRESSION_OJPEG: image->compression=JPEGCompression; break;
#if defined(COMPRESSION_LZMA)
      case COMPRESSION_LZMA: image->compression=LZMACompression; break;
#endif
      case COMPRESSION_LZW: image->compression=LZWCompression; break;
      case COMPRESSION_DEFLATE: image->compression=ZipCompression; break;
      case COMPRESSION_ADOBE_DEFLATE: image->compression=ZipCompression; break;
      default: image->compression=RLECompression; break;
    }
    quantum_info=(QuantumInfo *) NULL;
    if ((photometric == PHOTOMETRIC_PALETTE) &&
        (pow(2.0,1.0*bits_per_sample) <= MaxColormapSize))
      {
        size_t
          colors;

        colors=(size_t) GetQuantumRange(bits_per_sample)+1;
        if (AcquireImageColormap(image,colors,exception) == MagickFalse)
          {
            TIFFClose(tiff);
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
          }
      }
    value=(unsigned short) image->scene;
    if (TIFFGetFieldDefaulted(tiff,TIFFTAG_PAGENUMBER,&value,&pages) == 1)
      image->scene=value;
    if (image->storage_class == PseudoClass)
      {
        int
          tiff_status;

        size_t
          range;

        uint16
          *blue_colormap,
          *green_colormap,
          *red_colormap;

        /*
          Initialize colormap.
        */
        tiff_status=TIFFGetField(tiff,TIFFTAG_COLORMAP,&red_colormap,
          &green_colormap,&blue_colormap);
        if (tiff_status == 1)
          {
            if ((red_colormap != (uint16 *) NULL) &&
                (green_colormap != (uint16 *) NULL) &&
                (blue_colormap != (uint16 *) NULL))
              {
                range=255;  /* might be old style 8-bit colormap */
                for (i=0; i < (ssize_t) image->colors; i++)
                  if ((red_colormap[i] >= 256) || (green_colormap[i] >= 256) ||
                      (blue_colormap[i] >= 256))
                    {
                      range=65535;
                      break;
                    }
                for (i=0; i < (ssize_t) image->colors; i++)
                {
                  image->colormap[i].red=ClampToQuantum(((double)
                    QuantumRange*red_colormap[i])/range);
                  image->colormap[i].green=ClampToQuantum(((double)
                    QuantumRange*green_colormap[i])/range);
                  image->colormap[i].blue=ClampToQuantum(((double)
                    QuantumRange*blue_colormap[i])/range);
                }
              }
          }
      }
    if (image_info->ping != MagickFalse)
      {
        if (image_info->number_scenes != 0)
          if (image->scene >= (image_info->scene+image_info->number_scenes-1))
            break;
        goto next_tiff_frame;
      }
    status=SetImageExtent(image,image->columns,image->rows,exception);
    if (status == MagickFalse)
      return(DestroyImageList(image));
    /*
      Allocate memory for the image and pixel buffer.
    */
    quantum_info=AcquireQuantumInfo(image_info,image);
    if (quantum_info == (QuantumInfo *) NULL)
      {
        TIFFClose(tiff);
        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
      }
    if (sample_format == SAMPLEFORMAT_UINT)
      status=SetQuantumFormat(image,quantum_info,UnsignedQuantumFormat);
    if (sample_format == SAMPLEFORMAT_INT)
      status=SetQuantumFormat(image,quantum_info,SignedQuantumFormat);
    if (sample_format == SAMPLEFORMAT_IEEEFP)
      status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
    if (status == MagickFalse)
      {
        TIFFClose(tiff);
        quantum_info=DestroyQuantumInfo(quantum_info);
        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
      }
    status=MagickTrue;
    switch (photometric)
    {
      case PHOTOMETRIC_MINISBLACK:
      {
        quantum_info->min_is_white=MagickFalse;
        break;
      }
      case PHOTOMETRIC_MINISWHITE:
      {
        quantum_info->min_is_white=MagickTrue;
        break;
      }
      default:
        break;
    }
    tiff_status=TIFFGetFieldDefaulted(tiff,TIFFTAG_EXTRASAMPLES,&extra_samples,
      &sample_info);
    if (tiff_status == 1)
      {
        (void) SetImageProperty(image,"tiff:alpha","unspecified",exception);
        if (extra_samples == 0)
          {
            if ((samples_per_pixel == 4) && (photometric == PHOTOMETRIC_RGB))
              image->alpha_trait=BlendPixelTrait;
          }
        else
          for (i=0; i < extra_samples; i++)
          {
            image->alpha_trait=BlendPixelTrait;
            if (sample_info[i] == EXTRASAMPLE_ASSOCALPHA)
              {
                SetQuantumAlphaType(quantum_info,DisassociatedQuantumAlpha);
                (void) SetImageProperty(image,"tiff:alpha","associated",
                  exception);
              }
            else
              if (sample_info[i] == EXTRASAMPLE_UNASSALPHA)
                (void) SetImageProperty(image,"tiff:alpha","unassociated",
                  exception);
          }
      }
    method=ReadGenericMethod;
    if (TIFFGetField(tiff,TIFFTAG_ROWSPERSTRIP,&rows_per_strip) == 1)
      {
        char
          value[MagickPathExtent];

        method=ReadStripMethod;
        (void) FormatLocaleString(value,MagickPathExtent,"%u",
          (unsigned int) rows_per_strip);
        (void) SetImageProperty(image,"tiff:rows-per-strip",value,exception);
      }
    if ((samples_per_pixel >= 3) && (interlace == PLANARCONFIG_CONTIG))
      if ((image->alpha_trait == UndefinedPixelTrait) ||
          (samples_per_pixel >= 4))
        method=ReadRGBAMethod;
    if ((samples_per_pixel >= 4) && (interlace == PLANARCONFIG_SEPARATE))
      if ((image->alpha_trait == UndefinedPixelTrait) ||
          (samples_per_pixel >= 5))
        method=ReadCMYKAMethod;
    if ((photometric != PHOTOMETRIC_RGB) &&
        (photometric != PHOTOMETRIC_CIELAB) &&
        (photometric != PHOTOMETRIC_SEPARATED))
      method=ReadGenericMethod;
    if (image->storage_class == PseudoClass)
      method=ReadSingleSampleMethod;
    if ((photometric == PHOTOMETRIC_MINISBLACK) ||
        (photometric == PHOTOMETRIC_MINISWHITE))
      method=ReadSingleSampleMethod;
    if ((photometric != PHOTOMETRIC_SEPARATED) &&
        (interlace == PLANARCONFIG_SEPARATE) && (bits_per_sample < 64))
      method=ReadGenericMethod;
    if (image->compression == JPEGCompression)
      method=GetJPEGMethod(image,tiff,photometric,bits_per_sample,
        samples_per_pixel);
    if (compress_tag == COMPRESSION_JBIG)
      method=ReadStripMethod;
    if (TIFFIsTiled(tiff) != MagickFalse)
      method=ReadTileMethod;
    quantum_info->endian=LSBEndian;
    quantum_type=RGBQuantum;
    tiff_pixels=(unsigned char *) AcquireMagickMemory(MagickMax(
      TIFFScanlineSize(tiff),(ssize_t) (image->columns*samples_per_pixel*
      pow(2.0,ceil(log(bits_per_sample)/log(2.0))))));
    if (tiff_pixels == (unsigned char *) NULL)
      {
        TIFFClose(tiff);
        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
      }
    switch (method)
    {
      case ReadSingleSampleMethod:
      {
        /*
          Convert TIFF image to PseudoClass MIFF image.
        */
        quantum_type=IndexQuantum;
        pad=(size_t) MagickMax((size_t) samples_per_pixel-1,0);
        if (image->alpha_trait != UndefinedPixelTrait)
          {
            if (image->storage_class != PseudoClass)
              {
                quantum_type=samples_per_pixel == 1 ? AlphaQuantum :
                  GrayAlphaQuantum;
                pad=(size_t) MagickMax((size_t) samples_per_pixel-2,0);
              }
            else
              {
                quantum_type=IndexAlphaQuantum;
                pad=(size_t) MagickMax((size_t) samples_per_pixel-2,0);
              }
          }
        else
          if (image->storage_class != PseudoClass)
            {
              quantum_type=GrayQuantum;
              pad=(size_t) MagickMax((size_t) samples_per_pixel-1,0);
            }
        status=SetQuantumPad(image,quantum_info,pad*pow(2,ceil(log(
          bits_per_sample)/log(2))));
        if (status == MagickFalse)
          {
            TIFFClose(tiff);
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
          }
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          int
            status;

          register Quantum
            *magick_restrict q;

          status=TIFFReadPixels(tiff,bits_per_sample,0,y,(char *) tiff_pixels);
          if (status == -1)
            break;
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
            quantum_type,tiff_pixels,exception);
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
        break;
      }
      case ReadRGBAMethod:
      {
        /*
          Convert TIFF image to DirectClass MIFF image.
        */
        pad=(size_t) MagickMax((size_t) samples_per_pixel-3,0);
        quantum_type=RGBQuantum;
        if (image->alpha_trait != UndefinedPixelTrait)
          {
            quantum_type=RGBAQuantum;
            pad=(size_t) MagickMax((size_t) samples_per_pixel-4,0);
          }
        if (image->colorspace == CMYKColorspace)
          {
            pad=(size_t) MagickMax((size_t) samples_per_pixel-4,0);
            quantum_type=CMYKQuantum;
            if (image->alpha_trait != UndefinedPixelTrait)
              {
                quantum_type=CMYKAQuantum;
                pad=(size_t) MagickMax((size_t) samples_per_pixel-5,0);
              }
          }
        status=SetQuantumPad(image,quantum_info,pad*((bits_per_sample+7) >> 3));
        if (status == MagickFalse)
          {
            TIFFClose(tiff);
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
          }
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          int
            status;

          register Quantum
            *magick_restrict q;

          status=TIFFReadPixels(tiff,bits_per_sample,0,y,(char *) tiff_pixels);
          if (status == -1)
            break;
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
            quantum_type,tiff_pixels,exception);
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
        break;
      }
      case ReadCMYKAMethod:
      {
        /*
          Convert TIFF image to DirectClass MIFF image.
        */
        for (i=0; i < (ssize_t) samples_per_pixel; i++)
        {
          for (y=0; y < (ssize_t) image->rows; y++)
          {
            register Quantum
              *magick_restrict q;

            int
              status;

            status=TIFFReadPixels(tiff,bits_per_sample,(tsample_t) i,y,(char *)
              tiff_pixels);
            if (status == -1)
              break;
            q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
            if (q == (Quantum *) NULL)
              break;
            if (image->colorspace != CMYKColorspace)
              switch (i)
              {
                case 0: quantum_type=RedQuantum; break;
                case 1: quantum_type=GreenQuantum; break;
                case 2: quantum_type=BlueQuantum; break;
                case 3: quantum_type=AlphaQuantum; break;
                default: quantum_type=UndefinedQuantum; break;
              }
            else
              switch (i)
              {
                case 0: quantum_type=CyanQuantum; break;
                case 1: quantum_type=MagentaQuantum; break;
                case 2: quantum_type=YellowQuantum; break;
                case 3: quantum_type=BlackQuantum; break;
                case 4: quantum_type=AlphaQuantum; break;
                default: quantum_type=UndefinedQuantum; break;
              }
            (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
              quantum_type,tiff_pixels,exception);
            if (SyncAuthenticPixels(image,exception) == MagickFalse)
              break;
          }
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
        break;
      }
      case ReadYCCKMethod:
      {
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          int
            status;

          register Quantum
            *magick_restrict q;

          register ssize_t
            x;

          unsigned char
            *p;

          status=TIFFReadPixels(tiff,bits_per_sample,0,y,(char *) tiff_pixels);
          if (status == -1)
            break;
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          p=tiff_pixels;
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            SetPixelCyan(image,ScaleCharToQuantum(ClampYCC((double) *p+
              (1.402*(double) *(p+2))-179.456)),q);
            SetPixelMagenta(image,ScaleCharToQuantum(ClampYCC((double) *p-
              (0.34414*(double) *(p+1))-(0.71414*(double ) *(p+2))+
              135.45984)),q);
            SetPixelYellow(image,ScaleCharToQuantum(ClampYCC((double) *p+
              (1.772*(double) *(p+1))-226.816)),q);
            SetPixelBlack(image,ScaleCharToQuantum((unsigned char) *(p+3)),q);
            q+=GetPixelChannels(image);
            p+=4;
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
        break;
      }
      case ReadStripMethod:
      {
        register uint32
          *p;

        /*
          Convert stripped TIFF image to DirectClass MIFF image.
        */
        i=0;
        p=(uint32 *) NULL;
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          if (i == 0)
            {
              if (TIFFReadRGBAStrip(tiff,(tstrip_t) y,(uint32 *) tiff_pixels) == 0)
                break;
              i=(ssize_t) MagickMin((ssize_t) rows_per_strip,(ssize_t)
                image->rows-y);
            }
          i--;
          p=((uint32 *) tiff_pixels)+image->columns*i;
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            SetPixelRed(image,ScaleCharToQuantum((unsigned char)
              (TIFFGetR(*p))),q);
            SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
              (TIFFGetG(*p))),q);
            SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
              (TIFFGetB(*p))),q);
            if (image->alpha_trait != UndefinedPixelTrait)
              SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
                (TIFFGetA(*p))),q);
            p++;
            q+=GetPixelChannels(image);
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
        break;
      }
      case ReadTileMethod:
      {
        register uint32
          *p;

        uint32
          *tile_pixels,
          columns,
          rows;

        /*
          Convert tiled TIFF image to DirectClass MIFF image.
        */
        if ((TIFFGetField(tiff,TIFFTAG_TILEWIDTH,&columns) != 1) ||
            (TIFFGetField(tiff,TIFFTAG_TILELENGTH,&rows) != 1))
          {
            TIFFClose(tiff);
            ThrowReaderException(CoderError,"ImageIsNotTiled");
          }
        (void) SetImageStorageClass(image,DirectClass,exception);
        number_pixels=(MagickSizeType) columns*rows;
        if (HeapOverflowSanityCheck(rows,sizeof(*tile_pixels)) != MagickFalse)
          {
            TIFFClose(tiff);
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
          }
        tile_pixels=(uint32 *) AcquireQuantumMemory(columns,rows*
          sizeof(*tile_pixels));
        if (tile_pixels == (uint32 *) NULL)
          {
            TIFFClose(tiff);
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
          }
        for (y=0; y < (ssize_t) image->rows; y+=rows)
        {
          register ssize_t
            x;

          register Quantum
            *magick_restrict q,
            *magick_restrict tile;

          size_t
            columns_remaining,
            rows_remaining;

          rows_remaining=image->rows-y;
          if ((ssize_t) (y+rows) < (ssize_t) image->rows)
            rows_remaining=rows;
          tile=QueueAuthenticPixels(image,0,y,image->columns,rows_remaining,
            exception);
          if (tile == (Quantum *) NULL)
            break;
          for (x=0; x < (ssize_t) image->columns; x+=columns)
          {
            size_t
              column,
              row;

            if (TIFFReadRGBATile(tiff,(uint32) x,(uint32) y,tile_pixels) == 0)
              break;
            columns_remaining=image->columns-x;
            if ((ssize_t) (x+columns) < (ssize_t) image->columns)
              columns_remaining=columns;
            p=tile_pixels+(rows-rows_remaining)*columns;
            q=tile+GetPixelChannels(image)*(image->columns*(rows_remaining-1)+
              x);
            for (row=rows_remaining; row > 0; row--)
            {
              if (image->alpha_trait != UndefinedPixelTrait)
                for (column=columns_remaining; column > 0; column--)
                {
                  SetPixelRed(image,ScaleCharToQuantum((unsigned char)
                    TIFFGetR(*p)),q);
                  SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
                    TIFFGetG(*p)),q);
                  SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
                    TIFFGetB(*p)),q);
                  SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
                    TIFFGetA(*p)),q);
                  p++;
                  q+=GetPixelChannels(image);
                }
              else
                for (column=columns_remaining; column > 0; column--)
                {
                  SetPixelRed(image,ScaleCharToQuantum((unsigned char)
                    TIFFGetR(*p)),q);
                  SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
                    TIFFGetG(*p)),q);
                  SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
                    TIFFGetB(*p)),q);
                  p++;
                  q+=GetPixelChannels(image);
                }
              p+=columns-columns_remaining;
              q-=GetPixelChannels(image)*(image->columns+columns_remaining);
            }
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
        tile_pixels=(uint32 *) RelinquishMagickMemory(tile_pixels);
        break;
      }
      case ReadGenericMethod:
      default:
      {
        MemoryInfo
          *pixel_info;

        register uint32
          *p;

        uint32
          *pixels;

        /*
          Convert TIFF image to DirectClass MIFF image.
        */
        number_pixels=(MagickSizeType) image->columns*image->rows;
        if (HeapOverflowSanityCheck(image->rows,sizeof(*pixels)) != MagickFalse)
          {
            TIFFClose(tiff);
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
          }
        pixel_info=AcquireVirtualMemory(image->columns,image->rows*
          sizeof(uint32));
        if (pixel_info == (MemoryInfo *) NULL)
          {
            TIFFClose(tiff);
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
          }
        pixels=(uint32 *) GetVirtualMemoryBlob(pixel_info);
        (void) TIFFReadRGBAImage(tiff,(uint32) image->columns,(uint32)
          image->rows,(uint32 *) pixels,0);
        /*
          Convert image to DirectClass pixel packets.
        */
        p=pixels+number_pixels-1;
        for (y=0; y < (ssize_t) image->rows; y++)
        {
          register ssize_t
            x;

          register Quantum
            *magick_restrict q;

          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
          if (q == (Quantum *) NULL)
            break;
          q+=GetPixelChannels(image)*(image->columns-1);
          for (x=0; x < (ssize_t) image->columns; x++)
          {
            SetPixelRed(image,ScaleCharToQuantum((unsigned char)
              TIFFGetR(*p)),q);
            SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
              TIFFGetG(*p)),q);
            SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
              TIFFGetB(*p)),q);
            if (image->alpha_trait != UndefinedPixelTrait)
              SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
                TIFFGetA(*p)),q);
            p--;
            q-=GetPixelChannels(image);
          }
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
          if (image->previous == (Image *) NULL)
            {
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                image->rows);
              if (status == MagickFalse)
                break;
            }
        }
        pixel_info=RelinquishVirtualMemory(pixel_info);
        break;
      }
    }
    tiff_pixels=(unsigned char *) RelinquishMagickMemory(tiff_pixels);
    SetQuantumImageType(image,quantum_type);
  next_tiff_frame:
    if (quantum_info != (QuantumInfo *) NULL)
      quantum_info=DestroyQuantumInfo(quantum_info);
    if (photometric == PHOTOMETRIC_CIELAB)
      DecodeLabImage(image,exception);
    if ((photometric == PHOTOMETRIC_LOGL) ||
        (photometric == PHOTOMETRIC_MINISBLACK) ||
        (photometric == PHOTOMETRIC_MINISWHITE))
      {
        image->type=GrayscaleType;
        if (bits_per_sample == 1)
          image->type=BilevelType;
      }
    /*
      Proceed to next image.
    */
    if (image_info->number_scenes != 0)
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
        break;
    status=TIFFReadDirectory(tiff) != 0 ? MagickTrue : MagickFalse;
    if (status != MagickFalse)
      {
        /*
          Allocate next image structure.
        */
        AcquireNextImage(image_info,image,exception);
        if (GetNextImageInList(image) == (Image *) NULL)
          {
            image=DestroyImageList(image);
            return((Image *) NULL);
          }
        image=SyncNextImageInList(image);
        status=SetImageProgress(image,LoadImagesTag,image->scene-1,
          image->scene);
        if (status == MagickFalse)
          break;
      }
  } while (status != MagickFalse);
  TIFFClose(tiff);
  TIFFReadPhotoshopLayers(image,image_info,exception);
  if (image_info->number_scenes != 0)
    {
      if (image_info->scene >= GetImageListLength(image))
        {
          /* Subimage was not found in the Photoshop layer */
          image=DestroyImageList(image);
          return((Image *)NULL);
        }
    }
  return(GetFirstImageInList(image));
}


static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { MP3Context *mp3 = s->priv_data; AVIndexEntry *ie; AVStream *st = s->streams[0]; int64_t ret = av_index_search_timestamp(st, timestamp, flags); uint32_t header = 0; if (!mp3->xing_toc) { st->skip_samples = timestamp <= 0 ? mp3->start_pad + 528 + 1 : 0; return -1; } if (ret < 0) return ret; ie = &st->index_entries[ret]; ret = avio_seek(s->pb, ie->pos, SEEK_SET); if (ret < 0) return ret; while (!s->pb->eof_reached) { header = (header << 8) + avio_r8(s->pb); if (ff_mpa_check_header(header) >= 0) { ff_update_cur_dts(s, st, ie->timestamp); ret = avio_seek(s->pb, -4, SEEK_CUR); st->skip_samples = ie->timestamp <= 0 ? mp3->start_pad + 528 + 1 : 0; return (ret >= 0) ? 0 : ret; } } return AVERROR_EOF; }


int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
                                  const Signature *s, const SigMatchData *smd,
                                  Flow *f,
                                  uint8_t *buffer, uint32_t buffer_len,
                                  uint32_t stream_start_offset,
                                  uint8_t inspection_mode, void *data)
{
    SCEnter();
    KEYWORD_PROFILING_START;

    det_ctx->inspection_recursion_counter++;

    if (det_ctx->inspection_recursion_counter == de_ctx->inspection_recursion_limit) {
        det_ctx->discontinue_matching = 1;
        KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
        SCReturnInt(0);
    }

    if (smd == NULL || buffer_len == 0) {
        KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
        SCReturnInt(0);
    }

    /* \todo unify this which is phase 2 of payload inspection unification */
    if (smd->type == DETECT_CONTENT) {

        DetectContentData *cd = (DetectContentData *)smd->ctx;
        SCLogDebug("inspecting content %"PRIu32" buffer_len %"PRIu32, cd->id, buffer_len);

        /* we might have already have this content matched by the mpm.
         * (if there is any other reason why we'd want to avoid checking
         *  it here, please fill it in) */
        //if (cd->flags & DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED) {
        //    goto match;
        //}

        /* rule parsers should take care of this */
#ifdef DEBUG
        BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
#endif

        /* search for our pattern, checking the matches recursively.
         * if we match we look for the next SigMatch as well */
        uint8_t *found = NULL;
        uint32_t offset = 0;
        uint32_t depth = buffer_len;
        uint32_t prev_offset = 0; /**< used in recursive searching */
        uint32_t prev_buffer_offset = det_ctx->buffer_offset;

        do {
            if ((cd->flags & DETECT_CONTENT_DISTANCE) ||
                (cd->flags & DETECT_CONTENT_WITHIN)) {
                SCLogDebug("det_ctx->buffer_offset %"PRIu32, det_ctx->buffer_offset);

                offset = prev_buffer_offset;
                depth = buffer_len;

                int distance = cd->distance;
                if (cd->flags & DETECT_CONTENT_DISTANCE) {
                    if (cd->flags & DETECT_CONTENT_DISTANCE_BE) {
                        distance = det_ctx->bj_values[cd->distance];
                    }
                    if (distance < 0 && (uint32_t)(abs(distance)) > offset)
                        offset = 0;
                    else
                        offset += distance;

                    SCLogDebug("cd->distance %"PRIi32", offset %"PRIu32", depth %"PRIu32,
                               distance, offset, depth);
                }

                if (cd->flags & DETECT_CONTENT_WITHIN) {
                    if (cd->flags & DETECT_CONTENT_WITHIN_BE) {
                        if ((int32_t)depth > (int32_t)(prev_buffer_offset + det_ctx->bj_values[cd->within] + distance)) {
                            depth = prev_buffer_offset + det_ctx->bj_values[cd->within] + distance;
                        }
                    } else {
                        if ((int32_t)depth > (int32_t)(prev_buffer_offset + cd->within + distance)) {
                            depth = prev_buffer_offset + cd->within + distance;
                        }

                        SCLogDebug("cd->within %"PRIi32", det_ctx->buffer_offset %"PRIu32", depth %"PRIu32,
                                   cd->within, prev_buffer_offset, depth);
                    }

                    if (stream_start_offset != 0 && prev_buffer_offset == 0) {
                        if (depth <= stream_start_offset) {
                            goto no_match;
                        } else if (depth >= (stream_start_offset + buffer_len)) {
                            ;
                        } else {
                            depth = depth - stream_start_offset;
                        }
                    }
                }

                if (cd->flags & DETECT_CONTENT_DEPTH_BE) {
                    if ((det_ctx->bj_values[cd->depth] + prev_buffer_offset) < depth) {
                        depth = prev_buffer_offset + det_ctx->bj_values[cd->depth];
                    }
                } else {
                    if (cd->depth != 0) {
                        if ((cd->depth + prev_buffer_offset) < depth) {
                            depth = prev_buffer_offset + cd->depth;
                        }

                        SCLogDebug("cd->depth %"PRIu32", depth %"PRIu32, cd->depth, depth);
                    }
                }

                if (cd->flags & DETECT_CONTENT_OFFSET_BE) {
                    if (det_ctx->bj_values[cd->offset] > offset)
                        offset = det_ctx->bj_values[cd->offset];
                } else {
                    if (cd->offset > offset) {
                        offset = cd->offset;
                        SCLogDebug("setting offset %"PRIu32, offset);
                    }
                }
            } else { /* implied no relative matches */
                /* set depth */
                if (cd->flags & DETECT_CONTENT_DEPTH_BE) {
                    depth = det_ctx->bj_values[cd->depth];
                } else {
                    if (cd->depth != 0) {
                        depth = cd->depth;
                    }
                }

                if (stream_start_offset != 0 && cd->flags & DETECT_CONTENT_DEPTH) {
                    if (depth <= stream_start_offset) {
                        goto no_match;
                    } else if (depth >= (stream_start_offset + buffer_len)) {
                        ;
                    } else {
                        depth = depth - stream_start_offset;
                    }
                }

                /* set offset */
                if (cd->flags & DETECT_CONTENT_OFFSET_BE)
                    offset = det_ctx->bj_values[cd->offset];
                else
                    offset = cd->offset;
                prev_buffer_offset = 0;
            }

            /* update offset with prev_offset if we're searching for
             * matches after the first occurence. */
            SCLogDebug("offset %"PRIu32", prev_offset %"PRIu32, offset, prev_offset);
            if (prev_offset != 0)
                offset = prev_offset;

            SCLogDebug("offset %"PRIu32", depth %"PRIu32, offset, depth);

            if (depth > buffer_len)
                depth = buffer_len;

            /* if offset is bigger than depth we can never match on a pattern.
             * We can however, "match" on a negated pattern. */
            if (offset > depth || depth == 0) {
                if (cd->flags & DETECT_CONTENT_NEGATED) {
                    goto match;
                } else {
                    goto no_match;
                }
            }

            uint8_t *sbuffer = buffer + offset;
            uint32_t sbuffer_len = depth - offset;
            uint32_t match_offset = 0;
            SCLogDebug("sbuffer_len %"PRIu32, sbuffer_len);
#ifdef DEBUG
            BUG_ON(sbuffer_len > buffer_len);
#endif

            /* \todo Add another optimization here.  If cd->content_len is
             * greater than sbuffer_len found is anyways NULL */

            /* do the actual search */
            found = SpmScan(cd->spm_ctx, det_ctx->spm_thread_ctx, sbuffer,
                            sbuffer_len);

            /* next we evaluate the result in combination with the
             * negation flag. */
            SCLogDebug("found %p cd negated %s", found, cd->flags & DETECT_CONTENT_NEGATED ? "true" : "false");

            if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
                goto no_match;
            } else if (found == NULL && (cd->flags & DETECT_CONTENT_NEGATED)) {
                goto match;
            } else if (found != NULL && (cd->flags & DETECT_CONTENT_NEGATED)) {
                SCLogDebug("content %"PRIu32" matched at offset %"PRIu32", but negated so no match", cd->id, match_offset);
                /* don't bother carrying recursive matches now, for preceding
                 * relative keywords */
                if (DETECT_CONTENT_IS_SINGLE(cd))
                    det_ctx->discontinue_matching = 1;
                goto no_match;
            } else {
                match_offset = (uint32_t)((found - buffer) + cd->content_len);
                SCLogDebug("content %"PRIu32" matched at offset %"PRIu32"", cd->id, match_offset);
                det_ctx->buffer_offset = match_offset;

                /* Match branch, add replace to the list if needed */
                if (cd->flags & DETECT_CONTENT_REPLACE) {
                    if (inspection_mode == DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD) {
                        /* we will need to replace content if match is confirmed */
                        det_ctx->replist = DetectReplaceAddToList(det_ctx->replist, found, cd);
                    } else {
                        SCLogWarning(SC_ERR_INVALID_VALUE, "Can't modify payload without packet");
                    }
                }
                if (!(cd->flags & DETECT_CONTENT_RELATIVE_NEXT)) {
                    SCLogDebug("no relative match coming up, so this is a match");
                    goto match;
                }

                /* bail out if we have no next match. Technically this is an
                 * error, as the current cd has the DETECT_CONTENT_RELATIVE_NEXT
                 * flag set. */
                if (smd->is_last) {
                    goto no_match;
                }

                SCLogDebug("content %"PRIu32, cd->id);
                KEYWORD_PROFILING_END(det_ctx, smd->type, 1);

                /* see if the next buffer keywords match. If not, we will
                 * search for another occurence of this content and see
                 * if the others match then until we run out of matches */
                int r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd+1,
                        f, buffer, buffer_len, stream_start_offset, inspection_mode, data);
                if (r == 1) {
                    SCReturnInt(1);
                }

                if (det_ctx->discontinue_matching)
                    goto no_match;

                /* set the previous match offset to the start of this match + 1 */
                prev_offset = (match_offset - (cd->content_len - 1));
                SCLogDebug("trying to see if there is another match after prev_offset %"PRIu32, prev_offset);
            }

        } while(1);

    } else if (smd->type == DETECT_ISDATAAT) {
        SCLogDebug("inspecting isdataat");

        DetectIsdataatData *id = (DetectIsdataatData *)smd->ctx;
        if (id->flags & ISDATAAT_RELATIVE) {
            if (det_ctx->buffer_offset + id->dataat > buffer_len) {
                SCLogDebug("det_ctx->buffer_offset + id->dataat %"PRIu32" > %"PRIu32, det_ctx->buffer_offset + id->dataat, buffer_len);
                if (id->flags & ISDATAAT_NEGATED)
                    goto match;
                goto no_match;
            } else {
                SCLogDebug("relative isdataat match");
                if (id->flags & ISDATAAT_NEGATED)
                    goto no_match;
                goto match;
            }
        } else {
            if (id->dataat < buffer_len) {
                SCLogDebug("absolute isdataat match");
                if (id->flags & ISDATAAT_NEGATED)
                    goto no_match;
                goto match;
            } else {
                SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", buffer_len %"PRIu32"", id->dataat, buffer_len);
                if (id->flags & ISDATAAT_NEGATED)
                    goto match;
                goto no_match;
            }
        }

    } else if (smd->type == DETECT_PCRE) {
        SCLogDebug("inspecting pcre");
        DetectPcreData *pe = (DetectPcreData *)smd->ctx;
        uint32_t prev_buffer_offset = det_ctx->buffer_offset;
        uint32_t prev_offset = 0;
        int r = 0;

        det_ctx->pcre_match_start_offset = 0;
        do {
            Packet *p = NULL;
            if (inspection_mode == DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD)
                p = (Packet *)data;
            r = DetectPcrePayloadMatch(det_ctx, s, smd, p, f,
                                       buffer, buffer_len);
            if (r == 0) {
                goto no_match;
            }

            if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
                SCLogDebug("no relative match coming up, so this is a match");
                goto match;
            }
            KEYWORD_PROFILING_END(det_ctx, smd->type, 1);

            /* save it, in case we need to do a pcre match once again */
            prev_offset = det_ctx->pcre_match_start_offset;

            /* see if the next payload keywords match. If not, we will
             * search for another occurence of this pcre and see
             * if the others match, until we run out of matches */
            r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd+1,
                    f, buffer, buffer_len, stream_start_offset, inspection_mode, data);
            if (r == 1) {
                SCReturnInt(1);
            }

            if (det_ctx->discontinue_matching)
                goto no_match;

            det_ctx->buffer_offset = prev_buffer_offset;
            det_ctx->pcre_match_start_offset = prev_offset;
        } while (1);

    } else if (smd->type == DETECT_BYTETEST) {
        DetectBytetestData *btd = (DetectBytetestData *)smd->ctx;
        uint8_t flags = btd->flags;
        int32_t offset = btd->offset;
        uint64_t value = btd->value;
        if (flags & DETECT_BYTETEST_OFFSET_BE) {
            offset = det_ctx->bj_values[offset];
        }
        if (flags & DETECT_BYTETEST_VALUE_BE) {
            value = det_ctx->bj_values[value];
        }

        /* if we have dce enabled we will have to use the endianness
         * specified by the dce header */
        if (flags & DETECT_BYTETEST_DCE && data != NULL) {
            DCERPCState *dcerpc_state = (DCERPCState *)data;
            /* enable the endianness flag temporarily.  once we are done
             * processing we reset the flags to the original value*/
            flags |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] & 0x10) ?
                      DETECT_BYTETEST_LITTLE: 0);
        }

        if (DetectBytetestDoMatch(det_ctx, s, smd->ctx, buffer, buffer_len, flags,
                                  offset, value) != 1) {
            goto no_match;
        }

        goto match;

    } else if (smd->type == DETECT_BYTEJUMP) {
        DetectBytejumpData *bjd = (DetectBytejumpData *)smd->ctx;
        uint8_t flags = bjd->flags;
        int32_t offset = bjd->offset;

        if (flags & DETECT_BYTEJUMP_OFFSET_BE) {
            offset = det_ctx->bj_values[offset];
        }

        /* if we have dce enabled we will have to use the endianness
         * specified by the dce header */
        if (flags & DETECT_BYTEJUMP_DCE && data != NULL) {
            DCERPCState *dcerpc_state = (DCERPCState *)data;
            /* enable the endianness flag temporarily.  once we are done
             * processing we reset the flags to the original value*/
            flags |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] & 0x10) ?
                      DETECT_BYTEJUMP_LITTLE: 0);
        }

        if (DetectBytejumpDoMatch(det_ctx, s, smd->ctx, buffer, buffer_len,
                                  flags, offset) != 1) {
            goto no_match;
        }

        goto match;

    } else if (smd->type == DETECT_BYTE_EXTRACT) {

        DetectByteExtractData *bed = (DetectByteExtractData *)smd->ctx;
        uint8_t endian = bed->endian;

        /* if we have dce enabled we will have to use the endianness
         * specified by the dce header */
        if ((bed->flags & DETECT_BYTE_EXTRACT_FLAG_ENDIAN) &&
            endian == DETECT_BYTE_EXTRACT_ENDIAN_DCE && data != NULL) {

            DCERPCState *dcerpc_state = (DCERPCState *)data;
            /* enable the endianness flag temporarily.  once we are done
             * processing we reset the flags to the original value*/
            endian |= ((dcerpc_state->dcerpc.dcerpchdr.packed_drep[0] == 0x10) ?
                       DETECT_BYTE_EXTRACT_ENDIAN_LITTLE : DETECT_BYTE_EXTRACT_ENDIAN_BIG);
        }

        if (DetectByteExtractDoMatch(det_ctx, smd, s, buffer,
                                     buffer_len,
                                     &det_ctx->bj_values[bed->local_id],
                                     endian) != 1) {
            goto no_match;
        }

        goto match;

        /* we should never get here, but bail out just in case */
    } else if (smd->type == DETECT_AL_URILEN) {
        SCLogDebug("inspecting uri len");

        int r = 0;
        DetectUrilenData *urilend = (DetectUrilenData *) smd->ctx;

        switch (urilend->mode) {
            case DETECT_URILEN_EQ:
                if (buffer_len == urilend->urilen1)
                    r = 1;
                break;
            case DETECT_URILEN_LT:
                if (buffer_len < urilend->urilen1)
                    r = 1;
                break;
            case DETECT_URILEN_GT:
                if (buffer_len > urilend->urilen1)
                    r = 1;
                break;
            case DETECT_URILEN_RA:
                if (buffer_len > urilend->urilen1 &&
                    buffer_len < urilend->urilen2) {
                    r = 1;
                }
                break;
        }

        if (r == 1) {
            goto match;
        }

        det_ctx->discontinue_matching = 0;

        goto no_match;
#ifdef HAVE_LUA
    }
    else if (smd->type == DETECT_LUA) {
        SCLogDebug("lua starting");

        if (DetectLuaMatchBuffer(det_ctx, s, smd, buffer, buffer_len,
                    det_ctx->buffer_offset, f) != 1)
        {
            SCLogDebug("lua no_match");
            goto no_match;
        }
        SCLogDebug("lua match");
        goto match;
#endif /* HAVE_LUA */
    } else if (smd->type == DETECT_BASE64_DECODE) {
        if (DetectBase64DecodeDoMatch(det_ctx, s, smd, buffer, buffer_len)) {
            if (s->sm_arrays[DETECT_SM_LIST_BASE64_DATA] != NULL) {
                KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
                if (DetectBase64DataDoMatch(de_ctx, det_ctx, s, f)) {
                    /* Base64 is a terminal list. */
                    goto final_match;
                }
            }
        }
    } else {
        SCLogDebug("sm->type %u", smd->type);
#ifdef DEBUG
        BUG_ON(1);
#endif
    }

no_match:
    KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
    SCReturnInt(0);

match:
    /* this sigmatch matched, inspect the next one. If it was the last,
     * the buffer portion of the signature matched. */
    if (!smd->is_last) {
        KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
        int r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd+1,
                f, buffer, buffer_len, stream_start_offset, inspection_mode, data);
        SCReturnInt(r);
    }
final_match:
    KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
    SCReturnInt(1);
}


static void test_bmdma_no_busmaster(void) { QPCIDevice *dev; void *bmdma_base, *ide_base; uint8_t status; dev = get_pci_device(&bmdma_base, &ide_base); /* No PRDT_EOT, each entry addr 0/size 64k, and in theory qemu shouldn't be * able to access it anyway because the Bus Master bit in the PCI command * register isn't set. This is complete nonsense, but it used to be pretty * good at confusing and occasionally crashing qemu. */ PrdtEntry prdt[4096] = { }; status = send_dma_request(CMD_READ_DMA | CMDF_NO_BM, 0, 512, prdt, ARRAY_SIZE(prdt), NULL); /* Not entirely clear what the expected result is, but this is what we get * in practice. At least we want to be aware of any changes. */ g_assert_cmphex(status, ==, BM_STS_ACTIVE | BM_STS_INTR); assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); }


static SplinePointList * EraseStroke ( SplineChar * sc , SplinePointList * head , SplinePointList * erase ) {
 SplineSet * spl , * last ;
 SplinePoint * sp ;
 if ( head == NULL ) {
 SplinePointListsFree ( erase ) ;
 return ( NULL ) ;
 }
 last = NULL ;
 for ( spl = head ;
 spl != NULL ;
 spl = spl -> next ) {
 for ( sp = spl -> first ;
 sp != NULL ;
 ) {
 sp -> selected = false ;
 if ( sp -> next == NULL ) break ;
 sp = sp -> next -> to ;
 if ( sp == spl -> first ) break ;
 }
 last = spl ;
 }
 for ( spl = erase ;
 spl != NULL ;
 spl = spl -> next ) {
 for ( sp = spl -> first ;
 sp != NULL ;
 ) {
 sp -> selected = true ;
 if ( sp -> next == NULL ) break ;
 sp = sp -> next -> to ;
 if ( sp == spl -> first ) break ;
 }
 }
 last -> next = erase ;
 return ( SplineSetRemoveOverlap ( sc , head , over_exclude ) ) ;
 }


static void qed_check_for_leaks(QEDCheck *check) { BDRVQEDState *s = check->s; size_t i; for (i = s->header.header_size; i < check->nclusters; i++) { if (!qed_test_bit(check->used_clusters, i)) { check->result->leaks++; } } }


xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) {
    int ret = -1;
    xmlDocPtr import = NULL;
    xmlChar *base = NULL;
    xmlChar *uriRef = NULL;
    xmlChar *URI = NULL;
    xsltStylesheetPtr res;
    xsltSecurityPrefsPtr sec;

    if ((cur == NULL) || (style == NULL))
	return (ret);

    uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL);
    if (uriRef == NULL) {
	xsltTransformError(NULL, style, cur,
	    "xsl:import : missing href attribute\n");
	goto error;
    }

    base = xmlNodeGetBase(style->doc, cur);
    URI = xmlBuildURI(uriRef, base);
    if (URI == NULL) {
	xsltTransformError(NULL, style, cur,
	    "xsl:import : invalid URI reference %s\n", uriRef);
	goto error;
    }

    res = style;
    while (res != NULL) {
        if (res->doc == NULL)
	    break;
	if (xmlStrEqual(res->doc->URL, URI)) {
	    xsltTransformError(NULL, style, cur,
	       "xsl:import : recursion detected on imported URL %s\n", URI);
	    goto error;
	}
	res = res->parent;
    }

    /*
     * Security framework check
     */
    sec = xsltGetDefaultSecurityPrefs();
    if (sec != NULL) {
	int secres;

	secres = xsltCheckRead(sec, NULL, URI);
	if (secres == 0) {
	    xsltTransformError(NULL, NULL, NULL,
		 "xsl:import: read rights for %s denied\n",
			     URI);
	    goto error;
	}
    }

    import = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
                                  (void *) style, XSLT_LOAD_STYLESHEET);
    if (import == NULL) {
	xsltTransformError(NULL, style, cur,
	    "xsl:import : unable to load %s\n", URI);
	goto error;
    }

    res = xsltParseStylesheetImportedDoc(import, style);
    if (res != NULL) {
	res->next = style->imports;
	style->imports = res;
	if (style->parent == NULL) {
	    xsltFixImportedCompSteps(style, res);
	}
	ret = 0;
    } else {
	xmlFreeDoc(import);
	}

error:
    if (uriRef != NULL)
	xmlFree(uriRef);
    if (base != NULL)
	xmlFree(base);
    if (URI != NULL)
	xmlFree(URI);

    return (ret);
}


char *spapr_get_cpu_core_type(const char *model) { char *core_type; gchar **model_pieces = g_strsplit(model, ",", 2); core_type = g_strdup_printf("%s-%s", model_pieces[0], TYPE_SPAPR_CPU_CORE); g_strfreev(model_pieces); /* Check whether it exists or whether we have to look up an alias name */ if (!object_class_by_name(core_type)) { const char *realmodel; g_free(core_type); realmodel = ppc_cpu_lookup_alias(model); if (realmodel) { return spapr_get_cpu_core_type(realmodel); } return NULL; } return core_type; }


static const char * name ## _get_name ( void * ctx ) \ {
 return # name ;
 \ }
 static const AVClass name ## _class = {
 . class_name = # name , . item_name = name ## _get_name , . option = name ## _options \ }
 typedef struct DefaultContext {
 const AVClass * class ;
 int nokey ;
 int noprint_wrappers ;
 int nested_section [ SECTION_MAX_NB_LEVELS ] ;
 }
 DefaultContext ;
 # undef OFFSET # define OFFSET ( x ) offsetof ( DefaultContext , x ) static const AVOption default_options [ ] = {
 {
 "noprint_wrappers" , "do not print headers and footers" , OFFSET ( noprint_wrappers ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 "nw" , "do not print headers and footers" , OFFSET ( noprint_wrappers ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 "nokey" , "force no key printing" , OFFSET ( nokey ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 "nk" , "force no key printing" , OFFSET ( nokey ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 NULL }
 , }
 ;
 DEFINE_WRITER_CLASS ( default ) ;
 static inline char * upcase_string ( char * dst , size_t dst_size , const char * src ) {
 int i ;
 for ( i = 0 ;
 src [ i ] && i < dst_size - 1 ;
 i ++ ) dst [ i ] = av_toupper ( src [ i ] ) ;
 dst [ i ] = 0 ;
 return dst ;
 }
 static void default_print_section_header ( WriterContext * wctx ) {
 DefaultContext * def = wctx -> priv ;
 char buf [ 32 ] ;
 const struct section * section = wctx -> section [ wctx -> level ] ;
 const struct section * parent_section = wctx -> level ? wctx -> section [ wctx -> level - 1 ] : NULL ;
 av_bprint_clear ( & wctx -> section_pbuf [ wctx -> level ] ) ;
 if ( parent_section && ! ( parent_section -> flags & ( SECTION_FLAG_IS_WRAPPER | SECTION_FLAG_IS_ARRAY ) ) ) {
 def -> nested_section [ wctx -> level ] = 1 ;
 av_bprintf ( & wctx -> section_pbuf [ wctx -> level ] , "%s%s:" , wctx -> section_pbuf [ wctx -> level - 1 ] . str , upcase_string ( buf , sizeof ( buf ) , av_x_if_null ( section -> element_name , section -> name ) ) ) ;
 }
 if ( def -> noprint_wrappers || def -> nested_section [ wctx -> level ] ) return ;
 if ( ! ( section -> flags & ( SECTION_FLAG_IS_WRAPPER | SECTION_FLAG_IS_ARRAY ) ) ) printf ( "[%s]\n" , upcase_string ( buf , sizeof ( buf ) , section -> name ) ) ;
 }
 static void default_print_section_footer ( WriterContext * wctx ) {
 DefaultContext * def = wctx -> priv ;
 const struct section * section = wctx -> section [ wctx -> level ] ;
 char buf [ 32 ] ;
 if ( def -> noprint_wrappers || def -> nested_section [ wctx -> level ] ) return ;
 if ( ! ( section -> flags & ( SECTION_FLAG_IS_WRAPPER | SECTION_FLAG_IS_ARRAY ) ) ) printf ( "[/%s]\n" , upcase_string ( buf , sizeof ( buf ) , section -> name ) ) ;
 }
 static void default_print_str ( WriterContext * wctx , const char * key , const char * value ) {
 DefaultContext * def = wctx -> priv ;
 if ( ! def -> nokey ) printf ( "%s%s=" , wctx -> section_pbuf [ wctx -> level ] . str , key ) ;
 printf ( "%s\n" , value ) ;
 }
 static void default_print_int ( WriterContext * wctx , const char * key , long long int value ) {
 DefaultContext * def = wctx -> priv ;
 if ( ! def -> nokey ) printf ( "%s%s=" , wctx -> section_pbuf [ wctx -> level ] . str , key ) ;
 printf ( "%lld\n" , value ) ;
 }
 static const Writer default_writer = {
 . name = "default" , . priv_size = sizeof ( DefaultContext ) , . print_section_header = default_print_section_header , . print_section_footer = default_print_section_footer , . print_integer = default_print_int , . print_string = default_print_str , . flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS , . priv_class = & default_class , }
 ;
 static const char * c_escape_str ( AVBPrint * dst , const char * src , const char sep , void * log_ctx ) {
 const char * p ;
 for ( p = src ;
 * p ;
 p ++ ) {
 switch ( * p ) {
 case '\b' : av_bprintf ( dst , "%s" , "\\b" ) ;
 break ;
 case '\f' : av_bprintf ( dst , "%s" , "\\f" ) ;
 break ;
 case '\n' : av_bprintf ( dst , "%s" , "\\n" ) ;
 break ;
 case '\r' : av_bprintf ( dst , "%s" , "\\r" ) ;
 break ;
 case '\\' : av_bprintf ( dst , "%s" , "\\\\" ) ;
 break ;
 default : if ( * p == sep ) av_bprint_chars ( dst , '\\' , 1 ) ;
 av_bprint_chars ( dst , * p , 1 ) ;
 }
 }
 return dst -> str ;
 }
 static const char * csv_escape_str ( AVBPrint * dst , const char * src , const char sep , void * log_ctx ) {
 char meta_chars [ ] = {
 sep , '"' , '\n' , '\r' , '\0' }
 ;
 int needs_quoting = ! ! src [ strcspn ( src , meta_chars ) ] ;
 if ( needs_quoting ) av_bprint_chars ( dst , '"' , 1 ) ;
 for ( ;
 * src ;
 src ++ ) {
 if ( * src == '"' ) av_bprint_chars ( dst , '"' , 1 ) ;
 av_bprint_chars ( dst , * src , 1 ) ;
 }
 if ( needs_quoting ) av_bprint_chars ( dst , '"' , 1 ) ;
 return dst -> str ;
 }
 static const char * none_escape_str ( AVBPrint * dst , const char * src , const char sep , void * log_ctx ) {
 return src ;
 }
 typedef struct CompactContext {
 const AVClass * class ;
 char * item_sep_str ;
 char item_sep ;
 int nokey ;
 int print_section ;
 char * escape_mode_str ;
 const char * ( * escape_str ) ( AVBPrint * dst , const char * src , const char sep , void * log_ctx ) ;
 int nested_section [ SECTION_MAX_NB_LEVELS ] ;
 int has_nested_elems [ SECTION_MAX_NB_LEVELS ] ;
 int terminate_line [ SECTION_MAX_NB_LEVELS ] ;
 }
 CompactContext ;
 # undef OFFSET # define OFFSET ( x ) offsetof ( CompactContext , x ) static const AVOption compact_options [ ] = {
 {
 "item_sep" , "set item separator" , OFFSET ( item_sep_str ) , AV_OPT_TYPE_STRING , {
 . str = "|" }
 , CHAR_MIN , CHAR_MAX }
 , {
 "s" , "set item separator" , OFFSET ( item_sep_str ) , AV_OPT_TYPE_STRING , {
 . str = "|" }
 , CHAR_MIN , CHAR_MAX }
 , {
 "nokey" , "force no key printing" , OFFSET ( nokey ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 "nk" , "force no key printing" , OFFSET ( nokey ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 "escape" , "set escape mode" , OFFSET ( escape_mode_str ) , AV_OPT_TYPE_STRING , {
 . str = "c" }
 , CHAR_MIN , CHAR_MAX }
 , {
 "e" , "set escape mode" , OFFSET ( escape_mode_str ) , AV_OPT_TYPE_STRING , {
 . str = "c" }
 , CHAR_MIN , CHAR_MAX }
 , {
 "print_section" , "print section name" , OFFSET ( print_section ) , AV_OPT_TYPE_BOOL , {
 . i64 = 1 }
 , 0 , 1 }
 , {
 "p" , "print section name" , OFFSET ( print_section ) , AV_OPT_TYPE_BOOL , {
 . i64 = 1 }
 , 0 , 1 }
 , {
 NULL }
 , }
 ;
 DEFINE_WRITER_CLASS ( compact ) ;
 static av_cold int compact_init ( WriterContext * wctx ) {
 CompactContext * compact = wctx -> priv ;
 if ( strlen ( compact -> item_sep_str ) != 1 ) {
 av_log ( wctx , AV_LOG_ERROR , "Item separator '%s' specified, but must contain a single character\n" , compact -> item_sep_str ) ;
 return AVERROR ( EINVAL ) ;
 }
 compact -> item_sep = compact -> item_sep_str [ 0 ] ;
 if ( ! strcmp ( compact -> escape_mode_str , "none" ) ) compact -> escape_str = none_escape_str ;
 else if ( ! strcmp ( compact -> escape_mode_str , "c" ) ) compact -> escape_str = c_escape_str ;
 else if ( ! strcmp ( compact -> escape_mode_str , "csv" ) ) compact -> escape_str = csv_escape_str ;
 else {
 av_log ( wctx , AV_LOG_ERROR , "Unknown escape mode '%s'\n" , compact -> escape_mode_str ) ;
 return AVERROR ( EINVAL ) ;
 }
 return 0 ;
 }
 static void compact_print_section_header ( WriterContext * wctx ) {
 CompactContext * compact = wctx -> priv ;
 const struct section * section = wctx -> section [ wctx -> level ] ;
 const struct section * parent_section = wctx -> level ? wctx -> section [ wctx -> level - 1 ] : NULL ;
 compact -> terminate_line [ wctx -> level ] = 1 ;
 compact -> has_nested_elems [ wctx -> level ] = 0 ;
 av_bprint_clear ( & wctx -> section_pbuf [ wctx -> level ] ) ;
 if ( ! ( section -> flags & SECTION_FLAG_IS_ARRAY ) && parent_section && ! ( parent_section -> flags & ( SECTION_FLAG_IS_WRAPPER | SECTION_FLAG_IS_ARRAY ) ) ) {
 compact -> nested_section [ wctx -> level ] = 1 ;
 compact -> has_nested_elems [ wctx -> level - 1 ] = 1 ;
 av_bprintf ( & wctx -> section_pbuf [ wctx -> level ] , "%s%s:" , wctx -> section_pbuf [ wctx -> level - 1 ] . str , ( char * ) av_x_if_null ( section -> element_name , section -> name ) ) ;
 wctx -> nb_item [ wctx -> level ] = wctx -> nb_item [ wctx -> level - 1 ] ;
 }
 else {
 if ( parent_section && compact -> has_nested_elems [ wctx -> level - 1 ] && ( section -> flags & SECTION_FLAG_IS_ARRAY ) ) {
 compact -> terminate_line [ wctx -> level - 1 ] = 0 ;
 printf ( "\n" ) ;
 }
 if ( compact -> print_section && ! ( section -> flags & ( SECTION_FLAG_IS_WRAPPER | SECTION_FLAG_IS_ARRAY ) ) ) printf ( "%s%c" , section -> name , compact -> item_sep ) ;
 }
 }
 static void compact_print_section_footer ( WriterContext * wctx ) {
 CompactContext * compact = wctx -> priv ;
 if ( ! compact -> nested_section [ wctx -> level ] && compact -> terminate_line [ wctx -> level ] && ! ( wctx -> section [ wctx -> level ] -> flags & ( SECTION_FLAG_IS_WRAPPER | SECTION_FLAG_IS_ARRAY ) ) ) printf ( "\n" ) ;
 }
 static void compact_print_str ( WriterContext * wctx , const char * key , const char * value ) {
 CompactContext * compact = wctx -> priv ;
 AVBPrint buf ;
 if ( wctx -> nb_item [ wctx -> level ] ) printf ( "%c" , compact -> item_sep ) ;
 if ( ! compact -> nokey ) printf ( "%s%s=" , wctx -> section_pbuf [ wctx -> level ] . str , key ) ;
 av_bprint_init ( & buf , 1 , AV_BPRINT_SIZE_UNLIMITED ) ;
 printf ( "%s" , compact -> escape_str ( & buf , value , compact -> item_sep , wctx ) ) ;
 av_bprint_finalize ( & buf , NULL ) ;
 }
 static void compact_print_int ( WriterContext * wctx , const char * key , long long int value ) {
 CompactContext * compact = wctx -> priv ;
 if ( wctx -> nb_item [ wctx -> level ] ) printf ( "%c" , compact -> item_sep ) ;
 if ( ! compact -> nokey ) printf ( "%s%s=" , wctx -> section_pbuf [ wctx -> level ] . str , key ) ;
 printf ( "%lld" , value ) ;
 }
 static const Writer compact_writer = {
 . name = "compact" , . priv_size = sizeof ( CompactContext ) , . init = compact_init , . print_section_header = compact_print_section_header , . print_section_footer = compact_print_section_footer , . print_integer = compact_print_int , . print_string = compact_print_str , . flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS , . priv_class = & compact_class , }
 ;
 # undef OFFSET # define OFFSET ( x ) offsetof ( CompactContext , x ) static const AVOption csv_options [ ] = {
 {
 "item_sep" , "set item separator" , OFFSET ( item_sep_str ) , AV_OPT_TYPE_STRING , {
 . str = "," }
 , CHAR_MIN , CHAR_MAX }
 , {
 "s" , "set item separator" , OFFSET ( item_sep_str ) , AV_OPT_TYPE_STRING , {
 . str = "," }
 , CHAR_MIN , CHAR_MAX }
 , {
 "nokey" , "force no key printing" , OFFSET ( nokey ) , AV_OPT_TYPE_BOOL , {
 . i64 = 1 }
 , 0 , 1 }
 , {
 "nk" , "force no key printing" , OFFSET ( nokey ) , AV_OPT_TYPE_BOOL , {
 . i64 = 1 }
 , 0 , 1 }
 , {
 "escape" , "set escape mode" , OFFSET ( escape_mode_str ) , AV_OPT_TYPE_STRING , {
 . str = "csv" }
 , CHAR_MIN , CHAR_MAX }
 , {
 "e" , "set escape mode" , OFFSET ( escape_mode_str ) , AV_OPT_TYPE_STRING , {
 . str = "csv" }
 , CHAR_MIN , CHAR_MAX }
 , {
 "print_section" , "print section name" , OFFSET ( print_section ) , AV_OPT_TYPE_BOOL , {
 . i64 = 1 }
 , 0 , 1 }
 , {
 "p" , "print section name" , OFFSET ( print_section ) , AV_OPT_TYPE_BOOL , {
 . i64 = 1 }
 , 0 , 1 }
 , {
 NULL }
 , }
 ;
 DEFINE_WRITER_CLASS ( csv ) ;
 static const Writer csv_writer = {
 . name = "csv" , . priv_size = sizeof ( CompactContext ) , . init = compact_init , . print_section_header = compact_print_section_header , . print_section_footer = compact_print_section_footer , . print_integer = compact_print_int , . print_string = compact_print_str , . flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS , . priv_class = & csv_class , }
 ;
 typedef struct FlatContext {
 const AVClass * class ;
 const char * sep_str ;
 char sep ;
 int hierarchical ;
 }
 FlatContext ;
 # undef OFFSET # define OFFSET ( x ) offsetof ( FlatContext , x ) static const AVOption flat_options [ ] = {
 {
 "sep_char" , "set separator" , OFFSET ( sep_str ) , AV_OPT_TYPE_STRING , {
 . str = "." }
 , CHAR_MIN , CHAR_MAX }
 , {
 "s" , "set separator" , OFFSET ( sep_str ) , AV_OPT_TYPE_STRING , {
 . str = "." }
 , CHAR_MIN , CHAR_MAX }
 , {
 "hierarchical" , "specify if the section specification should be hierarchical" , OFFSET ( hierarchical ) , AV_OPT_TYPE_BOOL , {
 . i64 = 1 }
 , 0 , 1 }
 , {
 "h" , "specify if the section specification should be hierarchical" , OFFSET ( hierarchical ) , AV_OPT_TYPE_BOOL , {
 . i64 = 1 }
 , 0 , 1 }
 , {
 NULL }
 , }
 ;
 DEFINE_WRITER_CLASS ( flat ) ;
 static av_cold int flat_init ( WriterContext * wctx ) {
 FlatContext * flat = wctx -> priv ;
 if ( strlen ( flat -> sep_str ) != 1 ) {
 av_log ( wctx , AV_LOG_ERROR , "Item separator '%s' specified, but must contain a single character\n" , flat -> sep_str ) ;
 return AVERROR ( EINVAL ) ;
 }
 flat -> sep = flat -> sep_str [ 0 ] ;
 return 0 ;
 }
 static const char * flat_escape_key_str ( AVBPrint * dst , const char * src , const char sep ) {
 const char * p ;
 for ( p = src ;
 * p ;
 p ++ ) {
 if ( ! ( ( * p >= '0' && * p <= '9' ) || ( * p >= 'a' && * p <= 'z' ) || ( * p >= 'A' && * p <= 'Z' ) ) ) av_bprint_chars ( dst , '_' , 1 ) ;
 else av_bprint_chars ( dst , * p , 1 ) ;
 }
 return dst -> str ;
 }
 static const char * flat_escape_value_str ( AVBPrint * dst , const char * src ) {
 const char * p ;
 for ( p = src ;
 * p ;
 p ++ ) {
 switch ( * p ) {
 case '\n' : av_bprintf ( dst , "%s" , "\\n" ) ;
 break ;
 case '\r' : av_bprintf ( dst , "%s" , "\\r" ) ;
 break ;
 case '\\' : av_bprintf ( dst , "%s" , "\\\\" ) ;
 break ;
 case '"' : av_bprintf ( dst , "%s" , "\\\"" ) ;
 break ;
 case '`' : av_bprintf ( dst , "%s" , "\\`" ) ;
 break ;
 case '$' : av_bprintf ( dst , "%s" , "\\$" ) ;
 break ;
 default : av_bprint_chars ( dst , * p , 1 ) ;
 break ;
 }
 }
 return dst -> str ;
 }
 static void flat_print_section_header ( WriterContext * wctx ) {
 FlatContext * flat = wctx -> priv ;
 AVBPrint * buf = & wctx -> section_pbuf [ wctx -> level ] ;
 const struct section * section = wctx -> section [ wctx -> level ] ;
 const struct section * parent_section = wctx -> level ? wctx -> section [ wctx -> level - 1 ] : NULL ;
 av_bprint_clear ( buf ) ;
 if ( ! parent_section ) return ;
 av_bprintf ( buf , "%s" , wctx -> section_pbuf [ wctx -> level - 1 ] . str ) ;
 if ( flat -> hierarchical || ! ( section -> flags & ( SECTION_FLAG_IS_ARRAY | SECTION_FLAG_IS_WRAPPER ) ) ) {
 av_bprintf ( buf , "%s%s" , wctx -> section [ wctx -> level ] -> name , flat -> sep_str ) ;
 if ( parent_section -> flags & SECTION_FLAG_IS_ARRAY ) {
 int n = parent_section -> id == SECTION_ID_PACKETS_AND_FRAMES ? wctx -> nb_section_packet_frame : wctx -> nb_item [ wctx -> level - 1 ] ;
 av_bprintf ( buf , "%d%s" , n , flat -> sep_str ) ;
 }
 }
 }
 static void flat_print_int ( WriterContext * wctx , const char * key , long long int value ) {
 printf ( "%s%s=%lld\n" , wctx -> section_pbuf [ wctx -> level ] . str , key , value ) ;
 }
 static void flat_print_str ( WriterContext * wctx , const char * key , const char * value ) {
 FlatContext * flat = wctx -> priv ;
 AVBPrint buf ;
 printf ( "%s" , wctx -> section_pbuf [ wctx -> level ] . str ) ;
 av_bprint_init ( & buf , 1 , AV_BPRINT_SIZE_UNLIMITED ) ;
 printf ( "%s=" , flat_escape_key_str ( & buf , key , flat -> sep ) ) ;
 av_bprint_clear ( & buf ) ;
 printf ( "\"%s\"\n" , flat_escape_value_str ( & buf , value ) ) ;
 av_bprint_finalize ( & buf , NULL ) ;
 }
 static const Writer flat_writer = {
 . name = "flat" , . priv_size = sizeof ( FlatContext ) , . init = flat_init , . print_section_header = flat_print_section_header , . print_integer = flat_print_int , . print_string = flat_print_str , . flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS | WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER , . priv_class = & flat_class , }
 ;
 typedef struct INIContext {
 const AVClass * class ;
 int hierarchical ;
 }
 INIContext ;
 # undef OFFSET # define OFFSET ( x ) offsetof ( INIContext , x ) static const AVOption ini_options [ ] = {
 {
 "hierarchical" , "specify if the section specification should be hierarchical" , OFFSET ( hierarchical ) , AV_OPT_TYPE_BOOL , {
 . i64 = 1 }
 , 0 , 1 }
 , {
 "h" , "specify if the section specification should be hierarchical" , OFFSET ( hierarchical ) , AV_OPT_TYPE_BOOL , {
 . i64 = 1 }
 , 0 , 1 }
 , {
 NULL }
 , }
 ;
 DEFINE_WRITER_CLASS ( ini ) ;
 static char * ini_escape_str ( AVBPrint * dst , const char * src ) {
 int i = 0 ;
 char c = 0 ;
 while ( c = src [ i ++ ] ) {
 switch ( c ) {
 case '\b' : av_bprintf ( dst , "%s" , "\\b" ) ;
 break ;
 case '\f' : av_bprintf ( dst , "%s" , "\\f" ) ;
 break ;
 case '\n' : av_bprintf ( dst , "%s" , "\\n" ) ;
 break ;
 case '\r' : av_bprintf ( dst , "%s" , "\\r" ) ;
 break ;
 case '\t' : av_bprintf ( dst , "%s" , "\\t" ) ;
 break ;
 case '\\' : case '#' : case '=' : case ':' : av_bprint_chars ( dst , '\\' , 1 ) ;
 default : if ( ( unsigned char ) c < 32 ) av_bprintf ( dst , "\\x00%02x" , c & 0xff ) ;
 else av_bprint_chars ( dst , c , 1 ) ;
 break ;
 }
 }
 return dst -> str ;
 }
 static void ini_print_section_header ( WriterContext * wctx ) {
 INIContext * ini = wctx -> priv ;
 AVBPrint * buf = & wctx -> section_pbuf [ wctx -> level ] ;
 const struct section * section = wctx -> section [ wctx -> level ] ;
 const struct section * parent_section = wctx -> level ? wctx -> section [ wctx -> level - 1 ] : NULL ;
 av_bprint_clear ( buf ) ;
 if ( ! parent_section ) {
 printf ( "# ffprobe output\n\n" ) ;
 return ;
 }
 if ( wctx -> nb_item [ wctx -> level - 1 ] ) printf ( "\n" ) ;
 av_bprintf ( buf , "%s" , wctx -> section_pbuf [ wctx -> level - 1 ] . str ) ;
 if ( ini -> hierarchical || ! ( section -> flags & ( SECTION_FLAG_IS_ARRAY | SECTION_FLAG_IS_WRAPPER ) ) ) {
 av_bprintf ( buf , "%s%s" , buf -> str [ 0 ] ? "." : "" , wctx -> section [ wctx -> level ] -> name ) ;
 if ( parent_section -> flags & SECTION_FLAG_IS_ARRAY ) {
 int n = parent_section -> id == SECTION_ID_PACKETS_AND_FRAMES ? wctx -> nb_section_packet_frame : wctx -> nb_item [ wctx -> level - 1 ] ;
 av_bprintf ( buf , ".%d" , n ) ;
 }
 }
 if ( ! ( section -> flags & ( SECTION_FLAG_IS_ARRAY | SECTION_FLAG_IS_WRAPPER ) ) ) printf ( "[%s]\n" , buf -> str ) ;
 }
 static void ini_print_str ( WriterContext * wctx , const char * key , const char * value ) {
 AVBPrint buf ;
 av_bprint_init ( & buf , 1 , AV_BPRINT_SIZE_UNLIMITED ) ;
 printf ( "%s=" , ini_escape_str ( & buf , key ) ) ;
 av_bprint_clear ( & buf ) ;
 printf ( "%s\n" , ini_escape_str ( & buf , value ) ) ;
 av_bprint_finalize ( & buf , NULL ) ;
 }
 static void ini_print_int ( WriterContext * wctx , const char * key , long long int value ) {
 printf ( "%s=%lld\n" , key , value ) ;
 }
 static const Writer ini_writer = {
 . name = "ini" , . priv_size = sizeof ( INIContext ) , . print_section_header = ini_print_section_header , . print_integer = ini_print_int , . print_string = ini_print_str , . flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS | WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER , . priv_class = & ini_class , }
 ;
 typedef struct JSONContext {
 const AVClass * class ;
 int indent_level ;
 int compact ;
 const char * item_sep , * item_start_end ;
 }
 JSONContext ;
 # undef OFFSET # define OFFSET ( x ) offsetof ( JSONContext , x ) static const AVOption json_options [ ] = {
 {
 "compact" , "enable compact output" , OFFSET ( compact ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 "c" , "enable compact output" , OFFSET ( compact ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 NULL }
 }
 ;
 DEFINE_WRITER_CLASS ( json ) ;
 static av_cold int json_init ( WriterContext * wctx ) {
 JSONContext * json = wctx -> priv ;
 json -> item_sep = json -> compact ? ", " : ",\n" ;
 json -> item_start_end = json -> compact ? " " : "\n" ;
 return 0 ;
 }
 static const char * json_escape_str ( AVBPrint * dst , const char * src , void * log_ctx ) {
 static const char json_escape [ ] = {
 '"' , '\\' , '\b' , '\f' , '\n' , '\r' , '\t' , 0 }
 ;
 static const char json_subst [ ] = {
 '"' , '\\' , 'b' , 'f' , 'n' , 'r' , 't' , 0 }
 ;
 const char * p ;
 for ( p = src ;
 * p ;
 p ++ ) {
 char * s = strchr ( json_escape , * p ) ;
 if ( s ) {
 av_bprint_chars ( dst , '\\' , 1 ) ;
 av_bprint_chars ( dst , json_subst [ s - json_escape ] , 1 ) ;
 }
 else if ( ( unsigned char ) * p < 32 ) {
 av_bprintf ( dst , "\\u00%02x" , * p & 0xff ) ;
 }
 else {
 av_bprint_chars ( dst , * p , 1 ) ;
 }
 }
 return dst -> str ;
 }
 # define JSON_INDENT ( ) printf ( "%*c" , json -> indent_level * 4 , ' ' ) static void json_print_section_header ( WriterContext * wctx ) {
 JSONContext * json = wctx -> priv ;
 AVBPrint buf ;
 const struct section * section = wctx -> section [ wctx -> level ] ;
 const struct section * parent_section = wctx -> level ? wctx -> section [ wctx -> level - 1 ] : NULL ;
 if ( wctx -> level && wctx -> nb_item [ wctx -> level - 1 ] ) printf ( ",\n" ) ;
 if ( section -> flags & SECTION_FLAG_IS_WRAPPER ) {
 printf ( "{
\n" ) ;
 json -> indent_level ++ ;
 }
 else {
 av_bprint_init ( & buf , 1 , AV_BPRINT_SIZE_UNLIMITED ) ;
 json_escape_str ( & buf , section -> name , wctx ) ;
 JSON_INDENT ( ) ;
 json -> indent_level ++ ;
 if ( section -> flags & SECTION_FLAG_IS_ARRAY ) {
 printf ( "\"%s\": [\n" , buf . str ) ;
 }
 else if ( parent_section && ! ( parent_section -> flags & SECTION_FLAG_IS_ARRAY ) ) {
 printf ( "\"%s\": {
%s" , buf . str , json -> item_start_end ) ;
 }
 else {
 printf ( "{
%s" , json -> item_start_end ) ;
 if ( parent_section && parent_section -> id == SECTION_ID_PACKETS_AND_FRAMES ) {
 if ( ! json -> compact ) JSON_INDENT ( ) ;
 printf ( "\"type\": \"%s\"%s" , section -> name , json -> item_sep ) ;
 }
 }
 av_bprint_finalize ( & buf , NULL ) ;
 }
 }
 static void json_print_section_footer ( WriterContext * wctx ) {
 JSONContext * json = wctx -> priv ;
 const struct section * section = wctx -> section [ wctx -> level ] ;
 if ( wctx -> level == 0 ) {
 json -> indent_level -- ;
 printf ( "\n}
\n" ) ;
 }
 else if ( section -> flags & SECTION_FLAG_IS_ARRAY ) {
 printf ( "\n" ) ;
 json -> indent_level -- ;
 JSON_INDENT ( ) ;
 printf ( "]" ) ;
 }
 else {
 printf ( "%s" , json -> item_start_end ) ;
 json -> indent_level -- ;
 if ( ! json -> compact ) JSON_INDENT ( ) ;
 printf ( "}
" ) ;
 }
 }
 static inline void json_print_item_str ( WriterContext * wctx , const char * key , const char * value ) {
 AVBPrint buf ;
 av_bprint_init ( & buf , 1 , AV_BPRINT_SIZE_UNLIMITED ) ;
 printf ( "\"%s\":" , json_escape_str ( & buf , key , wctx ) ) ;
 av_bprint_clear ( & buf ) ;
 printf ( " \"%s\"" , json_escape_str ( & buf , value , wctx ) ) ;
 av_bprint_finalize ( & buf , NULL ) ;
 }
 static void json_print_str ( WriterContext * wctx , const char * key , const char * value ) {
 JSONContext * json = wctx -> priv ;
 if ( wctx -> nb_item [ wctx -> level ] ) printf ( "%s" , json -> item_sep ) ;
 if ( ! json -> compact ) JSON_INDENT ( ) ;
 json_print_item_str ( wctx , key , value ) ;
 }
 static void json_print_int ( WriterContext * wctx , const char * key , long long int value ) {
 JSONContext * json = wctx -> priv ;
 AVBPrint buf ;
 if ( wctx -> nb_item [ wctx -> level ] ) printf ( "%s" , json -> item_sep ) ;
 if ( ! json -> compact ) JSON_INDENT ( ) ;
 av_bprint_init ( & buf , 1 , AV_BPRINT_SIZE_UNLIMITED ) ;
 printf ( "\"%s\": %lld" , json_escape_str ( & buf , key , wctx ) , value ) ;
 av_bprint_finalize ( & buf , NULL ) ;
 }
 static const Writer json_writer = {
 . name = "json" , . priv_size = sizeof ( JSONContext ) , . init = json_init , . print_section_header = json_print_section_header , . print_section_footer = json_print_section_footer , . print_integer = json_print_int , . print_string = json_print_str , . flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER , . priv_class = & json_class , }
 ;
 typedef struct XMLContext {
 const AVClass * class ;
 int within_tag ;
 int indent_level ;
 int fully_qualified ;
 int xsd_strict ;
 }
 XMLContext ;
 # undef OFFSET # define OFFSET ( x ) offsetof ( XMLContext , x ) static const AVOption xml_options [ ] = {
 {
 "fully_qualified" , "specify if the output should be fully qualified" , OFFSET ( fully_qualified ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 "q" , "specify if the output should be fully qualified" , OFFSET ( fully_qualified ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 "xsd_strict" , "ensure that the output is XSD compliant" , OFFSET ( xsd_strict ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 "x" , "ensure that the output is XSD compliant" , OFFSET ( xsd_strict ) , AV_OPT_TYPE_BOOL , {
 . i64 = 0 }
 , 0 , 1 }
 , {
 NULL }
 , }
 ;
 DEFINE_WRITER_CLASS ( xml )


static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) { RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; int size, i, err; char *content; char url[1024]; /* read the whole sdp file */ /* XXX: better loading */ content = av_malloc(SDP_MAX_SIZE); size = get_buffer(s->pb, content, SDP_MAX_SIZE - 1); if (size <= 0) { av_free(content); return AVERROR_INVALIDDATA; } content[size] ='\0'; sdp_parse(s, content); av_free(content); /* open each RTP stream */ for(i=0;i<rt->nb_rtsp_streams;i++) { rtsp_st = rt->rtsp_streams[i]; snprintf(url, sizeof(url), "rtp://%s:%d?localport=%d&ttl=%d", inet_ntoa(rtsp_st->sdp_ip), rtsp_st->sdp_port, rtsp_st->sdp_port, rtsp_st->sdp_ttl); if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { err = AVERROR_INVALIDDATA; goto fail; } if ((err = rtsp_open_transport_ctx(s, rtsp_st))) goto fail; } return 0; fail: rtsp_close_streams(rt); return err; }


static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value) { M48t59State *NVRAM = opaque; m48t59_write(NVRAM, addr, (value >> 24) & 0xff); m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff); m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff); m48t59_write(NVRAM, addr + 3, value & 0xff); }


TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
{
	TIFFDirectory *td = &tif->tif_dir;
	char *sep;
	long l, n;

#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
	fprintf(fd, "TIFF Directory at offset 0x%I64x (%I64u)\n",
		(unsigned __int64) tif->tif_diroff,
		(unsigned __int64) tif->tif_diroff);
#else
	fprintf(fd, "TIFF Directory at offset 0x%llx (%llu)\n",
		(unsigned long long) tif->tif_diroff,
		(unsigned long long) tif->tif_diroff);
#endif
	if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) {
		fprintf(fd, "  Subfile Type:");
		sep = " ";
		if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) {
			fprintf(fd, "%sreduced-resolution image", sep);
			sep = "/";
		}
		if (td->td_subfiletype & FILETYPE_PAGE) {
			fprintf(fd, "%smulti-page document", sep);
			sep = "/";
		}
		if (td->td_subfiletype & FILETYPE_MASK)
			fprintf(fd, "%stransparency mask", sep);
		fprintf(fd, " (%lu = 0x%lx)\n",
		    (unsigned long) td->td_subfiletype, (long) td->td_subfiletype);
	}
	if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) {
		fprintf(fd, "  Image Width: %lu Image Length: %lu",
		    (unsigned long) td->td_imagewidth, (unsigned long) td->td_imagelength);
		if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH))
			fprintf(fd, " Image Depth: %lu",
			    (unsigned long) td->td_imagedepth);
		fprintf(fd, "\n");
	}
	if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) {
		fprintf(fd, "  Tile Width: %lu Tile Length: %lu",
		    (unsigned long) td->td_tilewidth, (unsigned long) td->td_tilelength);
		if (TIFFFieldSet(tif,FIELD_TILEDEPTH))
			fprintf(fd, " Tile Depth: %lu",
			    (unsigned long) td->td_tiledepth);
		fprintf(fd, "\n");
	}
	if (TIFFFieldSet(tif,FIELD_RESOLUTION)) {
		fprintf(fd, "  Resolution: %g, %g",
		    td->td_xresolution, td->td_yresolution);
		if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) {
			switch (td->td_resolutionunit) {
			case RESUNIT_NONE:
				fprintf(fd, " (unitless)");
				break;
			case RESUNIT_INCH:
				fprintf(fd, " pixels/inch");
				break;
			case RESUNIT_CENTIMETER:
				fprintf(fd, " pixels/cm");
				break;
			default:
				fprintf(fd, " (unit %u = 0x%x)",
				    td->td_resolutionunit,
				    td->td_resolutionunit);
				break;
			}
		}
		fprintf(fd, "\n");
	}
	if (TIFFFieldSet(tif,FIELD_POSITION))
		fprintf(fd, "  Position: %g, %g\n",
		    td->td_xposition, td->td_yposition);
	if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE))
		fprintf(fd, "  Bits/Sample: %u\n", td->td_bitspersample);
	if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) {
		fprintf(fd, "  Sample Format: ");
		switch (td->td_sampleformat) {
		case SAMPLEFORMAT_VOID:
			fprintf(fd, "void\n");
			break;
		case SAMPLEFORMAT_INT:
			fprintf(fd, "signed integer\n");
			break;
		case SAMPLEFORMAT_UINT:
			fprintf(fd, "unsigned integer\n");
			break;
		case SAMPLEFORMAT_IEEEFP:
			fprintf(fd, "IEEE floating point\n");
			break;
		case SAMPLEFORMAT_COMPLEXINT:
			fprintf(fd, "complex signed integer\n");
			break;
		case SAMPLEFORMAT_COMPLEXIEEEFP:
			fprintf(fd, "complex IEEE floating point\n");
			break;
		default:
			fprintf(fd, "%u (0x%x)\n",
			    td->td_sampleformat, td->td_sampleformat);
			break;
		}
	}
	if (TIFFFieldSet(tif,FIELD_COMPRESSION)) {
		const TIFFCodec* c = TIFFFindCODEC(td->td_compression);
		fprintf(fd, "  Compression Scheme: ");
		if (c)
			fprintf(fd, "%s\n", c->name);
		else
			fprintf(fd, "%u (0x%x)\n",
			    td->td_compression, td->td_compression);
	}
	if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) {
		fprintf(fd, "  Photometric Interpretation: ");
		if (td->td_photometric < NPHOTONAMES)
			fprintf(fd, "%s\n", photoNames[td->td_photometric]);
		else {
			switch (td->td_photometric) {
			case PHOTOMETRIC_LOGL:
				fprintf(fd, "CIE Log2(L)\n");
				break;
			case PHOTOMETRIC_LOGLUV:
				fprintf(fd, "CIE Log2(L) (u',v')\n");
				break;
			default:
				fprintf(fd, "%u (0x%x)\n",
				    td->td_photometric, td->td_photometric);
				break;
			}
		}
	}
	if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) {
		uint16 i;
		fprintf(fd, "  Extra Samples: %u<", td->td_extrasamples);
		sep = "";
		for (i = 0; i < td->td_extrasamples; i++) {
			switch (td->td_sampleinfo[i]) {
			case EXTRASAMPLE_UNSPECIFIED:
				fprintf(fd, "%sunspecified", sep);
				break;
			case EXTRASAMPLE_ASSOCALPHA:
				fprintf(fd, "%sassoc-alpha", sep);
				break;
			case EXTRASAMPLE_UNASSALPHA:
				fprintf(fd, "%sunassoc-alpha", sep);
				break;
			default:
				fprintf(fd, "%s%u (0x%x)", sep,
				    td->td_sampleinfo[i], td->td_sampleinfo[i]);
				break;
			}
			sep = ", ";
		}
		fprintf(fd, ">\n");
	}
	if (TIFFFieldSet(tif,FIELD_INKNAMES)) {
		char* cp;
		uint16 i;
		fprintf(fd, "  Ink Names: ");
		i = td->td_samplesperpixel;
		sep = "";
		for (cp = td->td_inknames;
		     i > 0 && cp < td->td_inknames + td->td_inknameslen;
		     cp = strchr(cp,'\0')+1, i--) {
			size_t max_chars =
				td->td_inknameslen - (cp - td->td_inknames);
			fputs(sep, fd);
			_TIFFprintAsciiBounded(fd, cp, max_chars);
			sep = ", ";
		}
                fputs("\n", fd);
	}
	if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) {
		fprintf(fd, "  Thresholding: ");
		switch (td->td_threshholding) {
		case THRESHHOLD_BILEVEL:
			fprintf(fd, "bilevel art scan\n");
			break;
		case THRESHHOLD_HALFTONE:
			fprintf(fd, "halftone or dithered scan\n");
			break;
		case THRESHHOLD_ERRORDIFFUSE:
			fprintf(fd, "error diffused\n");
			break;
		default:
			fprintf(fd, "%u (0x%x)\n",
			    td->td_threshholding, td->td_threshholding);
			break;
		}
	}
	if (TIFFFieldSet(tif,FIELD_FILLORDER)) {
		fprintf(fd, "  FillOrder: ");
		switch (td->td_fillorder) {
		case FILLORDER_MSB2LSB:
			fprintf(fd, "msb-to-lsb\n");
			break;
		case FILLORDER_LSB2MSB:
			fprintf(fd, "lsb-to-msb\n");
			break;
		default:
			fprintf(fd, "%u (0x%x)\n",
			    td->td_fillorder, td->td_fillorder);
			break;
		}
	}
	if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING))
        {
		fprintf(fd, "  YCbCr Subsampling: %u, %u\n",
			td->td_ycbcrsubsampling[0], td->td_ycbcrsubsampling[1] );
	}
	if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) {
		fprintf(fd, "  YCbCr Positioning: ");
		switch (td->td_ycbcrpositioning) {
		case YCBCRPOSITION_CENTERED:
			fprintf(fd, "centered\n");
			break;
		case YCBCRPOSITION_COSITED:
			fprintf(fd, "cosited\n");
			break;
		default:
			fprintf(fd, "%u (0x%x)\n",
			    td->td_ycbcrpositioning, td->td_ycbcrpositioning);
			break;
		}
	}
	if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS))
		fprintf(fd, "  Halftone Hints: light %u dark %u\n",
		    td->td_halftonehints[0], td->td_halftonehints[1]);
	if (TIFFFieldSet(tif,FIELD_ORIENTATION)) {
		fprintf(fd, "  Orientation: ");
		if (td->td_orientation < NORIENTNAMES)
			fprintf(fd, "%s\n", orientNames[td->td_orientation]);
		else
			fprintf(fd, "%u (0x%x)\n",
			    td->td_orientation, td->td_orientation);
	}
	if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL))
		fprintf(fd, "  Samples/Pixel: %u\n", td->td_samplesperpixel);
	if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) {
		fprintf(fd, "  Rows/Strip: ");
		if (td->td_rowsperstrip == (uint32) -1)
			fprintf(fd, "(infinite)\n");
		else
			fprintf(fd, "%lu\n", (unsigned long) td->td_rowsperstrip);
	}
	if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE))
		fprintf(fd, "  Min Sample Value: %u\n", td->td_minsamplevalue);
	if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE))
		fprintf(fd, "  Max Sample Value: %u\n", td->td_maxsamplevalue);
	if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) {
		int i;
		int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1;
		fprintf(fd, "  SMin Sample Value:");
		for (i = 0; i < count; ++i)
			fprintf(fd, " %g", td->td_sminsamplevalue[i]);
		fprintf(fd, "\n");
	}
	if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) {
		int i;
		int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1;
		fprintf(fd, "  SMax Sample Value:");
		for (i = 0; i < count; ++i)
			fprintf(fd, " %g", td->td_smaxsamplevalue[i]);
		fprintf(fd, "\n");
	}
	if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) {
		fprintf(fd, "  Planar Configuration: ");
		switch (td->td_planarconfig) {
		case PLANARCONFIG_CONTIG:
			fprintf(fd, "single image plane\n");
			break;
		case PLANARCONFIG_SEPARATE:
			fprintf(fd, "separate image planes\n");
			break;
		default:
			fprintf(fd, "%u (0x%x)\n",
			    td->td_planarconfig, td->td_planarconfig);
			break;
		}
	}
	if (TIFFFieldSet(tif,FIELD_PAGENUMBER))
		fprintf(fd, "  Page Number: %u-%u\n",
		    td->td_pagenumber[0], td->td_pagenumber[1]);
	if (TIFFFieldSet(tif,FIELD_COLORMAP)) {
		fprintf(fd, "  Color Map: ");
		if (flags & TIFFPRINT_COLORMAP) {
			fprintf(fd, "\n");
			n = 1L<<td->td_bitspersample;
			for (l = 0; l < n; l++)
				fprintf(fd, "   %5ld: %5u %5u %5u\n",
				    l,
				    td->td_colormap[0][l],
				    td->td_colormap[1][l],
				    td->td_colormap[2][l]);
		} else
			fprintf(fd, "(present)\n");
	}
	if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) {
		int i;
		fprintf(fd, "  Reference Black/White:\n");
		for (i = 0; i < 3; i++)
		fprintf(fd, "    %2d: %5g %5g\n", i,
			td->td_refblackwhite[2*i+0],
			td->td_refblackwhite[2*i+1]);
	}
	if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) {
		fprintf(fd, "  Transfer Function: ");
		if (flags & TIFFPRINT_CURVES) {
			fprintf(fd, "\n");
			n = 1L<<td->td_bitspersample;
			for (l = 0; l < n; l++) {
				uint16 i;
				fprintf(fd, "    %2ld: %5u",
				    l, td->td_transferfunction[0][l]);
				for (i = 1; i < td->td_samplesperpixel; i++)
					fprintf(fd, " %5u",
					    td->td_transferfunction[i][l]);
				fputc('\n', fd);
			}
		} else
			fprintf(fd, "(present)\n");
	}
	if (TIFFFieldSet(tif, FIELD_SUBIFD) && (td->td_subifd)) {
		uint16 i;
		fprintf(fd, "  SubIFD Offsets:");
		for (i = 0; i < td->td_nsubifd; i++)
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
			fprintf(fd, " %5I64u",
				(unsigned __int64) td->td_subifd[i]);
#else
			fprintf(fd, " %5llu",
				(unsigned long long) td->td_subifd[i]);
#endif
		fputc('\n', fd);
	}

	/*
	** Custom tag support.
	*/
	{
		int  i;
		short count;

		count = (short) TIFFGetTagListCount(tif);
		for(i = 0; i < count; i++) {
			uint32 tag = TIFFGetTagListEntry(tif, i);
			const TIFFField *fip;
			uint32 value_count;
			int mem_alloc = 0;
			void *raw_data;

			fip = TIFFFieldWithTag(tif, tag);
			if(fip == NULL)
				continue;

			if(fip->field_passcount) {
				if (fip->field_readcount == TIFF_VARIABLE2 ) {
					if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1)
						continue;
				} else if (fip->field_readcount == TIFF_VARIABLE ) {
					uint16 small_value_count;
					if(TIFFGetField(tif, tag, &small_value_count, &raw_data) != 1)
						continue;
					value_count = small_value_count;
				} else {
					assert (fip->field_readcount == TIFF_VARIABLE
						|| fip->field_readcount == TIFF_VARIABLE2);
					continue;
				}
			} else {
				if (fip->field_readcount == TIFF_VARIABLE
				    || fip->field_readcount == TIFF_VARIABLE2)
					value_count = 1;
				else if (fip->field_readcount == TIFF_SPP)
					value_count = td->td_samplesperpixel;
				else
					value_count = fip->field_readcount;
				if (fip->field_tag == TIFFTAG_DOTRANGE
				    && strcmp(fip->field_name,"DotRange") == 0) {
					/* TODO: This is an evil exception and should not have been
					   handled this way ... likely best if we move it into
					   the directory structure with an explicit field in
					   libtiff 4.1 and assign it a FIELD_ value */
					static uint16 dotrange[2];
					raw_data = dotrange;
					TIFFGetField(tif, tag, dotrange+0, dotrange+1);
				} else if (fip->field_type == TIFF_ASCII
					   || fip->field_readcount == TIFF_VARIABLE
					   || fip->field_readcount == TIFF_VARIABLE2
					   || fip->field_readcount == TIFF_SPP
					   || value_count > 1) {
					if(TIFFGetField(tif, tag, &raw_data) != 1)
						continue;
				} else {
					raw_data = _TIFFmalloc(
					    _TIFFDataSize(fip->field_type)
					    * value_count);
					mem_alloc = 1;
					if(TIFFGetField(tif, tag, raw_data) != 1) {
						_TIFFfree(raw_data);
						continue;
					}
				}
			}

			/*
			 * Catch the tags which needs to be specially handled
			 * and pretty print them. If tag not handled in
			 * _TIFFPrettyPrintField() fall down and print it as
			 * any other tag.
			 */
			if (!_TIFFPrettyPrintField(tif, fip, fd, tag, value_count, raw_data))
				_TIFFPrintField(fd, fip, value_count, raw_data);

			if(mem_alloc)
				_TIFFfree(raw_data);
		}
	}

	if (tif->tif_tagmethods.printdir)
		(*tif->tif_tagmethods.printdir)(tif, fd, flags);

        _TIFFFillStriles( tif );

	if ((flags & TIFFPRINT_STRIPS) &&
	    TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) {
		uint32 s;

		fprintf(fd, "  %lu %s:\n",
		    (unsigned long) td->td_nstrips,
		    isTiled(tif) ? "Tiles" : "Strips");
		for (s = 0; s < td->td_nstrips; s++)
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
			fprintf(fd, "    %3lu: [%8I64u, %8I64u]\n",
			    (unsigned long) s,
			    (unsigned __int64) td->td_stripoffset[s],
			    (unsigned __int64) td->td_stripbytecount[s]);
#else
			fprintf(fd, "    %3lu: [%8llu, %8llu]\n",
			    (unsigned long) s,
			    (unsigned long long) td->td_stripoffset[s],
			    (unsigned long long) td->td_stripbytecount[s]);
#endif
	}
}