Exemplo n.º 1
0
bool
Component::isNumberWithMarker(uint8_t marker) const
{
  return (!empty() && value()[0] == marker &&
          (value_size() == 2 || value_size() == 3 ||
           value_size() == 5 || value_size() == 9));
}
Exemplo n.º 2
0
Block::Block(uint32_t type, const Block& value)
  : m_buffer(value.m_buffer)
  , m_type(type)
  , m_begin(m_buffer->end())
  , m_end(m_buffer->end())
  , m_value_begin(value.begin())
  , m_value_end(value.end())
{
  m_size = Tlv::sizeOfVarNumber(m_type) + Tlv::sizeOfVarNumber(value_size()) + value_size();
}
Exemplo n.º 3
0
size_t
Component::wireEncode(EncodingImpl<TAG>& encoder) const
{
  size_t totalLength = 0;
  if (value_size() > 0)
    totalLength += encoder.prependByteArray(value(), value_size());
  totalLength += encoder.prependVarNumber(value_size());
  totalLength += encoder.prependVarNumber(type());
  return totalLength;
}
Exemplo n.º 4
0
void
Block::encode()
{
  if (hasWire())
    return;

  OBufferStream os;
  Tlv::writeVarNumber(os, type());

  if (hasValue())
    {
      Tlv::writeVarNumber(os, value_size());
      os.write(reinterpret_cast<const char*>(value()), value_size());
    }
  else if (m_subBlocks.size() == 0)
    {
      Tlv::writeVarNumber(os, 0);
    }
  else
    {
      size_t valueSize = 0;
      for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
        valueSize += i->size();
      }

      Tlv::writeVarNumber(os, valueSize);

      for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
        if (i->hasWire())
          os.write(reinterpret_cast<const char*>(i->wire()), i->size());
        else if (i->hasValue()) {
          Tlv::writeVarNumber(os, i->type());
          Tlv::writeVarNumber(os, i->value_size());
          os.write(reinterpret_cast<const char*>(i->value()), i->value_size());
        }
        else
          throw Error("Underlying value buffer is empty");
      }
    }

  // now assign correct block

  m_buffer = os.buf();
  m_begin = m_buffer->begin();
  m_end   = m_buffer->end();
  m_size  = m_end - m_begin;

  m_value_begin = m_buffer->begin();
  m_value_end   = m_buffer->end();

  Tlv::readType(m_value_begin, m_value_end);
  Tlv::readVarNumber(m_value_begin, m_value_end);
}
Exemplo n.º 5
0
void
Block::parse() const
{
  if (!m_subBlocks.empty() || value_size() == 0)
    return;

  Buffer::const_iterator begin = value_begin();
  Buffer::const_iterator end = value_end();

  while (begin != end)
    {
      Buffer::const_iterator element_begin = begin;

      uint32_t type = Tlv::readType(begin, end);
      uint64_t length = Tlv::readVarNumber(begin, end);

      if (length > static_cast<uint64_t>(end - begin))
        {
          m_subBlocks.clear();
          throw Tlv::Error("TLV length exceeds buffer length");
        }
      Buffer::const_iterator element_end = begin + length;

      m_subBlocks.push_back(Block(m_buffer,
                                  type,
                                  element_begin, element_end,
                                  begin, element_end));

      begin = element_end;
      // don't do recursive parsing, just the top level
    }
}
Exemplo n.º 6
0
Arquivo: value.c Projeto: 5py/ltrace
int
value_reify(struct value *val, struct value_dict *arguments)
{
	if (val->where != VAL_LOC_INFERIOR)
		return 0;
	assert(val->inferior != NULL);

	size_t size = value_size(val, arguments);
	if (size == (size_t)-1)
		return -1;

	void *data;
	enum value_location_t nloc;
	if (size <= sizeof(val->u.value)) {
		data = &val->u.value;
		nloc = VAL_LOC_WORD;
	} else {
		data = malloc(size);
		if (data == NULL)
			return -1;
		nloc = VAL_LOC_COPY;
	}

	if (umovebytes(val->inferior, val->u.inf_address, data, size) < size) {
		if (nloc == VAL_LOC_COPY)
			free(data);
		return -1;
	}

	val->where = nloc;
	if (nloc == VAL_LOC_COPY)
		val->u.address = data;

	return 0;
}
Exemplo n.º 7
0
bool
Component::equals(const Component& other) const
{
  return type() == other.type() &&
         value_size() == other.value_size() &&
         (empty() || // needed with Apple clang < 9.0.0 due to libc++ bug
          std::equal(value_begin(), value_end(), other.value_begin()));
}
Exemplo n.º 8
0
bool
Interest::decode02()
{
  auto element = m_wire.elements_begin();

  // Name
  if (element != m_wire.elements_end() && element->type() == tlv::Name) {
    m_name.wireDecode(*element);
    ++element;
  }
  else {
    return false;
  }

  // Selectors?
  if (element != m_wire.elements_end() && element->type() == tlv::Selectors) {
    m_selectors.wireDecode(*element);
    ++element;
  }
  else {
    m_selectors = {};
  }

  // Nonce
  if (element != m_wire.elements_end() && element->type() == tlv::Nonce) {
    uint32_t nonce = 0;
    if (element->value_size() != sizeof(nonce)) {
      NDN_THROW(Error("Nonce element is malformed"));
    }
    std::memcpy(&nonce, element->value(), sizeof(nonce));
    m_nonce = nonce;
    ++element;
  }
  else {
    return false;
  }

  // InterestLifetime?
  if (element != m_wire.elements_end() && element->type() == tlv::InterestLifetime) {
    m_interestLifetime = time::milliseconds(readNonNegativeInteger(*element));
    ++element;
  }
  else {
    m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
  }

  // ForwardingHint?
  if (element != m_wire.elements_end() && element->type() == tlv::ForwardingHint) {
    m_forwardingHint.wireDecode(*element, false);
    ++element;
  }
  else {
    m_forwardingHint = {};
  }

  return element == m_wire.elements_end();
}
Exemplo n.º 9
0
uint64_t
Component::toNumberWithMarker(uint8_t marker) const
{
  if (!isNumberWithMarker(marker))
    NDN_THROW(Error("Name component does not have the requested marker "
                    "or the value is not a nonNegativeInteger"));

  Buffer::const_iterator valueBegin = value_begin() + 1;
  return tlv::readNonNegativeInteger(value_size() - 1, valueBegin, value_end());
}
Exemplo n.º 10
0
int
Component::compare(const Component& other) const
{
  if (this->hasWire() && other.hasWire()) {
    // In the common case where both components have wire encoding,
    // it's more efficient to simply compare the wire encoding.
    // This works because lexical order of TLV encoding happens to be
    // the same as canonical order of the value.
    return std::memcmp(wire(), other.wire(), std::min(size(), other.size()));
  }

  int cmpType = type() - other.type();
  if (cmpType != 0)
    return cmpType;

  int cmpSize = value_size() - other.value_size();
  if (cmpSize != 0)
    return cmpSize;

  if (empty())
    return 0;

  return std::memcmp(value(), other.value(), value_size());
}
Exemplo n.º 11
0
size_t
valuearray_size(Slapi_Value **va)
{
	size_t s= 0;
	if(va!=NULL && va[0]!=NULL)
	{
		int i;
	    for (i = 0; va[i]; i++)
		{
			s += value_size(va[i]);
		}
            s += (i + 1) * sizeof(Slapi_Value*);
	}
	return s;
}
Exemplo n.º 12
0
/* See pxoper.h for details. */
static int
px_save_array(px_value_t * pv, px_state_t * pxs, client_name_t cname,
              uint nbytes)
{
    if (pv->type & pxd_on_heap) {       /* Turn off the "on heap" bit, to prevent freeing. */
        pv->type &= ~pxd_on_heap;
    } else {                    /* Allocate a heap copy.  Only the first nbytes bytes */
        /* of the data are valid. */
        uint num_elements = pv->value.array.size;
        uint elt_size = value_size(pv);
        byte *copy = gs_alloc_byte_array(pxs->memory, num_elements,
                                         elt_size, cname);

        if (copy == 0)
            return_error(errorInsufficientMemory);
        memcpy(copy, pv->value.array.data, nbytes);
        pv->value.array.data = copy;
    }
    return 0;
}
Exemplo n.º 13
0
Block
Block::blockFromValue() const
{
  if (value_size() == 0)
    throw Error("Underlying value buffer is empty");

  Buffer::const_iterator begin = value_begin(),
    end = value_end();

  Buffer::const_iterator element_begin = begin;

  uint32_t type = Tlv::readType(begin, end);
  uint64_t length = Tlv::readVarNumber(begin, end);

  if (length != static_cast<uint64_t>(end - begin))
    throw Tlv::Error("TLV length mismatches buffer length");

  return Block(m_buffer,
               type,
               element_begin, end,
               begin, end);
}
Exemplo n.º 14
0
bool ProtoMessage::from(const std::string& data)
{
	if (m_protoMsg == nullptr || !m_protoMsg->ParseFromString(data))
	{
		return false;
	}
	clearMap();
	clearList();
	clearTable();
	
	int32_t index = -1;
	while (index++ != m_protoMsg->keymapdata_size() - 1)
	{
		auto protokeyMapData = m_protoMsg->mutable_keymapdata(index);
		const int32_t& key = protokeyMapData->key();
		auto mapData = protokeyMapData->mutable_mapdata();
		int32_t dataIndex = -1;
		while (dataIndex++ != mapData->mapkeyvalue_size() - 1)
		{
			auto mapKeyValue = mapData->mutable_mapkeyvalue(dataIndex);
			const int32_t& dataKey = mapKeyValue->key();
			auto variantValue = mapKeyValue->mutable_value();
			m_keyMapData[key][dataKey] = Variant(variantValue->data(), (Variant::VariantType)(variantValue->type()), true);
		}
	}

	index = -1;
	while (index++ != m_protoMsg->keylistdata_size() - 1)
	{
		auto protokeyListData = m_protoMsg->mutable_keylistdata(index);
		const int32_t& key = protokeyListData->key();
		auto listData = protokeyListData->mutable_listdata();
		int32_t dataIndex = -1;
		while (dataIndex++ != listData->value_size() - 1)
		{
			auto variantValue = listData->mutable_value(dataIndex);
			m_keyListData[key].push_back(Variant(variantValue->data(), (Variant::VariantType)(variantValue->type()), true));
		}
	}

	index = -1;
	while (index++ != m_protoMsg->keytabledata_size() - 1)
	{
		auto protokeyTableData = m_protoMsg->mutable_keytabledata(index);
		const int32_t& key = protokeyTableData->key();
		auto tableData = protokeyTableData->mutable_tabledata();
		std::vector<std::vector<Variant>> vecData;
		int32_t lineIndex = -1;
		while (lineIndex++ != tableData->listdata_size() - 1)
		{
			std::vector<Variant> vecLine;
			auto list = tableData->mutable_listdata(lineIndex);
			int32_t dataIndex = -1;
			while (dataIndex++ != list->value_size() - 1)
			{
				auto variantValue = list->mutable_value(dataIndex);
				vecLine.push_back(Variant(variantValue->data(), (Variant::VariantType)(variantValue->type()), true));
			}
			vecData.push_back(vecLine);
		}
		m_keyTableData[key] = vecData;
	}

	return true;
}
Exemplo n.º 15
0
void
Interest::decode03()
{
  // Interest ::= INTEREST-TYPE TLV-LENGTH
  //                Name
  //                CanBePrefix?
  //                MustBeFresh?
  //                ForwardingHint?
  //                Nonce?
  //                InterestLifetime?
  //                HopLimit?
  //                ApplicationParameters?

  auto element = m_wire.elements_begin();
  if (element == m_wire.elements_end() || element->type() != tlv::Name) {
    NDN_THROW(Error("Name element is missing or out of order"));
  }
  m_name.wireDecode(*element);
  if (m_name.empty()) {
    NDN_THROW(Error("Name has zero name components"));
  }
  int lastElement = 1; // last recognized element index, in spec order

  m_selectors = Selectors().setMaxSuffixComponents(1); // CanBePrefix=0
  m_nonce.reset();
  m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
  m_forwardingHint = {};
  m_parameters = {};

  for (++element; element != m_wire.elements_end(); ++element) {
    switch (element->type()) {
      case tlv::CanBePrefix: {
        if (lastElement >= 2) {
          NDN_THROW(Error("CanBePrefix element is out of order"));
        }
        if (element->value_size() != 0) {
          NDN_THROW(Error("CanBePrefix element has non-zero TLV-LENGTH"));
        }
        m_selectors.setMaxSuffixComponents(-1);
        lastElement = 2;
        break;
      }
      case tlv::MustBeFresh: {
        if (lastElement >= 3) {
          NDN_THROW(Error("MustBeFresh element is out of order"));
        }
        if (element->value_size() != 0) {
          NDN_THROW(Error("MustBeFresh element has non-zero TLV-LENGTH"));
        }
        m_selectors.setMustBeFresh(true);
        lastElement = 3;
        break;
      }
      case tlv::ForwardingHint: {
        if (lastElement >= 4) {
          NDN_THROW(Error("ForwardingHint element is out of order"));
        }
        m_forwardingHint.wireDecode(*element);
        lastElement = 4;
        break;
      }
      case tlv::Nonce: {
        if (lastElement >= 5) {
          NDN_THROW(Error("Nonce element is out of order"));
        }
        uint32_t nonce = 0;
        if (element->value_size() != sizeof(nonce)) {
          NDN_THROW(Error("Nonce element is malformed"));
        }
        std::memcpy(&nonce, element->value(), sizeof(nonce));
        m_nonce = nonce;
        lastElement = 5;
        break;
      }
      case tlv::InterestLifetime: {
        if (lastElement >= 6) {
          NDN_THROW(Error("InterestLifetime element is out of order"));
        }
        m_interestLifetime = time::milliseconds(readNonNegativeInteger(*element));
        lastElement = 6;
        break;
      }
      case tlv::HopLimit: {
        if (lastElement >= 7) {
          break; // HopLimit is non-critical, ignore out-of-order appearance
        }
        if (element->value_size() != 1) {
          NDN_THROW(Error("HopLimit element is malformed"));
        }
        // TLV-VALUE is ignored
        lastElement = 7;
        break;
      }
      case tlv::ApplicationParameters: {
        if (lastElement >= 8) {
          break; // ApplicationParameters is non-critical, ignore out-of-order appearance
        }
        m_parameters = *element;
        lastElement = 8;
        break;
      }
      default: {
        if (tlv::isCriticalType(element->type())) {
          NDN_THROW(Error("Unrecognized element of critical type " + to_string(element->type())));
        }
        break;
      }
    }
  }
}
Exemplo n.º 16
0
bool
Component::isNumber() const
{
  return (value_size() == 1 || value_size() == 2 ||
          value_size() == 4 || value_size() == 8);
}
Exemplo n.º 17
0
 cstring_span footer(void) const
 noexcept {
     return {data()+header_size()+value_size(), header_size()};
 }
