/**
 * \brief Remove a processing step
 */
void	ProcessingStep::remove_me() {
	// remove me from precursors
	debug(LOG_DEBUG, DEBUG_LOG, 0, "remove from precursors of %s @ %p",
		type_name().c_str(), this);
	steps	stepvector = _precursors;
	std::for_each(stepvector.begin(), stepvector.end(),
		[this](steps::value_type& x) {
			debug(LOG_DEBUG, DEBUG_LOG, 0, "remove precursor %s",
				get_typename(x).c_str());
			x->remove_successor(this);
		}
	);

	// remove me from successors
	debug(LOG_DEBUG, DEBUG_LOG, 0, "remove from successors of %s @ %p",
		type_name().c_str(), this);
	stepvector = _successors;
	std::for_each(stepvector.begin(), stepvector.end(),
		[this](steps::value_type& x) {
			debug(LOG_DEBUG, DEBUG_LOG, 0, "remove successor %s",
				get_typename(x).c_str());
			x->remove_precursor(this);
		}
	);
}
Esempio n. 2
0
void SystemException::print() const{
    Console::println("\n", 'R');
    Console::println_labelc("System Exception Encountered", get_typename());
    Console::println();
    if (!m_function.empty()){
        Console::println_labelm("In Function:", m_function);
    }
    Console::println_labelm("Error Code: ", m_code);
    Console::println();
    Console::println(m_message);
    Console::println("\n");
    Console::SetColor('w');
}
Esempio n. 3
0
static char *checkAttrib( char *s, char **ptype, char *buff, int *errs,
                          a_sym *lhs, a_sym **rhs, unsigned base, unsigned n )
{
    char        save;
    char        *type;
    int         err_count;
    int         i;

    err_count = 0;
    ++s;
    if( *s == '<' ) {
        ++s;
        type = s;
        s = get_typename( type );
        if( type == s || *s != '>' )  {
            ++err_count;
            msg( "Bad type specifier.\n" );
        }
        save = *s;
        *s = '\0';
        type = strdup( type );
        *s = save;
        ++s;
    } else {
        type = NULL;
    }
    if( *s == '$' ) {
        strcpy( buff, "yyval" );
        if( type == NULL && lhs->type != NULL ) {
            type = strdup( lhs->type );
        }
        ++s;
    } else {
        i = n + 1;
        if( *s == '-' || isdigit( *s ) ) {
            i = strtol( s, &s, 10 );
        }
        if( i >= 0 && i > n ) {
            ++err_count;
            msg( "Invalid $ parameter (%d).\n", i );
        }
        i -= base + 1;
        sprintf( buff, "yyvp[%d]", i );
        if( type == NULL && i >= 0 && rhs[ i ]->type != NULL ) {
            type = strdup( rhs[ i ]->type );
        }
    }
    *ptype = type;
    *errs = err_count;
    return( s );
}
/**
 * \brief add a successor
 */
void	ProcessingStep::add_successor(ProcessingStep *step) {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "add successor %s @ %p",
		get_typename(step).c_str(),  step);
	// don't add if already present
	if (_successors.end()
		!= std::find(_successors.begin(), _successors.end(), step)) {
		debug(LOG_DEBUG, DEBUG_LOG, 0, "%p alread present", step);
		return;
	}
	// add to the successors vector
	_successors.push_back(step);
	// tell the new step that we are it's precursor
	step->add_precursor(this);
}
Esempio n. 5
0
 SymbolicExpr::VisitAction preVisit(const SymbolicExpr::Ptr &node) {
     if (!seen.insert(getRawPointer(node)).second)
         return SymbolicExpr::TRUNCATE;          // already processed this subexpression
     if (SymbolicExpr::LeafPtr leaf = node->isLeafNode()) {
         if (leaf->isVariable()) {
             if (defns->find(leaf->nameId())==defns->end()) {
                 defns->insert(leaf->nameId());
                 o <<"\n";
                 if (!leaf->comment().empty())
                     o <<StringUtility::prefixLines(leaf->comment(), "; ") <<"\n";
                 o <<"(define v" <<leaf->nameId() <<"::" <<get_typename(leaf) <<")\n";
             }
         } else if (leaf->isMemory()) {
             if (defns->find(leaf->nameId())==defns->end()) {
                 defns->insert(leaf->nameId());
                 o <<"\n";
                 if (!leaf->comment().empty())
                     o <<StringUtility::prefixLines(leaf->comment(), "; ") <<"\n";
                 o <<"(define m" <<leaf->nameId() <<"::" <<get_typename(leaf) <<")\n";
             }
         }
     }
     return SymbolicExpr::CONTINUE;
 }
