int tableSet(PTable t,const pchar Name,const pchar Value) { PTablePage p=t->pFirst,q; int idx0,idx=0,res=0; p=tableFind(p,&idx,Name); if(p) { q=p;idx0=idx; while((p=tableFind(p,&idx,Name))) { if(t->iFlags&TABLE_FLAG_ALLOCNAME)xfree(p->Values[idx].szName); if(t->iFlags&TABLE_FLAG_ALLOCVALUE)xfree(p->Values[idx].szValue); if(idx!=p->iCount-1)memmove(&p->Values[idx],&p->Values[idx+1],sizeof(SAttr)*(p->iCount-idx-1)); p->iCount--; t->iCount--; res++; } if(res)t->iHoles++; if(t->iFlags&TABLE_FLAG_ALLOCVALUE)xfree(q->Values[idx].szValue); if(xstrlen(q->Values[idx0].szValue)>=xstrlen(Value)) xstrcpy(q->Values[idx0].szValue,Value); else q->Values[idx0].szValue=xstrdup(t->pPool,Value); return t->iCount; }else return tableAdd(t,Name,Value); }
/* * Returns the value, or -1 for failure */ int tableInsert(table_t *table, const char *key, int value) { const int v = tableFind(table, key); if(v > 0) /* duplicate key */ return (v == value) ? value : -1; /* allow real dups */ assert(value != -1); /* that would confuse us */ if(table->tableHead == NULL) table->tableLast = table->tableHead = (tableEntry *)cli_malloc(sizeof(tableEntry)); else table->tableLast = table->tableLast->next = (tableEntry *)cli_malloc(sizeof(tableEntry)); if(table->tableLast == NULL) return -1; table->tableLast->next = NULL; table->tableLast->key = strdup(key); table->tableLast->value = value; return value; }
//变量声明的四元式生成 std::string* varDefEmit(AST_node t) { std::vector<AST_node>::iterator i = t->children->begin(); std::string *name = NULL, *op1 = NULL, *op2 = NULL, op; for (; i != t->children->end(); i++) { if ((*i)->lex_symbol == IDENT) { name = (*i)->val.ident; tableItem *item = tableFind(*(*i)->symTable, *(*i)->val.ident, (*i)->parent); if (item->attribute == CHAR) { op = "char"; } else if(item->attribute == INT) { op = "int"; } else { op = "arraydef"; op1 = ((arrayTemplet*)item->addr)->type == INT ? new std::string("int") : new std::string("char"); char _s[5], *s = itoa(((arrayTemplet*)item->addr)->length, _s, 10); op2 = new std::string(s); } emit(op, name, op1, op2); } } return name; }
//常量声明的四元式生成 std::string* constDefEmit(AST_node t) { std::vector<AST_node>::iterator i = t->children->begin(); std::string *res = NULL, *op1 = NULL, *op2 = NULL, op; if (i == t->children->end() || (*i)->lex_symbol != IDENT) { return NULL; } if ((*i)->lex_symbol == IDENT) { res = (*i)->val.ident; tableItem *item = tableFind(*(*i)->symTable, *res, (*i)->parent); if (item->attribute == CHAR) { char c[2]; c[0] = *((char*)item->addr); c[1] = '\0'; op1 = new std::string(c); op = "char"; } else { char _s[5], *s; s = itoa(*((int*)item->addr), _s, 10); op1 = new std::string(s); op = "int"; } } i += 2; emit(op, res, op1, op2); return res; }
//过程调用语句 //<过程调用语句>::=<标识符>[<实在参数表>] //<实在参数表>::='('<实在参数>{,<实在参数>}') std::string* callStatEmit(AST_node t) { std::vector<AST_node>::iterator i = t->children->begin(); std::vector<std::string*> args; std::string *name = new std::string(*(*i)->val.ident); i++; if (i == t->children->end()) { //无参数调用 std::string *n = new std::string("0"); return emit("call", NULL, name, n); } //记录参数 for (std::vector<AST_node>::iterator j = (*i)->children->begin(); j != (*i)->children->end(); j++) { if ((*j)->ast_type == EXPRESSION) args.push_back(expEmit(*j)); } //从右至左将参数压栈 for (std::vector<std::string*>::reverse_iterator j = args.rbegin(); j != args.rend(); j++) { if((*j)->c_str()[0] > '9' || (*j)->c_str()[0] < '0') { //j是标识符 tableItem *item = tableFind(*(t->symTable), *name, t->parent); //函数的符号表项 if(tableFind(*(item->table),*(*j),NULL)->type == REFERENCE) { //该参数是传引用 emit("param", *j, new std::string("reference"), NULL); continue; } } //j是数或者传值的参数 emit("param", *j, NULL, NULL); } std::string *n = NULL; char _s[5], *s = NULL; s = itoa(args.size(), _s, 10); n = new std::string(s); return emit("call", NULL, name, n); }
pchar tableGet(PTable t,const pchar Name) { PTablePage p; int idx=0; if(!t)return NULL; p=t->pFirst; p=tableFind(p,&idx,Name); if(p)return p->Values[idx].szValue;else return NULL; }
//函数声明的四元式生成 //t的类型为FUNDEF std::string* funDefEmit(AST_node t) { std::vector<AST_node>::iterator i = t->children->begin(); //t的子节点是prohead和program std::string *name = (*i)->children->at(1)->val.ident; tableItem *item = tableFind(*(t->symTable), *name, t->parent); char _s[5]; char *s = itoa(((functionTemplet*)item->addr)->args, _s, 10); std::string *op2 = NULL; op2 = item->attribute == INT ? new std::string("int") : new std::string("char"); emit("function", name, new std::string(s), op2); i++; IREmit((*i)); return NULL; }
//过程声明的四元式生成 //t的类型为PRODEF std::string* proDefEmit(AST_node t) { std::vector<AST_node>::iterator i = t->children->begin(); //t的子节点是prohead和program std::string *name = (*i)->children->at(1)->val.ident; tableItem *item = tableFind(*(t->symTable), *name, t->parent); char _s[5]; char *s = itoa(((procedureTemplet*)item->addr)->args, _s, 10); i++; emit("procedure", name, new std::string(s), NULL); IREmit(*i); return NULL; }
/* * Returns the value, or -1 for failure */ int tableInsert(table_t *table, const char *key, int value) { const int v = tableFind(table, key); if(v > 0) /* duplicate key */ return (v == value) ? value : -1; /* allow real dups */ assert(value != -1); /* that would confuse us */ if(table->tableHead == NULL) table->tableLast = table->tableHead = (tableEntry *)cli_malloc(sizeof(tableEntry)); else { /* * Re-use deleted items */ if(table->flags&TABLE_HAS_DELETED_ENTRIES) { tableEntry *tableItem; assert(table->tableHead != NULL); for(tableItem = table->tableHead; tableItem; tableItem = tableItem->next) if(tableItem->key == NULL) { /* This item has been deleted */ tableItem->key = cli_strdup(key); tableItem->value = value; return value; } table->flags &= ~TABLE_HAS_DELETED_ENTRIES; } table->tableLast = table->tableLast->next = (tableEntry *)cli_malloc(sizeof(tableEntry)); } if(table->tableLast == NULL) { cli_dbgmsg("tableInsert: Unable to allocate memory for table\n"); return -1; } table->tableLast->next = NULL; table->tableLast->key = cli_strdup(key); table->tableLast->value = value; return value; }
/* 查找操作:若在所给符号表中找到则返回指向该符号表项的指针,否则返回NULL t:待查找的符号表 name:欲查找的符号 level:欲查找符号所属层数 */ tableItem* tableFind(Table &t, std::string name, AST_node parent) { Table::iterator res = t.find(name); tableItem *ret = NULL; if (res == t.end()) { if (parent == NULL || parent->symTable == NULL) { return NULL; } return tableFind(*(parent->symTable), name, parent->parent); } itemList* list = &(res->second); ret = &(list->at(0)); return ret; }
int tableDel(PTable t,const pchar Name) { PTablePage p=t->pFirst; int idx=0; int res=0; while(p) { p=tableFind(p,&idx,Name); if(p) { if(t->iFlags&TABLE_FLAG_ALLOCNAME)xfree(p->Values[idx].szName); if(t->iFlags&TABLE_FLAG_ALLOCVALUE)xfree(p->Values[idx].szValue); if(idx!=p->iCount-1)memmove(&p->Values[idx],&p->Values[idx+1],sizeof(SAttr)*(p->iCount-idx-1)); p->iCount--; t->iCount--; res++; } } if(res)t->iHoles++; return res; }
int cli_scanrtf(cli_ctx *ctx) { char* tempname; const unsigned char* ptr; const unsigned char* ptr_end; int ret = CL_CLEAN; struct rtf_state state; struct stack stack; size_t bread; table_t* actiontable; uint8_t main_symbols[256]; size_t offset = 0; cli_dbgmsg("in cli_scanrtf()\n"); memset(main_symbols, 0, 256); main_symbols['{']=1; main_symbols['}']=1; main_symbols['\\']=1; stack.stack_cnt = 0; stack.stack_size = 16; stack.elements = 0; stack.warned = 0; stack.states = cli_malloc(stack.stack_size*sizeof(*stack.states)); if(!stack.states) { cli_errmsg("ScanRTF: Unable to allocate memory for stack states\n"); return CL_EMEM; } if(!(tempname = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM; if(mkdir(tempname, 0700)) { cli_dbgmsg("ScanRTF -> Can't create temporary directory %s\n", tempname); free(stack.states); free(tempname); return CL_ETMPDIR; } actiontable = tableCreate(); if((ret = load_actions(actiontable))) { cli_dbgmsg("RTF: Unable to load rtf action table\n"); free(stack.states); if(!ctx->engine->keeptmp) cli_rmdirs(tempname); free(tempname); tableDestroy(actiontable); return ret; } init_rtf_state(&state); for (offset = 0; (ptr = fmap_need_off_once_len(*ctx->fmap, offset, BUFF_SIZE, &bread)) && bread; offset += bread) { ptr_end = ptr + bread; while(ptr < ptr_end) { switch(state.parse_state) { case PARSE_MAIN: switch(*ptr++) { case '{': if(( ret = push_state(&stack,&state) )) { cli_dbgmsg("RTF:Push failure!\n"); SCAN_CLEANUP; return ret; } break; case '}': if(state.cb_data && state.cb_end) if(( ret = state.cb_end(&state, ctx) )) { SCAN_CLEANUP; return ret; } if(( ret = pop_state(&stack,&state) )) { cli_dbgmsg("RTF:pop failure!\n"); SCAN_CLEANUP; return ret; } break; case '\\': state.parse_state = PARSE_CONTROL_; break; default: ptr--; { size_t i; size_t left = ptr_end - ptr; size_t use = left; for(i = 1;i < left; i++) if(main_symbols[ptr[i]]) { use = i; break; } if(state.cb_begin) { if(!state.cb_data) if(( ret = state.cb_begin(&state, ctx,tempname) )) { SCAN_CLEANUP; return ret; } if(( ret = state.cb_process(&state, ptr, use) )) { if(state.cb_end) { state.cb_end(&state,ctx); } SCAN_CLEANUP; return ret; } } ptr += use; } } break; case PARSE_CONTROL_: if(isalpha(*ptr)) { state.parse_state = PARSE_CONTROL_WORD; state.controlword_cnt = 0; } else state.parse_state = PARSE_CONTROL_SYMBOL; break; case PARSE_CONTROL_SYMBOL: ptr++; /* Do nothing */ state.parse_state = PARSE_MAIN; break; case PARSE_CONTROL_WORD: if(state.controlword_cnt == 32) { cli_dbgmsg("Invalid control word: maximum size exceeded:%s\n",state.controlword); state.parse_state = PARSE_MAIN; } else if(isalpha(*ptr)) state.controlword[state.controlword_cnt++] = *ptr++; else { if(isspace(*ptr)) { state.controlword[state.controlword_cnt++] = *ptr++; state.parse_state = PARSE_INTERPRET_CONTROLWORD; } else if (isdigit(*ptr)) { state.parse_state = PARSE_CONTROL_WORD_PARAM; state.controlword_param = 0; state.controlword_param_sign = 1; } else if(*ptr == '-') { ptr++; state.parse_state = PARSE_CONTROL_WORD_PARAM; state.controlword_param = 0; state.controlword_param_sign = -1; } else { state.parse_state = PARSE_INTERPRET_CONTROLWORD; } } break; case PARSE_CONTROL_WORD_PARAM: if(isdigit(*ptr)) { state.controlword_param = state.controlword_param*10 + *ptr++ - '0'; } else if(isalpha(*ptr)) { ptr++; } else { if(state.controlword_param_sign < 0) state.controlword_param = -state.controlword_param; state.parse_state = PARSE_INTERPRET_CONTROLWORD; } break; case PARSE_INTERPRET_CONTROLWORD: { int action; state.controlword[state.controlword_cnt] = '\0'; action = tableFind(actiontable, state.controlword); if(action != -1) { if(state.cb_data && state.cb_end) {/* premature end of previous block */ state.cb_end(&state,ctx); state.cb_begin = NULL; state.cb_end = NULL; state.cb_data = NULL; } rtf_action(&state,action); } state.parse_state = PARSE_MAIN; break; } } } } SCAN_CLEANUP; return ret; }