/* * replace ntok tokens starting at dtr->tp with the contents of str. * tp ends up pointing just beyond the replacement. * Canonical whitespace is assured on each side. */ void insertrow(Tokenrow *dtr, int ntok, Tokenrow *str) { int nrtok = rowlen(str); dtr->tp += ntok; adjustrow(dtr, nrtok-ntok); dtr->tp -= ntok; movetokenrow(dtr, str); makespace(dtr); dtr->tp += nrtok; makespace(dtr); }
/* 解析提交的数据 返回(表单域=表单值)对的个数 */ int get_input(FORM_VAR *nv) { char *method; char *form_data=0; char *form_data_ptr; char tmp[250]; int data_len,i; //读取环境变量”REQUEST_METHOD”, //获取提交数据的方式。 method=getenv("REQUEST_METHOD"); /*以GET方式传数据*/ if(strcmp(method,"GET")==0) { //从环境变量UERY_STRING 中取出提交数据 char *data_ptr=getenv("QUERY_STRING"); data_len=strlen(data_ptr); form_data=(char*)malloc(sizeof(char)*(data_len+1)); strcpy(form_data,data_ptr); form_data[data_len]='\0'; } /*以POST方法传数据*/ else if(strcmp(method,"POST")==0) { //从标准输入输出中读取相应的字符串, //读取长度有环境变量CONTENT_LENGTH 决定 data_len=atoi(getenv("CONTENT_LENGTH")); form_data=(char*)malloc(sizeof(char)*(data_len+1)); fread(form_data,1,data_len,stdin); } i=0; form_data_ptr=form_data; //分离出表单域和值 while(form_data_ptr[0] != '\0') { //分理处表单域 memset(tmp, 0, 250); split(form_data_ptr,'=',tmp); makespace(tmp); convert(tmp); strcpy(nv[i].name,tmp); //分离出值 split(form_data_ptr,'&',tmp); makespace(tmp); convert(tmp); strcpy(nv[i].value,tmp); i++; } free(form_data); return i--; }
/* * Find the first instance of a sub-string "pattern" in the string "str", * and replace it with the string "replacement". * str (IN/OUT) target string (pointer to in case of expansion) * pattern (IN) substring to look for in str * replacement (IN) string with which to replace the "pattern" string */ void _xstrsubstitute(char **str, const char *pattern, const char *replacement) { int pat_len, rep_len; char *ptr, *end_copy; int pat_offset; if (*str == NULL || pattern == NULL || pattern[0] == '\0') return; if ((ptr = strstr(*str, pattern)) == NULL) return; pat_offset = ptr - (*str); pat_len = strlen(pattern); if (replacement == NULL) rep_len = 0; else rep_len = strlen(replacement); end_copy = xstrdup(ptr + pat_len); if (rep_len != 0) { makespace(str, rep_len-pat_len); strcpy((*str)+pat_offset, replacement); } strcpy((*str)+pat_offset+rep_len, end_copy); xfree(end_copy); }
/* * substitute the argument list into the replacement string * This would be simple except for ## and # */ void substargs(Nlist * np, Tokenrow * rtr, Tokenrow ** atr) { Tokenrow tatr; Token *tp; int ntok, argno; for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;) { if (rtr->tp->type == SHARP) { /* string operator */ tp = rtr->tp; rtr->tp += 1; if ((argno = lookuparg(np, rtr->tp)) < 0) { error(ERROR, "# not followed by macro parameter"); continue; } ntok = 1 + (int)(rtr->tp - tp); rtr->tp = tp; insertrow(rtr, ntok, stringify(atr[argno])); continue; } if (rtr->tp->type == NAME && (argno = lookuparg(np, rtr->tp)) >= 0) { if (((rtr->tp + 1) < rtr->lp && (rtr->tp + 1)->type == DSHARP) || (rtr->tp != rtr->bp && (rtr->tp - 1)->type == DSHARP)) { copytokenrow(&tatr, atr[argno]); makespace(&tatr, rtr->tp); insertrow(rtr, 1, &tatr); dofree(tatr.bp); } else { copytokenrow(&tatr, atr[argno]); makespace(&tatr, rtr->tp); expandrow(&tatr, "<macro>"); insertrow(rtr, 1, &tatr); dofree(tatr.bp); } continue; } rtr->tp++; } }
/* * Concatenate len of str2 onto str1, expanding str1 as needed. * str1 (IN/OUT) target string (pointer to in case of expansion) * str2 (IN) source string * len (IN) len of str2 to concat */ void _xstrncat(char **str1, const char *str2, size_t len) { if (str2 == NULL) str2 = "(null)"; makespace(str1, len); strncat(*str1, str2, len); }
/* * Concatenate str2 onto str1, expanding str1 as needed. * str1 (IN/OUT) target string (pointer to in case of expansion) * str2 (IN) source string */ void _xstrcat(char **str1, const char *str2) { if (str2 == NULL) str2 = "(null)"; makespace(str1, strlen(str2)); strcat(*str1, str2); }
/* 將表單資料解碼,結果存入nv陣列中 */ int get_input(nv_set* nv) { char* method; char* my_data = 0; char* tmp_ptr, *tmp; int data_len; int i; /* 表單以GET方法傳送資料 */ method = getenv("REQUEST_METHOD"); if (strcmp(method, "GET") == 0) { tmp_ptr = getenv("QUERY_STRING"); data_len = strlen(tmp_ptr); /* 將表單編碼資料存入my_data中 */ my_data = (char*)malloc(sizeof(char) * (data_len + 1)); strcpy(my_data, getenv("QUERY_STRING")); my_data[data_len] = '\0'; } /* 表單以POST方法傳送資料 */ if (strcmp(method, "POST") == 0) { data_len = atoi(getenv("CONTENT_LENGTH")); /* 將表單編碼資料存入my_data中 */ my_data = (char*)malloc(sizeof(char) * (data_len + 1)); fread(my_data, 1, data_len, stdin); } i = 0; while (my_data[0] != '\0') { tmp = split(my_data, '='); // 分離資料對,取得欄位名 makespace(tmp); // 將+號還原成空白字元 tmp = convert(tmp); // 將十六進位碼還原成字元 strcpy(nv[i].name, tmp); // 結果存入nv結構的name成員 tmp = split(my_data, '&'); // 分離資料對,取得欄位值 makespace(tmp); // 將+號還原成空白字元 tmp = convert(tmp); // 將十六進位碼還原成字元 strcpy(nv[i].value, tmp); // 結果存入nv結構的value成員 i++; } return i--; // 傳回實際解碼的欄位數 }
void Buffer::append(const char *data , size_t len) { if(len > nonMakeSpaceWritable() && len <= nonAppendWritable()) makespace(); std::copy(data , data + len , &ibuf_[writeidx_]); writeidx_ += len; assert(readidx_ <= writeidx_ && writeidx_ < ibuf_.size()); }
/* * Evaluate the ## operators in a tokenrow */ void doconcat(Tokenrow *trp) { Token *ltp, *ntp; STATIC Tokenrow ntr; int len; CHECKIN(); for (trp->tp=trp->bp; trp->tp<trp->lp; trp->tp++) { if (trp->tp->type==DSHARP1) trp->tp->type = DSHARP; else if (trp->tp->type==DSHARP) { STATIC char tt[128]; ltp = trp->tp-1; ntp = trp->tp+1; if (ltp<trp->bp || ntp>=trp->lp) { error(ERROR, "## occurs at border of replacement"); continue; } len = ltp->len + ntp->len; strncpy((char*)tt, (char*)ltp->t, ltp->len); strncpy((char*)tt+ltp->len, (char*)ntp->t, ntp->len); tt[len] = '\0'; setsource("<##>", -1, tt); maketokenrow(3, &ntr); gettokens(&ntr, 1); unsetsource(); if (ntr.lp-ntr.bp!=2 || ntr.bp->type==UNCLASS) error(WARNING, "Bad token %r produced by ##", &ntr); ntr.lp = ntr.bp+1; trp->tp = ltp; makespace(&ntr); insertrow(trp, (ntp-ltp)+1, &ntr); dofree(ntr.bp); trp->tp--; } } CHECKOUT(); }
/* * rmap_grab() * Grab the requested range, or return failure if any of it is not free * * Returns 0 on success, 1 on failure. */ int rmap_grab(struct rmap *rmap, uint off, uint size) { struct rmap *r, *rlim; uint x, top, rtop; rlim = &rmap[rmap->r_off]; for (r = &rmap[1]; r <= rlim; ++r) { /* * If we've advanced beyond the requested offset, * we can never match, so end the loop. */ if (r->r_off > off) { break; } /* * See if this is the range which will hold our request */ top = r->r_off + r->r_size; if (!((r->r_off <= off) && (top > off))) { continue; } /* * Since this run encompasses the requested range, we * can either grab all of it, or none of it. */ /* * The top of our request extends beyond the block; fail. */ rtop = off + size; if (rtop > top) { return(1); } /* * If the requested start matches our range's start, we * can simply shave it off the front. */ if (off == r->r_off) { r->r_off += size; r->r_size -= size; if (r->r_size == 0) { collapse(rmap, r); } return(0); } /* * Similarly, if the end matches, we can shave the end */ if (rtop == top) { r->r_size -= size; /* * We know r_size > 0, since otherwise we would've * matched the previous case otherwise. */ ASSERT_DEBUG(r->r_size > 0, "phase error"); return(0); } /* * Otherwise we must split the range */ if (makespace(rmap, r)) { uint osize; /* * No room for further fragmentation, so chop off * to the tail. */ osize = r->r_size; r->r_size = top - rtop; lost_elems += (osize - r->r_size) - size; r->r_off = rtop; return(0); } /* * The current slot is everything below us */ r->r_size = off - r->r_off; /* * The new slot is everything above */ ++r; r->r_off = rtop; r->r_size = top - rtop; /* * OK */ return(0); } /* * Nope, not in our range of free entries */ return(1); }
/* * rmap_free() * Free some space back into the resource map * * The list is kept ordered, with the first free element flagged * with a size of 0. */ void rmap_free(struct rmap *rmap, uint off, uint size) { struct rmap *r, *rlim; ASSERT_DEBUG(off, "rmap_free: zero off"); ASSERT_DEBUG(size > 0, "rmap_free: zero size"); /* * Scan forward until we find the place we should be * inserted. */ rlim = &rmap[rmap->r_off]; for (r = &rmap[1]; r <= rlim; ++r) { /* * If the new free space abuts this entry, tack it * on and return. */ if ((r->r_off + r->r_size) == off) { r->r_size += size; /* * If this entry now abuts the next, coalesce */ if ((r < rlim) && ((r->r_off+r->r_size) == (r[1].r_off))) { r->r_size += r[1].r_size; rmap->r_off -= 1; ++r; if (r < rlim) { bcopy(r+1, r, sizeof(struct rmap)*(rlim-r)); } } return; } /* * If this space abuts the entry, pad it onto * the beginning. */ if ((off + size) == r->r_off) { r->r_size += size; r->r_off = off; return; } if (off < r->r_off) break; } /* * Need to add a new element. See if it'll fit. */ if (makespace(rmap, r)) { /* * Nope. Tabulate and lose the space. */ lost_elems += size; return; } /* * Record it */ r->r_off = off; r->r_size = size; }
/* * Add a character to str, expanding str1 as needed. * str1 (IN/OUT) target string (pointer to in case of expansion) * c (IN) character to add */ void _xstrcatchar(char **str, char c) { makespace(str, 1); strcatchar(*str, c); }
/* * Gather an arglist, starting in trp with tp pointing at the macro name. * Return total number of tokens passed, stash number of args found. * trp->tp is not changed relative to the tokenrow. */ int gatherargs(Tokenrow *trp, Tokenrow **atr, int *narg) { int parens = 1; int ntok = 0; Token *bp, *lp; Tokenrow ttr; int ntokp; int needspace; *narg = -1; /* means that there is no macro call */ /* look for the ( */ for (;;) { trp->tp++; ntok++; if (trp->tp >= trp->lp) { gettokens(trp, 0); if ((trp->lp-1)->type==END) { trp->lp -= 1; trp->tp -= ntok; return ntok; } } if (trp->tp->type==LP) break; if (trp->tp->type!=NL) return ntok; } *narg = 0; ntok++; ntokp = ntok; trp->tp++; /* search for the terminating ), possibly extending the row */ needspace = 0; while (parens>0) { if (trp->tp >= trp->lp) gettokens(trp, 0); if (needspace) { needspace = 0; makespace(trp); } if (trp->tp->type==END) { trp->lp -= 1; trp->tp -= ntok; error(ERROR, "EOF in macro arglist"); return ntok; } if (trp->tp->type==NL) { trp->tp += 1; adjustrow(trp, -1); trp->tp -= 1; makespace(trp); needspace = 1; continue; } if (trp->tp->type==LP) parens++; else if (trp->tp->type==RP) parens--; trp->tp++; ntok++; } trp->tp -= ntok; /* Now trp->tp won't move underneath us */ lp = bp = trp->tp+ntokp; for (; parens>=0; lp++) { if (lp->type == LP) { parens++; continue; } if (lp->type==RP) parens--; if (lp->type==DSHARP) lp->type = DSHARP1; /* ## not special in arg */ if (lp->type==COMMA && parens==0 || parens<0 && (lp-1)->type!=LP) { if (*narg>=NARG-1) error(FATAL, "Sorry, too many macro arguments"); ttr.bp = ttr.tp = bp; ttr.lp = lp; atr[(*narg)++] = normtokenrow(&ttr); bp = lp+1; } } return ntok; }
/* * Evaluate the ## operators in a tokenrow */ void doconcat(Tokenrow * trp) { Token *ltp, *ntp; Tokenrow ntr; size_t len; for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++) { if (trp->tp->type == DSHARP1) trp->tp->type = DSHARP; else if (trp->tp->type == DSHARP) { int i; char tt[NCONCAT]; ltp = trp->tp - 1; ntp = trp->tp + 1; if (ltp < trp->bp || ntp >= trp->lp) { error(ERROR, "## occurs at border of replacement"); continue; } ntp = ltp; i = 1; len = 0; do { if (len + ntp->len + ntp->wslen > sizeof(tt)) { error(ERROR, "## string concatination buffer overrun"); break; } if (ntp != trp->tp + 1) { strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen, ntp->len + ntp->wslen); len += ntp->len + ntp->wslen; } else // Leerzeichen um ## herum entfernen: { strncpy((char *) tt + len, (char *) ntp->t, ntp->len); len += ntp->len; } ntp = trp->tp + i; i++; } while (ntp < trp->lp); tt[len] = '\0'; setsource("<##>", -1, -1, tt, 0); maketokenrow(3, &ntr); gettokens(&ntr, 1); unsetsource(); if (ntr.bp->type == UNCLASS) error(WARNING, "Bad token %r produced by ##", &ntr); while ((ntr.lp-1)->len == 0 && ntr.lp != ntr.bp) ntr.lp--; doconcat(&ntr); trp->tp = ltp; makespace(&ntr, ltp); insertrow(trp, (int)(ntp - ltp), &ntr); dofree(ntr.bp); trp->tp--; } } }
/* * Expand the macro whose name is np, at token trp->tp, in the tokenrow. * Return trp->tp at the first token next to be expanded * (ordinarily the beginning of the expansion) * I.e.: the same position as before! * Only one expansion is performed, then we return to the expandrow() * loop and start at same position. */ void expand(Tokenrow * trp, Nlist * np, MacroValidatorList * pValidators) { Tokenrow ntr; int ntokc, narg; Tokenrow *atr[NARG + 1]; if (Mflag == 2) { if (np->ap) error(INFO, "Macro expansion of %t with %s(%r)", trp->tp, np->name, np->ap); else error(INFO, "Macro expansion of %t with %s", trp->tp, np->name); } copytokenrow(&ntr, np->vp); /* copy macro value */ if (np->ap == NULL) /* parameterless */ ntokc = 1; else { int i; ntokc = gatherargs(trp, atr, &narg); if (narg < 0) { /* not actually a call (no '(') */ trp->tp++; return; } if (narg != rowlen(np->ap)) { error(ERROR, "Disagreement in number of macro arguments"); trp->tp += ntokc; return; } /** If gatherargs passed a macro validating token, this token must become valid here. trp->tp+0 was checked in expandrow(), so we don't need to do it again here: */ for (i = 1; i < ntokc; i++) { mvl_check(pValidators,trp->tp+i); } substargs(np, &ntr, atr); /* put args into replacement */ for (i = 0; i < narg; i++) { dofree(atr[i]->bp); dofree(atr[i]); } } doconcat(&ntr); /* execute ## operators */ ntr.tp = ntr.bp; makespace(&ntr, trp->tp); tokenrow_zeroTokenIdentifiers(&ntr); insertrow(trp, ntokc, &ntr); /* add validator for just invalidated macro: */ np->flag |= ISACTIVE; if (trp->tp != trp->lp) { /* tp is a valid pointer: */ mvl_add(pValidators,np,trp->tp); } else { /* tp is == lp, therefore does not point to valid memory: */ mvl_add(pValidators,np,0); } /* reset trp->tp to original position: */ trp->tp -= ntr.lp - ntr.bp; /* so the result will be tested for macros from the same position again */ dofree(ntr.bp); return; }