Exemplo n.º 18
0
 cstring_span value(void) const
 noexcept {
     return {value_data(), value_size()};
 }
Exemplo n.º 19
0
int main(int argc, char * argv[]){
        dataBase *db;
        createDB(&db, "myDB");
        int temp = 0;
        while(temp != -1){
                char line[50];
                char data[100];
		char *key = (char*)inderectMalloc((size_t)(sizeof(char)*50));
		char *stringData;
                size_t size;
                printf("0 to Add key and data, 1 to get data, 2 to remove data, 3 for size, 4 for save, 5 for load, -1 for quit\n");
                if(fgets(line, sizeof(line), stdin)) {
                        if(1 == sscanf(line, "%d", &temp)){
                                switch(temp){
                                        case 0:
                                                printf("Enter key\n");
                                                fgets(line, sizeof(line), stdin);
                                                sscanf(line, "%s", key);
						printf("Enter data\n");
                                                fgets(data, sizeof(data), stdin);
                                                put(db, key, data, sizeof(data));
                                                break;
                                        case 1:
                                                printf("Enter key\n");
                                                fgets(line, sizeof(line), stdin);
                                                sscanf(line, "%s", key);
						get(db, key, (void**)&stringData);
                                                printf("Data is: %s \n", stringData);
                                                break;
                                        case 2:
                                                printf("Enter key\n");
                                                fgets(line, sizeof(line), stdin);
                                                sscanf(line, "%s", key);
						delete(db, key);
                                                break;
                                        case 3:
                                                printf("Enter key\n");
						fgets(line, sizeof(line), stdin);
						sscanf(line, "%s", key);
                                                size = value_size(db, key);
                                                printf("Size is: %d\n", (int)size);
                                                break;
					case 4:
						printf("Enter path\n");
						fgets(line, sizeof(line), stdin);
						sscanf(line, "%s", key);
						if(-1 == saveHT(db, key))
							printf("Failed saved\n");
						break;
					case 5:
						printf("Enter path\n");
						fgets(line, sizeof(line), stdin);
						sscanf(line, "%s", key);
						if(-1 == loadHT(db, key))
							printf("Failed load\n");
						break;
				}
			}
		}
	}
}
Exemplo n.º 20
0
/* Process a buffer of PCL XL commands. */
int
px_process(px_parser_state_t * st, px_state_t * pxs, stream_cursor_read * pr)
{
    const byte *orig_p = pr->ptr;
    const byte *next_p = orig_p;        /* start of data not copied to saved */
    const byte *p;
    const byte *rlimit;
    px_value_t *sp = &st->stack[st->stack_count];

#define stack_limit &st->stack[max_stack - 1]
    gs_memory_t *memory = st->memory;
    int code = 0;
    uint left;
    uint min_left;
    px_tag_t tag;
    const px_tag_syntax_t *syntax = 0;

    st->args.parser = st;
    st->parent_operator_count = 0;      /* in case of error */
    /* Check for leftover data from the previous call. */
  parse:if (st->saved_count) { /* Fill up the saved buffer so we can make progress. */
        int move = min(sizeof(st->saved) - st->saved_count,
                       pr->limit - next_p);

        memcpy(&st->saved[st->saved_count], next_p + 1, move);
        next_p += move;
        p = st->saved - 1;
        rlimit = p + st->saved_count + move;
    } else {                    /* No leftover data, just read from the input. */
        p = next_p;
        rlimit = pr->limit;
    }
  top:if (st->data_left) {     /* We're in the middle of reading an array or data block. */
        if (st->data_proc) {    /* This is a data block. */
            uint avail = min(rlimit - p, st->data_left);
            uint used;

            st->args.source.available = avail;
            st->args.source.data = p + 1;
            code = (*st->data_proc) (&st->args, pxs);
            /* If we get a 'remap_color' error, it means we are dealing with a
             * pattern, and the device supports high level patterns. So we must
             * use our high level pattern implementation.
             */
            if (code == gs_error_Remap_Color) {
                code = px_high_level_pattern(pxs->pgs);
                code = (*st->data_proc) (&st->args, pxs);
            }
            used = st->args.source.data - (p + 1);
#ifdef DEBUG
            if (gs_debug_c('I')) {
                px_value_t data_array;

                data_array.type = pxd_ubyte;
                data_array.value.array.data = p + 1;
                data_array.value.array.size = used;
                trace_array_data(pxs->memory, "data:", &data_array);
            }
#endif
            p = st->args.source.data - 1;
            st->data_left -= used;
            if (code < 0) {
                st->args.source.position = 0;
                goto x;
            } else if ((code == pxNeedData)
                       || (code == pxPassThrough && st->data_left != 0)) {
                code = 0;       /* exit for more data */
                goto x;
            } else {
                st->args.source.position = 0;
                st->data_proc = 0;
                if (st->data_left != 0) {
                    code = gs_note_error(errorExtraData);
                    goto x;
                }
                clear_stack();
            }
        } else {                /* This is an array. */
            uint size = sp->value.array.size;
            uint scale = value_size(sp);
            uint nbytes = size * scale;
            byte *dest =
                (byte *) sp->value.array.data + nbytes - st->data_left;

            left = rlimit - p;
            if (left < st->data_left) { /* We still don't have enough data to fill the array. */
                memcpy(dest, p + 1, left);
                st->data_left -= left;
                p = rlimit;
                code = 0;
                goto x;
            }
            /* Complete the array and continue parsing. */
            memcpy(dest, p + 1, st->data_left);
            trace_array(memory, sp);
            p += st->data_left;
        }
        st->data_left = 0;
    } else if (st->data_proc) { /* An operator is awaiting data. */
        /* Skip white space until we find some. */
        code = 0;               /* in case we exit */
        /* special case - VendorUnique has a length attribute which
           we've already parsed and error checked */
        if (st->data_proc == pxVendorUnique) {
            st->data_left =
                st->stack[st->attribute_indices[pxaVUDataLength]].value.i;
            goto top;
        } else {
            while ((left = rlimit - p) != 0) {
                switch ((tag = p[1])) {
                case pxtNull:
                case pxtHT:
                case pxtLF:
                case pxtVT:
                case pxtFF:
                case pxtCR:
                    ++p;
                    continue;
                case pxt_dataLength:
                    if (left < 5)
                        goto x; /* can't look ahead */
                    st->data_left = get_uint32(st, p + 2);
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
                               p[1], st->data_left);
                    p += 5;
                    goto top;
                case pxt_dataLengthByte:
                    if (left < 2)
                        goto x; /* can't look ahead */
                    st->data_left = p[2];
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
                               p[1], st->data_left);
                    p += 2;
                    goto top;
                default:
                    {
                        code = gs_note_error(errorMissingData);
                        goto x;
                    }
                }
            }
        }
    }
    st->args.source.position = 0;
    st->args.source.available = 0;
    while ((left = rlimit - p) != 0 &&
           left >= (min_left = (syntax = &tag_syntax[tag = p[1]])->min_input)
        ) {
        int count;

#ifdef DEBUG
        if (gs_debug_c('i')) {
            dmprintf1(memory, "tag=  0x%02x  ", tag);
            if (tag == pxt_attr_ubyte || tag == pxt_attr_uint16) {
                px_attribute_t attr =
                    (tag == pxt_attr_ubyte ? p[2] : get_uint16(st, p + 2));
                const char *aname = px_attribute_names[attr];

                if (aname)
                    dmprintf1(memory, "   @%s\n", aname);
                else
                    dmprintf1(memory, "   attribute %u ???\n", attr);
            } else {
                const char *format;
                const char *tname;
                bool operator = false;

                if (tag < 0x40)
                    format = "%s\n", tname = px_tag_0_names[tag];
                else if (tag < 0xc0)
                    format = "%s", tname = px_operator_names[tag - 0x40],
                        operator = true;
                else {
                    tname = px_tag_c0_names[tag - 0xc0];
                    if (tag < 0xf0)
                        format = "      %s";    /* data values follow */
                    else
                        format = "%s\n";
                }
                if (tname) {
                    dmprintf1(memory, format, tname);
                    if (operator)
                        dmprintf1(memory, " (%ld)\n", st->operator_count + 1);
                } else
                    dmputs(memory, "???\n");
            }
        }
#endif
        if ((st->macro_state & syntax->state_mask) != syntax->state_value) {
            /*
             * We should probably distinguish here between
             * out-of-context operators and illegal tags, but it's too
             * much trouble.
             */
            code = gs_note_error(errorIllegalOperatorSequence);
            if (tag >= 0x40 && tag < 0xc0)
                st->last_operator = tag;
            goto x;
        }
        st->macro_state ^= syntax->state_transition;
        switch (tag >> 3) {
            case 0:
                switch (tag) {
                    case pxtNull:
                        ++p;
                        continue;
                    default:
                        break;
                }
                break;
            case 1:
                switch (tag) {
                    case pxtHT:
                    case pxtLF:
                    case pxtVT:
                    case pxtFF:
                    case pxtCR:
                        ++p;
                        continue;
                    default:
                        break;
                }
                break;
            case 3:
                if (tag == pxt1b) {     /* ESC *//* Check for UEL */
                    if (memcmp(p + 1, "\033%-12345X", min(left, 9)))
                        break;  /* not UEL, error */
                    if (left < 9)
                        goto x; /* need more data */
                    p += 9;
                    code = e_ExitLanguage;
                    goto x;
                }
                break;
            case 4:
                switch (tag) {
                    case pxtSpace:
                        /* break; will error, compatible with lj */
                        /* ++p;continue; silently ignores the space */
                        ++p;
                        continue;
                    default:
                        break;
                }
                break;
            case 8:
            case 9:
            case 10:
            case 11:
            case 12:
            case 13:
            case 14:
            case 15:
            case 16:
            case 17:
            case 18:
            case 19:
            case 20:
            case 21:
            case 22:
            case 23:
                /* Operators */
                /* Make sure that we have all the required attributes, */
                /* and no attributes that are neither required nor */
                /* optional.  (It's up to the operator to make any */
                /* more precise checks than this. */
                st->operator_count++;
                /* if this is a passthrough operator we have to tell
                   the passthrough module if this operator was
                   preceded by another passthrough operator or a
                   different xl operator */
                if (tag == pxtPassThrough) {
                    pxpcl_passthroughcontiguous(st->last_operator == tag);
                } else if (st->last_operator == pxtPassThrough) {
                    pxpcl_endpassthroughcontiguous(pxs);
                }

                st->last_operator = tag;
                {
                    const px_operator_definition_t *pod =
                        &px_operator_definitions[tag - 0x40];
                    int left = sp - st->stack;
                    const byte /*px_attribute_t */  * pal = pod->attrs;
                    px_value_t **ppv = st->args.pv;
                    bool required = true;
                    code = 0;
                    /*
                     * Scan the attributes.  Illegal attributes take priority
                     * over missing attributes, which in turn take priority
                     * over illegal data types.
                     */
                    for (;; ++pal, ++ppv) {
                        px_attribute_t attr = *pal;
                        uint index;

                        if (!attr) {    /*
                                         * We've reached the end of either the required or
                                         * the optional attribute list.
                                         */
                            if (!required)
                                break;
                            required = false;
                            --ppv;      /* cancel incrementing */
                            continue;
                        }
                        if ((index = st->attribute_indices[attr]) == 0) {
                            if (required)
                                code = gs_note_error(errorMissingAttribute);
                            else
                                *ppv = 0;
                        } else {        /* Check the attribute data type and value. */
                            px_value_t *pv = *ppv = &st->stack[index];
                            const px_attr_value_type_t *pavt =
                                &px_attr_value_types[attr];
                            int acode;

                            if ((~pavt->mask & pv->type &
                                 (pxd_structure | pxd_representation)) ||
                                (pavt->mask == (pxd_scalar | pxd_ubyte) &&
                                 (pv->value.i < 0
                                  || pv->value.i > pavt->limit))
                                ) {
                                if (code >= 0)
                                    code =
                                        gs_note_error
                                        (errorIllegalAttributeDataType);
                            }
                            if (pavt->proc != 0
                                && (acode = (*pavt->proc) (pv)) < 0) {
                                if (code >= 0)
                                    code = acode;
                            }
                            --left;
                        }
                    }

                    /* Make sure there are no attributes left over. */
                    if (left)
                        code = gs_note_error(errorIllegalAttribute);
                    if (code >= 0) {
                        st->args.source.phase = 0;
                        code = (*pod->proc) (&st->args, pxs);
                        /* If we get a 'remap_color' error, it means we are dealing with a
                         * pattern, and the device supports high level patterns. So we must
                         * use our high level pattern implementation.
                         */
                        if (code == gs_error_Remap_Color) {
                            code = px_high_level_pattern(pxs->pgs);
                            if (code < 0)
                                goto x;
                            code = (*pod->proc) (&st->args, pxs);
                        }
                    }
                    if (code < 0)
                        goto x;
                    /* Check whether the operator wanted source data. */
                    if (code == pxNeedData) {
                        if (!pxs->data_source_open) {
                            code = gs_note_error(errorDataSourceNotOpen);
                            goto x;
                        }
                        st->data_proc = pod->proc;
                        ++p;
                        goto top;
                    }
                }
                clear_stack();
                ++p;
                continue;
            case 24:
                sp[1].type = pxd_scalar;
                count = 1;
                goto data;
            case 26:
                sp[1].type = pxd_xy;
                count = 2;
                goto data;
            case 28:
                sp[1].type = pxd_box;
                count = 4;
                goto data;
                /* Scalar, point, and box data */
              data:{
                    int i;

                    if (sp == stack_limit) {
                        code = gs_note_error(errorInternalOverflow);
                        goto x;
                    }
                    ++sp;
                    sp->attribute = 0;
                    p += 2;
#ifdef DEBUG
#  define trace_scalar(mem, format, cast, alt)\
                  if ( gs_debug_c('i') )\
                    trace_data(mem, format, cast, sp->value.alt, count)
#else
#  define trace_scalar(mem, format, cast, alt) DO_NOTHING
#endif
                    switch (tag & 7) {
                        case pxt_ubyte & 7:
                            sp->type |= pxd_ubyte;
                            for (i = 0; i < count; ++p, ++i)
                                sp->value.ia[i] = *p;
                          dux:trace_scalar(pxs->memory, " %lu", ulong,
                                         ia);
                            --p;
                            continue;
                        case pxt_uint16 & 7:
                            sp->type |= pxd_uint16;
                            for (i = 0; i < count; p += 2, ++i)
                                sp->value.ia[i] = get_uint16(st, p);
                            goto dux;
                        case pxt_uint32 & 7:
                            sp->type |= pxd_uint32;
                            for (i = 0; i < count; p += 4, ++i)
                                sp->value.ia[i] = get_uint32(st, p);
                            goto dux;
                        case pxt_sint16 & 7:
                            sp->type |= pxd_sint16;
                            for (i = 0; i < count; p += 2, ++i)
                                sp->value.ia[i] = get_sint16(st, p);
                          dsx:trace_scalar(pxs->memory, " %ld", long,
                                         ia);
                            --p;
                            continue;
                        case pxt_sint32 & 7:
                            sp->type |= pxd_sint32;
                            for (i = 0; i < count; p += 4, ++i)
                                sp->value.ia[i] = get_sint32(st, p);
                            goto dsx;
                        case pxt_real32 & 7:
                            sp->type |= pxd_real32;
                            for (i = 0; i < count; p += 4, ++i)
                                sp->value.ra[i] = get_real32(st, p);
                            trace_scalar(pxs->memory, " %g", double, ra);

                            --p;
                            continue;
                        default:
                            break;
                    }
                }
                break;
            case 25:
                /* Array data */
                {
                    const byte *dp;
                    uint nbytes;

                    if (sp == stack_limit) {
                        code = gs_note_error(errorInternalOverflow);
                        goto x;
                    }
                    switch (p[2]) {
                        case pxt_ubyte:
                            sp[1].value.array.size = p[3];
                            dp = p + 4;
                            break;
                        case pxt_uint16:
                            if (left < 4) {
                                if_debug0m('i', memory, "...\n");
                                /* Undo the state transition. */
                                st->macro_state ^= syntax->state_transition;
                                goto x;
                            }
                            sp[1].value.array.size = get_uint16(st, p + 3);
                            dp = p + 5;
                            break;
                        default:
                            st->last_operator = tag;    /* for error message */
                            code = gs_note_error(errorIllegalTag);
                            goto x;
                    }
                    nbytes = sp[1].value.array.size;
                    if_debug1m('i', memory, "[%u]\n", sp[1].value.array.size);
                    switch (tag) {
                        case pxt_ubyte_array:
                            sp[1].type = pxd_array | pxd_ubyte;
                          array:++sp;
                            if (st->big_endian)
                                sp->type |= pxd_big_endian;
                            sp->value.array.data = dp;
                            sp->attribute = 0;
                            /* Check whether we have enough data for the entire */
                            /* array. */
                            if (rlimit + 1 - dp < nbytes) {     /* Exit now, continue reading when we return. */
                                uint avail = rlimit + 1 - dp;

                                code = px_save_array(sp, pxs, "partial array",
                                                     avail);
                                if (code < 0)
                                    goto x;
                                sp->type |= pxd_on_heap;
                                st->data_left = nbytes - avail;
                                st->data_proc = 0;
                                p = rlimit;
                                goto x;
                            }
                            p = dp + nbytes - 1;
                            trace_array(memory, sp);
                            continue;
                        case pxt_uint16_array:
                            sp[1].type = pxd_array | pxd_uint16;
                          a16:nbytes <<= 1;
                            goto array;
                        case pxt_uint32_array:
                            sp[1].type = pxd_array | pxd_uint32;
                          a32:nbytes <<= 2;
                            goto array;
                        case pxt_sint16_array:
                            sp[1].type = pxd_array | pxd_sint16;
                            goto a16;
                        case pxt_sint32_array:
                            sp[1].type = pxd_array | pxd_sint32;
                            goto a32;
                        case pxt_real32_array:
                            sp[1].type = pxd_array | pxd_real32;
                            goto a32;
                        default:
                            break;
                    }
                    break;
                }
                break;
            case 31:
                {
                    px_attribute_t attr;
                    const byte *pnext;

                    switch (tag) {
                        case pxt_attr_ubyte:
                            attr = p[2];
                            pnext = p + 2;
                            goto a;
                        case pxt_attr_uint16:
                            attr = get_uint16(st, p + 2);
                            pnext = p + 3;
                          a:if (attr >=
                                px_attribute_next)
                                break;
                            /*
                             * We could check the attribute value type here, but
                             * in order to match the behavior of the H-P printers,
                             * we don't do it until we see the operator.
                             *
                             * It is legal to specify the same attribute more than
                             * once; the last value has priority.  If this happens,
                             * since the order of attributes doesn't matter, we can
                             * just replace the former value on the stack.
                             */
                            sp->attribute = attr;
                            if (st->attribute_indices[attr] != 0) {
                                px_value_t *old_sp =
                                    &st->stack[st->attribute_indices[attr]];
                                /* If the old value is on the heap, free it. */
                                if (old_sp->type & pxd_on_heap)
                                    gs_free_object(memory,
                                                   (void *)old_sp->value.
                                                   array.data,
                                                   "old value for duplicate attribute");
                                *old_sp = *sp--;
                            } else
                                st->attribute_indices[attr] = sp - st->stack;
                            p = pnext;
                            continue;
                        case pxt_dataLength:
                            /*
                             * Unexpected data length operators are normally not
                             * allowed, but there might be a zero-length data
                             * block immediately following a zero-size image,
                             * which doesn't ask for any data.
                             */
                            if (uint32at(p + 2, true /*arbitrary */ ) == 0) {
                                p += 5;
                                continue;
                            }
                            break;
                        case pxt_dataLengthByte:
                            /* See the comment under pxt_dataLength above. */
                            if (p[2] == 0) {
                                p += 2;
                                continue;
                            }
                            break;
                        default:
                            break;
                    }
                }
                break;
            default:
                break;
        }
        /* Unknown tag value.  Report an error. */
        st->last_operator = tag;        /* for error message */
        code = gs_note_error(errorIllegalTag);
        break;
    }
  x:                           /* Save any leftover input. */
    left = rlimit - p;
    if (rlimit != pr->limit) {  /* We were reading saved input. */
        if (left <= next_p - orig_p) {  /* We finished reading the previously saved input. */
            /* Continue reading current input, unless we got an error. */
            p = next_p -= left;
            rlimit = pr->limit;
            st->saved_count = 0;
            if (code >= 0)
                goto parse;
        } else {                /* There's still some previously saved input left over. */
            memmove(st->saved, p + 1, st->saved_count = left);
            p = next_p;
            rlimit = pr->limit;
            left = rlimit - p;
        }
    }
    /* Except in case of error, save any remaining input. */
    if (code >= 0) {
        if (left + st->saved_count > sizeof(st->saved)) {       /* Fatal error -- shouldn't happen! */
            code = gs_note_error(errorInternalOverflow);
            st->saved_count = 0;
        } else {
            memcpy(&st->saved[st->saved_count], p + 1, left);
            st->saved_count += left;
            p = rlimit;
        }
    }
    pr->ptr = p;
    st->stack_count = sp - st->stack;
    /* Move to the heap any arrays whose data was being referenced */
    /* directly in the input buffer. */
    for (; sp > st->stack; --sp)
        if ((sp->type & (pxd_array | pxd_on_heap)) == pxd_array) {
            int code = px_save_array(sp, pxs, "px stack array to heap",
                                     sp->value.array.size * value_size(sp));

            if (code < 0)
                break;
            sp->type |= pxd_on_heap;
        }
    if (code < 0 && syntax != 0) {      /* Undo the state transition. */
        st->macro_state ^= syntax->state_transition;
    }
    return code;
}