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; }
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; }
/** 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; }
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); }
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; }
/* 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; }