/* * 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 + (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)->type == DSHARP || (rtr->tp != rtr->bp && (rtr->tp - 1)->type == DSHARP)) insertrow(rtr, 1, atr[argno]); else { copytokenrow(&tatr, atr[argno]); expandrow(&tatr, "<macro>"); insertrow(rtr, 1, &tatr); dofree(tatr.bp); } continue; } rtr->tp++; } }
void process(Tokenrow *trp) { int anymacros = 0; for (;;) { if (trp->tp >= trp->lp) { trp->tp = trp->lp = trp->bp; outbufp = outbuf; anymacros |= gettokens(trp, 1); trp->tp = trp->bp; } if (trp->tp->type == END) { if (--incdepth >= 0) { if (cursource->ifdepth) error(ERROR, "Unterminated conditional in #include"); unsetsource(); cursource->line += cursource->lineinc; trp->tp = trp->lp; genline(); continue; } if (ifdepth) error(ERROR, "Unterminated #if/#ifdef/#ifndef"); break; } if (trp->tp->type == SHARP) { trp->tp += 1; control(trp); } else if (!skipping && anymacros) expandrow(trp, NULL); if (skipping) setempty(trp); puttokens(trp); anymacros = 0; cursource->line += cursource->lineinc; if (cursource->lineinc > 1) { genline(); } } }
/** * process - 处理c源程序的总函数 * @trp: 用来存储c源程序中的一行Token */ void process(Tokenrow *trp) { int anymacros = 0; for (;;) { if (trp->tp >= trp->lp) { /* 如果当前token row中没有有效数据 */ trp->tp = trp->lp = trp->bp; /* 重置token row的当前token指针 */ outp = outbuf; /* 重置输出缓冲区的当前指针 */ anymacros |= gettokens(trp, 1); /* 得到一行Token */ trp->tp = trp->bp; } if (trp->tp->type == END) { /* 如果遇到EOFC结束符 */ if (--incdepth >= 0) { if (cursource->ifdepth) error(ERROR,"Unterminated conditional in #include"); unsetsource(); cursource->line += cursource->lineinc; trp->tp = trp->lp; genline(); continue; } if (ifdepth) error(ERROR, "Unterminated #if/#ifdef/#ifndef"); break; } if (trp->tp->type==SHARP) { /* 如果当前Token是'#'字符 */ trp->tp += 1; /* tp移动到token row中的下一个token */ control(trp); /* 处理预处理指令部分(宏定义,条件编译,头文件包含) */ } else if (!skipping && anymacros) expandrow(trp, NULL); if (skipping) /* 如果当前是忽略状态 */ setempty(trp); /* 置空当前行 */ puttokens(trp); /* 输出当前行 */ anymacros = 0; cursource->line += cursource->lineinc; if (cursource->lineinc>1) { genline(); } } }
/* decode a run length encoded sgi image */ static void decode_rle_sgi(SGIInfo *info, unsigned char *data, mp_image_t *mpi) { unsigned char *rle_data, *dest_row; uint32_t *starttab; int y, z, xsize, ysize, zsize, chan_offset; long start_offset; xsize = info->xsize; ysize = info->ysize; zsize = info->zsize; /* rle offset table is right after the header */ starttab = (uint32_t*)(data + SGI_HEADER_LEN); for (z = 0; z < zsize; z++) { /* set chan_offset so RGB ends up BGR */ chan_offset = (zsize - 1) - z; /* The origin for SGI images is the lower-left corner so read scan lines from bottom to top */ for (y = ysize - 1; y >= 0; y--) { dest_row = mpi->planes[0] + mpi->stride[0] * (ysize - 1 - y); /* set start of next run (offsets are from start of header) */ start_offset = AV_RB32(&starttab[y + z * ysize]); rle_data = &data[start_offset]; if(info->zsize == SGI_GRAYSCALE_IMAGE) { expandrow_gs(dest_row, rle_data); } else { expandrow(dest_row, rle_data, chan_offset); } } } }
/* * Evaluate an #if #elif #ifdef #ifndef line. trp->tp points to the keyword. */ long eval(Tokenrow *trp, int kw) { Token *tp; Nlist *np; int ntok, rand; trp->tp++; if (kw==KIFDEF || kw==KIFNDEF) { if (trp->lp - trp->bp != 4 || trp->tp->type!=NAME) { error(ERROR, "Syntax error in #ifdef/#ifndef"); return 0; } np = lookup(trp->tp, 0); return (kw==KIFDEF) == (np && np->flag&(ISDEFINED|ISMAC)); } ntok = trp->tp - trp->bp; kwdefined->val = KDEFINED; /* activate special meaning of defined */ expandrow(trp, "<if>"); kwdefined->val = NAME; vp = vals; op = ops; *op++ = END; for (rand=0, tp = trp->bp+ntok; tp < trp->lp; tp++) { switch(tp->type) { case WS: case NL: continue; /* nilary */ case NAME: case NAME1: case NUMBER: case CCON: case STRING: if (rand) goto syntax; if (vp == &vals[NSTAK]) { error(ERROR, "Eval botch (stack overflow)"); return 0; } *vp++ = tokval(tp); rand = 1; continue; /* unary */ case DEFINED: case TILDE: case NOT: if (rand) goto syntax; *op++ = tp->type; continue; /* unary-binary */ case PLUS: case MINUS: case STAR: case AND: if (rand==0) { if (tp->type==MINUS) *op++ = UMINUS; if (tp->type==STAR || tp->type==AND) { error(ERROR, "Illegal operator * or & in #if/#elsif"); return 0; } continue; } /* flow through */ /* plain binary */ case EQ: case NEQ: case LEQ: case GEQ: case LSH: case RSH: case LAND: case LOR: case SLASH: case PCT: case LT: case GT: case CIRC: case OR: case QUEST: case COLON: case COMMA: if (rand==0) goto syntax; if (evalop(priority[tp->type])!=0) return 0; *op++ = tp->type; rand = 0; continue; case LP: if (rand) goto syntax; *op++ = LP; continue; case RP: if (!rand) goto syntax; if (evalop(priority[RP])!=0) return 0; if (op<=ops || op[-1]!=LP) { goto syntax; } op--; continue; default: error(ERROR,"Bad operator (%t) in #if/#elsif", tp); return 0; } } if (rand==0) goto syntax; if (evalop(priority[END])!=0) return 0; if (op!=&ops[1] || vp!=&vals[1]) { error(ERROR, "Botch in #if/#elsif"); return 0; } if (vals[0].type==UND) error(ERROR, "Undefined expression value"); return vals[0].val; syntax: error(ERROR, "Syntax error in #if/#elsif"); return 0; }
void control(Tokenrow *trp) { Nlist *np; Token *tp; tp = trp->tp; if (tp->type!=NAME) { if (tp->type==NUMBER) goto kline; if (tp->type != NL) error(ERROR, "Unidentifiable control line"); return; /* else empty line */ } if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) { error(WARNING, "Unknown preprocessor control %t", tp); return; } if (skipping) { if ((np->flag&ISKW)==0) return; switch (np->val) { case KENDIF: if (--ifdepth<skipping) skipping = 0; --cursource->ifdepth; setempty(trp); return; case KIFDEF: case KIFNDEF: case KIF: if (++ifdepth >= NIF) error(FATAL, "#if too deeply nested"); ++cursource->ifdepth; return; case KELIF: case KELSE: if (ifdepth<=skipping) break; return; default: return; } } switch (np->val) { case KDEFINE: dodefine(trp); break; case KUNDEF: tp += 1; if (tp->type!=NAME || trp->lp - trp->bp != 4) { error(ERROR, "Syntax error in #undef"); break; } if ((np = lookup(tp, 0)) != NULL) np->flag &= ~ISDEFINED; break; case KPRAGMA: return; case KIFDEF: case KIFNDEF: case KIF: if (++ifdepth >= NIF) error(FATAL, "#if too deeply nested"); ++cursource->ifdepth; ifsatisfied[ifdepth] = 0; if (eval(trp, np->val)) ifsatisfied[ifdepth] = 1; else skipping = ifdepth; break; case KELIF: if (ifdepth==0) { error(ERROR, "#elif with no #if"); return; } if (ifsatisfied[ifdepth]==2) error(ERROR, "#elif after #else"); if (eval(trp, np->val)) { if (ifsatisfied[ifdepth]) skipping = ifdepth; else { skipping = 0; ifsatisfied[ifdepth] = 1; } } else skipping = ifdepth; break; case KELSE: if (ifdepth==0 || cursource->ifdepth==0) { error(ERROR, "#else with no #if"); return; } if (ifsatisfied[ifdepth]==2) error(ERROR, "#else after #else"); if (trp->lp - trp->bp != 3) error(ERROR, "Syntax error in #else"); skipping = ifsatisfied[ifdepth]? ifdepth: 0; ifsatisfied[ifdepth] = 2; break; case KENDIF: if (ifdepth==0 || cursource->ifdepth==0) { error(ERROR, "#endif with no #if"); return; } --ifdepth; --cursource->ifdepth; if (trp->lp - trp->bp != 3) error(WARNING, "Syntax error in #endif"); break; case KERROR: trp->tp = tp+1; error(WARNING, "#error directive: %r", trp); break; case KLINE: trp->tp = tp+1; expandrow(trp, "<line>"); tp = trp->bp+2; kline: if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){ error(ERROR, "Syntax error in #line"); return; } cursource->line = atol((char*)tp->t)-1; if (cursource->line<0 || cursource->line>=32768) error(WARNING, "#line specifies number out of range"); tp = tp+1; if (tp+1<trp->lp) cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0); return; case KDEFINED: error(ERROR, "Bad syntax for control line"); break; case KINCLUDE: doinclude(trp); trp->lp = trp->bp; return; case KEVAL: eval(trp, np->val); break; default: error(ERROR, "Preprocessor control `%t' not yet implemented", tp); break; } setempty(trp); return; }
void doinclude(Tokenrow* trp) { char fname[256], iname[256]; Includelist* ip; int angled, len, fd, i; trp->tp += 1; if (trp->tp >= trp->lp) goto syntax; if (trp->tp->type != STRING && trp->tp->type != LT) { len = trp->tp - trp->bp; expandrow(trp, "<include>"); trp->tp = trp->bp + len; } if (trp->tp->type == STRING) { len = trp->tp->len - 2; if (len > sizeof(fname) - 1) len = sizeof(fname) - 1; strncpy(fname, (char*)trp->tp->t + 1, len); angled = 0; } else if (trp->tp->type == LT) { len = 0; trp->tp++; while (trp->tp->type != GT) { if (trp->tp > trp->lp || len + trp->tp->len + 2 >= sizeof(fname)) goto syntax; strncpy(fname + len, (char*)trp->tp->t, trp->tp->len); len += trp->tp->len; trp->tp++; } angled = 1; } else goto syntax; trp->tp += 2; if (trp->tp < trp->lp || len == 0) goto syntax; fname[len] = '\0'; appendDirToIncludeList(basepath(fname)); if (fname[0] == '/') { fd = open(fname, 0); strcpy(iname, fname); } else for (fd = -1, i = NINCLUDE - 1; i >= 0; i--) { ip = &includelist[i]; if (ip->file == NULL || ip->deleted || (angled && ip->always == 0)) continue; if (strlen(fname) + strlen(ip->file) + 2 > sizeof(iname)) continue; strcpy(iname, ip->file); strcat(iname, "/"); strcat(iname, fname); if ((fd = open(iname, 0)) >= 0) break; } if (Mflag > 1 || (!angled && Mflag == 1)) { write(1, objname, strlen(objname)); write(1, iname, strlen(iname)); write(1, "\n", 1); } if (fd >= 0) { if (++incdepth > 10) error(FATAL, "#include too deeply nested"); setsource((char*)newstring((uchar*)iname, strlen(iname), 0), fd, NULL); genline(); } else { trp->tp = trp->bp + 2; error(ERROR, "Could not find include file %r", trp); } return; syntax: error(ERROR, "Syntax error in #include"); return; }
/** * control - 处理预处理控制指令(头文件包含指令,行控制指令,条件编译指令) * @trp: 一行源程序的Token * 返回值:无 */ void control(Tokenrow *trp) { Nlist *np; Token *tp; tp = trp->tp; /* 获得Tokenrow中的当前Token(指向预处理控制指令关键字) */ if (tp->type!=NAME) { /* 如果当前Token不是标识符 */ if (tp->type==NUMBER) /* 如果当前Token是数字 */ goto kline; /* 跳转,处理行控制指令 */ if (tp->type != NL) /* 如果该Token既不是标识符,也不是数字 */ error(ERROR, "Unidentifiable control line"); /* 则,打印信息`无法识别的控制指令行' */ return; /* 该行处理完毕,函数返回(该行为空行,无控制信息,else empty line) */ } /* 如果当前Token是标识符但标识符不在标识符hash表中 或 标识符在hash表中但不是关键字且不能略过(TODO:啥是略过?) */ if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) { error(WARNING, "Unknown preprocessor control %t", tp); /* 打印信息,无法识别的预处理控制指令 */ return; /* 该行处理完毕 */ } if (skipping) { /* TODO: 啥是skipping? */ if ((np->flag&ISKW)==0) /* 如果np不是关键字 */ return; /* 函数返回 */ switch (np->val) { case KENDIF: if (--ifdepth<skipping) skipping = 0; --cursource->ifdepth; setempty(trp); return; case KIFDEF: case KIFNDEF: case KIF: if (++ifdepth >= NIF) error(FATAL, "#if too deeply nested"); ++cursource->ifdepth; return; case KELIF: case KELSE: if (ifdepth<=skipping) break; return; default: return; } } switch (np->val) { case KDEFINE: /* #define,定义宏 */ dodefine(trp); /* 定义宏 */ break; case KUNDEF: /* #undef */ tp += 1; /* tp指向宏名 */ if (tp->type!=NAME || trp->lp - trp->bp != 4) { /* 如果tp不是标识符类型 或者 lp-bp!=4 (lp和bp之间有4个Token) */ error(ERROR, "Syntax error in #undef"); /* 打印错误信息 */ break; } if ((np = lookup(tp, 0)) != NULL) /* 如果在hash表中找到了tp所指向的宏名 */ np->flag &= ~ISDEFINED; /* 清零ISDEFINED标志位 */ break; case KPRAGMA: /* #pragma */ return; case KIFDEF: /* #ifdef */ case KIFNDEF: /* #ifndef */ case KIF: /* #if */ if (++ifdepth >= NIF) /* 全局条件编译语句的嵌套深度值加1 */ error(FATAL, "#if too deeply nested"); /* 如果嵌套深度值大于NIF,则打印错误信息 `#if中嵌入太深' */ ++cursource->ifdepth; /* 当前输入源的条件编译语句的嵌套深度值加1 */ ifsatisfied[ifdepth] = 0; /* 设定条件编译语句的嵌套深度值对应的if语句还未被满足 */ if (eval(trp, np->val)) ifsatisfied[ifdepth] = 1; else skipping = ifdepth; break; case KELIF: /* #elif */ if (ifdepth==0) { error(ERROR, "#elif with no #if"); return; } if (ifsatisfied[ifdepth]==2) error(ERROR, "#elif after #else"); if (eval(trp, np->val)) { if (ifsatisfied[ifdepth]) skipping = ifdepth; else { skipping = 0; ifsatisfied[ifdepth] = 1; } } else skipping = ifdepth; break; case KELSE: /* #else */ if (ifdepth==0 || cursource->ifdepth==0) { error(ERROR, "#else with no #if"); return; } if (ifsatisfied[ifdepth]==2) error(ERROR, "#else after #else"); if (trp->lp - trp->bp != 3) error(ERROR, "Syntax error in #else"); skipping = ifsatisfied[ifdepth]? ifdepth: 0; ifsatisfied[ifdepth] = 2; break; case KENDIF: /* #endif */ if (ifdepth==0 || cursource->ifdepth==0) { error(ERROR, "#endif with no #if"); return; } --ifdepth; --cursource->ifdepth; if (trp->lp - trp->bp != 3) error(WARNING, "Syntax error in #endif"); break; case KERROR: /* #error */ trp->tp = tp+1; error(WARNING, "#error directive: %r", trp); break; case KLINE: /* #line */ trp->tp = tp+1; expandrow(trp, "<line>"); tp = trp->bp+2; kline: /* 行控制信息处理(line control)*/ if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')) { /* 如果行控制语法有误 */ /* 上面的if判断中共有5种语法错误检查: * 1. 如果只有`# 123\n' * 2. 如果当前token不是数字类型 * 3. 如果有类似`# 123 "file.c" 2 3'的行,那么这种行不被lcc的预处理程序支持。TODO:lcc不支持行控制中的flag语法. * 4. 如果在`# linenum filename'中,filename不是字符串 * 5. 如果filename是宽字符字符串 */ error(ERROR, "Syntax error in #line"); /* 打印错误信息 */ return; /* 该函数返回 */ } cursource->line = atol((char*)tp->t)-1; /* 更新当前输入源的行号信息 */ if (cursource->line<0 || cursource->line>=32768) /* 如果转化后的行号小于0或者行号大于32768 */ error(WARNING, "#line specifies number out of range"); /* 打印错误信息 */ tp = tp+1; /* 指针移动到filename位置 */ if (tp+1<trp->lp) /* 如果filename存在(因为filename后通常紧跟一个换行符token) */ cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0); /* 保存输入源的文件名 */ return; /* 该行处理完毕,函数返回 */ case KDEFINED: /* #defined */ error(ERROR, "Bad syntax for control line"); /* 打印语法错误提示 */ break; case KINCLUDE: /* #include */ doinclude(trp); trp->lp = trp->bp; return; case KEVAL: /* #eval */ eval(trp, np->val); break; default: /* # other */ error(ERROR, "Preprocessor control `%t' not yet implemented", tp); /* 未实现的预处理控制指令 */ break; } setempty(trp); /* 置空Tokenrow */ return; }