Esempio n. 6
0
/** Generate definitions for common subexpressions. */
void
YicesSolver::out_common_subexpressions(std::ostream &o, const std::vector<SymbolicExpr::Ptr> &exprs) {
    std::vector<SymbolicExpr::Ptr> cses = findCommonSubexpressions(exprs);
    for (size_t i=0; i<cses.size(); ++i) {
        o <<"\n";
        if (!cses[i]->comment().empty())
            o <<StringUtility::prefixLines(cses[i]->comment(), "; ") <<"\n";
        o <<"; effective size = " <<StringUtility::plural(cses[i]->nNodes(), "nodes")
          <<", actual size = " <<StringUtility::plural(cses[i]->nNodesUnique(), "nodes") <<"\n";
        std::string termName = "cse_" + StringUtility::numberToString(i);
        o <<"(define " <<termName <<"::" <<get_typename(cses[i]) <<" ";
        out_expr(o, cses[i]);
        o <<")\n";
        termNames.insert(cses[i], termName);
    }
}
Esempio n. 7
0
/* read */
static int fifo_read(ubx_block_t *i, ubx_data_t* msg)
{
	int ret=0;
	unsigned long readsz=0, readsz1=0, readsz2=0, used;
	struct fifo_block_info *bbi;

	bbi = (struct fifo_block_info*) i->private_data;

	if((ret=pthread_mutex_lock(&bbi->mutex))!=0) {
		ERR2(ret, "failed to lock mutex");
		goto out;
	}

	if(bbi->rdptr == bbi->wrptr) {
		goto out_unlock;
	}

	if(msg->type != bbi->type) {
		ERR("invalid read type '%s' (expected '%s'", get_typename(msg), bbi->type->name);
		ret=EPORT_INVALID_TYPE;
		goto out_unlock;
	}

	/* bytes */
	used = used_space(bbi);
	readsz=(used<readsz) ? used : readsz;

	/* chunk 2*/
	if(bbi->rdptr > bbi->wrptr) {
		readsz2 = readsz - (bbi->buff + bbi->size - bbi->wrptr);
		readsz1 = readsz-readsz2;
	}

	memcpy(msg->data, bbi->rdptr, readsz1);
	bbi->rdptr=&bbi->buff[readsz1];

	if(readsz2>0) {
		
	}

	ret=readsz/bbi->type->size;		/* compute # elements read */
 out_unlock:
	pthread_mutex_unlock(&bbi->mutex);
 out:
	return ret;
}
Esempio n. 8
0
static void hexdump_write(ubx_block_t *i, ubx_data_t* data) {
	const char* typename = get_typename(data);
	printf("hexdump (%s): ", (typename!=NULL) ? typename : "unknown");
	hexdump(data->data, data_size(data), 16);
}
std::string	ProcessingStep::type_name() const {
	return get_typename(this);
}
Esempio n. 10
0
/*
 *****************************************************************************
 * Function	: dump_resources
 * Syntax	: void dump_resources(const resource_t *top)
 * Input	:
 *	top	- Top of the resource tree
 * Output	:
 *	nop
 * Description	: Dump the parsed resource-tree to stdout
 * Remarks	:
 *****************************************************************************
*/
void dump_resources(const resource_t *top)
{
	printf("Internal resource-tree dump:\n");
	while(top)
	{
		printf("Resource: %s\nId: %s\n",
		       get_typename(top),
		       get_nameid_str(top->name));
		switch(top->type)
		{
		case res_acc:
			dump_accelerator(top->res.acc);
			break;
		case res_bmp:
			dump_bitmap(top->res.bmp);
			break;
		case res_cur:
			dump_cursor(top->res.cur);
			break;
		case res_curg:
			dump_cursor_group(top->res.curg);
			break;
		case res_dlg:
			dump_dialog(top->res.dlg);
			break;
		case res_dlgex:
			dump_dialogex(top->res.dlgex);
			break;
		case res_fnt:
			dump_font(top->res.fnt);
			break;
		case res_icog:
			dump_icon_group(top->res.icog);
			break;
		case res_ico:
			dump_icon(top->res.ico);
			break;
		case res_men:
			dump_menu(top->res.men);
			break;
		case res_menex:
			dump_menuex(top->res.menex);
			break;
		case res_rdt:
			dump_rcdata(top->res.rdt);
			break;
		case res_stt:
			dump_stringtable(top->res.stt);
			break;
		case res_usr:
			dump_user(top->res.usr);
			break;
		case res_msg:
			dump_messagetable(top->res.msg);
			break;
		case res_ver:
			dump_versioninfo(top->res.ver);
			break;
		case res_dlginit:
			dump_dlginit(top->res.dlgi);
			break;
		case res_toolbar:
			dump_toolbar(top->res.tbt);
			break;
		case res_anicur:
		case res_aniico:
			dump_ani_curico(top->res.ani);
			break;
		default:
			printf("Report this: Unknown resource type parsed %08x\n", top->type);
		}
		printf("\n");
		top = top->next;
	}
}
Esempio n. 11
0
/*
 * SendRowDescriptionMessage --- send a RowDescription message to the frontend
 *
 * Notes: the TupleDesc has typically been manufactured by ExecTypeFromTL()
 * or some similar function; it does not contain a full set of fields.
 * The targetlist will be NIL when executing a utility function that does
 * not have a plan.  If the targetlist isn't NIL then it is a Query node's
 * targetlist; it is up to us to ignore resjunk columns in it.	The formats[]
 * array pointer might be NULL (if we are doing Describe on a prepared stmt);
 * send zeroes for the format codes in that case.
 */
