Example #1
0
int parse_file(const char *filename)
{
    FILE *file;
    char line[MAX_LINE_SIZE];
    char left[MAX_LINE_SIZE], op[MAX_LINE_SIZE], right[MAX_LINE_SIZE];
    unsigned int line_num;

    file = fopen(filename, "r");
    if (file == NULL)
        return 0;

    /* Reads the entire file */
    line_num = 1;
    while (fgets(line, MAX_LINE_SIZE, file) != NULL) {
        int err;

#ifdef DEBUG
        fprintf(stderr, "%s", line);
#endif

        /* Skip comments, which are denoted by a '#' on the first line. */
        if ((strlen(line) > 1) && (line[0] == '#'))
            goto cleanup;

        /* Splits the line into bits */
        err = parse_line(line, left, op, right);
        if (err != 0) {
            fprintf(stderr, "Read error %d on line %d of %s:\n\t%s",
                    err, line_num, filename, line);
            return err;
        }

        /* Calls the correct function to parse this input line */
        if (parse_select(left, op, right) != 0) {
            fprintf(stderr, "Error parsing line %d:\n", line_num);
            fprintf(stderr, "%s\n", line);
            return -1;
        }

      cleanup:
        line_num++;
    }

    fclose(file);

    return 0;
}
Example #2
0
int pv_parse_select_name(pv_spec_p sp, str *in)
{
	select_t *sel = 0;
	char c;
	char *p;
	if (in == NULL || in->s == NULL || sp == NULL)
		return -1;

	c = in->s[in->len];
	in->s[in->len] = '\0';
	p = in->s;
	if(parse_select(&p, &sel)<0)
	{
		LM_ERR("invalid select name [%.*s]\n",
				in->len, in->s);
		in->s[in->len] = c;
		return -1;
	}
	in->s[in->len] = c;
	sp->pvp.pvn.u.dname = (void*)sel;
	sp->pvp.pvn.type = PV_NAME_OTHER;
	return 0;
}
Example #3
0
/** Generic parameter fixup function.
 *  Creates a fparam_t structure.
 *  @param type  contains allowed parameter types
 *  @param param is the parameter that will be fixed-up
 *
 * @return
 *    0 on success,
 *    1 if the param doesn't match the specified type
 *    <0 on failure
 */
