/* * Parse comma separated list of methods pointed by _body and assign their * enum bits to _methods. Returns 0 on success and -1 on failure. */ int parse_methods(str* _body, unsigned int* _methods) { str next; char *p; char *p0; unsigned int method; if (!_body || !_methods) { LM_ERR("invalid parameter value\n"); return -1; } next.len = _body->len; next.s = _body->s; trim_leading(&next); *_methods = 0; if (next.len == 0) { goto done; } method = 0; p = next.s; while (p<next.s+next.len) { if((p0=parse_method(p, next.s+next.len, &method))!=NULL) { *_methods |= method; p = p0; } else { LM_ERR("invalid method [%.*s]\n", next.len, next.s); return -1; } while(p<next.s+next.len && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n')) p++; if(p>=next.s+next.len || *p == '\0') goto done; if (*p == ',') { p++; while(p<next.s+next.len && (*p==' ' || *p=='\t' || *p=='\r' || *p=='\n')) p++; if(p>=next.s+next.len) goto done; } else { LM_ERR("comma expected\n"); return -1; } } done: LM_DBG("methods 0x%X\n", *_methods); return 0; }
int send_leg_msg(struct dlg_cell *dlg,str *method,int src_leg,int dst_leg, str *hdrs,str *body,dlg_request_callback func,void *param,dlg_release_func release) { context_p old_ctx; dlg_t* dialog_info; int result; unsigned int method_type; if (parse_method(method->s,method->s+method->len,&method_type) == 0) { LM_ERR("Failed to parse method - [%.*s]\n",method->len,method->s); return -1; } if (method_type == METHOD_INVITE && (body == NULL || body->s == NULL || body->len == 0)) { LM_ERR("Cannot send INVITE without SDP body\n"); return -1; } if ((dialog_info = build_dialog_info(dlg, dst_leg, src_leg)) == 0) { LM_ERR("failed to create dlg_t\n"); return -1; } LM_DBG("sending [%.*s] to %s (%d)\n",method->len,method->s, (dst_leg==DLG_CALLER_LEG)?"caller":"callee", dst_leg); /* set new processing context */ if (push_new_processing_context( dlg, &old_ctx, NULL)!=0) return -1; dialog_info->T_flags=T_NO_AUTOACK_FLAG; result = d_tmb.t_request_within (method, /* method*/ hdrs, /* extra headers*/ body, /* body*/ dialog_info, /* dialog structure*/ func, /* callback function*/ param, /* callback parameter*/ release); /* release function*/ /* reset the processing contect */ current_processing_ctx = old_ctx; if(result < 0) { LM_ERR("failed to send the in-dialog request\n"); free_tm_dlg(dialog_info); return -1; } free_tm_dlg(dialog_info); return 0; }
char* parse_cseq(char *buf, char* end, struct cseq_body* cb) { char *t, *m, *m_end; cb->error=PARSE_ERROR; t=buf; cb->number.s=t; t=eat_token_end(t, end); if (t>=end) goto error; cb->number.len=t-cb->number.s; m=eat_space_end(t, end); m_end=eat_token_end(m, end); if (m_end>=end) { LM_ERR("method terminated unexpectedly\n"); goto error; } if (m_end==m){ /* null method*/ LM_ERR("no method found\n"); goto error; } cb->method.s=m; t=m_end; cb->method.len=t-cb->method.s; /* cache the method id */ if(parse_method(cb->method.s, t, (unsigned int*)&cb->method_id)==0) { LM_ERR("cannot parse the method\n"); goto error; } /* there may be trailing LWS * (it was not my idea to put it in SIP; -jiri ) */ t=eat_lws_end(t, end); /*check if the header ends here*/ if (t>=end) { LM_ERR("strange EoHF\n"); goto error; } if (*t=='\r' && t+1<end && *(t+1)=='\n') { cb->error=PARSE_OK; return t+2; } if (*t=='\n') { cb->error=PARSE_OK; return t+1; } LM_ERR("expecting CSeq EoL\n"); error: LM_ERR("bad cseq\n"); return t; }
static bool parse_request_line(Iterator& it, Request& request) { bool ret = true; ret = ret && parse_method(it, request); ret = ret && parse_uri(it, request); ret = ret && parse_http_version(it, request); ret = ret && expect(it, HTTP_DELIMITER); return ret; }
void send_response() { str host = parse_host(client.request,find_header(client.request->headers,_("Host"))); str method = parse_method(client.request); begin_response(); client.response->status = host && method ? dispatch_method(method) : error_handler(400); end_response(); disconnect(); }
/* * Parse comma separated list of methods pointed by _body and assign their * enum bits to _methods. Returns 1 on success and 0 on failure. */ int parse_methods(str* _body, unsigned int* _methods) { str next; unsigned int method; method=0; /* fixes silly gcc 4.x warning */ if (!_body || !_methods) { LOG(L_ERR, "parse_methods: Invalid parameter value\n"); return 0; } next.len = _body->len; next.s = _body->s; trim_leading(&next); if (next.len == 0) { LOG(L_ERR, "ERROR: parse_methods: Empty body\n"); return 0; } *_methods = 0; while (1) { if (parse_method(&next, &method)) { *_methods |= method; } else { LOG(L_ERR, "ERROR: parse_methods: Invalid method\n"); return 0; } trim_leading(&next); if (next.len) { if (next.s[0] == ',') { next.len--; next.s++; trim_leading(&next); if (next.len == 0) { LOG(L_ERR, "ERROR: parse_methods: Method expected\n"); return 0; } } else { LOG(L_ERR, "ERROR: parse_methods: Comma expected\n"); return 0; } } else { break; } } return 1; }
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF const char* parse_request_line(unsigned char** p) { if (parse_method(p)) return ERR; if (parse_space(p)) return ERR; if (parse_request_uri(p)) return ERR; if (parse_space(p)) return ERR; if (parse_http_version(p)) return ERR; return parse_crlf(p); }
void ProguardMap::parse_line(const std::string& line) { if (parse_class(line)) { return; } if (parse_field(line)) { return; } if (parse_method(line)) { return; } always_assert_log(false, "Bogus line encountered in proguard map: %s\n", line.c_str()); }
http_request_t *parse_http_request(http_parser_t *parser, const char *data, size_t len) { if (!parser || !data || !len) return NULL; parser->data = data; parser->len = len; parser->parse_ptr = (char*)data; parse_method(parser); parse_char(parser, ' '); parse_absolute_path(parser); parse_params(parser); parse_char(parser, ' '); parse_http_version(parser); parse_crlf(parser); while (parse_message_header(parser) == 0) ; return &parser->req; }
// Parse message populating fields and return Method Method Parser::parse(char* buffer, int buffer_size) { data.clear(); tokenize(buffer, buffer_size); Errcode errcode = parse_method(_lines[0]); for (unsigned int line = 1; line < _lines.size(); ++line) { Errcode ec = parse_field(_lines[line]); // We always throw the first error we find if (errcode == OK) errcode = ec; } switch (_state) { case INIT: if (data.method == SETUP) _state = READY; else if (data.method == PLAY) throw METHOD_NOT_VALID_IN_THIS_STATE; break; case READY: if (data.method == PLAY) _state = PLAYING; else if (data.method == TEARDOWN) _state = INIT; break; case PLAYING: if (data.method == TEARDOWN) _state = INIT; break; } if (errcode != OK) throw errcode; return data.method; }
static int parse_icap_startline(char *line,struct pollfd_state *pfd,icap_status *istat){ icap_state *is = get_pfd_icap(pfd); const char *method; is->method = parse_method(&line); if(is->method == ICAP_METHOD_COUNT){ *istat = ICAPSTATUS_METHOD_NOT_IMPLEMENTED; return -1; } if((method = name_icap_method(is->method)) == NULL){ bitch("Couldn't stringize method %d\n",is->method); *istat = ICAPSTATUS_INTERNAL_ERROR; return -1; } // nag("Valid method: %s\n",method); inc_method_begun(is->method); if((is->icapuri = extract_uri(ICAP_URI_SCHEME,&line)) == NULL){ *istat = ICAPSTATUS_BAD_REQUEST; return -1; } if(verify_icap_uri(is->icapuri,is)){ bitch("Bad URI for %s\n",method); free_uri(&is->icapuri); *istat = ICAPSTATUS_METHOD_BAD_SERVICE; return -1; } if(parse_icap_version(&line)){ *istat = ICAPSTATUS_VERSION_NOT_SUPPORTED; return -1; } if(strcmp(line,CRLF)){ bitch("Excess data after ICAP version (%zu/%zu)\n", strlen(line),__builtin_strlen(CRLF)); *istat = ICAPSTATUS_BAD_REQUEST; return -1; } return 0; }
/* `struct` , `table`, or 'rpc_service' must already be matched. */ static void parse_compound_type(fb_parser_t *P, fb_compound_type_t *ct, long token) { fb_token_t *t = 0; if (!(t = match(P, LEX_TOK_ID, "Declaration expected an identifier"))) { goto fail; } ct->symbol.ident = t; ct->metadata = parse_metadata(P); if (!(match(P, '{', "Declaration expected '{'"))) { goto fail; } t = P->token; /* Allow empty tables and structs. */ #if 0 if (P->token->id == '}') { error_tok(P, t, "table / struct declaration cannot be empty"); } #endif while (P->token->id != '}') { if (token == tok_kw_rpc_service) { parse_method(P, fb_add_member(P, &ct->members)); } else { parse_field(P, fb_add_member(P, &ct->members)); } if (P->failed >= FLATCC_MAX_ERRORS) { goto fail; } } if (!optional(P, '}') && t) { error_tok_2(P, P->token, "Declaration missing closing '}' to match", t); } revert_symbols(&ct->members); return; fail: recover(P, '}', 1); }
str* client_new(client_info_t* ci,b2b_notify_t b2b_cback, b2b_add_dlginfo_t add_dlginfo, str* param) { int result; b2b_dlg_t* dlg; unsigned int hash_index; str* callid = NULL; int size; str ehdr = {0, 0}; str* b2b_key_shm = NULL; dlg_t td; str from_tag; str random_info = {0, 0}; if(ci == NULL || b2b_cback == NULL || param== NULL) { LM_ERR("Wrong parameters.\n"); return NULL; } if(param && param->len > B2BL_MAX_KEY_LEN) { LM_ERR("parameter too long, received [%d], maximum [%d]\n", param->len, B2BL_MAX_KEY_LEN); return 0; } hash_index = core_hash(&ci->from_uri, &ci->to_uri, client_hsize); if(ci->from_tag) from_tag = *ci->from_tag; else generate_tag(&from_tag, &ci->from_uri, ci->extra_headers); /* create a dummy b2b dialog structure to be inserted in the hash table*/ size = sizeof(b2b_dlg_t) + ci->to_uri.len + ci->from_uri.len + ci->from_dname.len + ci->to_dname.len + from_tag.len + ci->local_contact.len + B2B_MAX_KEY_SIZE + B2BL_MAX_KEY_LEN; /* create record in hash table */ dlg = (b2b_dlg_t*)shm_malloc(size); if(dlg == NULL) { LM_ERR("No more shared memory\n"); return 0; } memset(dlg, 0, size); size = sizeof(b2b_dlg_t); CONT_COPY(dlg, dlg->from_uri, ci->from_uri); CONT_COPY(dlg, dlg->to_uri, ci->to_uri); if(ci->to_dname.s) CONT_COPY(dlg, dlg->to_dname, ci->to_dname); if(ci->from_dname.s) CONT_COPY(dlg, dlg->from_dname, ci->from_dname); CONT_COPY(dlg, dlg->tag[CALLER_LEG], from_tag); CONT_COPY(dlg, dlg->contact[CALLER_LEG], ci->local_contact); if(param && param->s) { dlg->param.s = (char*)dlg + size; memcpy(dlg->param.s, param->s, param->len); dlg->param.len = param->len; size+= B2BL_MAX_KEY_LEN; } dlg->b2b_cback = b2b_cback; dlg->add_dlginfo = add_dlginfo; if(parse_method(ci->method.s, ci->method.s+ci->method.len, &dlg->last_method)< 0) { LM_ERR("wrong method %.*s\n", ci->method.len, ci->method.s); shm_free(dlg); goto error; } dlg->state = B2B_NEW; dlg->cseq[CALLER_LEG] =(ci->cseq?ci->cseq:1); dlg->send_sock = ci->send_sock; /* if the callid should be the same in more instances running at the same time (replication)*/ if(!replication_mode) { srand(get_uticks()); random_info.s = int2str(rand(), &random_info.len); } dlg->send_sock = ci->send_sock; dlg->id = core_hash(&from_tag, random_info.s?&random_info:0, HASH_SIZE); /* callid must have the special format */ dlg->db_flag = NO_UPDATEDB_FLAG; callid = b2b_htable_insert(client_htable, dlg, hash_index, B2B_CLIENT, 0); if(callid == NULL) { LM_ERR("Inserting new record in hash table failed\n"); shm_free(dlg); goto error; } if(b2breq_complete_ehdr(ci->extra_headers, &ehdr, ci->body, &ci->local_contact)< 0) { LM_ERR("Failed to complete extra headers\n"); goto error; } /* copy the key in shared memory to transmit it as a parameter to the tm callback */ b2b_key_shm = b2b_key_copy_shm(callid); if(b2b_key_shm== NULL) { LM_ERR("no more shared memory\n"); goto error; } CONT_COPY(dlg, dlg->callid, (*callid)); /* create the tm dialog structure with the a costum callid */ memset(&td, 0, sizeof(dlg_t)); td.loc_seq.value = dlg->cseq[CALLER_LEG]; dlg->last_invite_cseq = dlg->cseq[CALLER_LEG]; td.loc_seq.is_set = 1; td.id.call_id = *callid; td.id.loc_tag = from_tag; td.id.rem_tag.s = 0; td.id.rem_tag.len = 0; td.rem_uri = ci->to_uri; if(ci->req_uri.s) td.rem_target = ci->req_uri; else td.rem_target = ci->to_uri; if(td.rem_target.s[0] == '<') { td.rem_target.s++; td.rem_target.len-=2; } td.rem_dname = ci->to_dname; td.loc_uri = ci->from_uri; td.loc_dname = ci->from_dname; td.state= DLG_CONFIRMED; td.T_flags=T_NO_AUTOACK_FLAG|T_PASS_PROVISIONAL_FLAG ; td.send_sock = ci->send_sock; if(ci->dst_uri.len) td.obp = ci->dst_uri; td.avps = ci->avps; tmb.setlocalTholder(&dlg->uac_tran); /* send request */ result= tmb.t_request_within (&ci->method, /* method*/ &ehdr, /* extra headers*/ ci->body, /* body*/ &td, /* dialog structure*/ b2b_client_tm_cback, /* callback function*/ b2b_key_shm, shm_free_param); /* function to release the parameter*/ if(td.route_set) pkg_free(td.route_set); if(result< 0) { LM_ERR("while sending request with t_request\n"); pkg_free(callid); shm_free(b2b_key_shm); return NULL; } tmb.setlocalTholder(NULL); LM_DBG("new client entity [%p] callid=[%.*s] tag=[%.*s] param=[%.*s]" " last method=[%d] dlg->uac_tran=[%p]\n", dlg, callid->len, callid->s, dlg->tag[CALLER_LEG].len, dlg->tag[CALLER_LEG].s, dlg->param.len, dlg->param.s, dlg->last_method, dlg->uac_tran); return callid; error: if(callid) pkg_free(callid); return NULL; }
int parse_cseq(sip_cseq* cseq, const char* beg, int len) { enum { C_NUM=0, C_NUM_SWS, C_METHOD }; const char* c = beg; const char* end = c+len; int saved_st=0, st=C_NUM; for(;c!=end;c++){ switch(st){ case C_NUM: switch(*c){ case_CR_LF; case SP: case HTAB: st = C_NUM_SWS; cseq->num_str.set(beg, c-beg); break; default: if(!IS_DIGIT(*c)){ return MALFORMED_SIP_MSG; } cseq->num = cseq->num*10 + *c - '0'; break; } break; case C_NUM_SWS: switch(*c){ case_CR_LF; case SP: case HTAB: break; default: st = C_METHOD; beg = c; break; } break; case C_METHOD: switch(*c){ case_CR_LF; case SP: case HTAB: cseq->method_str.set(beg,c-beg); return 0; } break; case_ST_CR(*c); case ST_LF: case ST_CRLF: switch(saved_st){ case C_NUM: cseq->num_str.set(beg,c-(st==ST_CRLF?2:1)-beg); break; case C_METHOD: cseq->method_str.set(beg,c-beg); return 0; } st = saved_st; break; } } if(st != C_METHOD){ return MALFORMED_SIP_MSG; } cseq->method_str.set(beg,c-beg); if(parse_method(&cseq->method, cseq->method_str.s, cseq->method_str.len) < 0){ DBG("Cseq method parsing failed\n"); return MALFORMED_SIP_MSG; } return 0; }
/* parses the first line, returns pointer to next line & fills fl; also modifies buffer (to avoid extra copy ops) */ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) { char *tmp; char* second; char* third; char* nl; unsigned int offset; /* int l; */ char* end; char s1,s2,s3; char *prn; unsigned int t; /* grammar: request = method SP uri SP version CRLF response = version SP status SP reason CRLF (version = "SIP/2.0") */ end=buffer+len; /* see if it's a reply (status) */ /* jku -- parse well-known methods */ /* drop messages which are so short they are for sure useless; utilize knowledge of minimum size in parsing the first token */ if (len <=16 ) { LM_INFO("message too short: %d\n", len); goto error1; } tmp=buffer; /* is it perhaps a reply, ie does it start with "SIP...." ? */ if ( (*tmp=='S' || *tmp=='s') && strncasecmp( tmp+1, SIP_VERSION+1, SIP_VERSION_LEN-1)==0 && (*(tmp+SIP_VERSION_LEN)==' ')) { fl->type=SIP_REPLY; fl->u.reply.version.len=SIP_VERSION_LEN; tmp=buffer+SIP_VERSION_LEN; } else IFISMETHOD( INVITE, 'I' ) else IFISMETHOD( CANCEL, 'C') else IFISMETHOD( ACK, 'A' ) else IFISMETHOD( BYE, 'B' ) else IFISMETHOD( INFO, 'I' ) /* if you want to add another method XXX, include METHOD_XXX in H-file (this is the value which you will take later in processing and define XXX_LEN as length of method name; then just call IFISMETHOD( XXX, 'X' ) ... 'X' is the first latter; everything must be capitals */ else { /* neither reply, nor any of known method requests, let's believe it is an unknown method request */ tmp=eat_token_end(buffer,buffer+len); if ((tmp==buffer)||(tmp>=end)){ LM_INFO("empty or bad first line\n"); goto error1; } if (*tmp!=' ') { LM_INFO("method not followed by SP\n"); goto error1; } fl->type=SIP_REQUEST; /* see if it is another known method */ /* fl->u.request.method_value=METHOD_OTHER; */ if(parse_method(buffer, tmp, (unsigned int*)&fl->u.request.method_value)==0) { LM_INFO("failed to parse the method\n"); goto error1; } fl->u.request.method.len=tmp-buffer; } /* identifying type of message over now; tmp points at space after; go ahead */ fl->u.request.method.s=buffer; /* store ptr to first token */ second=tmp+1; /* jump to second token */ offset=second-buffer; /* EoJku */ /* next element */ tmp=eat_token_end(second, second+len-offset); if (tmp>=end){ goto error; } offset+=tmp-second; third=eat_space_end(tmp, tmp+len-offset); offset+=third-tmp; if ((third==tmp)||(tmp>=end)){ goto error; } fl->u.request.uri.s=second; fl->u.request.uri.len=tmp-second; /* jku: parse status code */ if (fl->type==SIP_REPLY) { if (fl->u.request.uri.len!=3) { LM_INFO("len(status code)!=3: %.*s\n", fl->u.request.uri.len, ZSW(second) ); goto error; } s1=*second; s2=*(second+1);s3=*(second+2); if (s1>='0' && s1<='9' && s2>='0' && s2<='9' && s3>='0' && s3<='9' ) { fl->u.reply.statuscode=(s1-'0')*100+10*(s2-'0')+(s3-'0'); } else { LM_INFO("status_code non-numerical: %.*s\n", fl->u.request.uri.len, ZSW(second) ); goto error; } } /* EoJku */ /* last part: for a request it must be the version, for a reply * it can contain almost anything, including spaces, so we don't care * about it*/ if (fl->type==SIP_REQUEST){ tmp=eat_token_end(third,third+len-offset); offset+=tmp-third; if ((tmp==third)||(tmp>=end)){ goto error; } if (! is_empty_end(tmp, tmp+len-offset)){ goto error; } }else{ tmp=eat_token2_end(third,third+len-offset,'\r'); /* find end of line ('\n' or '\r') */ if (tmp>=end){ /* no crlf in packet => invalid */ goto error; } offset+=tmp-third; } nl=eat_line(tmp,len-offset); if (nl>=end){ /* no crlf in packet or only 1 line > invalid */ goto error; } fl->u.request.version.s=third; fl->u.request.version.len=tmp-third; fl->len=nl-buffer; return nl; error: LM_ERR("bad %s first line\n", (fl->type==SIP_REPLY)?"reply(status)":"request"); LM_ERR("at line 0 char %d: \n", offset ); prn=pkg_malloc( offset ); if (prn) { for (t=0; t<offset; t++) if (*(buffer+t)) *(prn+t)=*(buffer+t); else *(prn+t)='°'; LM_ERR("parsed so far: %.*s\n", offset, ZSW(prn) ); pkg_free( prn ); }; error1: fl->type=SIP_INVALID; LM_INFO("bad message\n"); /* skip line */ nl=eat_line(buffer,len); return nl; }
/* * main function to parse the http request header. */ int parse_request(struct http_header *header, char *request, size_t len) { char ch, *p = request; int tmp; while (p < request + len) // for(p = request; p < request + len; p++) { ch = *p; switch (GET_HEADER_STATE(header)) { // some error happened, // and then ignore all data left in the buffer. case s_dead: return -1; // finshed parsing http request header, // but there are still some data in the buffer. case s_done: return p - request; // start to parse METHOD case s_request_start: case s_method_start: { // skip space at the beginning if (CR == ch || LF == ch || SP == ch) { p++; break; } // when match the first non-space character // parse the http method tmp = parse_method(header, p); if (tmp == -1) { // failed SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_invalid_method); return -1; } else if (tmp == E_INTERRUPT) { SET_HEADER_ERROR(header, e_again); return -1; } else { // success SET_HEADER_STATE(header, s_method_end); p += tmp; p++; break; } } // after found out the http method // there is an SP between METHOD and URL case s_method_end: { if (SP != ch) { // failed SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_invalid_method); return -1; } else { // success SET_HEADER_STATE(header, s_url_start); p++; break; } } // start to parse URL case s_url_start: case s_path_start: case s_query_start: { // TODO // handle the CONNECT and OPTION method tmp = parse_url(header, p, len - (p - request)); if (tmp == -1) { // failed SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_invalid_url); return -1; } else if (tmp == E_INTERRUPT) { SET_HEADER_ERROR(header, e_again); return -1; } else { SET_HEADER_STATE(header, s_version_start); p += tmp; p++; break; } } // http version, only support HTTP/1.0 and HTTP/1.1 case s_version_start: { int tmp = parse_version(header, p); if (tmp == -1) { SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_invalid_version); return -1; } else if (tmp == E_INTERRUPT) { SET_HEADER_ERROR(header, e_again); return -1; } else { SET_HEADER_STATE(header, s_line_cr); p += HTTP_VERSION_LENGTH; break; } } // CR character in the end of line case s_line_cr: { if (CR == ch) { SET_HEADER_STATE(header, s_line_lf); p++; break; } else { SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_eol); return -1; } } // LF character in the end of line case s_line_lf: { if (LF == ch) { SET_HEADER_STATE(header, s_done); break; } else { SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_eol); return -1; } } // header field start case s_field_start: { SET_HEADER_STATE(header, s_done); break; } default: SET_HEADER_STATE(header, s_dead); } } // three results // dead, done, again switch (GET_HEADER_STATE(header)) { // error case s_dead: return s_dead; // finished case s_done: return s_done; // again default: SET_HEADER_ERROR(header, e_again); return s_dead; } }
struct node *parse_factor(struct compiler *compiler) { switch (lexer_current(compiler)) { case T_BEGIN: return parse_begin(compiler); case T_IF: return parse_if(compiler); case T_UNLESS: return parse_unless(compiler); case T_CASE: return parse_case(compiler); case T_CLASS: return parse_class(compiler); case T_MODULE: return parse_module(compiler); case T_DEF: return parse_method(compiler); case T_YIELD: return parse_yield(compiler); case T_RETURN: return parse_return(compiler); case T_BREAK: return parse_break(compiler); case T_NEXT: return parse_next(compiler); case T_REDO: return parse_redo(compiler); case T_SQUARE_OPEN: { struct node *result = alloc_node(compiler, N_ARRAY); lexer_next(compiler); if(lexer_current(compiler) == T_SQUARE_CLOSE) result->left = 0; else result->left = parse_array_element(compiler); lexer_match(compiler, T_SQUARE_CLOSE); return result; } case T_STRING: { struct node *result = alloc_node(compiler, N_STRING); result->left = (void *)lexer_token(compiler)->start; lexer_next(compiler); return result; } case T_STRING_START: { struct node *result = alloc_node(compiler, N_STRING_CONTINUE); result->left = 0; result->middle = (void *)lexer_token(compiler)->start; lexer_next(compiler); result->right = parse_statements(compiler); while(lexer_current(compiler) == T_STRING_CONTINUE) { struct node *node = alloc_node(compiler, N_STRING_CONTINUE); node->left = result; node->middle = (void *)lexer_token(compiler)->start; lexer_next(compiler); node->right = parse_statements(compiler); result = node; } if(lexer_require(compiler, T_STRING_END)) { struct node *node = alloc_node(compiler, N_STRING_START); node->left = result; node->right = (void *)lexer_token(compiler)->start; lexer_next(compiler); return node; } return result; } case T_SELF: { lexer_next(compiler); return &self_node; } case T_TRUE: { lexer_next(compiler); return alloc_node(compiler, N_TRUE); } case T_FALSE: { lexer_next(compiler); return alloc_node(compiler, N_FALSE); } case T_NIL: { lexer_next(compiler); return &nil_node; } case T_NUMBER: { struct node *result = alloc_node(compiler, N_NUMBER); char *text = get_token_str(lexer_token(compiler)); result->left = (void* )atoi(text); lexer_next(compiler); return result; } case T_IVAR: { rt_value symbol = rt_symbol_from_lexer(compiler); lexer_next(compiler); switch (lexer_current(compiler)) { case T_ASSIGN_ADD: case T_ASSIGN_SUB: case T_ASSIGN_MUL: case T_ASSIGN_DIV: { struct node *result; enum token_type op_type = lexer_current(compiler) - OP_TO_ASSIGN; lexer_next(compiler); result = alloc_node(compiler, N_IVAR_ASSIGN); result->right = alloc_node(compiler, N_BINARY_OP); result->right->op = op_type; result->right->left = alloc_node(compiler, N_IVAR); result->right->left->left = (void *)symbol; result->right->right = parse_expression(compiler); result->left = (void *)symbol; return result; } case T_ASSIGN: { struct node *result; lexer_next(compiler); result = alloc_node(compiler, N_IVAR_ASSIGN); result->left = (void *)symbol; result->right = parse_expression(compiler); return result; } default: { struct node *result = alloc_node(compiler, N_IVAR); result->left = (void *)symbol; return result; } } } case T_IDENT: return parse_identifier(compiler); case T_EXT_IDENT: return parse_call(compiler, 0, &self_node, false); case T_PARAM_OPEN: { lexer_next(compiler); struct node *result = parse_statements(compiler); lexer_match(compiler, T_PARAM_CLOSE); return result; } default: { COMPILER_ERROR(compiler, "Expected expression but found %s", token_type_names[lexer_current(compiler)]); lexer_next(compiler); return 0; } } }
int COMPRESSION_METHOD::server() { char *service = p._str("service"); // Global services if (strequ (service, "register")) return FREEARC_OK; //to do: Register(); // Invocation-specific services if (strequ (service, "decompress")) {parse_method(); return decompress (p._callback("callback"), p);} #ifndef FREEARC_DECOMPRESS_ONLY if (strequ (service, "compress")) {parse_method(); return compress (p._callback("callback"), p);} if (strequ (service, "canonize")) {parse_method(); char a[1000]; ShowCompressionMethod(a); return p._return(a);} if (strequ (service, "SetCompressionMem")) {parse_method(); SetCompressionMem (p._int("mem")); char a[1000]; ShowCompressionMethod(a); return p._return(a);} if (strequ (service, "SetDictionary")) {parse_method(); SetDictionary (p._int("mem")); char a[1000]; ShowCompressionMethod(a); return p._return(a);} if (strequ (service, "SetBlockSize")) {parse_method(); SetBlockSize (p._int("mem")); char a[1000]; ShowCompressionMethod(a); return p._return(a);} if (strequ (service, "SetDecompressionMem")) {parse_method(); SetDecompressionMem(p._int("mem")); char a[1000]; ShowCompressionMethod(a); return p._return(a);} if (strequ (service, "GetCompressionMem")) {parse_method(); return p._return (GetCompressionMem());} if (strequ (service, "GetDictionary")) {parse_method(); return p._return (GetDictionary());} if (strequ (service, "GetBlockSize")) {parse_method(); return p._return (GetBlockSize());} #endif if (strequ (service, "GetDecompressionMem")) {parse_method(); return p._return (GetDecompressionMem());} return FREEARC_ERRCODE_NOT_IMPLEMENTED; }