void
SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats)
{
	Form_pg_attribute *attrs = typeinfo->attrs;
	int			natts = typeinfo->natts;
	int			proto = PG_PROTOCOL_MAJOR(FrontendProtocol);
	int			i;
	StringInfoData buf;
	ListCell   *tlist_item = list_head(targetlist);

	pq_beginmessage(&buf, 'T'); /* tuple descriptor message type */
	pq_sendint(&buf, natts, 2); /* # of attrs in tuples */

	for (i = 0; i < natts; ++i)
	{
		Oid			atttypid = attrs[i]->atttypid;
		int32		atttypmod = attrs[i]->atttypmod;

		pq_sendstring(&buf, NameStr(attrs[i]->attname));

#ifdef PGXC
		/*
		 * Send the type name from a Postgres-XC backend node.
		 * This preserves from OID inconsistencies as architecture is shared nothing.
		 */
		if (IsConnFromCoord())
		{
			char	   *typename;
			typename = get_typename(atttypid);
			pq_sendstring(&buf, typename);
		}
#endif

		/* column ID info appears in protocol 3.0 and up */
		if (proto >= 3)
		{
			/* Do we have a non-resjunk tlist item? */
			while (tlist_item &&
				   ((TargetEntry *) lfirst(tlist_item))->resjunk)
				tlist_item = lnext(tlist_item);
			if (tlist_item)
			{
				TargetEntry *tle = (TargetEntry *) lfirst(tlist_item);

				pq_sendint(&buf, tle->resorigtbl, 4);
				pq_sendint(&buf, tle->resorigcol, 2);
				tlist_item = lnext(tlist_item);
			}
			else
			{
				/* No info available, so send zeroes */
				pq_sendint(&buf, 0, 4);
				pq_sendint(&buf, 0, 2);
			}
		}
		/* If column is a domain, send the base type and typmod instead */
		atttypid = getBaseTypeAndTypmod(atttypid, &atttypmod);
		pq_sendint(&buf, (int) atttypid, sizeof(atttypid));
		pq_sendint(&buf, attrs[i]->attlen, sizeof(attrs[i]->attlen));
		/* typmod appears in protocol 2.0 and up */
		if (proto >= 2)
			pq_sendint(&buf, atttypmod, sizeof(atttypmod));
		/* format info appears in protocol 3.0 and up */
		if (proto >= 3)
		{
			if (formats)
				pq_sendint(&buf, formats[i], 2);
			else
				pq_sendint(&buf, 0, 2);
		}
	}
	pq_endmessage(&buf);
}
Esempio n. 12
0
static void bytecode_dump_frame_internal(MVMThreadContext *tc, MVMStaticFrame *frame, MVMSpeshCandidate *maybe_candidate, MVMuint8 *frame_cur_op, char ***frame_lexicals, char **oo, MVMuint32 *os, MVMuint32 *ol) {
    /* since "references" are not a thing in C, keep a local copy of these
     * and update the passed-in pointers at the end of the function */
    char *o = *oo;
    MVMuint32 s = *os;
    MVMuint32 l = *ol;

    MVMuint32 i, j, k;

    /* mostly stolen from validation.c */
    MVMStaticFrame *static_frame = frame;
    MVMuint32 bytecode_size = maybe_candidate ? maybe_candidate->bytecode_size : static_frame->body.bytecode_size;
    MVMuint8 *bytecode_start = maybe_candidate ? maybe_candidate->bytecode : static_frame->body.bytecode;
    MVMuint8 *bytecode_end = bytecode_start + bytecode_size;
    /* current position in the bytestream */
    MVMuint8 *cur_op = bytecode_start;
    /* positions in the bytestream that are starts of ops and goto targets */
    MVMuint8 *labels = MVM_calloc(1, bytecode_size);
    MVMuint32 *jumps = MVM_calloc(1, sizeof(MVMuint32) * bytecode_size);
    char **lines = MVM_malloc(sizeof(char *) * bytecode_size);
    MVMuint32 *linelocs = MVM_malloc(sizeof(MVMuint32) * bytecode_size);
    MVMuint32 lineno = 0;
    MVMuint32 lineloc;
    MVMuint16 op_num;
    const MVMOpInfo *op_info;
    MVMuint32 operand_size = 0;
    unsigned char op_rw;
    unsigned char op_type;
    unsigned char op_flags;
    MVMOpInfo tmp_extop_info;
    /* stash the outer output buffer */
    MVMuint32 sP = s;
    MVMuint32 lP = l;
    char *oP = o;
    char *tmpstr;
    char mark_this_line = 0;
    MVMCompUnit *cu = static_frame->body.cu;

    while (cur_op < bytecode_end - 1) {

        /* allocate a line buffer */
        s = 200;
        l = 0;
        o = MVM_calloc(s, sizeof(char));

        lineloc = cur_op - bytecode_start;
        /* mark that this line starts at this point in the bytestream */
        linelocs[lineno] = lineloc;
        /* mark that this point in the bytestream is an op boundary */
        labels[lineloc] |= MVM_val_op_boundary;


        mark_this_line = 0;
        if (frame_cur_op) {
            if (frame_cur_op == cur_op || frame_cur_op == cur_op + 2) {
                mark_this_line = 1;
            }
        }

        if (mark_this_line) {
            a("-> ");
        } else {
            a("   ");
        }

        op_num = *((MVMint16 *)cur_op);
        cur_op += 2;
        if (op_num < MVM_OP_EXT_BASE) {
            op_info = MVM_op_get_op(op_num);
            if (op_info)
                a("%-18s ", op_info->name);
            else
                a("invalid OP        ");
        }
        else {
            MVMint16 ext_op_num = op_num - MVM_OP_EXT_BASE;
            if (0 <= ext_op_num && ext_op_num < cu->body.num_extops) {
                MVMExtOpRecord r = cu->body.extops[ext_op_num];
                MVMuint8 j;
                memset(&tmp_extop_info, 0, sizeof(MVMOpInfo));
                tmp_extop_info.name = MVM_string_utf8_encode_C_string(tc, r.name);
                memcpy(tmp_extop_info.operands, r.operand_descriptor, 8);
                for (j = 0; j < 8; j++)
                    if (tmp_extop_info.operands[j])
                        tmp_extop_info.num_operands++;
                    else
                        break;
                op_info = &tmp_extop_info;
                a("%-12s ", tmp_extop_info.name);
                MVM_free((void *)tmp_extop_info.name);
                tmp_extop_info.name = NULL;
            }
            else {
                a("Extension op %d out of range", (int)op_num);
            }
        }

        if (!op_info)
            continue;

        for (i = 0; i < op_info->num_operands; i++) {
            if (i) a(", ");
            op_flags = op_info->operands[i];
            op_rw   = op_flags & MVM_operand_rw_mask;
            op_type = op_flags & MVM_operand_type_mask;

            if (op_rw == MVM_operand_literal) {
                switch (op_type) {
                    case MVM_operand_int8:
                        operand_size = 1;
                        a("%"PRId8, GET_I8(cur_op, 0));
                        break;
                    case MVM_operand_int16:
                        operand_size = 2;
                        a("%"PRId16, GET_I16(cur_op, 0));
                        break;
                    case MVM_operand_int32:
                        operand_size = 4;
                        a("%"PRId32, GET_I32(cur_op, 0));
                        break;
                    case MVM_operand_int64:
                        operand_size = 8;
                        a("%"PRId64, MVM_BC_get_I64(cur_op, 0));
                        break;
                    case MVM_operand_uint8:
                        operand_size = 1;
                        a("%"PRIu8, GET_I8(cur_op, 0));
                        break;
                    case MVM_operand_uint16:
                        operand_size = 2;
                        a("%"PRIu16, GET_I16(cur_op, 0));
                        break;
                    case MVM_operand_uint32:
                        operand_size = 4;
                        a("%"PRIu32, GET_I32(cur_op, 0));
                        break;
                    case MVM_operand_uint64:
                        operand_size = 8;
                        a("%"PRIu64, MVM_BC_get_I64(cur_op, 0));
                        break;
                    case MVM_operand_num32:
                        operand_size = 4;
                        a("%f", GET_N32(cur_op, 0));
                        break;
                    case MVM_operand_num64:
                        operand_size = 8;
                        a("%f", MVM_BC_get_N64(cur_op, 0));
                        break;
                    case MVM_operand_callsite:
                        operand_size = 2;
                        a("Callsite_%"PRIu16, GET_UI16(cur_op, 0));
                        break;
                    case MVM_operand_coderef:
                        operand_size = 2;
                        a("Frame_%"PRIu16, GET_UI16(cur_op, 0));
                        break;
                    case MVM_operand_str:
                        operand_size = 4;
                        if (GET_UI32(cur_op, 0) < cu->body.num_strings) {
                            tmpstr = MVM_string_utf8_encode_C_string(
                                    tc, MVM_cu_string(tc, cu, GET_UI32(cur_op, 0)));
                            /* XXX C-string-literal escape the \ and '
                                and line breaks and non-ascii someday */
                            a("'%s'", tmpstr);
                            MVM_free(tmpstr);
                        }
                        else
                            a("invalid string index: %d", GET_UI32(cur_op, 0));
                        break;
                    case MVM_operand_ins:
                        operand_size = 4;
                        /* luckily all the ins operands are at the end
                        of op operands, so I can wait to resolve the label
                        to the end. */
                        if (GET_UI32(cur_op, 0) < bytecode_size) {
                            labels[GET_UI32(cur_op, 0)] |= MVM_val_branch_target;
                            jumps[lineno] = GET_UI32(cur_op, 0);
                        }
                        break;
                    case MVM_operand_obj:
                        /* not sure what a literal object is */
                        operand_size = 4;
                        break;
                    case MVM_operand_spesh_slot:
                        operand_size = 2;
                        a("sslot(%d)", GET_UI16(cur_op, 0));
                        break;
                    default:
                        fprintf(stderr, "what is an operand of type %d??\n", op_type);
                        abort(); /* never reached, silence compiler warnings */
                }
            }
            else if (op_rw == MVM_operand_read_reg || op_rw == MVM_operand_write_reg) {
                /* register operand */
                MVMuint8 frame_has_inlines = maybe_candidate && maybe_candidate->num_inlines ? 1 : 0;
                MVMuint16 *local_types = frame_has_inlines ? maybe_candidate->local_types : frame->body.local_types;
                MVMuint16 num_locals   = frame_has_inlines ? maybe_candidate->num_locals : frame->body.num_locals;
                operand_size = 2;
                a("loc_%u_%s", GET_REG(cur_op, 0),
                    get_typename(local_types[GET_REG(cur_op, 0)]));
            }
            else if (op_rw == MVM_operand_read_lex || op_rw == MVM_operand_write_lex) {
                /* lexical operand */
                MVMuint16 idx, frames, m;
                MVMStaticFrame *applicable_frame = static_frame;

                operand_size = 4;
                idx = GET_UI16(cur_op, 0);
                frames = GET_UI16(cur_op, 2);

                m = frames;
                while (m > 0) {
                    applicable_frame = applicable_frame->body.outer;
                    m--;
                }
                /* inefficient, I know. should use a hash. */
                for (m = 0; m < cu->body.num_frames; m++) {
                    if (get_frame(tc, cu, m) == applicable_frame) {
                        char *lexname = frame_lexicals ? frame_lexicals[m][idx] : "lex??";
                        a("lex_Frame_%u_%s_%s", m, lexname,
                            get_typename(applicable_frame->body.lexical_types[idx]));
                    }
                }
            }
            cur_op += operand_size;
        }

        lines[lineno++] = o;
    }
    {
        MVMuint32 *linelabels = MVM_calloc(lineno, sizeof(MVMuint32));
        MVMuint32 byte_offset = 0;
        MVMuint32 line_number = 0;
        MVMuint32 label_number = 1;
        MVMuint32 *annotations = MVM_calloc(lineno, sizeof(MVMuint32));

        for (; byte_offset < bytecode_size; byte_offset++) {
            if (labels[byte_offset] & MVM_val_branch_target) {
                /* found a byte_offset where a label should be.
                 now crawl up through the lines to find which line starts there */
                while (line_number < lineno && linelocs[line_number] != byte_offset) line_number++;
                if (line_number < lineno)
                    linelabels[line_number] = label_number++;
            }
        }
        o = oP;
        l = lP;
        s = sP;

        i = 0;
        /* resolve annotation line numbers */
        for (j = 0; j < frame->body.num_annotations; j++) {
            MVMuint32 ann_offset = GET_UI32(frame->body.annotations_data, j*12);
            for (; i < lineno; i++) {
                if (linelocs[i] == ann_offset) {
                    annotations[i] = j + 1;
                    break;
                }
            }
        }

        for (j = 0; j < lineno; j++) {
            if (annotations[j]) {
                MVMuint16 shi = GET_UI16(frame->body.annotations_data + 4, (annotations[j] - 1)*12);
                tmpstr = MVM_string_utf8_encode_C_string(
                    tc, MVM_cu_string(tc, cu, shi < cu->body.num_strings ? shi : 0));
                a("     annotation: %s:%u\n", tmpstr, GET_UI32(frame->body.annotations_data, (annotations[j] - 1)*12 + 8));
                MVM_free(tmpstr);
            }
            if (linelabels[j])
                a("     label_%u:\n", linelabels[j]);
            a("%05d   %s", j, lines[j]);
            MVM_free(lines[j]);
            if (jumps[j]) {
                /* horribly inefficient for large frames.  again, should use a hash */
                line_number = 0;
                while (line_number < lineno && linelocs[line_number] != jumps[j]) line_number++;
                if (line_number < lineno)
                    a("label_%u(%05u)", linelabels[line_number], line_number);
                else
                    a("label (invalid: %05u)", jumps[j]);
            }
            a("\n");
        }
        MVM_free(lines);
        MVM_free(jumps);
        MVM_free(linelocs);
        MVM_free(linelabels);
        MVM_free(labels);
        MVM_free(annotations);
    }

    *oo = o;
    *os = s;
    *ol = l;
}
void datum_to_bson(const char* field_name, mongo::BSONObjBuilder& builder,
    Datum val, bool is_null, Oid typid)
{
    PGBSON_LOG << "BEGIN datum_to_bson, field_name=" << field_name << ", typeid=" << typid << PGBSON_ENDL;

    if (field_name == NULL)
    {
        field_name = "";
    }

    if (is_null)
    {
        builder.appendNull(field_name);
    }
    else
    {
        switch(typid)
        {
            case BOOLOID:
                 builder.append(field_name, DatumGetBool(val));
                 break;

            case CHAROID:
            {
                char c = DatumGetChar(val);
                builder.append(field_name, &c, 1);
                break;
            }

            case INT8OID:
                builder.append(field_name, (long long)DatumGetInt64(val));
                break;

            case INT2OID:
                builder.append(field_name, DatumGetInt16(val));
                break;

            case INT4OID:
                builder.append(field_name, DatumGetInt32(val));
                break;

            case TEXTOID:
            case JSONOID:
            case XMLOID:
            {
                text* t = DatumGetTextP(val);
                builder.append(field_name, VARDATA(t), VARSIZE(t)-VARHDRSZ+1);
                break;
            }

            case FLOAT4OID:
                builder.append(field_name, DatumGetFloat4(val));
                break;

            case FLOAT8OID:
                builder.append(field_name, DatumGetFloat8(val));
                break;

            case RECORDOID:
            {
                mongo::BSONObjBuilder sub(builder.subobjStart(field_name));
                composite_to_bson(sub, val);
                sub.done();
                break;
            }

            case TIMESTAMPOID:
            {
                Timestamp ts = DatumGetTimestamp(val);
                #ifdef HAVE_INT64_TIMESTAMP
                mongo::Date_t date(ts);
                #else
                mongo::Date_t date(ts * 1000);
                #endif

                builder.append(field_name, date);
                break;
            }

            default:
            {
                PGBSON_LOG << "datum_to_bson - unknown type, using text output." << PGBSON_ENDL;
                PGBSON_LOG << "datum_to_bson - type=" << get_typename(typid) << PGBSON_ENDL;
                if (get_typename(typid) == "bson")
                {
                    bytea* data = DatumGetBson(val);
                    mongo::BSONObj obj(VARDATA_ANY(data));
                    builder.append(field_name, obj);
                }
                else
                {
                    // use text output for the type
                    bool typisvarlena = false;
                    Oid typoutput;
                    getTypeOutputInfo(typid, &typoutput, &typisvarlena);
                    PGBSON_LOG << "datum_to_bson - typisvarlena=" << std::boolalpha << typisvarlena << PGBSON_ENDL;
                    Datum out_val = val;
                    /*
                     * If we have a toasted datum, forcibly detoast it here to avoid
                     * memory leakage inside the type's output routine.
                     */
                    if (typisvarlena)
                    {
                        out_val = PointerGetDatum(PG_DETOAST_DATUM(val));
                        PGBSON_LOG << "datum_to_bson - var len valuie detoasted" << PGBSON_ENDL;
                    }

                    char* outstr = OidOutputFunctionCall(typoutput, out_val);
                    builder.append(field_name, outstr);

                    /* Clean up detoasted copy, if any */
                    if (val != out_val)
                        pfree(DatumGetPointer(out_val));
                }
            }
        } // switch
    } // if not null

    PGBSON_LOG << "END datum_to_bson, field_name=" << field_name << PGBSON_ENDL;

}