Ejemplo n.º 1
0
Bool core_swstart_run(core_init_t initialisers[], size_t n_init,
                      SWSTART *params)
{
  size_t i ;

  HQASSERT(core_init_state == CORE_DOING_SWSTART,
           "Running SwStart initialisers when not in SwStart()") ;

  HQTRACE(trace_initialisers, ("Doing starters ..."));
  for (i = 0 ; i < n_init ; ++i, ++core_init_error ) {
    if ( initialisers[i].fns.swstart ) {
      HQTRACE(trace_initialisers, ("Starting: %s", initialisers[i].name));
      if ( force_module_fail(initialisers[i].name, FAIL_PHASE_START) ||
           !(*initialisers[i].fns.swstart)(params) ) {
        HQTRACE(trace_initialisers, ("... failed"));
        /* A previous phase may have successfully initialised modules after
           this one in the list, so run all of the finalisers. */
        core_finish_run(initialisers, n_init) ;
        return core_init_failed(initialisers[i].name) ;
      }
      initialisers[i].needs_finish = TRUE ;
    }
  }
  HQTRACE(trace_initialisers, ("... starters finished."));

  return TRUE ;
}
Ejemplo n.º 2
0
Bool core_swinit_run(core_init_t initialisers[], size_t n_init,
                     SWSTART *params)
{
  size_t i ;

  HQASSERT(core_init_state == CORE_DOING_SWINIT,
           "Running SwInit initialisers when not in SwInit()") ;

  HQTRACE(trace_initialisers, ("Doing initialisers ..."));
  for (i = 0 ; i < n_init ; ++i, ++core_init_error ) {
    if ( initialisers[i].fns.swinit ) {
      HQTRACE(trace_initialisers, ("Initializing: %s", initialisers[i].name));
      if ( force_module_fail(initialisers[i].name, FAIL_PHASE_INIT) ||
           !(*initialisers[i].fns.swinit)(params) ) {
        HQTRACE(trace_initialisers, ("... failed"));
        /* In this case we know that no previous phases have run, so we can
           use the current number as the number of finalisers to check. */
        core_finish_run(initialisers, i) ;
        return core_init_failed(initialisers[i].name) ;
      }
      initialisers[i].needs_finish = TRUE ;
    }
  }
  HQTRACE(trace_initialisers, ("... initialisers finished."));

  return TRUE ;
}
Ejemplo n.º 3
0
static int dll_u_feof(const void *context, void *filestream)
{
  DEVICELIST *os ;
  DEVICETYPE *dev ;
  int32 *last_error = (int32 *)context ;
  DEVICE_FILEDESCRIPTOR handle = Dll_PtrToHandle(filestream) ;
  Hq32x2 size ;

  HQTRACE(!swstart_called,
          ("ICU feof() called before SwStart()")) ;

  if ( !os_device(&os, &dev) || handle < 0 ) {
    *last_error = TRUE ;
    return TRUE ;
  }

  if ( (*dev->bytes_file)(os, handle, &size, SW_BYTES_AVAIL_REL) < 0 ) {
    *last_error = ((*dev->last_error)(os) != DeviceNoError) ;
    return TRUE ;
  }

  *last_error = FALSE ;

  return FALSE ;
}
Ejemplo n.º 4
0
static int32 dll_u_fwrite(const void *context, const void *addr,
                          int32 bytes, void *filestream)
{
  DEVICELIST *os ;
  DEVICETYPE *dev ;
  int32 *last_error = (int32 *)context ;
  DEVICE_FILEDESCRIPTOR handle = Dll_PtrToHandle(filestream) ;
  int32 size ;

  HQTRACE(!swstart_called,
          ("ICU fwrite() called before SwStart()")) ;

  if ( !os_device(&os, &dev) || addr == NULL || bytes < 0 || handle < 0 ) {
    *last_error = TRUE ;
    return 0 ;
  }

  if ( (size = (*dev->write_file)(os, handle, (uint8 *)addr, bytes)) < 0 ) {
    *last_error = ((*dev->last_error)(os) != DeviceNoError) ;
    return 0 ;
  }

  *last_error = FALSE ;

  return size ;
}
Ejemplo n.º 5
0
void core_finish_run(core_init_t initialisers[], size_t n_init)
{
  HQTRACE(trace_initialisers, ("Doing finishers ..."));
  /* Call finish functions in reverse order. */
  while ( n_init-- > 0 ) {
    if (initialisers[n_init].needs_finish) {
      if ( initialisers[n_init].fns.finish != NULL ) {
        /* Report module being finished to track crashes. */
        HQTRACE(trace_initialisers, ("Finishing: %s", initialisers[n_init].name));
        (*initialisers[n_init].fns.finish)();
      }
      initialisers[n_init].needs_finish = FALSE ;
    }
  }
  HQTRACE(trace_initialisers, ("... finishers finished."));
}
Ejemplo n.º 6
0
/** Set the region height, limited by MaxBackdropHeight. */
void set_region_size(DL_STATE *page)
{
  int32 band_height = page->band_lines ;
  int32 max_height = page->max_region_height ;

  HQASSERT(max_height >= 0, "Max region height should not be negative") ;

  /** \todo ajcd 2009-12-09: Set the region width. This is taken from the
      transparency surface, if it is found. We default to the original
      backdrop region width if no transparency surface is found, just so
      nothing explodes. If the pagedevice parameter MaxBackdropWidth is set,
      it only applies if the backdrop has a variable width. */
  page->region_width = REGION_WIDTH ;
  if ( page->surfaces != NULL ) {
    const transparency_surface_t *transurf ;
    if ( (transurf = surface_find_transparency(page->surfaces)) != NULL ) {
      HQASSERT(transurf->region_width >= 0,
               "Transparency surface region width should not be negative") ;
      if ( transurf->region_width == 0 ) {
        page->region_width = page->page_w ;
        if ( page->max_region_width > 0 &&
             page->region_width > page->max_region_width )
          page->region_width = page->max_region_width ;
      } else
        page->region_width = transurf->region_width ;
    }
  }

  if ( band_height > max_height && max_height > 0 ) {
    /* If the band height is very large, we try to limit the region size. We
       try to find an exact factor of the band height as close as possible to
       the max region height. This algorithm just uses trial division for
       the factorisation, because we don't expect MaxBackdropHeight to be set
       very large. If there is only one band, then we can select the exact
       max backdrop height we wanted. */
    if ( page->sizedisplaylist > 1 ) {
      while ( max_height > 1 ) {
        if ( band_height % max_height == 0 ) {
          page->region_height = max_height ;
          return ;
        }
        --max_height ;
      }
      /* We've run out of possibilities. Since we can't exceed max_height,
         we'll have to use a region height of 1. This will probably cause
         trouble. */
      HQTRACE(TRUE, ("Setting region height to 1 is likely to be very inefficient"));
    }

    page->region_height = max_height ;
    return ;
  }

  page->region_height = band_height ;
}
Ejemplo n.º 7
0
Bool core_postboot_run(core_init_t initialisers[], size_t n_init)
{
  size_t i ;

  HQTRACE(trace_initialisers, ("Doing postboot ..."));
  for (i = 0 ; i < n_init ; ++i, ++core_init_error ) {
    if ( initialisers[i].fns.postboot ) {
      HQTRACE(trace_initialisers, ("PostBoot: %s", initialisers[i].name));
      if ( force_module_fail(initialisers[i].name, FAIL_PHASE_POSTBOOT) ||
           !(*initialisers[i].fns.postboot)() ) {
        HQTRACE(trace_initialisers, ("... failed"));
        /* A previous phase may have successfully initialised modules after
           this one in the list, so run all of the finalisers. */
        core_finish_run(initialisers, n_init) ;
        return core_init_failed(initialisers[i].name) ;
      }
      initialisers[i].needs_finish = TRUE ;
    }
  }
  HQTRACE(trace_initialisers, ("... postbooters finished."));

  return TRUE ;
}
Ejemplo n.º 8
0
static int dll_u_ferror(const void *context, void *filestream)
{
  DEVICELIST *os ;
  DEVICETYPE *dev ;
  int32 *last_error = (int32 *)context ;
  DEVICE_FILEDESCRIPTOR handle = Dll_PtrToHandle(filestream) ;

  HQTRACE(!swstart_called,
          ("ICU ferror() called before SwStart()")) ;

  if ( !os_device(&os, &dev) || handle < 0 || *last_error )
    return TRUE ;

  return FALSE ;
}
Ejemplo n.º 9
0
static void dll_u_fclose(const void *context, void *filestream)
{
  DEVICELIST *os ;
  DEVICETYPE *dev ;
  int32 *last_error = (int32 *)context ;
  DEVICE_FILEDESCRIPTOR handle = Dll_PtrToHandle(filestream) ;

  HQTRACE(!swstart_called,
          ("ICU fclose() called before SwStart()")) ;

  if ( !os_device(&os, &dev) || handle < 0 ) {
    *last_error = TRUE ;
    return ;
  }

  if ( (*dev->close_file)(os, handle) < 0 ) {
    *last_error = ((*dev->last_error)(os) != DeviceNoError) ;
    return ;
  }

  *last_error = FALSE ;
}
Ejemplo n.º 10
0
static Bool genericFilterLastError( FILELIST *filter )
{
  Bool result = FALSE;
  DEVICELIST *dev;

  HQTRACE( debug_filters , ( "In genericFilterLastError" )) ;

  /* I (JJ) am not totally convinced by this test. It's throwing an error from
   * the device if one hasn't already been thrown by the filter code.
   * Right or wrong, it corresponds to what was there before.
   */
  if ( newerror <= 0 ) {
    dev = theIDeviceList( filter ) ;
    HQASSERT( dev, "Null device in genericFilterLastError" );
    result = device_error_handler( dev ) ;
  }

  if ( isIOpenFile( filter ))
    (void)genericFilterCloseAbort( filter , TRUE ) ;

  return result ;
}
Ejemplo n.º 11
0
static int dll_u_fremove(const void *context, const char *filename)
{
  DEVICELIST *os ;
  DEVICETYPE *dev ;
  int32 *last_error = (int32 *)context ;

  HQTRACE(!swstart_called,
          ("ICU fremove() called before SwStart()")) ;

  if ( !os_device(&os, &dev) || filename == NULL ) {
    *last_error = TRUE ;
    return -1 ;
  }

  if ( (*dev->delete_file)(os, (uint8 *)filename) < 0 ) {
    *last_error = ((*dev->last_error)(os) != DeviceNoError) ;
    return -1 ;
  }

  *last_error = FALSE ;

  return 0 ;
}
Ejemplo n.º 12
0
static Bool genericDecodeBuffer( FILELIST *filter, int32 *ret_bytes )
/* called from fillbuff() */
{
  DEVICELIST *dev;
  uint8      *buff;
  int32      nbytes, len;

  HQTRACE( debug_filters , ( "In genericDecodeBuffer" )) ;

  dev = theIDeviceList( filter );
  HQASSERT(dev, "encountered bad filter");
  buff = theIBuffer( filter );
  len = theIBufferSize( filter );

  nbytes = (*theIReadFile( dev ))( dev, theIDescriptor(filter), buff, len );

  if ( nbytes >= 0 ) {
    *ret_bytes = nbytes ;
    return TRUE;
  }

  return device_error_handler( dev );
}
Ejemplo n.º 13
0
/* Initialise XPS PrintTicket state for the start of a new Job. */
void pt_init(
/*@out@*/ /*@notnull@*/
  XPS_PT*  pt)
{
  device_iterator_t dev_iter;

  HQASSERT((pt != NULL),
           "pt_init: state pointer NULL");

  /* Always start with job scope */
  pt->scope = PT_SCOPE_JOB;

  /* No start file associated with scope yet */
  pt->scope_file = onothing; /* Struct copy to set slot properties */

  /* Find first mounted and enable XPS PT device */
  for ( pt->device = device_first(&dev_iter, DEVICEENABLED|DEVICEWRITABLE|DEVICERELATIVE);
        pt->device != NULL;
        pt->device = device_next(&dev_iter) ) {
    /** \todo TODO Add PT device number as constant when can add swdevice.h */
    if ( theIDevTypeNumber(theIDevType(pt->device)) == XPSPT_DEVICE_TYPE ) {
#ifdef DEBUG_BUILD
      {
        /* Check no other PT devices are enabled! */
        DEVICELIST* dev = device_next(&dev_iter);
        while ( dev != NULL ) {
          HQTRACE(theIDevTypeNumber(theIDevType(dev)) == XPSPT_DEVICE_TYPE,
                  ("Warning: Found another enabled PT device: %s\n", theIDevName(dev)));
          dev = device_next(&dev_iter);
        }
      }
#endif /* DEBUG_BUILD */
      break;
    }
  }

} /* pt_init */
Ejemplo n.º 14
0
static void *dll_u_fopen(const void *context, const char *filename, const char *mode)
{
  DEVICELIST *os ;
  DEVICETYPE *dev ;
  int32 *last_error = (int32 *)context ;
  int32 openflags = 0 ;
  DEVICE_FILEDESCRIPTOR handle ;

  HQTRACE(!swstart_called,
          ("ICU fopen('%s','%s') called before SwStart()", filename, mode)) ;

  if ( !os_device(&os, &dev) || filename == NULL || mode == NULL ) {
    *last_error = TRUE ;
    return NULL ;
  }

  switch ( mode[0] ) {
  case 'r':
    openflags |= SW_RDONLY ;
    break ;
  case 'w':
    openflags |= SW_WRONLY|SW_CREAT|SW_TRUNC ;
    break ;
  default:
    *last_error = TRUE ;
    return NULL ;
  }

  if ( (handle = (*dev->open_file)(os, (uint8 *)filename, openflags)) < 0 ) {
    *last_error = ((*dev->last_error)(os) != DeviceNoError) ;
    return NULL ;
  }

  *last_error = FALSE ;

  return Dll_HandleToPtr(handle) ;
}
Ejemplo n.º 15
0
static void rbt_rightrotate( /*@in@*/ RBT_ROOT *root ,
                             /*@in@*/ RBT_NODE *x )
{
  RBT_NODE *y = x->left ;

  HQASSERT( y != &( root->nil ) , "Left descendent shouldn't be a leaf." ) ;

  HQTRACE( rbt_debug ,
           ( "rbt_rightrotate: [%x] %x , %x" , root , x->key , y->key )) ;

  /* Turn y's right subtree into x's left subtree. */

  x->left = y->right ;
  if ( y->right != &( root->nil ) ) {
    y->right->p = x ;
  }

  /* Link x's parent to y. */

  y->p = x->p ;
  if ( x->p == &( root->nil ) ) {
    root->node = y ;
  }
  else {
    if ( x == x->p->right ) {
      x->p->right = y ;
    }
    else {
      x->p->left = y ;
    }
  }

  /* Put x on y's right. */

  y->right = x ;
  x->p = y ;
}
Ejemplo n.º 16
0
static void dll_u_frewind(const void *context, void *filestream)
{
  DEVICELIST *os ;
  DEVICETYPE *dev ;
  int32 *last_error = (int32 *)context ;
  DEVICE_FILEDESCRIPTOR handle = Dll_PtrToHandle(filestream) ;
  Hq32x2 where ;

  HQTRACE(!swstart_called,
          ("ICU frewind() called before SwStart()")) ;

  if ( !os_device(&os, &dev) || handle < 0 ) {
    *last_error = TRUE ;
    return ;
  }

  Hq32x2FromUint32(&where, 0) ;
  if ( (*dev->seek_file)(os, handle, &where, SW_SET) < 0 ) {
    *last_error = ((*dev->last_error)(os) != DeviceNoError) ;
    return ;
  }

  *last_error = FALSE ;
}
Ejemplo n.º 17
0
static Bool genericFilterInit( FILELIST *filter ,
                               OBJECT *args ,
                               STACK *stack )
{
  DEVICELIST  *dlist;
  uint8       *buff;
  DEVICE_FILEDESCRIPTOR desc;
  int32 flag;
  int32 pop_args = 0 ;

  HQTRACE( debug_filters , ( "In genericFilterInit" )) ;

  dlist = theIDeviceList( filter );
  HQASSERT(dlist, "encountered bad filter");
  theINextDev( dlist ) = ( DEVICELIST *)filter;   /* connect up strs */

  HQASSERT(args != NULL || stack != NULL,
           "Arguments and stack should not both be empty") ;
  if ( ! args && !isEmpty(*stack) ) {
    args = theITop(stack) ;
    if ( oType(*args) == ODICTIONARY )
      pop_args = 1 ;
  }

  if ( args && oType(*args) == ODICTIONARY ) {
    if ( ! oCanRead(*oDict(*args)) &&
         ! object_access_override(oDict(*args)))
      return error_handler(INVALIDACCESS ) ;
    if ( ! FilterCheckArgs( filter , args ))
      return FALSE ;
    OCopy( theIParamDict( filter ), *args ) ;
  } else
    args = NULL ;

  /* Get underlying source/target if we have a stack supplied. */
  if ( stack ) {
    if ( theIStackSize(stack) < pop_args )
      return error_handler(STACKUNDERFLOW) ;

    if ( ! filter_target_or_source(filter, stackindex(pop_args, stack)) )
      return FALSE ;

    ++pop_args ;
  }

  if ( args ) {
    if ( ! walk_dictionary( args, device_set_params, (void *)dlist) )
      return FALSE ;
  }

  /* allocate space for buffer */
  theIBufferSize( filter ) = (*theIGetBuffSize( dlist ))( dlist );
  buff = ( uint8 * )mm_alloc( mm_pool_temp , theIBufferSize( filter ) + 4 ,
                              MM_ALLOC_CLASS_FILTER_BUFFER ) ;
  if ( buff == NULL )
    return error_handler( VMERROR ) ;
  theIBuffer( filter ) = buff + 4 ;
  theIPtr( filter ) = buff + 4 ;
  theICount( filter ) = 0 ;
  theIFilterState( filter ) = FILTER_INIT_STATE ;

  if ( isIInputFile( filter ))
    flag = SW_RDONLY ;
  else                         /* assume isIOutputFile is TRUE */
    flag = SW_WRONLY ;

 /* open a file on the transform device */

  desc = ( * theIOpenFile( dlist ))( dlist , NULL , flag ) ;
  if ( desc < 0 )
    return device_error_handler(dlist);

  theIDescriptor( filter ) = desc ;

  HQASSERT(pop_args == 0 || stack != NULL, "Popping args but no stack") ;
  if ( pop_args > 0 )
    npop(pop_args, stack) ;

  return TRUE ;
}
Ejemplo n.º 18
0
Bool externalfilter_(ps_context_t *pscontext)
{
  OBJECT *o1, *o2 ;
  int32 dev_number, name_length ;
  uint8 *filter_name ;

  UNUSED_PARAM(ps_context_t *, pscontext) ;

  HQTRACE( debug_filters , ( "Welcome to externalfilter" )) ;

  /* externalfilter is always called with two args on the stack, even if
     the second one isn't used */
  if ( theStackSize( operandstack ) < 1 )
    return error_handler( STACKUNDERFLOW ) ;

  o1 = theTop( operandstack ) ;   /* integer code or dictionary */

  switch ( oType(*o1) ) {
  case OINTEGER:
    dev_number = oInteger(*o1);
    break ;
  case ODICTIONARY:
    o2 = stackindex( 1, &operandstack ) ; /* filter name */
    return filter_external_define( o1 , o2 );  /* device to be added */
  default:
    return error_handler(TYPECHECK) ;
  }

  if ( dev_number == -3 ) {            /* resourceforall */
    pop( &operandstack ) ;
    return filter_external_forall(&operandstack);
  }

  o2 = stackindex(1, &operandstack ) ;         /* filter name */

  switch ( oType(*o2) ) {
  case ONAME:
    filter_name = theICList(oName(*o2)) ;
    name_length = theINLen(oName(*o2)) ;
    break ;
  case OSTRING:
    /* undocumented - but they allow strings as an argument */
    filter_name = oString(*o2) ;
    name_length = theLen(*o2) ;
    break ;
  default:
    return error_handler( TYPECHECK ) ;

  }

  switch ( dev_number ) {
  case -2: /* findresource */
    if ( filter_external_exists(filter_name, name_length) ) {
      Copy(o1, &tnewobj) ;
    } else {
      Copy(o1, &fnewobj) ;
    }
    return TRUE ;
  case -1: /* undefineresource */
    npop(2, &operandstack) ;

    return filter_external_undefine(filter_name, name_length);
  }

  return error_handler(RANGECHECK) ;
}
Ejemplo n.º 19
0
static int32 genericFilterCloseAbort( FILELIST * filter, int32 fAbort )
{
  /* close transform file and dismount transform device if no other
     filter of this type is active */

  int32 result = 0 ;
  DEVICELIST *dlist ;
  FILELIST *uflptr ;

  HQASSERT( filter , "filter NULL in genericFilterCloseAbort." ) ;

  HQTRACE( debug_filters , ( "In genericFilterCloseAbort" )) ;

  dlist = theIDeviceList( filter ) ;

  SetIClosingFlag( filter ) ;

  if ( isIOutputFile( filter ))
    result = ( *theIMyFlushFile( filter ))( filter ) ;

  uflptr = theIUnderFile( filter ) ;

  if ( uflptr && isICST( filter ) &&
       isIOpenFileFilterById( theIUnderFilterId( filter ) , uflptr )) {
    /* While this filter may be being closed implicitly, the closing of the
     * source is explicit */
    if (( *theIMyCloseFile( uflptr ))( uflptr, CLOSE_EXPLICIT ) == EOF )
      result = EOF ;
  }

  if ( dlist ) {
    DEVICE_FILEDESCRIPTOR desc = theIDescriptor( filter ) ;

    HQASSERT( theIBuffer( filter ) != NULL , "encountered bad filter" ) ;

    if ( fAbort )
     (void)( *theIAbortFile( dlist ))( dlist , desc ) ;
    else
     (void)( *theICloseFile( dlist ))( dlist , desc ) ;

    (void)closeReadFileProgress( filter ) ;

    /* call to dismount device unconditional */
    (void)( *theIDevDismount( dlist ))( dlist ) ;

    device_free(dlist) ;

    theIDeviceList( filter ) = NULL ;
  }

  if (theIBuffer(filter)) {
    mm_free( mm_pool_temp ,
             ( mm_addr_t )( theIBuffer( filter ) - 4 ) ,
             ( mm_size_t )( theIBufferSize( filter ) + 4 )) ;
    theIBuffer( filter ) = NULL ;
  }

  ClearIClosingFlag( filter ) ;
  SetIEofFlag( filter ) ;
  if ( ! isIRewindable( filter ))
    ClearIOpenFlag( filter ) ;

  return result ;
}
Ejemplo n.º 20
0
RBT_NODE *rbt_remove( RBT_ROOT *root , RBT_NODE *z )
{
  RBT_NODE *x ;
  RBT_NODE *y ;

  if ( z == &( root->nil ) ) {
    return NULL ;
  }

  HQTRACE( rbt_debug ,
           ( "rbt_remove: [%x] %x" , root , z->key )) ;

  if ( z->left == &( root->nil ) || z->right == &( root->nil ) ) {
    y = z ;
  }
  else {
    y = rbt_successor( root , z ) ;
  }

  HQASSERT( y != NULL , "Should rbt_successor return NULL?" ) ;

  if ( y->left != &( root->nil ) ) {
    x = y->left ;
  }
  else {
    x = y->right ;
  }

  x->p = y->p ;

  if ( y->p == &( root->nil ) ) {
    root->node = x ;
  }
  else {
    if ( y == y->p->left ) {
      y->p->left = x ;
    }
    else {
      y->p->right = x ;
    }
  }

  if ( y != z ) {
    uintptr_t tk ;
    void *td ;

    /* The example pseudo-code just copies data and "other fields"
       from y to z. That's not good enough when any one of them is a
       pointer: we end up with one data struct being doubly referenced
       and the other one orphaned. Solution: swap the pointers
       instead. */

    tk = z->key ;
    z->key = y->key ;
    y->key = tk ;

    td = z->data ;
    z->data = y->data ;
    y->data = td ;
  }

  if ( y->red == FALSE ) {
    rbt_remove_fixup( root , x ) ;
  }

  root->count-- ;
  rbt_validate( root , root->node , NULL ) ;

  return y ;
}
Ejemplo n.º 21
0
static void rbt_remove_fixup( RBT_ROOT *root , RBT_NODE *x )
{
  RBT_NODE *w ;

  while ( x != root->node && ! x->red ) {
    HQTRACE( rbt_debug ,
             ( "rbt_remove_fixup: [%x] %x" , root , x->key )) ;

    if ( x == x->p->left ) {
      w = x->p->right ;

      if ( w->red ) {
        w->red = FALSE ;
        x->p->red = TRUE ;
        rbt_leftrotate( root , x->p ) ;
        w = x->p->right ;
      }

      if ( ! w->left->red && ! w->right->red ) {
        w->red = TRUE ;
        x = x->p ;
      }
      else {
        if ( ! w->right->red ) {
          w->left->red = FALSE ;
          w->red = TRUE ;
          rbt_rightrotate( root , w ) ;
          w = x->p->right ;
        }

        w->red = x->p->red ;
        x->p->red = FALSE ;
        w->right->red = FALSE ;
        rbt_leftrotate( root , x->p ) ;
        x = root->node ;
      }
    }
    else {
      w = x->p->left ;

      if ( w->red ) {
        w->red = FALSE ;
        x->p->red = TRUE ;
        rbt_rightrotate( root , x->p ) ;
        w = x->p->left ;
      }

      if ( ! w->right->red && ! w->left->red ) {
        w->red = TRUE ;
        x = x->p ;
      }
      else {
        if ( ! w->left->red ) {
          w->right->red = FALSE ;
          w->red = TRUE ;
          rbt_leftrotate( root , w ) ;
          w = x->p->left ;
        }

        w->red = x->p->red ;
        x->p->red = FALSE ;
        w->left->red = FALSE ;
        rbt_rightrotate( root , x->p ) ;
        x = root->node ;
      }
    }
  }

  x->red = FALSE ;

  HQTRACE( rbt_debug ,
           ( "rbt_remove_fixup complete: [%x] %x" , root , x->key )) ;

  rbt_validate( root , root->node , NULL ) ;
}
Ejemplo n.º 22
0
void rbt_insert( /*@in@*/ RBT_ROOT *root , RBT_NODE *x )
{
  RBT_NODE *y ;

  rbt_validate( root , root->node , NULL ) ;

  HQTRACE( rbt_debug ,
           ( "rbt_insert: [%x] %x" , root , x->key )) ;

  bt_insert( root , x ) ;

  x->red = TRUE ;

  while ( x != root->node && x->p->red ) {
    if ( x->p == x->p->p->left ) {
      y = x->p->p->right ;

      if ( y->red ) {
        x->p->red = FALSE ;
        y->red = FALSE ;
        x->p->p->red = TRUE ;
        x = x->p->p ;
      }
      else {
        if ( x == x->p->right ) {
          x = x->p ;
          rbt_leftrotate( root , x ) ;
        }

        x->p->red = FALSE ;
        x->p->p->red = TRUE ;
        rbt_rightrotate( root , x->p->p ) ;
      }
    }
    else {
      y = x->p->p->left ;

      if ( y->red ) {
        x->p->red = FALSE ;
        y->red = FALSE ;
        x->p->p->red = TRUE ;
        x = x->p->p ;
      }
      else {
        if ( x == x->p->left ) {
          x = x->p ;
          rbt_rightrotate( root , x ) ;
        }

        x->p->red = FALSE ;
        x->p->p->red = TRUE ;
        rbt_leftrotate( root , x->p->p ) ;
      }
    }
  }

  root->node->red = FALSE ;
  root->count++ ;

  rbt_validate( root , root->node , NULL ) ;
}
Ejemplo n.º 23
0
void HqStr__Test(void)
{

#define BUF_SIZE 50
    char abBuf[BUF_SIZE];
    
    /* The following strings end at the embedded null character.  The four 
     * plus-signs that follow the null character should never be read or 
     * copied by HqStrCopy or HqStrCopyTrunc.
     */

#define LARGE_SIZE     40
#define LARGE_MAXLEN   LARGE_SIZE-1
    char *pbzLarge =   "nine-long character sequences 123456789\0++++";
    
#define MEDIUM_SIZE    24
#define MEDIUM_MAXLEN  MEDIUM_SIZE-1
    
#define SMALL_SIZE     5
#define SMALL_MAXLEN   SMALL_SIZE-1
    char *pbzSmall =   "tiny\0++++";

#define EMPTY_SIZE     1
#define EMPTY_MAXLEN   EMPTY_SIZE-1
    char *pbzEmpty =   "\0++++";

    static int HqStr__TestDoDangerous = FALSE;
    
    char *src, *dest;
    int i;
    
#if 1
    /* Copy and Trunc */
    /* ============== */
    
    /* Copy a Large string to a destination just big enough
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    dest = abBuf; src = pbzLarge;
    dest = HqStrCopy(dest, src, LARGE_SIZE);
    HQTRACE( TRUE, ("Copy a Large string to a destination just big enough\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* Copy a Small string to a Large destination, pad with zeroes
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    dest = abBuf; src = pbzSmall;
    dest = HqStrCopy(dest, src, LARGE_SIZE);
    /* this will not have read beyond strlen(src) -- no easy way to check for this though! */
    HQTRACE( TRUE, ("Copy a Small string to a Large destination, pad with zeroes\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* Copy an Empty string to a One-byte destination just big enough
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    dest = abBuf; src = pbzEmpty;
    dest = HqStrCopy(dest, src, EMPTY_SIZE);
    HQTRACE( TRUE, ("Copy an Empty string to a One-byte destination just big enough\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* Copy string to a zero-sized destination (should do nothing)
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    dest = abBuf; src = pbzEmpty;
    dest = HqStrCopy(dest, src, 0);
    HQTRACE( TRUE, ("Copy string to a zero-sized destination (should do nothing)\n" 
                    "no-got! followby(%s) from(%s).", dest+0, src) );
    
    if (HqStr__TestDoDangerous) {
      /* BEWARE: If you 'ignore' the assert on 
       *         this test, memory will be nuked.
       */    
      /* Copy string to a NEGATIVE-SIZED destination
       */
      memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
      dest = abBuf; src = pbzSmall;
      dest = HqStrCopy(dest, src, -1);
      HQTRACE( TRUE, ("Copy string to a NEGATIVE-SIZED destination\n" 
                      "no-got! followby(%s) from(%s).", dest+0, src) );
    }
    
    /* Copy a Large string to a destination that's TOO SMALL
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    dest = abBuf; src = pbzLarge;
    dest = HqStrCopy(dest, src, MEDIUM_SIZE);
    /* Asserts! (but still terminates safely, and doesn't write more than destsize bytes) */
    HQTRACE( TRUE, ("Copy a Large string to a destination that's TOO SMALL\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* CopyTrunc a Large string to a smaller destination
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    dest = abBuf; src = pbzLarge;
    dest = HqStrCopyTrunc(dest, src, MEDIUM_SIZE);
    HQTRACE( TRUE, ("CopyTrunc a Large string to a smaller destination\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
    
    
    /* Copy Overlapping? */
    /* ================= */
    
    /* Copy to an immediately following, but not overlapping, destination
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    memset(abBuf, 'S', SMALL_SIZE-1); abBuf[SMALL_SIZE-1] = 0;
    dest = abBuf+SMALL_SIZE; src = abBuf;
    dest = HqStrCopy(dest, src, SMALL_SIZE);
    HQTRACE( TRUE, ("Copy to an immediately following, but not overlapping, destination\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* Copy to an immediately preceding, but not overlapping, destination
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    memset(abBuf+SMALL_SIZE, 'S', SMALL_SIZE-1); abBuf[SMALL_SIZE+SMALL_SIZE-1] = 0;
    dest = abBuf; src = abBuf+SMALL_SIZE;
    dest = HqStrCopy(dest, src, SMALL_SIZE);
    HQTRACE( TRUE, ("Copy to an immediately preceding, but not overlapping, destination\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* Copy from short string to an immediately following, but not overlapping, longer destination
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    memset(abBuf, 'S', SMALL_SIZE-1); abBuf[SMALL_SIZE-1] = 0;
    dest = abBuf+SMALL_SIZE; src = abBuf;
    dest = HqStrCopy(dest, src, MEDIUM_SIZE);
    HQTRACE( TRUE, ("Copy from short string to an immediately following, but not overlapping, longer destination\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* Copy to an OVERLAPPING following destination
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    memset(abBuf, 'S', SMALL_SIZE-1); abBuf[SMALL_SIZE-1] = 0;
    dest = abBuf+SMALL_SIZE-1; src = abBuf;
    dest = HqStrCopy(dest, src, SMALL_SIZE);
    /* Assert! overlapping! */
    HQTRACE( TRUE, ("Copy to an OVERLAPPING following destination\n" 
                    "got(%s) followby(%s) from-now-corrupt(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* Copy to an OVERLAPPING preceding destination
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    memset(abBuf+SMALL_SIZE, 'S', SMALL_SIZE-1); abBuf[SMALL_SIZE+SMALL_SIZE-1] = 0;
    dest = abBuf+1; src = abBuf+SMALL_SIZE;
    dest = HqStrCopy(dest, src, SMALL_SIZE);
    /* Assert! overlapping! */
    HQTRACE( TRUE, ("Copy to an OVERLAPPING preceding destination\n" 
                    "got(%s) followby(%s) from-now-corrupt(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* TruncCopy small initial portion to a destination that overlaps src string but not the portion being copied
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    memset(abBuf, 'M', MEDIUM_SIZE-1); abBuf[MEDIUM_SIZE-1] = 0;
    dest = abBuf+SMALL_SIZE; src = abBuf;
    dest = HqStrCopyTrunc(dest, src, SMALL_SIZE);
    /* Truncate as requested.  Src gets corrupted, but not our problem. */
    HQTRACE( TRUE, ("TruncCopy small initial portion to a destination that overlaps src string but not the portion being copied\n" 
                    "got(%s) followby(%s) from-now-corrupt(%s).", dest, dest+strlen(dest)+1, src) );
#endif
    
    
#if 1
    /* the check macro */
    /* =============== */
    /* ASSERTCHECK_HqStrBlat confirms that the storage sizes for two 
     * strings match, confirming that HqStrBlat between these strings will 
     * be safe.  If the sizes don't match, it should assert, but only once.
     */
    
    for (i=1; i<=2; i++) {
      ASSERTCHECK_HqStrBlat( BUF_SIZE , MEDIUM_SIZE );
      /* fails! */
      ASSERTCHECK_HqStrBlat( MEDIUM_SIZE , MEDIUM_SIZE+1 );
      /* fails! */
      ASSERTCHECK_HqStrBlat( MEDIUM_SIZE , MEDIUM_SIZE );
      /* okay */
      /* Only assert once -- second pass should be silent */
    }
#endif
    

#if 1
    /* Blat and Blind */
    /* ============== */
    
    /* Blat from a small string to small storage
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    dest = abBuf; src = pbzSmall;
    dest = HqStrBlat(dest, src, SMALL_SIZE);
    HQTRACE( TRUE, ("Blat from a small string to small storage\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* Blat, ILLEGALLY, from a small string to medium storage
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    dest = abBuf; src = pbzSmall;
    dest = HqStrBlat(dest, src, MEDIUM_SIZE);
    /* unsafe! reads beyond strlen(src) */
    HQTRACE( TRUE, ("Blat, ILLEGALLY, from a small string to medium storage\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
    
    /* Blat, ILLEGALLY, from a large string to medium storage
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    dest = abBuf; src = pbzLarge;
    dest = HqStrBlat(dest, src, MEDIUM_SIZE);
    /* unsafe! doesn't terminate copy */
    HQTRACE( TRUE, ("Blat, ILLEGALLY, from a large string to medium storage\n" 
                    "got(%s) from(%s).", dest, src) );
    
    /* CopyBlind from what happens to be a large string into what happens to be sufficient storage
     */
    memset(abBuf, '^', BUF_SIZE-1); abBuf[BUF_SIZE-1] = 0;
    dest = abBuf; src = pbzLarge;
    dest = HqStrCopyBlind(dest, src);
    /* Works, because we 'know' that strlen(pbzLarge)+1 will fit in abBuf's storage */
    HQTRACE( TRUE, ("CopyBlind from what happens to be a large string into what happens to be sufficient storage\n" 
                    "got(%s) followby(%s) from(%s).", dest, dest+strlen(dest)+1, src) );
#endif

#if 0

/* HqStr__Test should produce the following asserts and traces.
 * (Explicit file-and-line has been changed to "<in hqstr.c>")
 */

/*

<in hqstr.c>: Copy a Large string to a destination just big enough
got(nine-long character sequences 123456789) followby(^^^^^^^^^) from(nine-long character sequences 123456789).
<in hqstr.c>: Copy a Small string to a Large destination, pad with zeroes
got(tiny) followby() from(tiny).
<in hqstr.c>: Copy an Empty string to a One-byte destination just big enough
got() followby(^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^) from().
<in hqstr.c>: Copy string to a zero-sized destination (should do nothing)
no-got! followby(^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^) from().
Assert failed <in hqstr.c>: HqStrCopy: string was truncated
<in hqstr.c>: Copy a Large string to a destination that's TOO SMALL
got(nine-long character seq) followby(^^^^^^^^^^^^^^^^^^^^^^^^^) from(nine-long character sequences 123456789).
<in hqstr.c>: CopyTrunc a Large string to a smaller destination
got(nine-long character seq) followby(^^^^^^^^^^^^^^^^^^^^^^^^^) from(nine-long character sequences 123456789).
<in hqstr.c>: Copy to an immediately following, but not overlapping, destination
got(SSSS) followby(^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^) from(SSSS).
<in hqstr.c>: Copy to an immediately preceding, but not overlapping, destination
got(SSSS) followby(SSSS) from(SSSS).
<in hqstr.c>: Copy from short string to an immediately following, but not overlapping, longer destination
got(SSSS) followby() from(SSSS).
Assert failed <in hqstr.c>: HqStrCopy: dest and src must not overlap
Assert failed <in hqstr.c>: HqStrCopy: string was truncated
<in hqstr.c>: Copy to an OVERLAPPING following destination
got(SSSS) followby(^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^) from-now-corrupt(SSSSSSSS).
Assert failed <in hqstr.c>: HqStrCopy: dest and src must not overlap
<in hqstr.c>: Copy to an OVERLAPPING preceding destination
got(SSSS) followby(SSS) from-now-corrupt().
<in hqstr.c>: TruncCopy small initial portion to a destination that overlaps src string but not the portion being copied
got(MMMM) followby(MMMMMMMMMMMMM) from-now-corrupt(MMMMMMMMM).
Assert failed <in hqstr.c>: BUF_SIZE and MEDIUM_SIZE are no longer of equal magnitude; there are calls to HqStrBlat between strings with storage of these sizes, and these calls are now broken; you must use HqStrCopy instead.
Assert failed <in hqstr.c>: MEDIUM_SIZE and MEDIUM_SIZE+1 are no longer of equal magnitude; there are calls to HqStrBlat between strings with storage of these sizes, and these calls are now broken; you must use HqStrCopy instead.
<in hqstr.c>: Blat from a small string to small storage
got(tiny) followby(^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^) from(tiny).
<in hqstr.c>: Blat, ILLEGALLY, from a small string to medium storage
got(tiny) followby(++++) from(tiny).
<in hqstr.c>: Blat, ILLEGALLY, from a large string to medium storage
got(nine-long character sequ^^^^^^^^^^^^^^^^^^^^^^^^^) from(nine-long character sequences 123456789).
<in hqstr.c>: CopyBlind from what happens to be a large string into what happens to be sufficient storage
got(nine-long character sequences 123456789) followby(^^^^^^^^^) from(nine-long character sequences 123456789).

*/

#endif

}
Ejemplo n.º 24
0
/** Implementation for pdf_lookupxref(), with additional support for a stack of
nested objnum's. If the objnum matches an objnum in the stack, it means that
the original object is cyclic and there's no need to continue, and if we did
it'll go infinite. 'idMatch' will be set to TRUE if the objnum matches one in
the stack, otherwise FALSE.

This allows repeated lookups of the same object within a particular context
(such as pdf_resolvexrefs()) to be detected.
*/
static Bool pdf_lookupxref_with_id( PDFCONTEXT *pdfc , OBJECT **rpdfobj ,
                                    int32 objnum , uint16 objgen ,
                                    Bool streamDictOnly ,
                                    Bool* idMatch )
{
  XREFCACHE *xrefcache ;
  XREFCACHE **p_xrefcache ;
  OBJECT *pdfobj ;
  int i;

  GET_PDFXC_AND_IXC;

  HQASSERT( rpdfobj != NULL && idMatch != NULL,
            "pdf_lookupxref_with_id - parameters cannot be null.");
  HQASSERT( objnum >= 0 ,
            "pdf_lookupxref_with_id - object number must not be -ve" ) ;
  HQTRACE( pdftrace_xreflookups , ( "%d %d obj" , objnum , objgen )) ;

  pdfobj = NULL ;
  *rpdfobj = NULL ;
  *idMatch = FALSE ;

  /* Look up pdfobj in cache. */
  for ( p_xrefcache = &pdfxc->xrefcache[ objnum & (XREF_CACHE_SIZE-1) ] ;
        (xrefcache = *p_xrefcache) != NULL ;
        p_xrefcache = &xrefcache->xrefnxt ) {
    if ( xrefcache->objnum == objnum ) {
      if ( xrefcache->streamDict != XREF_StreamDict || streamDictOnly ) {
        /* Move entry to start of list */
        *p_xrefcache = xrefcache->xrefnxt;
        xrefcache->xrefnxt = pdfxc->xrefcache[objnum & (XREF_CACHE_SIZE - 1)];
        pdfxc->xrefcache[objnum & (XREF_CACHE_SIZE - 1)] = xrefcache;

#if defined( DEBUG_BUILD )
        pdfxc->debugtotal_cachehits++ ;
#endif
        HQASSERT( xrefcache->objgen == objgen ,
                  "objgen should be correct in cache" ) ;
        /* Update the last accessing page member to ensure that objects used on
        this page don't get deallocated during a sweep. */
        if ( xrefcache->lastAccessId != pdfxc->pageId &&
             xrefcache->lastAccessId >= 0 ) {
          if ( ! pdf_set_xref_last_access( pdfxc , xrefcache ,
                                           pdfxc->pageId )) {
            return FALSE ;
          }
#if defined( DEBUG_BUILD )
          pdfxc->debugtotal_cachereclaims++ ;
#endif
        }
        else if ( xrefcache->lastAccessId < 0 ) {
          /* Make sure all child objects have the same negative
             lastAccessId as the parent, otherwise we'll end up with
             dangling pointers. */
          if ( ! pdf_set_xref_last_access( pdfxc , xrefcache ,
                                           xrefcache->lastAccessId )) {
            return FALSE ;
          }
        }

        /* Set 'idMatch' if objnum matches one in the stack, i.e. the object
           references are cyclic. */
        HQASSERT( pdfxc->lookup_depth > 0 &&
                  pdfxc->lookup_depth <= PDF_MAX_RECURSION_DEPTH &&
                  pdfxc->nestedObjnum[pdfxc->lookup_depth - 1] == objnum,
                  "Inconsistent nestedObjnum stack") ;
        for ( i = 0; i < pdfxc->lookup_depth - 1; i++ ) {
          if ( pdfxc->nestedObjnum[ i ] == objnum ) {
            HQFAIL("Self-referential PDF object - please tell us");
            *idMatch = TRUE ;
          }
        }

        pdfobj = & xrefcache->pdfobj ;
        /* If object is a stream, then try to rewind it. */
        if ( oType(*pdfobj) == OFILE ) {
          FILELIST *flptr ;

          /* If pdfxc is an input context, flptr will be rewindable; PDF output
             filters are not rewindable. Output and Rewindability are mutually
             exclusive, but we cannot guarantee that either are set; the
             rewindable flag is cleared when a PDF stream is terminated. */
          flptr = oFile( *pdfobj ) ;
          HQASSERT(!isIOutputFile(flptr) || !isIRewindable(flptr),
                   "Output streams should not be rewindable") ;

          if ( !isIOutputFile(flptr) ) {
            Bool rewound = FALSE ;
            if ( !pdf_rewindstream(pdfc, pdfobj, &rewound))
              return FALSE ;
          }
        }

        *rpdfobj = pdfobj ;
        return TRUE ;
      }
      else {
        /* We have the stream dict cached, but now the caller wants
           the whole stream complete with filter chain (or vice versa,
           I suppose, but this was written to speed up HqnPDFChecker
           so the normal pattern is a flurry of calls with
           streamDictOnly set to TRUE during the checking phase
           followed by a bunch with streamDictOnly FALSE during the
           running of the job). Free this cache entry and drop through
           to build a new one. */
        XREFCACHE **ref ;

        for ( ref = & pdfxc->xrefcache[ objnum & (XREF_CACHE_SIZE-1) ] ;
              *ref != xrefcache ;
              ref = & ( *ref )->xrefnxt )
          EMPTY_STATEMENT() ;

        *ref = xrefcache->xrefnxt ;
        pdf_freexrefcache( pdfc , xrefcache ) ;

        /* Since we just freed the cache we found, drop out of the
           loop in order go and re-cache the object. */
        break ;
      }
    }
  }

  /* pdfobj not found in cache; so need to read from disk. */
  {
    FILELIST *flptr, * objfile ;
    OBJECT object = OBJECT_NOTVM_NOTHING ;
    int32 objuse ;
    int8 streamDict = XREF_NotStream ;

    flptr = pdfxc->flptr ;
    HQASSERT( flptr , "flptr is null in pdf_xreflookup" ) ;

    if ( ! pdf_seek_to_xrefobj( pdfc , flptr , objnum , objgen ,
                                & objuse, &objfile ))
      return FALSE ;

    if ( objuse == XREF_Free )
      return TRUE ;

    theGen( object ) = objgen ;
    oXRefID( object ) = objnum ;

    if (objuse == XREF_Uninitialised) {
      OBJECT nullobj = OBJECT_NOTVM_NULL;
      Copy(&object, &nullobj);

    } else {
      PDF_CHECK_METHOD(get_xref_object) ;

      if (objfile == flptr) {
        if ( !(*pdfxc->methods.get_xref_object)(pdfc, flptr, &object,
                                                NULL /* stream info */,
                                                streamDictOnly, &streamDict) )
          return FALSE ;
      } else {
        if ( !(*pdfxc->methods.get_xref_streamobj)(pdfc, objfile, &object) )
          return FALSE ;

        if (( *theIMyCloseFile( objfile ))( objfile, CLOSE_EXPLICIT ) == EOF )
          return FALSE ;
      }

      if ( oType( object ) == ONOTHING )
        return error_handler( UNDEFINEDRESULT ) ;
    }

    xrefcache = pdf_allocxrefcache( pdfc , objnum , objgen ,
                                    & object , streamDict ) ;
    if ( ! xrefcache ) {
      pdf_freeobject( pdfc , & object ) ;
      return error_handler( VMERROR ) ;
    }

    *rpdfobj = & xrefcache->pdfobj ;
  }

  return TRUE ;
}
Ejemplo n.º 25
0
Bool setg(DL_STATE *page, int32 colorType, int32 options)
{
  corecontext_t *context = get_core_context_interp();
  int32 patternid = INVALID_PATTERN_ID, parent_patternid = INVALID_PATTERN_ID ;
  int32 patterntype = -1 ;
  size_t retryFree = 512 * 1024, retryLastFree = 0 ;
  STATEOBJECT newstate, *dlstate ;
  int saved_dl_safe_recursion = dl_safe_recursion;

  if (colorType != GSC_UNDEFINED)
    COLORTYPE_ASSERT(colorType, "setg");

  HQASSERT(colorType != GSC_UNDEFINED ||
           (options & DEVICE_SETG_GROUP) != 0,
           "GSC_UNDEFINED only allowed for groups") ;

  /* Setup a default newstate; spotno may be overriden later. */
  newstate = stateobject_new(page->default_spot_no) ;

  if ( (options & DEVICE_SETG_GROUP) == 0 ) {
    /* Now call any procedures we should call on the first graphics object;
       note that this may potentially change the graphics state, or indeed
       call setg recursively. */
    static Bool fRecursive = FALSE;
    Bool fResult;

    if (! fRecursive) {
      fRecursive = TRUE;
      fResult = runHooks(&thegsDevicePageDict(*gstateptr), GENHOOK_StartPainting);
      fRecursive = FALSE;
      setHookStatus(GENHOOK_StartPainting, FALSE);
      if (! fResult)
        return FALSE;
    }

    if ( theICMYKDetected( workingsave ))
      if ( theICMYKDetect( workingsave ))
        if ( gsc_getcolorspace( gstateptr->colorInfo , colorType ) == SPACE_DeviceGray )
          if ( ! detect_setcmykcolor_separation(gstateptr->colorInfo))
            return FALSE ;

    if ( colorType != GSC_UNDEFINED ) {
      /* Set object's rendering intent. This is overridden for vignettes, and
         ignored for shfills, which give the Background and body
         of the shfill different intents. */
      if ( colorType != GSC_SHFILL &&
           colorType != GSC_SHFILL_INDEXED_BASE &&
           colorType != GSC_VIGNETTE ) {
        uint8 currentReproType;

        /* This is a BIG hack to get the text context right. It can be done
         * properly when the target work arrives.
         */
        if (textContextLevel > 0) {
          currentReproType = REPRO_TYPE_TEXT;
          if (!gsc_setRequiredReproType( gstateptr->colorInfo ,
                                         colorType ,
                                         currentReproType ))
            return FALSE;
        } else
          currentReproType = gsc_getRequiredReproType(gstateptr->colorInfo, colorType);

        DISPOSITION_STORE(dl_currentdisposition, currentReproType, colorType,
                          gstateptr->user_label ? DISPOSITION_FLAG_USER : 0);
      }
    } else /* HDLs have mixed dispositions, no use for USER flag. */
      DISPOSITION_STORE(dl_currentdisposition,
                        REPRO_DISPOSITION_MIXED, colorType, 0);
  } else { /* Groups have mixed dispositions, no use for USER flag. */
    DISPOSITION_STORE(dl_currentdisposition,
                      REPRO_DISPOSITION_MIXED, colorType, 0);
  }

  degenerateClipping = FALSE ;
#ifdef DEBUG_BUILD
  if ( debug_dl_skipsetg() )
    degenerateClipping = TRUE ;
#endif

  /* Here starts the creation of the DL state for this object. Partial paints
     are suppressed during the construction, so that the state is not destroyed,
     but if memory runs out, low-memory handling is performed which may partial
     paint, after which the state is recreated. After the state is created,
     partial paints are prevented until the operator that called DEVICE_SETG()
     is complete. */
  for (;;) {
    STACK_POSITIONS stackPositions;
    Bool errorFound = FALSE;

    ++dl_safe_recursion;
    saveStackPositions(&stackPositions);

    /* Find the appropriate HDL to add object for this device type and ID to */
    page->targetHdl = hdlTarget(page->currentHdl, gstateptr) ;

    if ( ! setup_dl_clipping(page, &newstate.clipstate))
      return FALSE ;

    if ( newstate.clipstate ) {
      cclip_bbox = newstate.clipstate->bounds ;
    } else {
      degenerateClipping = TRUE ;
      cclip_bbox = gstateptr->thePAGEinfo.theclip.bounds ;
    }

    if ( oType(gstateptr->theGSTAGinfo.dict) == ODICTIONARY ) {
      HQASSERT( gstateptr->theGSTAGinfo.data ,
        "Tags dictionary present but there's nowhere to put the data" ) ;
      if ( gstateptr->theGSTAGinfo.structure == NULL )  {
        if ( !make_gstagstructureobject(page, &gstateptr->theGSTAGinfo.dict,
                                        &gstateptr->theGSTAGinfo.structure) ) {
          /* We *could* be out of DL memory, it could be nasty tricks,
           * but one likely explanation is a bug in my code - paulc */
          HQFAIL( "Nasty tricks can cause this but a bug is more likely" ) ;
          return FALSE ;
        }
        if ( gstateptr->theGSTAGinfo.data[0] != gstateptr->theGSTAGinfo.structure->alloc_words ) {
          HQFAIL( "Nasty tricks can cause this but a bug is more likely" ) ;
          /* Get gstate into a consistent state before failing */
          theTags( gstateptr->theGSTAGinfo.dict ) = ONULL | LITERAL ; /* see null_ */
          gstateptr->theGSTAGinfo.structure = NULL ;
          mm_free( mm_pool_temp, gstateptr->theGSTAGinfo.data,
            gstateptr->theGSTAGinfo.data[0] * sizeof(gstateptr->theGSTAGinfo.data[0])) ;
          gstateptr->theGSTAGinfo.data = NULL ;
          return error_handler( CONFIGURATIONERROR ) ;
        }
      }
#if defined( ASSERT_BUILD )
    } else {
      HQASSERT( gstateptr->theGSTAGinfo.structure == NULL,
        "tstructure should have been set to NULL if dict is null." ) ;
#endif
    }

    /* Use a do - while loop as an error catcher */
    errorFound = TRUE;
    do {
      if ( !getTransparencyState(&gstateptr->tranState, page,
                                 colorType == GSC_STROKE,
                                 &newstate.tranAttrib) )
        break;

      if ( colorType != GSC_UNDEFINED ) {
        HQASSERT(!error_signalled_context(context->error),
                 "Should not be invoking colour chains in error condition") ;

        /* When invoking the color chains, some operators may cause the gstate
           to change. Therefore, we must not directly reference the gstate
           variables after this point. Instead, refer to the variables that have
           been nicely cached above here. We won't invoke the colour chain if
           colour is not required for this call (eg via gs_pseudo_erasepage,
           where dlc_currentcolor is already set). */
        if ( !is_pseudo_erasepage() &&
             !gsc_invokeChainSingle(gstateptr->colorInfo, colorType) )
          break;

        /* Get the late color management state - depends on gsc_invokeChainSingle. */
        if ( !getLateColorState(gstateptr, page, colorType,
                                &newstate.lateColorAttrib) )
          break;

        /* Pattern state should not be set up for groups, or the
           render loop will composite the pattern data twice.
           Must be called after gsc_invokeChainSingle.
           NB. This will likely call setg recursively. */
        if ( (options & DEVICE_SETG_GROUP) == 0 &&
             !patterncheck(page, gstateptr, colorType, &patternid,
                           &parent_patternid, &patterntype, newstate.tranAttrib) )
          break;
      }

      if ( !getPclAttrib(page, colorType == GSC_IMAGE,
                         (options & DEVICE_SETG_RETRY) == 0 &&
                         dl_safe_recursion <= 1 &&
                         retryLastFree == 0 /* first time for this object */,
                         &newstate.pclAttrib) )
        break;

      errorFound = FALSE;
    } while (FALSE);    /* End of error catcher */

    /* Retry after VMERROR.  Don't use newerror since it gets
     * cleared if the error was inside a recursive interpreter call
     * (patterncheck calls createPatternDL which calls interpreter)
     */
    if ( errorFound ) {
      if ( error_latest_context(context->error) == VMERROR ) {
        int32     actionNumber = 0 ;
        Bool free_test = FALSE;

        error_clear_context(context->error);
        /* Loop calling handleLowMemory until freed as much as we want or none */
        for (;;) {
          dl_safe_recursion = saved_dl_safe_recursion ;

          HQTRACE( debug_lowmemory,
                   ( "CALL(handleLowMemory): setg with action %d", actionNumber )) ;
          actionNumber = handleLowMemory( actionNumber, TRY_NORMAL_METHODS, NULL ) ;
          if ( actionNumber < 0 )
            return FALSE;
          if ( actionNumber == 0 ) /* Couldn't free up anything more */
            break ;
          free_test = setg_test_free_mem(retryFree, page);
          if ( free_test )
            break;
        }

        /* Retry if we have at least as much free as we tried to free last time */
        if ( retryLastFree != 0 )
          free_test = setg_test_free_mem(retryLastFree, page);
        if ( retryLastFree == 0 || free_test ) {
          retryLastFree = retryFree ;
          retryFree += retryFree ; /* Try to free twice as much next time */

          if ( !restoreStackPositions(&stackPositions, FALSE) )
            return FAILURE(FALSE);  /* stack underflow */
          continue ; /* restart outer loop */
        }
        return error_handler(VMERROR); /* Give up */
      }
      return FALSE; /* Some error has already been raised */
    }

    break ; /* Successful - end outer loop */
  }

  /* Continue preventing partial paints until the end of this operator, unless
     the operator is a group start. This is reset to the previous value by the
     interpreter loop. */
  if ( (options & DEVICE_SETG_GROUP) != 0 )
    dl_safe_recursion = saved_dl_safe_recursion;

  /* Now that we've got the colour, after possible extra loops for error
   * handling, we'll reset the reproType for fill & stroke chains. The other
   * chain types are always initialised prior to use.
   * NB. There is no central point where this can be done at the start of
   * each object.
   */
  if ( colorType != GSC_UNDEFINED ) {
    if (!gsc_resetRequiredReproType(gstateptr->colorInfo, colorType))
      return FALSE;
  }

  if ( patternid != INVALID_PATTERN_ID &&
       (dl_currentspflags(page->dlc_context) & RENDER_PATTERN) != 0 ) {
    Bool overprinting[2] = {FALSE, FALSE};

    HQASSERT(patterntype != -1, "Should have a valid patterntype by now");
    if (context->userparams->PatternOverprintOverride && patterntype == 2) {
      overprinting[GSC_FILL] = gsc_getoverprint(gstateptr->colorInfo, GSC_FILL);
      overprinting[GSC_STROKE] = gsc_getoverprint(gstateptr->colorInfo, GSC_STROKE);
    }

    /* We might have a pattern screen which is actually drawn in black or
       white, in which case it isn't to be treated as a pattern screen at
       all. This should have already been checked in
       updateHTCacheForPatternContone. */
    /** \todo @@@ TODO FIXME ajcd 2002-12-30: We shouldn't really be using
       currentGroup here, because a setgstate may have altered the target
       HDL. However, the group stack doesn't currently recognise this, and
       a pattern group will be opened with currentGroup is its parent, so
       we need to match that. We need to think about using
       groupTop(inputpage->targetHdl) for all currentGroup references, and
       allowing a tree rather than stack structure to the groups. */
    newstate.patternstate = patternObjectLookup(page->stores.pattern,
                                                patternid, parent_patternid,
                                                pageBaseMatrixId,
                                                page->currentGroup,
                                                dlc_currentcolor(page->dlc_context),
                                                overprinting,
                                                newstate.tranAttrib ) ;
    HQASSERT(newstate.patternstate,
             "Pattern found but no corresponding state created") ;
  }

  /* Pattern shapes vary independently of pattern objects; a single pattern
     object may have multiple pattern shapes.  Look at the state from the last
     setg to see if that pattern shape can be continued). */
  if ( !patternshape_lookup(page, page->currentdlstate, &newstate) )
    return FALSE ;

  /* Transparent objects should use the page's default screen, set up in
     newstate above; Override opaque objects to current gstate screen. */
  if ( tsOpaque(gsTranState(gstateptr),
                (colorType == GSC_STROKE ? TsStroke : TsNonStroke),
                gstateptr->colorInfo)
       && (page->currentGroup == NULL
           || !groupMustComposite(page->currentGroup)) )
    newstate.spotno = gsc_getSpotno(gstateptr->colorInfo);

  newstate.gstagstructure = gstateptr->theGSTAGinfo.structure ;

#ifdef METRICS_BUILD
  /* Only update the setg count when we get here; we're only interested in how
  many times we query the state cache. */
  dl_metrics()->store.setgCount++;
#endif

  /* In English:
   * If ( there is no current dlstate set up -OR-
   *      the clip in the gstate ISNT the same as the one in the dlstate -OR-
   *      what we want for the pattern ISNT the same as the dlstate -OR-
   *      the spotno in the gstate ISNT the same as the dlstate -OR-
   *      gs tags in the gstate ISNT the same as the dlstate -OR-
   *      soft mask in the gstate ISNT the same as the dlstate )
   * then make a new dlstate record.
   */
  dlstate = page->currentdlstate ;
  if ( ! dlstate ||
       newstate.clipstate != dlstate->clipstate ||
       newstate.patternstate != dlstate->patternstate ||
       newstate.patternshape != dlstate->patternshape ||
       newstate.spotno != dlstate->spotno ||
       newstate.gstagstructure != dlstate->gstagstructure ||
       newstate.tranAttrib != dlstate->tranAttrib ||
       newstate.lateColorAttrib != dlstate->lateColorAttrib ||
       newstate.pclAttrib != dlstate->pclAttrib ) {

    /* Set new DL state */
    page->currentdlstate =
      (STATEOBJECT*)dlSSInsert( page->stores.state, &newstate.storeEntry, TRUE ) ;
    if ( page->currentdlstate == NULL )
      return FALSE ;
  }

  return TRUE ;
}