int fix_param(int type, void** param)
{
	fparam_t* p;
	str name, s;
	int num;
	int err;

	p = (fparam_t*)pkg_malloc(sizeof(fparam_t));
	if (!p) {
		LM_ERR("No memory left\n");
		return E_OUT_OF_MEM;
	}
	memset(p, 0, sizeof(fparam_t));
	p->orig = *param;

	switch(type) {
		case FPARAM_UNSPEC:
			LM_ERR("Invalid type value\n");
			goto error;
		case FPARAM_STRING:
			p->v.asciiz = *param;
			/* no break */
		case FPARAM_STR:
			p->v.str.s = (char*)*param;
			p->v.str.len = strlen(p->v.str.s);
			p->fixed = &p->v;
			break;
		case FPARAM_INT:
			s.s = (char*)*param;
			s.len = strlen(s.s);
			err = str2sint(&s, &num);
			if (err == 0) {
				p->v.i = (int)num;
			} else {
				/* Not a number */
				pkg_free(p);
				return 1;
			}
			p->fixed = (void*)(long)num;
			break;
		case FPARAM_REGEX:
			if ((p->v.regex = pkg_malloc(sizeof(regex_t))) == 0) {
				LM_ERR("No memory left\n");
				goto error;
			}
			if (regcomp(p->v.regex, *param,
						REG_EXTENDED|REG_ICASE|REG_NEWLINE)) {
				pkg_free(p->v.regex);
				p->v.regex=0;
				/* not a valid regex */
				goto no_match;
			}
			p->fixed = p->v.regex;
			break;
		case FPARAM_AVP:
			name.s = (char*)*param;
			name.len = strlen(name.s);
			trim(&name);
			if (!name.len || name.s[0] != '$') {
				/* Not an AVP identifier */
				goto no_match;
			}
			name.s++;
			name.len--;
			if (parse_avp_ident(&name, &p->v.avp) < 0) {
				/* invalid avp identifier (=> no match) */
				goto no_match;
			}
			p->fixed = &p->v;
			break;
		case FPARAM_SELECT:
			name.s = (char*)*param;
			name.len = strlen(name.s);
			trim(&name);
			if (!name.len || name.s[0] != '@') {
				/* Not a select identifier */
				goto no_match;
			}
			if (parse_select(&name.s, &p->v.select) < 0) {
				LM_ERR("Error while parsing select identifier\n");
				goto error;
			}
			p->fixed = &p->v;
			break;
		case FPARAM_SUBST:
			s.s = *param;
			s.len = strlen(s.s);
			p->v.subst = subst_parser(&s);
			if (!p->v.subst) {
				LM_ERR("Error while parsing regex substitution\n");
				goto error;
			}
			p->fixed = &p->v;
			break;
		case FPARAM_PVS:
			name.s = (char*)*param;
			name.len = strlen(name.s);
			trim(&name);
			if (!name.len || name.s[0] != '$'){
				/* not a pvs identifier */
				goto no_match;
			}
			p->v.pvs=pkg_malloc(sizeof(pv_spec_t));
			if (p->v.pvs==0){
				LM_ERR("out of memory while parsing pv_spec_t\n");
				goto error;
			}
			if (pv_parse_spec2(&name, p->v.pvs, 1)==0){
				/* not a valid pvs identifier (but it might be an avp) */
				pkg_free(p->v.pvs);
				p->v.pvs=0;
				goto no_match;
			}
			p->fixed = p->v.pvs;
			break;
		case FPARAM_PVE:
			name.s = (char*)*param;
			name.len = strlen(name.s);
			if (pv_parse_format(&name, &p->v.pve)<0){
				LM_ERR("bad PVE format: \"%.*s\"\n", name.len, name.s);
				goto error;
			}
			p->fixed = &p->v;
			break;
	}

	p->type = type;
	*param = (void*)p;
	return 0;

no_match:
	pkg_free(p);
	return 1;
error:
	pkg_free(p);
	return E_UNSPEC;
}
Example #4
0
File: main.cpp Project: CCJY/coliru
constexpr
std::tuple<const char*, const char*, const char*, const char*>
    operator"" _sql(const char* begin, size_t len)
{
    return parse_select(begin, begin + len);
}
Example #5
0
int xl_parse_format(char *s, xl_elog_p *el)
{
	char *p, c;
	int n = 0;
	xl_elog_p e, e0;
	struct hdr_field  hdr;
	str name;
	int avp_flags, avp_index;
	int_str avp_name;
	select_t *sel;
	
	if(s==NULL || el==NULL)
		return -1;

	DBG("XLOG: xl_parse_format: parsing [%s]\n", s);

	p = s;
	*el = NULL;
	e = e0 = NULL;

	while(*p)
	{
		e0 = e;
		e = pkg_malloc(sizeof(xl_elog_t));
		if(!e)
			goto error;
		memset(e, 0, sizeof(xl_elog_t));
		n++;
		if(*el == NULL)
			*el = e;
		if(e0)
			e0->next = e;

		e->text.s = p;
		while(*p && *p!='%')
			p++;
		e->text.len = p - e->text.s;
		if(*p == '\0')
			break;

		p++;
		switch(*p)
		{
			case 'b':
				p++;
				switch(*p)
				{
					case 'r':
						e->itf = xl_get_branch;
					break;
					case 'R':
						e->itf = xl_get_branches;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'c':
				p++;
				switch(*p)
				{
					case 'i':
						e->itf = xl_get_callid;
					break;
					case 's':
						e->itf = xl_get_cseq;
					break;
					case 't':
						e->itf = xl_get_contact;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'C':
				p++;
				e->hparam.s = p;

				/* foreground */
				switch(*p)
                {
					case 'x':
					case 's': case 'r': case 'g':
					case 'y': case 'b': case 'p':
					case 'c': case 'w': case 'S':
					case 'R': case 'G': case 'Y':
					case 'B': case 'P': case 'C':
					case 'W':
					break;
					default:
						e->itf = xl_get_empty;
						goto error;
				}
				p++;

				/* background */
				switch(*p)
				{
					case 'x':
					case 's': case 'r': case 'g':
					case 'y': case 'b': case 'p':
					case 'c': case 'w':
					break;
					default:
						e->itf = xl_get_empty;
						goto error;
				}

				/* end */
				e->hparam.len = 2;
				e->itf = xl_get_color;
			break;
			case 'd':
				p++;
				switch(*p)
				{
					case 's':
						e->itf = xl_get_dset;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'f':
				p++;
				switch(*p)
				{
					case 'u':
						e->itf = xl_get_from;
					break;
					case 't':
						e->itf = xl_get_from_tag;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'H':
				p++;
				e->itf = xl_get_host;
				switch(*p)
				{
					case 'n':
						e->hindex = XL_HOST_NAME;
					break;
					case 'd':
						e->hindex = XL_HOST_DOMAIN;
					break;
					case 'f':
						e->hindex = XL_HOST_FULL;
					break;
					case 'i':
						e->hindex = XL_HOST_IPADDR;
					break;
					default:
						e->hindex = XL_HOST_NULL;
						break;
				}
				break;
			case 'm':
				p++;
				switch(*p)
				{
					case 'b':
						e->itf = xl_get_msg_buf;
					break;
					case 'f':
						e->itf = xl_get_flags;
					break;
					case 'i':
						e->itf = xl_get_msgid;
						e->hindex = 10;
					break;
					case 'l':
						e->itf = xl_get_msg_len;
					break;
					case 'x':
						e->itf = xl_get_msgid;
						e->hindex = 16;
					break;
					default:
						e->itf = xl_get_null;
				}
				break;
			case 'n':
				p++;
				switch(*p)
				{
					case 'h':
						e->itf = xl_get_nexthop;
					break;
					default:
						e->itf = xl_get_null;
				}
				break;
			case 'p':
				p++;
				switch(*p)
				{
					case 'p':
						e->itf = xl_get_pid;
						e->hindex = 10;
					break;
					case 'x':
						e->itf = xl_get_pid;
						e->hindex = 16;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'r':
				p++;
				switch(*p)
				{
					case 'm':
						e->itf = xl_get_method;
					break;
					case 'u':
						e->itf = xl_get_ruri;
					break;
					case 's':
						e->itf = xl_get_status;
					break;
					case 'r':
						e->itf = xl_get_reason;
					break;
					case 't':
						e->itf = xl_get_refer_to;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'R':
				p++;
				switch(*p)
				{
					case 'i':
						e->itf = xl_get_rcvip;
					break;
					case 'p':
						e->itf = xl_get_rcvport;
					break;
					default:
					e->itf = xl_get_null;
				}
			break;
			case 's':
				p++;
				switch(*p)
				{
					case 'i':
						e->itf = xl_get_srcip;
					break;
					case 'p':
						e->itf = xl_get_srcport;
					break;
					default:
					e->itf = xl_get_null;
				}
			break;
			case 't':
				p++;
				switch(*p)
				{
					case 'u':
						e->itf = xl_get_to;
					break;
					case 't':
						e->itf = xl_get_to_tag;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'T':
				p++;
				switch(*p)
				{
					case 's':
						e->itf = xl_get_times;
						e->hindex = 10;
					break;
					case 'f':
						e->itf = xl_get_timef;
					break;
					case 'x':
						e->itf = xl_get_times;
						e->hindex = 16;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'u':
				p++;
				switch(*p)
				{
					case 'a':
						e->itf = xl_get_useragent;
					break;
					case 'q':
						e->itf = xl_get_unique;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case '{':
				p++;
				/* we expect a letter */
				if((*p < 'A' || *p > 'Z') && (*p < 'a' || *p > 'z'))
				{
					LOG(L_ERR, "xlog: xl_parse_format: error parsing format"
						" [%s] pos [%d]\n", s, (int)(p-s));
					goto error;
				}
				e->hparam.s = p;
				while(*p && *p!='}' && *p!='[')
					p++;
				if(*p == '\0')
				{
					LOG(L_ERR, "xlog: xl_parse_format: error parsing format"
						" [%s] expecting '}' after position [%d]\n", s,
						(int)(e->hparam.s-s));
					goto error;
				}

				e->hparam.len = p - e->hparam.s;
				/* check if we have index */
				if(*p == '[')
				{
					p++;
					if(*p=='-')
					{
						p++;
						if(*p!='1')
						{
							LOG(L_ERR, "xlog: xl_parse_format: error"
								" parsing format [%s] -- only -1 is accepted"
								" as a negative index\n", s);
								goto error;
						}
						e->hindex = XLOG_PRINT_LAST;
						p++;
					} else if (*p=='*') {
						e->hindex = XLOG_PRINT_ALL;
						p++;
					} else {
						while(*p>='0' && *p<='9')
						{
							e->hindex = e->hindex * 10 + *p - '0';
							p++;
						}
					}
					if(*p != ']')
					{
						LOG(L_ERR, "xlog: xl_parse_format: error parsing format"
							" [%s] expecting ']' after position [%d]\n", s,
							(int)(e->hparam.s - s + e->hparam.len));
						goto error;
					}
					p++;
				}
				if(*p != '}')
				{
					LOG(L_ERR, "xlog: xl_parse_format: error parsing format"
						" [%s] expecting '}' after position [%d]!\n", s,
						(int)(e->hparam.s-s));
					goto error;
				}

				DBG("xlog: xl_parse_format: header name [%.*s] index [%d]\n",
						e->hparam.len, e->hparam.s, e->hindex);

				/* optimize for known headers -- fake header name */
				c = e->hparam.s[e->hparam.len];
				e->hparam.s[e->hparam.len] = ':';
				e->hparam.len++;
				/* ugly hack for compact header names -- !!fake length!!
				 * -- parse_hname2 expects name buffer length >= 4
				 */
				if (parse_hname2(e->hparam.s,
						e->hparam.s + ((e->hparam.len<4)?4:e->hparam.len),
						&hdr)==0)
				{
					LOG(L_ERR,"xlog: xl_parse_format: strange error\n");
					goto error;
				}
				e->hparam.len--;
				e->hparam.s[e->hparam.len] = c;
				if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T)
				{
					LOG(L_INFO,"INFO:xlog: xl_parse_format: using "
						"hdr type (%d) instead of <%.*s>\n",
						hdr.type, e->hparam.len, e->hparam.s);
					e->hparam.len = hdr.type;
					e->hparam.s = NULL;
				}
				e->itf = xl_get_header;
			break;
			case '<':
				p++;
				/* we expect a letter */
				if((*p < 'A' || *p > 'Z') && (*p < 'a' || *p > 'z'))
				{
					LOG(L_ERR, "xlog: xl_parse_format: error parsing format"
						" [%s] pos [%d]\n", s, (int)(p-s));
					goto error;
				}
				e->hparam.s = p;
				while(*p && *p!='>' && *p!='[')
					p++;
				if(*p == '\0')
				{
					LOG(L_ERR, "xlog: xl_parse_format: error parsing format"
						" [%s] expecting '>' after position [%d]\n", s,
						(int)(e->hparam.s-s));
					goto error;
				}

				e->hparam.len = p - e->hparam.s;
				/* check if we have index */
				if(*p == '[')
				{
					p++;
					if(*p=='-')
					{
						p++;
						if(*p!='1')
						{
							LOG(L_ERR, "xlog: xl_parse_format: error"
								" parsing format [%s] -- only -1 is accepted"
								" as a negative index\n", s);
								goto error;
						}
						e->hindex = -1;
						p++;
					}
					else
					{
						while(*p>='0' && *p<='9')
						{
							e->hindex = e->hindex * 10 + *p - '0';
							p++;
						}
					}
					if(*p != ']')
					{
						LOG(L_ERR, "xlog: xl_parse_format: error parsing format"
							" [%s] expecting ']' after position [%d]\n", s,
							(int)(e->hparam.s - s + e->hparam.len));
						goto error;
					}
					p++;
				}
				if(*p != '>')
				{
					LOG(L_ERR, "xlog: xl_parse_format: error parsing format"
						" [%s] expecting '>' after position [%d]!\n", s,
						(int)(e->hparam.s-s));
					goto error;
				}

				DBG("xlog: xl_parse_format: AVP [%.*s] index [%d]\n",
						e->hparam.len, e->hparam.s, e->hindex);

				e->itf = xl_get_avp;
			break;
			case '$':
				p++;
				name.s=p;
				while ( (*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9') || (*p=='_') || (*p=='+') || (*p=='-') || (*p=='[') || (*p==']') || (*p=='.') ) p++;
				name.len=p-name.s;
				p--;
				if (parse_avp_name(&name, &avp_flags, &avp_name, &avp_index) < 0) {
					ERR("error while parsing AVP name\n");
					goto error;
				}
				e->itf = xl_get_avp;
				e->hflags=avp_flags;
				e->hparam.s=name.s;
				e->hparam.len=name.len;
				e->hindex=avp_index;
				DBG("flags %x  name %.*s  index %d\n", avp_flags, avp_name.s.len, avp_name.s.s, avp_index);
				break;
			case '@':
					/* fill select structure and call resolve_select */
				DBG("xlog: xl_parse_format: @\n");
				n=parse_select(&p, &sel);
				if (n<0) {
					ERR("xlog: xl_parse_format: parse_select returned error\n");
					goto error;
				}
				e->itf = xl_get_select;
				e->hparam.s = (char*)sel;
				p--;
				break;
			case '%':
				e->itf = xl_get_percent;
				break;
			case ' ':	/* enables spaceless terminating of avp, e.g. "blah%$avp% text goes on" */
			case '|':
				e->itf = xl_get_empty;
				break;
			default:
				e->itf = xl_get_null;
		}

		if(*p == '\0')
			break;
		p++;
	}
	DBG("XLOG: xl_parse_format: format parsed OK: [%d] items\n", n);

	return 0;

error:
	xl_elog_free_all(*el);
	*el = NULL;
	return -1;
}
Example #6
0
/* Parse an xl-formatted string pointed by s.
 * el points to the resulted linked list that is allocated
 * in shared memory when shm==1 otherwise in pkg memory.
 * If parse_cb is not NULL then regular expression back references
 * are passed to the parse_cb function that is supposed to farther parse
 * the back reference and fill in the xl_elog_t structure.
 *
 * Return value:
 *   0: success
 *  -1: error
 */
static int _xl_parse_format(char *s, xl_elog_p *el, int shm, xl_parse_cb parse_cb)
{
	char *p, c;
	int n = 0;
	xl_elog_p e, e0;
	struct hdr_field  hdr;
	str name;
	int avp_flags, avp_index;
	int_str avp_name;
	select_t *sel;
	int *range;
	
	if(s==NULL || el==NULL)
		return -1;

	DBG("XLOG: xl_parse_format: parsing [%s]\n", s);

	p = s;
	*el = NULL;
	e = e0 = NULL;
	range = NULL;

	while(*p)
	{
		e0 = e;
		if (shm)
			e = shm_malloc(sizeof(xl_elog_t));
		else
			e = pkg_malloc(sizeof(xl_elog_t));
		if(!e)
			goto error;
		memset(e, 0, sizeof(xl_elog_t));
		n++;
		if(*el == NULL)
			*el = e;
		if(e0)
			e0->next = e;

		e->text.s = p;
		while(*p && *p!='%' && *p!='\\' && !range)
			p++;

		e->text.len = p - e->text.s;
		if(*p == '\0')
			break;

		if ((*p == '\\') && !range) {
			p++;
			switch(*p)
			{
				case '\\':
					e->itf = xl_get_special;
					e->hindex = '\\';
					break;
				case 'r':
					e->itf = xl_get_special;
					e->hindex = '\r';
					break;
				case 'n':
					e->itf = xl_get_special;
					e->hindex = '\n';
					break;
				case 't':
					e->itf = xl_get_special;
					e->hindex = '\t';
					break;
				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
					/* Regular expression back reference found */
					if (!parse_cb) {
						/* There is no callback function, hence the
						 * result will be written as it is. */
						e->itf = xl_get_special;
						e->hindex = *p;
						break;
					}
					name.s = p;
					/* eat all the numeric characters */
					while ((*(p+1) >= '0') && (*(p+1) <= '9'))
						p++;
					name.len = p - name.s + 1;
					if (parse_cb(&name, shm, e)) {
						ERR("xprint: xl_parse_format: failed to parse '%.*s'\n",
							name.len, name.s);
						goto error;
					}
					break;
				default:
					/* not a special character, it will be just
					written to the result as it is */
					e->itf = xl_get_special;
					e->hindex = *p;
			}
			goto cont;
		}

		if (range)
			range = NULL;
		else
			p++;
		switch(*p)
		{
			case 'b':
				p++;
				switch(*p)
				{
					case 'r':
						e->itf = xl_get_branch;
					break;
					case 'R':
						e->itf = xl_get_branches;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'c':
				p++;
				switch(*p)
				{
					case 'i':
						e->itf = xl_get_callid;
					break;
					case 's':
						e->itf = xl_get_cseq;
					break;
					case 't':
						e->itf = xl_get_contact;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'C':
				p++;
				e->hparam.s = p;

				/* foreground */
				switch(*p)
                {
					case 'x':
					case 's': case 'r': case 'g':
					case 'y': case 'b': case 'p':
					case 'c': case 'w': case 'S':
					case 'R': case 'G': case 'Y':
					case 'B': case 'P': case 'C':
					case 'W':
					break;
					default:
						e->itf = xl_get_empty;
						goto error;
				}
				p++;

				/* background */
				switch(*p)
				{
					case 'x':
					case 's': case 'r': case 'g':
					case 'y': case 'b': case 'p':
					case 'c': case 'w':
					break;
					default:
						e->itf = xl_get_empty;
						goto error;
				}

				/* end */
				e->hparam.len = 2;
				e->itf = xl_get_color;
			break;
			case 'd':
				p++;
				switch(*p)
				{
					case 's':
						e->itf = xl_get_dset;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'f':
				p++;
				switch(*p)
				{
					case 'u':
						e->itf = xl_get_from;
					break;
					case 't':
						e->itf = xl_get_from_tag;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'H':
				p++;
				e->itf = xl_get_host;
				switch(*p)
				{
					case 'n':
						e->hindex = XL_HOST_NAME;
					break;
					case 'd':
						e->hindex = XL_HOST_DOMAIN;
					break;
					case 'f':
						e->hindex = XL_HOST_FULL;
					break;
					case 'i':
						e->hindex = XL_HOST_IPADDR;
					break;
					default:
						e->hindex = XL_HOST_NULL;
						break;
				}
				break;
			case 'm':
				p++;
				switch(*p)
				{
					case 'b':
						e->itf = xl_get_msg_buf;
					break;
					case 'f':
						e->itf = xl_get_flags;
					break;
					case 'i':
						e->itf = xl_get_msgid;
						e->hindex = 10;
					break;
					case 'l':
						e->itf = xl_get_msg_len;
					break;
					case 'x':
						e->itf = xl_get_msgid;
						e->hindex = 16;
					break;
					default:
						e->itf = xl_get_null;
				}
				break;
			case 'n':
				p++;
				switch(*p)
				{
					case 'h':
						e->itf = xl_get_nexthop;
					break;
					default:
						e->itf = xl_get_null;
				}
				break;
			case 'p':
				p++;
				switch(*p)
				{
					case 'p':
						e->itf = xl_get_pid;
						e->hindex = 10;
					break;
					case 'x':
						e->itf = xl_get_pid;
						e->hindex = 16;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'r':
				p++;
				switch(*p)
				{
					case 'm':
						e->itf = xl_get_method;
					break;
					case 'u':
						e->itf = xl_get_ruri;
					break;
					case 's':
						e->itf = xl_get_status;
					break;
					case 'r':
						e->itf = xl_get_reason;
					break;
					case 't':
						e->itf = xl_get_refer_to;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'R':
				p++;
				switch(*p)
				{
					case 'i':
						e->itf = xl_get_rcvip;
					break;
					case 'p':
						e->itf = xl_get_rcvport;
					break;
					default:
					e->itf = xl_get_null;
				}
			break;
			case 's':
				p++;
				switch(*p)
				{
					case 'i':
						e->itf = xl_get_srcip;
					break;
					case 'p':
						e->itf = xl_get_srcport;
					break;
					default:
					e->itf = xl_get_null;
				}
			break;
			case 't':
				p++;
				switch(*p)
				{
					case 'u':
						e->itf = xl_get_to;
					break;
					case 't':
						e->itf = xl_get_to_tag;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'T':
				p++;
				switch(*p)
				{
					case 's':
						e->itf = xl_get_times;
						e->hindex = 10;
					break;
					case 'f':
						e->itf = xl_get_timef;
					break;
					case 'x':
						e->itf = xl_get_times;
						e->hindex = 16;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case 'u':
				p++;
				switch(*p)
				{
					case 'a':
						e->itf = xl_get_useragent;
					break;
					case 'q':
						e->itf = xl_get_unique;
					break;
					default:
						e->itf = xl_get_null;
				}
			break;
			case '{':
				p++;
				/* we expect a letter */
				if((*p < 'A' || *p > 'Z') && (*p < 'a' || *p > 'z'))
				{
					LOG(L_ERR, "xprint: xl_parse_format: error parsing format"
						" [%s] pos [%d]\n", s, (int)(p-s));
					goto error;
				}
				e->hparam.s = p;
				while(*p && *p!='}' && *p!='[')
					p++;
				if(*p == '\0')
				{
					LOG(L_ERR, "xprint: xl_parse_format: error parsing format"
						" [%s] expecting '}' after position [%d]\n", s,
						(int)(e->hparam.s-s));
					goto error;
				}

				e->hparam.len = p - e->hparam.s;
				/* check if we have index */
				if(*p == '[')
				{
					p++;
					if(*p=='-')
					{
						p++;
						if(*p!='1')
						{
							LOG(L_ERR, "xprint: xl_parse_format: error"
								" parsing format [%s] -- only -1 is accepted"
								" as a negative index\n", s);
								goto error;
						}
						e->hindex = XLOG_PRINT_LAST;
						p++;
					} else if (*p=='*') {
						e->hindex = XLOG_PRINT_ALL;
						p++;
					} else {
						while(*p>='0' && *p<='9')
						{
							e->hindex = e->hindex * 10 + *p - '0';
							p++;
						}
					}
					if(*p != ']')
					{
						LOG(L_ERR, "xprint: xl_parse_format: error parsing format"
							" [%s] expecting ']' after position [%d]\n", s,
							(int)(e->hparam.s - s + e->hparam.len));
						goto error;
					}
					p++;
				}
				if(*p != '}')
				{
					LOG(L_ERR, "xprint: xl_parse_format: error parsing format"
						" [%s] expecting '}' after position [%d]!\n", s,
						(int)(e->hparam.s-s));
					goto error;
				}

				DBG("xprint: xl_parse_format: header name [%.*s] index [%d]\n",
						e->hparam.len, e->hparam.s, e->hindex);

				/* optimize for known headers -- fake header name */
				c = e->hparam.s[e->hparam.len];
				e->hparam.s[e->hparam.len] = ':';
				e->hparam.len++;
				/* ugly hack for compact header names -- !!fake length!!
				 * -- parse_hname2 expects name buffer length >= 4
				 */
				if (parse_hname2(e->hparam.s,
						e->hparam.s + ((e->hparam.len<4)?4:e->hparam.len),
						&hdr)==0)
				{
					LOG(L_ERR,"xprint: xl_parse_format: strange error\n");
					goto error;
				}
				e->hparam.len--;
				e->hparam.s[e->hparam.len] = c;
				if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T)
				{
					LOG(L_INFO,"INFO:xprint: xl_parse_format: using "
						"hdr type (%d) instead of <%.*s>\n",
						hdr.type, e->hparam.len, e->hparam.s);
					e->hparam.len = hdr.type;
					e->hparam.s = NULL;
				}
				e->itf = xl_get_header;
			break;
			case '<':
				p++;
				/* we expect a letter */
				if((*p < 'A' || *p > 'Z') && (*p < 'a' || *p > 'z'))
				{
					LOG(L_ERR, "xprint: xl_parse_format: error parsing format"
						" [%s] pos [%d]\n", s, (int)(p-s));
					goto error;
				}
				e->hparam.s = p;
				while(*p && *p!='>' && *p!='[')
					p++;
				if(*p == '\0')
				{
					LOG(L_ERR, "xprint: xl_parse_format: error parsing format"
						" [%s] expecting '>' after position [%d]\n", s,
						(int)(e->hparam.s-s));
					goto error;
				}

				e->hparam.len = p - e->hparam.s;
				/* check if we have index */
				if(*p == '[')
				{
					p++;
					if(*p=='-')
					{
						p++;
						if(*p!='1')
						{
							LOG(L_ERR, "xprint: xl_parse_format: error"
								" parsing format [%s] -- only -1 is accepted"
								" as a negative index\n", s);
								goto error;
						}
						e->hindex = -1;
						p++;
					}
					else
					{
						while(*p>='0' && *p<='9')
						{
							e->hindex = e->hindex * 10 + *p - '0';
							p++;
						}
					}
					if(*p != ']')
					{
						LOG(L_ERR, "xprint: xl_parse_format: error parsing format"
							" [%s] expecting ']' after position [%d]\n", s,
							(int)(e->hparam.s - s + e->hparam.len));
						goto error;
					}
					p++;
				}
				if(*p != '>')
				{
					LOG(L_ERR, "xprint: xl_parse_format: error parsing format"
						" [%s] expecting '>' after position [%d]!\n", s,
						(int)(e->hparam.s-s));
					goto error;
				}

				DBG("xprint: xl_parse_format: AVP [%.*s] index [%d]\n",
						e->hparam.len, e->hparam.s, e->hindex);

				e->itf = xl_get_avp;
			break;
			case '$':
				p++;
				name.s=p;
				while ( (*p>='a' && *p<='z') || (*p>='A' && *p<='Z') || (*p>='0' && *p<='9') || (*p=='_') || (*p=='+') || (*p=='-') || (*p=='[') || (*p==']') || (*p=='.') ) p++;
				name.len=p-name.s;
				p--;
				if (parse_avp_name(&name, &avp_flags, &avp_name, &avp_index) < 0) {
					ERR("error while parsing AVP name\n");
					goto error;
				}
				e->itf = xl_get_avp;
				e->hflags=avp_flags;
				e->hparam.s=name.s;
				e->hparam.len=name.len;
				e->hindex=avp_index;
				DBG("flags %x  name %.*s  index %d\n", avp_flags, avp_name.s.len, avp_name.s.s, avp_index);
				break;
			case '@':
					/* fill select structure and call resolve_select */
				DBG("xprint: xl_parse_format: @\n");
				if (shm)
					n=shm_parse_select(&p, &sel);
				else
					n=parse_select(&p, &sel);
				if (n<0) {
					ERR("xprint: xl_parse_format: parse_select returned error\n");
					goto error;
				}
				e->itf = xl_get_select;
				e->hparam.s = (char*)sel;
				e->free_f = (shm) ? xl_shm_free_select : xl_free_select;
				p--;
				break;
			case '%':
				e->itf = xl_get_percent;
				break;
			case ' ':	/* enables spaceless terminating of avp, e.g. "blah%$avp% text goes on" */
			case '|':
				e->itf = xl_get_empty;
				break;
			case '[':
				range = &e->hindex;
				e->itf = xl_get_range;
				while (1) {
					p++;
					if (((*p) >= '0') && ((*p) <= '9')) {
						(*range) *= 10;
						(*range) += (*p) - '0';

					} else if ((*p) == '-') {
						if (range == &e->hindex) {
							range = &e->hflags;
						} else {
							ERR("xprint: xl_parse_format: syntax error in the range specification\n");
							goto error;
						}

					} else if ((*p) == ']') {
						if (range == &e->hindex) {
							/* no range, only a single number */
							e->hflags = e->hindex;
						} else if (e->hflags == 0) {
							/* only the left side is defined */
							e->hflags = -1;
						} else if (e->hindex > e->hflags) {
							ERR("xprint: xl_parse_format: syntax error in the range specification\n");
							goto error;
						}
						break;

					} else {
						ERR("xprint: xl_parse_format: syntax error in the range specification\n");
						goto error;
					}
				}
				break;
			default:
				e->itf = xl_get_null;
		}

cont:
		if(*p == '\0')
			break;
		p++;
	}
	DBG("XLOG: xl_parse_format: format parsed OK: [%d] items\n", n);

	return 0;

error:
	_xl_elog_free_all(*el, shm);
	*el = NULL;
	return -1;
}