⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 erl_printf_term.c

📁 OTP是开放电信平台的简称
💻 C
字号:
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include "erl_printf_term.h"#include "sys.h"#include "big.h"#define PRINT_CHAR(CNT, FN, ARG, C)					\do {									\    int res__ = erts_printf_char((FN), (ARG), (C));			\    if (res__ < 0)							\	return res__;							\    (CNT) += res__;							\} while (0)#define PRINT_STRING(CNT, FN, ARG, STR)					\do {									\    int res__ = erts_printf_string((FN), (ARG), (STR));			\    if (res__ < 0)							\	return res__;							\    (CNT) += res__;							\} while (0)#define PRINT_BUF(CNT, FN, ARG, BUF, LEN)				\do {									\    int res__ = erts_printf_buf((FN), (ARG), (char*)(BUF), (LEN));	\    if (res__ < 0)							\	return res__;							\    (CNT) += res__;							\} while (0)#define PRINT_POINTER(CNT, FN, ARG, PTR)				\do {									\    int res__ = erts_printf_pointer((FN), (ARG), (void *) (PTR));	\    if (res__ < 0)							\	return res__;							\    (CNT) += res__;							\} while (0)#define PRINT_ULONG(CNT, FN, ARG, C, P, W, I)				\do {									\    int res__ = erts_printf_ulong((FN), (ARG), (C), (P), (W), (I));	\    if (res__ < 0)							\	return res__;							\    (CNT) += res__;							\} while (0)#define PRINT_SLONG(CNT, FN, ARG, C, P, W, I)				\do {									\    int res__ = erts_printf_slong((FN), (ARG), (C), (P), (W), (I));	\    if (res__ < 0)							\	return res__;							\    (CNT) += res__;							\} while (0)#define PRINT_DOUBLE(CNT, FN, ARG, C, P, W, I)				\do {									\    int res__ = erts_printf_double((FN), (ARG), (C), (P), (W), (I));	\    if (res__ < 0)							\	return res__;							\    (CNT) += res__;							\} while (0)/* CTYPE macros */#define LATIN1#define IS_DIGIT(c)  ((c) >= '0' && (c) <= '9')#ifdef LATIN1#define IS_LOWER(c)  (((c) >= 'a' && (c) <= 'z') \		      || ((c) >= 128+95 && (c) <= 255 && (c) != 247))#define IS_UPPER(c)  (((c) >= 'A' && (c) <= 'Z') \		      || ((c) >= 128+64 && (c) <= 128+94 && (c) != 247-32))#else#define IS_LOWER(c)  ((c) >= 'a' && (c) <= 'z')#define IS_UPPER(c)  ((c) >= 'A' && (c) <= 'Z')#endif#define IS_ALNUM(c)  (IS_DIGIT(c) || IS_LOWER(c) || IS_UPPER(c))/* We don't include 160 (non-breaking space). */#define IS_SPACE(c)  (c == ' ' || c == '\n' || c == '\t' || c == '\r')#ifdef LATIN1#define IS_CNTRL(c)  ((c) < ' ' || (c) == 127 \		      || ((c) >= 128 && (c) < 128+32))#else/* Treat all non-ASCII as control characters */#define IS_CNTRL(c)  ((c) < ' ' || (c) >= 127)#endif#define IS_PRINT(c)  (!IS_CNTRL(c))/* return 0 if list is not a non-empty flat list of printable characters */static intis_printable_string(Eterm list){    int len = 0;    int c;    while(is_list(list)) {	Eterm* consp = list_val(list);	Eterm hd = CAR(consp);	if (!is_byte(hd))	    return 0;	c = signed_val(hd);	/* IS_PRINT || IS_SPACE would be another way to put it */	if (IS_CNTRL(c) && !IS_SPACE(c))	   return 0;	len++;	list = CDR(consp);    }    if (is_nil(list))	return len;    return 0;}/* print a atom doing what quoting is necessary */static int print_atom_name(fmtfn_t fn, void* arg, Eterm atom, long *dcount){    int n, i;    int res;    int need_quote;    int pos;    byte *s;    byte *cpos;    int c;    res = 0;    i = atom_val(atom);    if ((i < 0) || (i >= atom_table_size()) ||  (atom_tab(i) == NULL)) {	PRINT_STRING(res, fn, arg, "<bad atom index: ");	PRINT_SLONG(res, fn, arg, 'd', 0, 1, (signed long) i);	PRINT_CHAR(res, fn, arg, '>');	return res;    }    s = atom_tab(i)->name;    n = atom_tab(i)->len;    *dcount -= atom_tab(i)->len;    if (n == 0) {	PRINT_STRING(res, fn, arg, "''");	return res;    }    need_quote = 0;    cpos = s;    pos = n - 1;    c = *cpos++;    if (!IS_LOWER(c))	need_quote++;    else {	while (pos--) {	    c = *cpos++;	    if (!IS_ALNUM(c) && (c != '_')) {		need_quote++;		break;	    }	}    }    cpos = s;    pos = n;    if (need_quote)	PRINT_CHAR(res, fn, arg, '\'');    while(pos--) {	c = *cpos++;	switch(c) {	case '\'': PRINT_STRING(res, fn, arg, "\\'"); break;	case '\\': PRINT_STRING(res, fn, arg, "\\\\"); break;	case '\n': PRINT_STRING(res, fn, arg, "\\n"); break;	case '\f': PRINT_STRING(res, fn, arg, "\\f"); break;	case '\t': PRINT_STRING(res, fn, arg, "\\t"); break;	case '\r': PRINT_STRING(res, fn, arg, "\\r"); break;	case '\b': PRINT_STRING(res, fn, arg, "\\b"); break;	case '\v': PRINT_STRING(res, fn, arg, "\\v"); break;	default:	    if (IS_CNTRL(c)) {		PRINT_CHAR(res, fn, arg, '\\');		PRINT_ULONG(res, fn, arg, 'o', 1, 3, (unsigned long) c);	    }	    else		PRINT_CHAR(res, fn, arg, (char) c);	    break;	}    }    if (need_quote)	PRINT_CHAR(res, fn, arg, '\'');    return res;}static intprint_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount){    int res;    int i;    Uint32 *ref_num;    Eterm* nobj;    res = 0;    if ((*dcount)-- <= 0)	return res;#ifdef HYBRID___NOT_ACTIVE    /* Color coded output based on memory location */    if(ptr_val(obj) >= global_heap && ptr_val(obj) < global_hend)        PRINT_STRING(res, fn, arg, "\033[32m");#ifdef INCREMENTAL    else if(ptr_val(obj) >= inc_fromspc && ptr_val(obj) < inc_fromend)        PRINT_STRING(res, fn, arg, "\033[33m");#endif    else if(IS_CONST(obj))        PRINT_STRING(res, fn, arg, "\033[34m");    else        PRINT_STRING(res, fn, arg, "\033[31m");#endif    if (is_CP(obj)) {	PRINT_STRING(res, fn, arg, "<cp/header:");	PRINT_POINTER(res, fn, arg, obj);	PRINT_CHAR(res, fn, arg, '>');	return res;    }    switch (tag_val_def(obj)) {    case NIL_DEF:	PRINT_STRING(res, fn, arg, "[]");	break;    case ATOM_DEF: {	int tres = print_atom_name(fn, arg, obj, dcount);	if (tres < 0)	    return tres;	res += tres;	if (*dcount <= 0)	    return res;	break;    }    case SMALL_DEF:	PRINT_SLONG(res, fn, arg, 'd', 0, 1, (signed long) signed_val(obj));	break;    case BIG_DEF: {	int print_res;	char def_buf[64];	char *buf, *big_str;	Uint sz = (Uint) big_decimal_estimate(obj);	sz++;	if (sz <= 64)	    buf = &def_buf[0];	else	    buf = erts_alloc(ERTS_ALC_T_TMP, sz);	big_str = erts_big_to_string(obj, buf, sz);	print_res = erts_printf_string(fn, arg, big_str);	if (buf != &def_buf[0])	    erts_free(ERTS_ALC_T_TMP, (void *) buf);	if (print_res < 0)	    return print_res;	res += print_res;	break;    }    case REF_DEF:    case EXTERNAL_REF_DEF:	PRINT_STRING(res, fn, arg, "#Ref<");	PRINT_ULONG(res, fn, arg, 'u', 0, 1,		    (unsigned long) ref_channel_no(obj));	ref_num = ref_numbers(obj);	for (i = ref_no_of_numbers(obj)-1; i >= 0; i--) {	    PRINT_CHAR(res, fn, arg, '.');	    PRINT_ULONG(res, fn, arg, 'u', 0, 1, (unsigned long) ref_num[i]);	}	PRINT_CHAR(res, fn, arg, '>');	break;    case PID_DEF:    case EXTERNAL_PID_DEF:	PRINT_CHAR(res, fn, arg, '<');	PRINT_ULONG(res, fn, arg, 'u', 0, 1,		    (unsigned long) pid_channel_no(obj));	PRINT_CHAR(res, fn, arg, '.');	PRINT_ULONG(res, fn, arg, 'u', 0, 1,		    (unsigned long) pid_number(obj));	PRINT_CHAR(res, fn, arg, '.');	PRINT_ULONG(res, fn, arg, 'u', 0, 1,		    (unsigned long) pid_serial(obj));	PRINT_CHAR(res, fn, arg, '>');	break;    case PORT_DEF:    case EXTERNAL_PORT_DEF:	PRINT_STRING(res, fn, arg, "#Port<");	PRINT_ULONG(res, fn, arg, 'u', 0, 1,		    (unsigned long) port_channel_no(obj));	PRINT_CHAR(res, fn, arg, '.');	PRINT_ULONG(res, fn, arg, 'u', 0, 1,		    (unsigned long) port_number(obj));	PRINT_CHAR(res, fn, arg, '>');	break;    case LIST_DEF:	if (is_printable_string(obj)) {	    int c;	    PRINT_CHAR(res, fn, arg, '"');	    nobj = list_val(obj);	    while (1) {		if ((*dcount)-- <= 0)		    return res;		c = signed_val(*nobj++);		if (c == '\n')		    PRINT_STRING(res, fn, arg, "\\n");		else {		    if (c == '"')			PRINT_CHAR(res, fn, arg, '\\');		    PRINT_CHAR(res, fn, arg, (char) c);		}		if (is_not_list(*nobj))		    break;		nobj = list_val(*nobj);	    }	    PRINT_CHAR(res, fn, arg, '"');	} else {	    PRINT_CHAR(res, fn, arg, '[');	    nobj = list_val(obj);	    while (1) {		int tres = print_term(fn, arg, *nobj++, dcount);		if (tres < 0)		    return tres;		res += tres;		if (*dcount <= 0)		    return res;		if (is_not_list(*nobj))		    break;		PRINT_CHAR(res, fn, arg, ',');		nobj = list_val(*nobj);	    }	    if (is_not_nil(*nobj)) {		int tres;		PRINT_CHAR(res, fn, arg, '|');		tres = print_term(fn, arg, *nobj, dcount);		if (tres < 0)		    return tres;		res += tres;		if (*dcount <= 0)		    return res;	    }	    PRINT_CHAR(res, fn, arg, ']');	}	break;    case TUPLE_DEF:	nobj = tuple_val(obj);	/* pointer to arity */	i = arityval(*nobj);	/* arity */	PRINT_CHAR(res, fn, arg, '{');	while (i--) {	    int tres = print_term(fn, arg, *++nobj, dcount);	    if (tres < 0)		return tres;	    res += tres;	    if (*dcount <= 0)		return res;	    if (i >= 1)		PRINT_CHAR(res, fn, arg, ',');	}	PRINT_CHAR(res, fn, arg, '}');	break;    case FLOAT_DEF: {	    FloatDef ff;	    GET_DOUBLE(obj, ff);	    PRINT_DOUBLE(res, fn, arg, 'e', 6, 0, ff.fd);	}	break;    case BINARY_DEF:	{	    ProcBin* pb = (ProcBin *) binary_val(obj);	    if (pb->size == 1)		PRINT_STRING(res, fn, arg, "<<1 byte>>");	    else {		PRINT_STRING(res, fn, arg, "<<");		PRINT_ULONG(res, fn, arg, 'u', 0, 1, (unsigned long) pb->size);		PRINT_STRING(res, fn, arg, " bytes>>");	    }	}	break;    case EXPORT_DEF:	{	    Export* ep = (Export *) (export_val(obj))[1];	    Atom* module = atom_tab(atom_val(ep->code[0]));	    Atom* name = atom_tab(atom_val(ep->code[1]));	    PRINT_STRING(res, fn, arg, "#Fun<");	    PRINT_BUF(res, fn, arg, module->name, module->len);	    PRINT_CHAR(res, fn, arg, '.');	    PRINT_BUF(res, fn, arg, name->name, name->len);	    PRINT_CHAR(res, fn, arg, '.');	    PRINT_SLONG(res, fn, arg, 'd', 0, 1,			(signed long) ep->code[2]);	    PRINT_CHAR(res, fn, arg, '>');	}	break;    case FUN_DEF:	{	    ErlFunThing *funp = (ErlFunThing *) fun_val(obj);	    Atom *ap = atom_tab(atom_val(funp->fe->module));	    PRINT_STRING(res, fn, arg, "#Fun<");	    PRINT_BUF(res, fn, arg, ap->name, ap->len);	    PRINT_CHAR(res, fn, arg, '.');	    PRINT_SLONG(res, fn, arg, 'd', 0, 1,			(signed long) funp->fe->old_index);	    PRINT_CHAR(res, fn, arg, '.');	    PRINT_SLONG(res, fn, arg, 'd', 0, 1,			(signed long) funp->fe->old_uniq);	    PRINT_CHAR(res, fn, arg, '>');	}	break;    default:	PRINT_STRING(res, fn, arg, "<unknown:");	PRINT_POINTER(res, fn, arg, obj);	PRINT_CHAR(res, fn, arg, '>');	break;    }    return res;}interts_printf_term(fmtfn_t fn, void* arg, unsigned long term, long precision){    int res = print_term(fn, arg, (Uint) term, &precision);    if (res < 0)	return res;    if (precision <= 0)	PRINT_STRING(res, fn, arg, "... ");    return res;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -