static void setfile(const char *name, struct stat *fs) { static struct timeval tv[2]; fs->st_mode &= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO; TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atim); TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtim); if (utimes(name, tv)) cwarn("utimes: %s", name); /* * Changing the ownership probably won't succeed, unless we're root * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting * the mode; current BSD behavior is to remove all setuid bits on * chown. If chown fails, lose setuid/setgid bits. */ if (chown(name, fs->st_uid, fs->st_gid)) { if (errno != EPERM) cwarn("chown: %s", name); fs->st_mode &= ~(S_ISUID|S_ISGID); } if (chmod(name, fs->st_mode) && errno != EOPNOTSUPP) cwarn("chmod: %s", name); if (chflags(name, fs->st_flags) && errno != EOPNOTSUPP) cwarn("chflags: %s", name); }
static int post_preproc( char * out ) /* * Convert digraphs and double '\\' of the second byte of SJIS (BIGFIVE or * ISO2022_JP). * Note: Output of -K option embeds macro informations into comments. * scan_token() does not recognize comment and parses it as '/', '*', etc. */ { #if ! HAVE_DIGRAPHS int di_count = 0; #endif int token_type; int c; char * str; char * cp = out; unget_string( out, NULL); while ((c = get_ch()) != '\n') { /* Not to read over to next line */ if (char_type[ c] & HSP) { *cp++ = c; continue; } str = cp; token_type = scan_token( c, &cp, out_wend); switch (token_type) { #if ! MBCHAR_IS_ESCAPE_FREE case WSTR : case WCHR : str++; /* Skip prefix 'L' */ /* Fall through */ case STR : case CHR : if (bsl_need_escape) cp = esc_mbchar( str, cp); break; #endif /* ! MBCHAR_IS_ESCAPE_FREE */ #if ! HAVE_DIGRAPHS case OPE : if (mcpp_mode == STD && (openum & OP_DIGRAPH)) { cp = conv_a_digraph( cp); /* Convert a digraph */ di_count++; } break; #endif } } *cp++ = '\n'; *cp = EOS; #if ! HAVE_DIGRAPHS if (mcpp_mode == STD && di_count && (warn_level & 16)) cwarn( "%.0s%ld digraph(s) converted" /* _W16_ */ , NULL, (long) di_count, NULL); #endif return 0; }
/* * Remove the symbol from the defined list. * Called from the #control processor. */ void doundef() { int c; if (type[(c = skipws())] != LET) cerror("Illegal #undef argument", NULLST); else { scanid(c); /* Get name to token[] */ if (defendel(token, TRUE) == NULL) { #ifdef STRICT_UNDEF cwarn("Symbol \"%s\" not defined in #undef", token); #endif } } }
static void decompress(const char *in, const char *out, int bits) { size_t nr; struct stat sb; FILE *ifp, *ofp; int exists, isreg, oreg; u_char buf[1024]; exists = !stat(out, &sb); if (!force && exists && S_ISREG(sb.st_mode) && !permission(out)) return; isreg = oreg = !exists || S_ISREG(sb.st_mode); ifp = ofp = NULL; if ((ifp = zopen(in, "r", bits)) == NULL) { cwarn("%s", in); return; } if (stat(in, &sb)) { cwarn("%s", in); goto err; } if (!S_ISREG(sb.st_mode)) isreg = 0; /* * Try to read the first few uncompressed bytes from the input file * before blindly truncating the output file. */ if ((nr = fread(buf, 1, sizeof(buf), ifp)) == 0) { cwarn("%s", in); (void)fclose(ifp); return; } if ((ofp = fopen(out, "w")) == NULL || (nr != 0 && fwrite(buf, 1, nr, ofp) != nr)) { cwarn("%s", out); (void)fclose(ifp); return; } while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0) if (fwrite(buf, 1, nr, ofp) != nr) { cwarn("%s", out); goto err; } if (ferror(ifp) || fclose(ifp)) { cwarn("%s", in); goto err; } ifp = NULL; if (fclose(ofp)) { cwarn("%s", out); goto err; } if (isreg) { setfile(out, &sb); if (unlink(in)) cwarn("%s", in); } return; err: if (ofp) { if (oreg) (void)unlink(out); (void)fclose(ofp); } if (ifp) (void)fclose(ifp); }
INLINE FILE_LOCAL ReturnCode cppmain(struct Global *global) { /* * Main process for cpp -- copies tokens from the current input * stream (main file, include file, or a macro) to the output * file. */ int c; /* Current character */ int counter; /* newlines and spaces */ ReturnCode ret; /* return code variable type */ long bracelevel = 0; long parenlevel = 0; long bracketlevel = 0; int fake = 0; #define MAX_FUNC_LENGTH 50 char tempfunc[MAX_FUNC_LENGTH + 1]; char tempfunc2[MAX_FUNC_LENGTH + 1]; char define = 0; /* probability of a function define phase in the program */ char prev = 0; /* previous type */ char go = 0; char include = 0; char initfunc = 0; /* Initialize for reading tokens */ global->tokenbsize = 50; global->tokenbuf = malloc(global->tokenbsize + 1); if(!global->tokenbuf) return(FPP_OUT_OF_MEMORY); global->functionname = malloc(global->tokenbsize + 1); if(!global->functionname) return(FPP_OUT_OF_MEMORY); global->functionname[0] = '\0'; if(global->showspace) { global->spacebuf = (char *)malloc(MAX_SPACE_SIZE); if(!global->spacebuf) return(FPP_OUT_OF_MEMORY); } if(global->showversion) Error(global, VERSION_TEXT); /* * Explicitly output a #line at the start of cpp output so * that lint (etc.) knows the name of the original source * file. If we don't do this explicitly, we may get * the name of the first #include file instead. */ if(global->linelines) /* if #line lines are wanted! */ sharp(global); /* * This loop is started "from the top" at the beginning of each line * wrongline is set TRUE in many places if it is necessary to write * a #line record. (But we don't write them when expanding macros.) * * The counter variable has two different uses: at * the start of a line, it counts the number of blank lines that * have been skipped over. These are then either output via * #line records or by outputting explicit blank lines. * When expanding tokens within a line, the counter remembers * whether a blank/tab has been output. These are dropped * at the end of the line, and replaced by a single blank * within lines. */ include = global->included; while(include--) { openinclude(global, global->include[include], TRUE); } for (;;) { counter = 0; /* Count empty lines */ for (;;) { /* For each line, ... */ global->comment = FALSE; /* No comment yet! */ global->chpos = 0; /* Count whitespaces */ while (type[(c = get(global))] == SPA) /* Skip leading blanks */ if(global->showspace) { if(global->chpos<MAX_SPACE_SIZE-1) /* we still have buffer to store this! */ global->spacebuf[global->chpos++]=(char)c; } if (c == '\n') { /* If line's all blank, */ if(global->comment) { /* A comment was output! */ Putchar(global, '\n'); } else ++counter; /* Do nothing now */ } else if (c == '#') { /* Is 1st non-space '#' */ global->keepcomments = FALSE; /* Don't pass comments */ ret = control(global, &counter); /* Yes, do a #command */ if(ret) return(ret); global->keepcomments = (global->cflag && compiling); } else if (c == EOF_CHAR) /* At end of file? */ break; else if (!compiling) { /* #ifdef false? */ skipnl(global); /* Skip to newline */ counter++; /* Count it, too. */ } else { break; /* Actual token */ } } if (c == EOF_CHAR) /* Exit process at */ break; /* End of file */ /* * If the loop didn't terminate because of end of file, we * know there is a token to compile. First, clean up after * absorbing newlines. counter has the number we skipped. */ if(global->linelines) { /* if #line lines are wanted! */ if ((global->wrongline && global->infile->fp != NULL) || counter > 4) sharp(global); /* Output # line number */ else { /* If just a few, stuff */ while (--counter >= 0) /* them out ourselves */ Putchar(global, (int)'\n'); } } if(global->showspace) { /* Show all whitespaces! */ global->spacebuf[global->chpos] = '\0'; Putstring(global, global->spacebuf); } /* * Process each token on this line. */ unget(global); /* Reread the char. */ for (;;) { /* For the whole line, */ do { /* Token concat. loop */ for (global->chpos = counter = 0; (type[(c = get(global))] == SPA);) { #if COMMENT_INVISIBLE if (c != COM_SEP) counter++; #else if(global->showspace && global->chpos < MAX_SPACE_SIZE-1) { global->spacebuf[global->chpos++]=(char)c; } counter++; /* Skip over blanks */ #endif } if (c == EOF_CHAR || c == '\n') break; /* Exit line loop */ else if (counter > 0) { /* If we got any spaces */ if(!global->showspace) /* We don't output all spaces */ Putchar(global, (int)' ');/* Output one space */ else { global->spacebuf[global->chpos] = '\0'; Putstring(global, global->spacebuf); /* Output all whitespaces */ } } if(ret=macroid(global, &c)) /* Grab the token */ return(ret); } while (type[c] == LET && catenate(global, &ret) && !ret); if(ret) /* If the loop was broken because of a fatal error! */ return(ret); if (c == EOF_CHAR || c == '\n') /* From macro exp error */ break; /* Exit line loop */ go++; switch (type[c]) { case LET: go =0; /* Quite ordinary token */ Putstring(global, global->tokenbuf); if(!define) { /* Copy the name */ strncpy(tempfunc, global->tokenbuf, MAX_FUNC_LENGTH); tempfunc[MAX_FUNC_LENGTH]=0; } /* fputs(global->tokenbuf, stdout); */ break; case DIG: /* Output a number */ case DOT: /* Dot may begin floats */ go = 0; ret=scannumber(global, c, (ReturnCode(*)(struct Global *, int))output); if(ret) return(ret); break; case QUO: /* char or string const */ go = 0; /* Copy it to output */ if(!global->webmode) { ret=scanstring(global, c, (ReturnCode(*)(struct Global *, int))output); if(ret) return(ret); break; } /* FALLTHROUGH */ default: /* Some other character */ define++; switch(c) { case '{': if(! bracelevel++ && define > 2) { /* * This is a starting brace. If there is a probability of a * function defining, we copy the `tempfunc' function name to * `global->functionname'. */ strcpy(global->functionname, tempfunc2); global->funcline = global->line; if(global->outputfunctions) { /* * Output the discovered function name to stderr! */ Error(global, "#> Function defined at line %d: %s <#\n", global->line, global->functionname); } if(global->initialfunc) { int a; for(a=0; a<global->excluded; a++) { /* check for excluded functions */ if(!strcmp(global->functionname, global->excludedinit[a])) break; } if(a==global->excluded) { expstuff(global, "__brace__", "{"); expstuff(global, "__init_func__", global->initialfunc); initfunc = TRUE; } } } break; case '}': go = 0; if( (--bracelevel == initfunc) && strcmp(global->infile->filename, "__init_func__") ) { /* we just stepped out of the function! */ global->functionname[0] = '\0'; global->funcline = 0; define = 1; if(initfunc) { Putchar(global, '}'); bracelevel--; initfunc=0; } } fake = 0; break; case ';': case ',': if(go == 2) { define = 1; fake = 0; go--; break; } break; case '(': if(! parenlevel++ && !bracelevel) { if(go == 2) { /* foobar(text) -> "(" is found. This can't be a function */ go--; define = 1; break; } if( define < 2 && prev == LET) { /* This is the first parenthesis on the ground brace level, and we did previously not have a probable function name */ strncpy(tempfunc2, global->tokenbuf, MAX_FUNC_LENGTH); tempfunc2[MAX_FUNC_LENGTH]=0; define++; } else { /* we have a fake start */ fake++; } } break; case ')': if(! --parenlevel && !bracelevel && define>1 && !fake) { /* * The starting parentheses level and * the starting brace level. * This might be the start of a function defining coming * up! */ define++; /* increase probability */ fake = 0; go = 1; } break; case '[': bracketlevel++; break; case ']': bracketlevel--; break; } define--; /* decrease function probability */ Putchar(global, c); /* Just output it */ break; } /* Switch ends */ prev = type[c]; } /* Line for loop */ if (c == '\n') { /* Compiling at EOL? */ Putchar(global, '\n'); /* Output newline, if */ if (global->infile->fp == NULL) /* Expanding a macro, */ global->wrongline = TRUE; /* Output # line later */ } } /* Continue until EOF */ if(global->showbalance) { if(bracketlevel) { cwarn(global, WARN_BRACKET_DEPTH, bracketlevel); } if(parenlevel) { cwarn(global, WARN_PAREN_DEPTH, parenlevel); } if(bracelevel) { cwarn(global, WARN_BRACE_DEPTH, bracelevel); } } if (global->wflag) { global->out = TRUE; /* enable output */ outdefines(global); /* Write out #defines */ } return(FPP_OK); }
int dooptions(int argc, char** argv) /* * dooptions is called to process command line arguments (-Detc). * It is called only at cpp startup. */ { register char *ap; register DEFBUF *dp; register int c; int i, j; char *arg; SIZES *sizp; /* For -S */ int size; /* For -S */ int isdatum; /* FALSE for -S* */ int endtest; /* For -S */ for (i = j = 1; i < argc; i++) { arg = ap = argv[i]; if (*ap++ != '-' || *ap == EOS) { argv[j++] = argv[i]; } else { c = *ap++; /* Option byte */ if (islower(c)) /* Normalize case */ c = toupper(c); switch (c) { /* Command character */ case 'C': /* Keep comments */ cflag = TRUE; keepcomments = TRUE; break; case 'D': /* Define symbol */ /* * If the option is just "-Dfoo", make it -Dfoo=1 */ while (*ap != EOS && *ap != '=') ap++; if (*ap == EOS) ap = "1"; else *ap++ = EOS; /* * Now, save the word and its definition. */ dp = defendel(argv[i] + 2, FALSE); dp->repl = savestring(ap); dp->nargs = DEF_NOARGS; break; case 'E': /* Ignore non-fatal */ eflag = TRUE; /* errors. */ break; case 'I': /* Include directory */ AddInclude( ap ); /* BP, 11.09.91 */ break; case 'N': /* No predefineds */ nflag++; /* Repeat to undefine */ break; /* __LINE__, etc. */ case 'S': sizp = size_table; if (0 != (isdatum = (*ap != '*'))) /* If it's just -S, */ endtest = T_FPTR; /* Stop here */ else { /* But if it's -S* */ ap++; /* Step over '*' */ endtest = 0; /* Stop at end marker */ } while (sizp->bits != endtest && *ap != EOS) { if (!isdigit(*ap)) { /* Skip to next digit */ ap++; continue; } size = 0; /* Compile the value */ while (isdigit(*ap)) { size *= 10; size += (*ap++ - '0'); } if (isdatum) sizp->size = size; /* Datum size */ else sizp->psize = size; /* Pointer size */ sizp++; } if (sizp->bits != endtest) cwarn("-S, too few values specified in %s", argv[i]); else if (*ap != EOS) cwarn("-S, too many values, \"%s\" unused", ap); break; case 'U': /* Undefine symbol */ if (defendel(ap, TRUE) == NULL) cwarn("\"%s\" wasn't defined", ap); break; #if OSL_DEBUG_LEVEL > 1 case 'X': /* Debug */ debug = (isdigit(*ap)) ? atoi(ap) : 1; #if (HOST == SYS_VMS || HOST == SYS_UNIX) signal(SIGINT, (void (*)(int)) abort); /* Trap "interrupt" */ #endif fprintf(stderr, "Debug set to %d\n", debug); break; #endif #if OSL_DEBUG_LEVEL > 1 case 'P': /* #define's dump */ bDumpDefs = 1; fprintf(stderr, "Dump #define's is on\n"); break; #endif default: /* What is this one? */ cwarn("Unknown option \"%s\"", arg); fprintf(stderr, "The following options are valid:\n\ -C\t\t\tWrite source file comments to output\n\ -Dsymbol=value\tDefine a symbol with the given (optional) value\n\ -Idirectory\t\tAdd a directory to the #include search list\n\ -N\t\t\tDon't predefine target-specific names\n\ -Stext\t\tSpecify sizes for #if sizeof\n\ -Usymbol\t\tUndefine symbol\n"); #if OSL_DEBUG_LEVEL > 1 fprintf(stderr, " -Xvalue\t\tSet internal debug flag\n"); fprintf(stderr, " -P\t\t\tdump #define's\n"); #endif break; } /* Switch on all options */ } /* If it's a -option */ } /* For all arguments */ #if OSL_DEBUG_LEVEL > 1 if ( (bDumpDefs ? j > 4 : j > 3) ) { #else if (j > 3) { #endif cerror( "Too many file arguments. Usage: cpp [input [output]]", NULLST); } return (j); /* Return new argc */ } int readoptions(char* filename, char*** pfargv) { FILE *fp; int c; int bInQuotes = 0; char optbuff[1024], *poptbuff; int fargc=0, back; char *fargv[PARALIMIT], **pfa; pfa=*pfargv=malloc(sizeof(fargv)); poptbuff=&optbuff[0]; filename++; if ((fp = fopen(filename, "r")) == NULL) { #if OSL_DEBUG_LEVEL > 1 if ( debug || !bDumpDefs ) perror(filename); #endif return (FALSE); } do { /* * #i27914# double ticks '"' now have a duplicate function: * 1. they define a string ( e.g. -DFOO="baz" ) * 2. a string can contain spaces, so -DFOO="baz zum" defines one * argument no two ! */ c=fgetc(fp); if ( c != ' ' && c != CR && c != NL && c != HT && c != EOF) { *poptbuff++=(char)c; if( c == '"' ) bInQuotes = ~bInQuotes; } else { if( c != EOF && bInQuotes ) *poptbuff++=(char)c; else { *poptbuff=EOS; if (strlen(optbuff)>0) { pfa[fargc+1]=malloc(strlen(optbuff)+1); strcpy(pfa[fargc+1],optbuff); fargc++; pfa[fargc+1]=0; poptbuff=&optbuff[0]; } } } } while ( c != EOF ); fclose(fp); back=dooptions(fargc+1,pfa); return (back); }
static void compress(const char *in, const char *out, int bits) { size_t nr; struct stat isb, sb; FILE *ifp, *ofp; int exists, isreg, oreg; u_char buf[1024]; exists = !stat(out, &sb); if (!force && exists && S_ISREG(sb.st_mode) && !permission(out)) return; isreg = oreg = !exists || S_ISREG(sb.st_mode); ifp = ofp = NULL; if ((ifp = fopen(in, "r")) == NULL) { cwarn("%s", in); return; } if (stat(in, &isb)) { /* DON'T FSTAT! */ cwarn("%s", in); goto err; } if (!S_ISREG(isb.st_mode)) isreg = 0; if ((ofp = zopen(out, "w", bits)) == NULL) { cwarn("%s", out); goto err; } while ((nr = fread(buf, 1, sizeof(buf), ifp)) != 0) if (fwrite(buf, 1, nr, ofp) != nr) { cwarn("%s", out); goto err; } if (ferror(ifp) || fclose(ifp)) { cwarn("%s", in); goto err; } ifp = NULL; if (fclose(ofp)) { cwarn("%s", out); goto err; } ofp = NULL; if (isreg) { if (stat(out, &sb)) { cwarn("%s", out); goto err; } if (!force && sb.st_size >= isb.st_size) { if (verbose) (void)fprintf(stderr, "%s: file would grow; left unmodified\n", in); eval = 2; if (unlink(out)) cwarn("%s", out); goto err; } setfile(out, &isb); if (unlink(in)) cwarn("%s", in); if (verbose) { (void)fprintf(stderr, "%s: ", out); if (isb.st_size > sb.st_size) (void)fprintf(stderr, "%.0f%% compression\n", ((float)sb.st_size / isb.st_size) * 100.0); else (void)fprintf(stderr, "%.0f%% expansion\n", ((float)isb.st_size / sb.st_size) * 100.0); } } return; err: if (ofp) { if (oreg) (void)unlink(out); (void)fclose(ofp); } if (ifp) (void)fclose(ifp); }
ReturnCode expand(struct Global *global, DEFBUF *tokenp) { /* * Expand a macro. Called from the cpp mainline routine (via subroutine * macroid()) when a token is found in the symbol table. It calls * expcollect() to parse actual parameters, checking for the correct number. * It then creates a "file" containing a single line containing the * macro with actual parameters inserted appropriately. This is * "pushed back" onto the input stream. (When the get() routine runs * off the end of the macro line, it will dismiss the macro itself.) */ int c; FILEINFO *file; ReturnCode ret=FPP_OK; /* * If no macro is pending, save the name of this macro * for an eventual error message. */ if (global->recursion++ == 0) global->macro = tokenp; else if (global->recursion == RECURSION_LIMIT) { cerror(global, ERROR_RECURSIVE_MACRO, tokenp->name, global->macro->name); if (global->rec_recover) { do { c = get(global); } while (global->infile != NULL && global->infile->fp == NULL); unget(global); global->recursion = 0; return(FPP_OK); } } /* * Here's a macro to expand. */ global->nargs = 0; /* Formals counter */ global->parmp = global->parm; /* Setup parm buffer */ switch (tokenp->nargs) { case (-2): /* __LINE__ */ if(global->infile->fp) /* This is a file */ sprintf(global->work, "%d", global->line); else /* This is a macro! Find out the file line number! */ for (file = global->infile; file != NULL; file = file->parent) { if (file->fp != NULL) { sprintf(global->work, "%d", file->line); break; } } ret=ungetstring(global, global->work); if(ret) return(ret); break; case (-3): /* __FILE__ */ for (file = global->infile; file != NULL; file = file->parent) { if (file->fp != NULL) { sprintf(global->work, "\"%s\"", (file->progname != NULL) ? file->progname : file->filename); ret=ungetstring(global, global->work); if(ret) return(ret); break; } } break; case (-4): /* __FUNC__ */ sprintf(global->work, "\"%s\"", global->functionname[0]? global->functionname : "<unknown function>"); ret=ungetstring(global, global->work); if(ret) return(ret); break; case (-5): /* __FUNC_LINE__ */ sprintf(global->work, "%d", global->funcline); ret=ungetstring(global, global->work); if(ret) return(ret); break; default: /* * Nothing funny about this macro. */ if (tokenp->nargs < 0) { cfatal(global, FATAL_ILLEGAL_MACRO, tokenp->name); return(FPP_ILLEGAL_MACRO); } while ((c = skipws(global)) == '\n') /* Look for (, skipping */ global->wrongline = TRUE; /* spaces and newlines */ if (c != '(') { /* * If the programmer writes * #define foo() ... * ... * foo [no ()] * just write foo to the output stream. */ unget(global); cwarn(global, WARN_MACRO_NEEDS_ARGUMENTS, tokenp->name); /* fputs(tokenp->name, stdout); */ Putstring(global, tokenp->name); return(FPP_OK); } else if (!(ret=expcollect(global))) { /* Collect arguments */ if (tokenp->nargs != global->nargs) { /* Should be an error? */ cwarn(global, WARN_WRONG_NUMBER_ARGUMENTS, tokenp->name); } } else { /* Collect arguments */ return(ret); /* We failed in argument colleting! */ } case DEF_NOARGS: /* No parameters just stuffs */ ret=expstuff(global, tokenp->name, tokenp->repl); /* expand macro */ } /* nargs switch */ return(ret); }
int dooptions(struct Global *global, struct fppTag *tags) { /* * dooptions is called to process command line arguments (-Detc). * It is called only at cpp startup. */ DEFBUF *dp; char end=FALSE; /* end of taglist */ while(tags && !end) { switch(tags->tag) { case FPPTAG_END: end=TRUE; break; case FPPTAG_INITFUNC: global->initialfunc = (char *) tags->data; break; case FPPTAG_DISPLAYFUNCTIONS: global->outputfunctions = TRUEFALSE(tags->data); break; case FPPTAG_RIGHTCONCAT: global->rightconcat = TRUEFALSE(tags->data); break; case FPPTAG_OUTPUTMAIN: global->outputfile = TRUEFALSE(tags->data); break; case FPPTAG_NESTED_COMMENTS: global->nestcomments = TRUEFALSE(tags->data); break; case FPPTAG_WARNMISSINCLUDE: global->warnnoinclude = TRUEFALSE(tags->data); break; case FPPTAG_WARN_NESTED_COMMENTS: global->warnnestcomments = TRUEFALSE(tags->data); break; case FPPTAG_OUTPUTSPACE: global->showspace = TRUEFALSE(tags->data); break; case FPPTAG_OUTPUTBALANCE: global->showbalance = TRUEFALSE(tags->data); break; case FPPTAG_OUTPUTINCLUDES: global->showincluded = TRUEFALSE(tags->data); break; case FPPTAG_IGNOREVERSION: global->showversion = TRUEFALSE(tags->data); break; case FPPTAG_WARNILLEGALCPP: global->warnillegalcpp=TRUEFALSE(tags->data); break; case FPPTAG_OUTPUTLINE: global->outputLINE= TRUEFALSE(tags->data); break; case FPPTAG_KEEPCOMMENTS: if(tags->data) { global->cflag = TRUE; global->keepcomments = TRUE; } break; case FPPTAG_DEFINE: /* * If the option is just "-Dfoo", make it -Dfoo=1 */ { char *symbol=(char *)tags->data; char *text=symbol; while (*text != EOS && *text != '=') text++; if (*text == EOS) text = "1"; else *text++ = EOS; /* * Now, save the word and its definition. */ dp = defendel(global, symbol, FALSE); if(!dp) return(FPP_OUT_OF_MEMORY); dp->repl = savestring(global, text); dp->nargs = DEF_NOARGS; } break; case FPPTAG_IGNORE_NONFATAL: global->eflag = TRUE; break; case FPPTAG_INCLUDE_DIR: if (global->incend >= &global->incdir[NINCLUDE]) { cfatal(global, FATAL_TOO_MANY_INCLUDE_DIRS); return(FPP_TOO_MANY_INCLUDE_DIRS); } *global->incend++ = (char *)tags->data; break; case FPPTAG_INCLUDE_FILE: case FPPTAG_INCLUDE_MACRO_FILE: if (global->included >= NINCLUDE) { cfatal(global, FATAL_TOO_MANY_INCLUDE_FILES); return(FPP_TOO_MANY_INCLUDE_FILES); } global->include[global->included] = (char *)tags->data; global->includeshow[global->included] = (tags->tag == FPPTAG_INCLUDE_FILE); global->included++; break; case FPPTAG_BUILTINS: global->nflag|=(tags->data?NFLAG_BUILTIN:0); break; case FPPTAG_PREDEFINES: global->nflag|=(tags->data?NFLAG_PREDEFINE:0); break; case FPPTAG_IGNORE_CPLUSPLUS: global->cplusplus=!tags->data; break; case FPPTAG_SIZEOF_TABLE: { SIZES *sizp; /* For -S */ int size; /* For -S */ int isdatum; /* FALSE for -S* */ int endtest; /* For -S */ char *text=(char *)tags->data; sizp = size_table; if (isdatum = (*text != '*')) /* If it's just -S, */ endtest = T_FPTR; /* Stop here */ else { /* But if it's -S* */ text++; /* Step over '*' */ endtest = 0; /* Stop at end marker */ } while (sizp->bits != endtest && *text != EOS) { if (!isdigit(*text)) { /* Skip to next digit */ text++; continue; } size = 0; /* Compile the value */ while (isdigit(*text)) { size *= 10; size += (*text++ - '0'); } if (isdatum) sizp->size = size; /* Datum size */ else sizp->psize = size; /* Pointer size */ sizp++; } if (sizp->bits != endtest) cwarn(global, WARN_TOO_FEW_VALUES_TO_SIZEOF, NULL); else if (*text != EOS) cwarn(global, WARN_TOO_MANY_VALUES_TO_SIZEOF, NULL); } break; case FPPTAG_UNDEFINE: if (defendel(global, (char *)tags->data, TRUE) == NULL) cwarn(global, WARN_NOT_DEFINED, tags->data); break; case FPPTAG_OUTPUT_DEFINES: global->wflag++; break; case FPPTAG_INPUT_NAME: strcpy(global->work, tags->data); /* Remember input filename */ global->first_file=tags->data; break; case FPPTAG_INPUT: global->input=(char *(*)(char *, int, void *))tags->data; break; case FPPTAG_OUTPUT: global->output=(void (*)(int, void *))tags->data; break; case FPPTAG_ERROR: global->error=(void (*)(void *, char *, va_list))tags->data; break; case FPPTAG_USERDATA: global->userdata=tags->data; break; case FPPTAG_LINE: global->linelines= TRUEFALSE(tags->data); break; case FPPTAG_EXCLFUNC: global->excludedinit[ global->excluded++ ] = (char *)tags->data; break; default: cwarn(global, WARN_INTERNAL_ERROR, NULL); break; } tags++; } return(0); }
/* * Expand a macro. Called from the cpp mainline routine (via subroutine * macroid()) when a token is found in the symbol table. It calls * expcollect() to parse actual parameters, checking for the correct number. * It then creates a "file" containing a single line containing the * macro with actual parameters inserted appropriately. This is * "pushed back" onto the input stream. (When the get() routine runs * off the end of the macro line, it will dismiss the macro itself.) */ void expand(DEFBUF* tokenp) { int c; FILEINFO* file; #if OSL_DEBUG_LEVEL > 1 if (debug) dumpadef("expand entry", tokenp); #endif /* * If no macro is pending, save the name of this macro * for an eventual error message. */ if (recursion++ == 0) macro = tokenp; else if (recursion == RECURSION_LIMIT) { cerror("Recursive macro definition of \"%s\"", tokenp->name); fprintf(stderr, "(Defined by \"%s\")\n", macro->name); if (rec_recover) { do { c = get(); } while (infile != NULL && infile->fp == NULL); unget(); recursion = 0; return; } } /* * Here's a macro to expand. */ nargs = 0; /* Formals counter */ parmp = parm; /* Setup parm buffer */ switch (tokenp->nargs) { case (-2): /* __LINE__ */ sprintf(work, "%d", line); ungetstring(work); break; case (-3): /* __FILE__ */ for (file = infile; file != NULL; file = file->parent) { if (file->fp != NULL) { sprintf(work, "\"%s\"", (file->progname != NULL) ? file->progname : file->filename); ungetstring(work); break; } } break; default: /* * Nothing funny about this macro. */ if (tokenp->nargs < 0) cfatal("Bug: Illegal __ macro \"%s\"", tokenp->name); while ((c = skipws()) == '\n') /* Look for (, skipping */ wrongline = TRUE; /* spaces and newlines */ if (c != '(') { /* * If the programmer writes * #define foo() ... * ... * foo [no ()] * just write foo to the output stream. */ unget(); cwarn("Macro \"%s\" needs arguments", tokenp->name); fputs(tokenp->name, pCppOut ); return; } else if (expcollect()) /* Collect arguments */ { if (tokenp->nargs != nargs) /* Should be an error? */ { cwarn("Wrong number of macro arguments for \"%s\"", tokenp->name); } #if OSL_DEBUG_LEVEL > 1 if (debug) dumpparm("expand"); #endif } /* Collect arguments */ case DEF_NOARGS: /* No parameters just stuffs */ expstuff(tokenp); /* Do actual parameters */ } /* nargs switch */ }
/* * Called from control when a #define is scanned. This module * parses formal parameters and the replacement string. When * the formal parameter name is encountered in the replacement * string, it is replaced by a character in the range 128 to * 128+NPARAM (this allows up to 32 parameters within the * Dec Multinational range). * * There is some special case code to distinguish * #define foo bar * from #define foo() bar * * Also, we make sure that * #define foo foo * expands to "foo" but doesn't put cpp into an infinite loop. * * A warning message is printed if you redefine a symbol to a * different text. I.e, * #define foo 123 * #define foo 123 * is ok, but * #define foo 123 * #define foo +123 * is not. * * The following subroutines are called from define(): * checkparm called when a token is scanned. It checks through the * array of formal parameters. If a match is found, the * token is replaced by a control byte which will be used * to locate the parameter when the macro is expanded. * textput puts a string in the macro work area (parm[]), updating * parmp to point to the first free byte in parm[]. * textput() tests for work buffer overflow. * charput puts a single character in the macro work area (parm[]) * in a manner analogous to textput(). */ void dodefine() { int c; DEFBUF* dp; /* -> new definition */ int isredefine; /* TRUE if redefined */ char* old = NULL; /* Remember redefined */ if (type[(c = skipws())] != LET) goto bad_define; isredefine = FALSE; /* Set if redefining */ if ((dp = lookid(c)) == NULL) /* If not known now */ dp = defendel(token, FALSE); /* Save the name */ else /* It's known: */ { isredefine = TRUE; /* Remember this fact */ old = dp->repl; /* Remember replacement */ dp->repl = NULL; /* No replacement now */ } parlist[0] = parmp = parm; /* Setup parm buffer */ if ((c = get()) == '(') /* With arguments? */ { nargs = 0; /* Init formals counter */ do /* Collect formal parms */ { if (nargs >= LASTPARM) cfatal("Too many arguments for macro", NULLST); else if ((c = skipws()) == ')') break; /* Got them all */ else if (type[c] != LET) /* Bad formal syntax */ goto bad_define; scanid(c); /* Get the formal param */ parlist[nargs++] = parmp; /* Save its start */ textput(token); /* Save text in parm[] */ } while ((c = skipws()) == ','); /* Get another argument */ if (c != ')') /* Must end at ) */ goto bad_define; c = ' '; /* Will skip to body */ } else { /* * DEF_NOARGS is needed to distinguish between * "#define foo" and "#define foo()". */ nargs = DEF_NOARGS; /* No () parameters */ } if (type[c] == SPA) /* At whitespace? */ c = skipws(); /* Not any more. */ workp = work; /* Replacement put here */ inmacro = TRUE; /* Keep \<newline> now */ while (c != EOF_CHAR && c != '\n') /* Compile macro body */ { if (c == '#') /* Token concatenation? */ { while (workp > work && type[(int)workp[-1]] == SPA) --workp; /* Erase leading spaces */ save(TOK_SEP); /* Stuff a delimiter */ c = skipws(); /* Eat whitespace */ if (type[c] == LET) /* Another token here? */ ; /* Stuff it normally */ else if (type[c] == DIG) /* Digit string after? */ { while (type[c] == DIG) /* Stuff the digits */ { save(c); c = get(); } save(TOK_SEP); /* Delimit 2nd token */ } else { ciwarn("Strange character after # (%d.)", c); } continue; } switch (type[c]) { case LET: checkparm(c, dp); /* Might be a formal */ break; case DIG: /* Number in mac. body */ case DOT: /* Maybe a float number */ scannumber(c, save); /* Scan it off */ break; case QUO: /* String in mac. body */ stparmscan(c); break; case BSH: /* Backslash */ save('\\'); if ((c = get()) == '\n') wrongline = TRUE; save(c); break; case SPA: /* Absorb whitespace */ /* * Note: the "end of comment" marker is passed on * to allow comments to separate tokens. */ if (workp[-1] == ' ') /* Absorb multiple */ break; /* spaces */ else if (c == '\t') c = ' '; /* Normalize tabs */ /* Fall through to store character */ default: /* Other character */ save(c); break; } c = get(); } inmacro = FALSE; /* Stop newline hack */ unget(); /* For control check */ if (workp > work && workp[-1] == ' ') /* Drop trailing blank */ workp--; *workp = EOS; /* Terminate work */ dp->repl = savestring(work); /* Save the string */ dp->nargs = nargs; /* Save arg count */ #if OSL_DEBUG_LEVEL > 1 if (debug) dumpadef("macro definition", dp); else if (bDumpDefs) dumpadef(NULL, dp); #endif if (isredefine) /* Error if redefined */ { if ((old != NULL && dp->repl != NULL && !streq(old, dp->repl)) || (old == NULL && dp->repl != NULL) || (old != NULL && dp->repl == NULL)) { #ifdef STRICT_UNDEF cerror("Redefining defined variable \"%s\"", dp->name); #else cwarn("Redefining defined variable \"%s\"", dp->name); #endif } if (old != NULL) /* We don't need the */ free(old); /* old definition now. */ } return; bad_define: cerror("#define syntax error", NULLST); inmacro = FALSE; /* Stop <newline> hack */ }
/* * dooptions is called to process command line arguments (-Detc). * It is called only at cpp startup. */ int dooptions(int argc, char** argv) { char* ap; DEFBUF* dp; int c; int i, j; char* arg; SIZES* sizp; /* For -S */ int size; /* For -S */ int isdatum; /* FALSE for -S* */ int endtest; /* For -S */ for (i = j = 1; i < argc; i++) { arg = ap = argv[i]; if (*ap++ != '-' || *ap == EOS) { argv[j++] = argv[i]; } else { c = *ap++; /* Option byte */ if (islower(c)) /* Normalize case */ c = toupper(c); switch (c) /* Command character */ { case 'C': /* Keep comments */ cflag = TRUE; keepcomments = TRUE; break; case 'D': /* Define symbol */ /* * If the option is just "-Dfoo", make it -Dfoo=1 */ while (*ap != EOS && *ap != '=') ap++; if (*ap == EOS) ap = "1"; else *ap++ = EOS; /* * Now, save the word and its definition. */ dp = defendel(argv[i] + 2, FALSE); dp->repl = savestring(ap); dp->nargs = DEF_NOARGS; break; case 'E': /* Ignore non-fatal */ eflag = TRUE; /* errors. */ break; case 'I': /* Include directory */ AddInclude( ap ); /* BP, 11.09.91 */ break; case 'N': /* No predefineds */ nflag++; /* Repeat to undefine */ break; /* __LINE__, etc. */ case 'S': sizp = size_table; if (0 != (isdatum = (*ap != '*'))) /* If it's just -S, */ endtest = T_FPTR; /* Stop here */ else /* But if it's -S* */ { ap++; /* Step over '*' */ endtest = 0; /* Stop at end marker */ } while (sizp->bits != endtest && *ap != EOS) { if (!isdigit(*ap)) /* Skip to next digit */ { ap++; continue; } size = 0; /* Compile the value */ while (isdigit(*ap)) { size *= 10; size += (*ap++ - '0'); } if (isdatum) sizp->size = size; /* Datum size */ else sizp->psize = size; /* Pointer size */ sizp++; } if (sizp->bits != endtest) cwarn("-S, too few values specified in %s", argv[i]); else if (*ap != EOS) cwarn("-S, too many values, \"%s\" unused", ap); break; case 'U': /* Undefine symbol */ if (defendel(ap, TRUE) == NULL) cwarn("\"%s\" wasn't defined", ap); break; #if OSL_DEBUG_LEVEL > 1 case 'X': /* Debug */ debug = (isdigit(*ap)) ? atoi(ap) : 1; #if (HOST == SYS_UNIX) signal(SIGINT, (void (*)(int)) abort); /* Trap "interrupt" */ #endif fprintf(stderr, "Debug set to %d\n", debug); break; #endif #if OSL_DEBUG_LEVEL > 1 case 'P': /* #define's dump */ bDumpDefs = 1; fprintf(stderr, "Dump #define's is on\n"); break; #endif default: /* What is this one? */ cwarn("Unknown option \"%s\"", arg); fprintf(stderr, "The following options are valid:\n\ -C\t\t\tWrite source file comments to output\n\ -Dsymbol=value\tDefine a symbol with the given (optional) value\n\ -Idirectory\t\tAdd a directory to the #include search list\n\ -N\t\t\tDon't predefine target-specific names\n\ -Stext\t\tSpecify sizes for #if sizeof\n\ -Usymbol\t\tUndefine symbol\n"); #if OSL_DEBUG_LEVEL > 1 fprintf(stderr, " -Xvalue\t\tSet internal debug flag\n"); fprintf(stderr, " -P\t\t\tdump #define's\n"); #endif break; } /* Switch on all options */ } /* If it's a -option */ } /* For all arguments */ #if OSL_DEBUG_LEVEL > 1 if ( (bDumpDefs ? j > 4 : j > 3) ) #else if (j > 3) #endif { cerror( "Too many file arguments. Usage: cpp [input [output]]", NULLST); } return (j); /* Return new argc */ }
int fppPreProcess(struct fppTag *tags) { int i=0; ReturnCode ret; /* cpp return code */ struct Global *global; global=(struct Global *)malloc(sizeof(struct Global)); if(!global) return(FPP_OUT_OF_MEMORY); memset(global, 0, sizeof(struct Global)); global->infile=NULL; global->line=0; global->wrongline=0; global->errors=0; global->recursion=0; global->rec_recover=TRUE; global->instring=FALSE; global->inmacro=FALSE; global->workp=NULL; global->keepcomments = FALSE; /* Write out comments flag */ global->cflag = FALSE; /* -C option (keep comments) */ global->eflag = FALSE; /* -E option (never fail) */ global->nflag = 0; /* -N option (no predefines) */ global->wflag = FALSE; /* -W option (write #defines) */ global->ifstack[0]=TRUE; /* #if information */ global->ifptr = global->ifstack; global->incend = global->incdir; /* names defined at cpp start */ global->preset[0]="frexxcpp"; /* This is the Frexx cpp program */ #if defined( unix ) global->preset[1]="unix"; global->preset[2]= NULL; #endif /* Note: order is important */ global->magic[0] = "__LINE__"; global->magic[1] = "__FILE__"; global->magic[2] = "__FUNCTION__"; global->magic[3] = "__FUNC_LINE__"; global->magic[4] = NULL; /* Must be last */ global->funcline = 0; global->cplusplus=1; global->sharpfilename=NULL; global->parmp=NULL; global->nargs=0; global->macro=NULL; global->evalue=0; global->error=NULL; global->first_file=NULL; global->linelines=TRUE; global->warnillegalcpp = FALSE; global->outputLINE = TRUE; global->warnnoinclude = TRUE; global->showversion = TRUE; global->showincluded = FALSE; global->showspace = FALSE; global->nestcomments = FALSE; global->warnnestcomments = FALSE; global->outputfile = TRUE; global->included = 0; global->comment = FALSE; global->rightconcat = FALSE; global->work[0] = '\0'; global->initialfunc = NULL; memset(global->symtab, 0, SBSIZE * sizeof(DEFBUF *)); ret=initdefines(global); /* O.S. specific def's */ if(ret) return(ret); dooptions(global, tags); /* Command line -flags */ ret=addfile(global, global->inputio, global->work); /* "open" main input file */ global->out = global->outputfile; if(!ret) ret=cppmain(global); /* Process main file */ if ((i = (int)(global->ifptr - global->ifstack)) != 0) { #if OLD_PREPROCESSOR cwarn(global, ERROR_IFDEF_DEPTH, i); #else cerror(global, ERROR_IFDEF_DEPTH, i); #endif } if (global->errors > 0 && !global->eflag) return(IO_ERROR); return(IO_NORMAL); /* No errors or -E option set */ }
int control(int counter) /* * Process #control lines. Simple commands are processed inline, * while complex commands have their own subroutines. * * The counter is used to force out a newline before #line, and * #pragma commands. This prevents these commands from ending up at * the end of the previous line if cpp is invoked with the -C option. */ { register int c; register char *tp; register int hash; char *ep; c = skipws(); if (c == '\n' || c == EOF_CHAR) return (counter + 1); if (!isdigit(c)) scanid(c); /* Get #word to token[] */ else { unget(); /* Hack -- allow #123 as a */ strcpy(token, "line"); /* synonym for #line 123 */ } hash = (token[1] == EOS) ? L_nogood : (token[0] + (token[2] << 1)); switch (hash) { case L_assert: tp = "assert"; break; case L_define: tp = "define"; break; case L_elif: tp = "elif"; break; case L_else: tp = "else"; break; case L_endif: tp = "endif"; break; case L_if: tp = "if"; break; case L_ifdef: tp = "ifdef"; break; case L_ifndef: tp = "ifndef"; break; case L_include: tp = "include"; break; case L_line: tp = "line"; break; case L_pragma: tp = "pragma"; break; case L_undef: tp = "undef"; break; case L_error: tp = "error"; break; #if OSL_DEBUG_LEVEL > 1 case L_debug: tp = "debug"; break; case L_nodebug: tp = "nodebug"; break; #endif default: hash = L_nogood; case L_nogood: tp = ""; break; } if (!streq(tp, token)) hash = L_nogood; /* * hash is set to a unique value corresponding to the * control keyword (or L_nogood if we think it's nonsense). */ if (infile->fp == NULL) cwarn("Control line \"%s\" within macro expansion", token); if (!compiling) { /* Not compiling now */ switch (hash) { case L_if: /* These can't turn */ case L_ifdef: /* compilation on, but */ case L_ifndef: /* we must nest #if's */ if (++ifptr >= &ifstack[BLK_NEST]) goto if_nest_err; *ifptr = 0; /* !WAS_COMPILING */ case L_line: /* Many */ /* * Are pragma's always processed? */ case L_pragma: /* options */ case L_include: /* are uninteresting */ case L_define: /* if we */ case L_undef: /* aren't */ case L_assert: /* compiling. */ case L_error: /* BP 5.3.92, #error */ dump_line: skipnl(); /* Ignore rest of line */ return (counter + 1); } } /* * Make sure that #line and #pragma are output on a fresh line. */ if (counter > 0 && (hash == L_line || hash == L_pragma)) { PUTCHAR('\n'); counter--; } switch (hash) { case L_line: /* * Parse the line to update the line number and "progname" * field and line number for the next input line. * Set wrongline to force it out later. */ c = skipws(); workp = work; /* Save name in work */ while (c != '\n' && c != EOF_CHAR) { save(c); c = get(); } unget(); save(EOS); /* * Split #line argument into <line-number> and <name> * We subtract 1 as we want the number of the next line. */ line = atoi(work) - 1; /* Reset line number */ for (tp = work; isdigit(*tp) || type[(int)*tp] == SPA; tp++) ; /* Skip over digits */ if (*tp != EOS) { /* Got a filename, so: */ if (*tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL) { tp++; /* Skip over left quote */ *ep = EOS; /* And ignore right one */ } if (infile->progname != NULL) /* Give up the old name */ free(infile->progname); /* if it's allocated. */ infile->progname = savestring(tp); } wrongline = TRUE; /* Force output later */ break; case L_include: doinclude(); break; case L_define: dodefine(); break; case L_undef: doundef(); break; case L_else: if (ifptr == &ifstack[0]) goto nest_err; else if ((*ifptr & ELSE_SEEN) != 0) goto else_seen_err; *ifptr |= ELSE_SEEN; if ((*ifptr & WAS_COMPILING) != 0) { if (compiling || (*ifptr & TRUE_SEEN) != 0) compiling = FALSE; else { compiling = TRUE; } } break; case L_elif: if (ifptr == &ifstack[0]) goto nest_err; else if ((*ifptr & ELSE_SEEN) != 0) { else_seen_err: cerror("#%s may not follow #else", token); goto dump_line; } if ((*ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) { compiling = FALSE; /* Done compiling stuff */ goto dump_line; /* Skip this clause */ } doif(L_if); break; case L_if: case L_ifdef: case L_ifndef: if (++ifptr >= &ifstack[BLK_NEST]) if_nest_err: cfatal("Too many nested #%s statements", token); *ifptr = WAS_COMPILING; doif(hash); break; case L_endif: if (ifptr == &ifstack[0]) { nest_err: cerror("#%s must be in an #if", token); goto dump_line; } if (!compiling && (*ifptr & WAS_COMPILING) != 0) wrongline = TRUE; compiling = ((*ifptr & WAS_COMPILING) != 0); --ifptr; break; case L_assert: if (eval() == 0) cerror("Preprocessor assertion failure", NULLST); break; case L_pragma: /* * #pragma is provided to pass "options" to later * passes of the compiler. cpp doesn't have any yet. */ fprintf( pCppOut, "#pragma "); while ((c = get()) != '\n' && c != EOF_CHAR) cput(c); unget(); break; #if OSL_DEBUG_LEVEL > 1 case L_debug: if (debug == 0) dumpdef("debug set on"); debug++; break; case L_nodebug: debug--; break; #endif case L_error: /* BP 5.3.92, #error */ { fprintf( pCppOut, "cpp: line %u, Error directive: ", line ); while ((c = get()) != '\n' && c != EOF_CHAR) cput(c); fprintf( pCppOut, "\n" ); exit( 1 ); break; } default: /* * Undefined #control keyword. * Note: the correct behavior may be to warn and * pass the line to a subsequent compiler pass. * This would allow #asm or similar extensions. */ cerror("Illegal # command \"%s\"", token); break; } if (hash != L_include) { #if OLD_PREPROCESSOR /* * Ignore the rest of the #control line so you can write * #if foo * #endif foo */ goto dump_line; /* Take common exit */ #else if (skipws() != '\n') { cwarn("Unexpected text in #control line ignored", NULLST); skipnl(); } #endif } return (counter + 1); }
int main (int argc, char **argv) { int i; struct stat sb; void * addr; rec *r, *e; struct tm *tmp; char fmt[1024]; /* std::map<int, cnt*> hstat; std::map<int, cnt*> dstat; cnt *ac = new cnt(); std::map<int, cnt*>::iterator it; std::map<int, int>::iterator ii; */ std::tr1::unordered_map<int, cnt*> hstat; std::tr1::unordered_map<int, cnt*> dstat; cnt *ac = new cnt(); std::tr1::unordered_map<int, cnt*>::iterator it; std::tr1::unordered_map<int, int>::iterator ii; for (i=1; i<argc; i++) { cwarn("%s",argv[i]); int fd = open(argv[i], O_RDONLY); if (fd == -1) die("open %s failed: %s",argv[i],strerror(errno)); if (fstat(fd, &sb) == -1) die("fstat %s failed: %s",argv[i],strerror(errno)); cwarn("fd = %d, size: %zd",fd, sb.st_size); addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE,fd, 0); if (addr == MAP_FAILED) die("mmap failed: %s",strerror(errno)); r = (rec *) addr; e = (rec *)((char *)addr + sb.st_size); int count = 0; int cur_day = 0,cur_hour = 0; while (r < e) { time_t time = r->ts; int ua = r->ua > AGENTS-1 ? 0xffffffff : r->ua; tmp = localtime( &time ); strftime(fmt,1024,"%Y%m%d",tmp); int day_id = atoi(fmt); strftime(fmt,1024,"%Y%m%d%H",tmp); int hour_id = atoi(fmt); cnt *hc,*dc; if (!( hc = hstat[hour_id] ) ) hc = hstat[hour_id] = new cnt(); if (!( dc = dstat[day_id] ) ) dc = dstat[day_id] = new cnt(); hc->hits++; hc->users[ r->uid ]++; hc->agent[ua][ r->uid ]++; dc->hits++; dc->users[ r->uid ]++; dc->agent[ua][ r->uid ]++; ac->hits++; ac->users[ r->uid ]++; ac->agent[ua][ r->uid ]++; r++; } } printf("day/hour\tnon\tios\tand\twin\tmac\tlin\twww\tunk\thits\tusers\n"); for( it = hstat.begin(); it!= hstat.end(); ++it) { printf("%-16d", (*it).first); for (i=0; i<AGENTS; i++) { printf("%d\t",(*it).second->agent[i].size()); } printf("%d\t",(*it).second->hits); printf("%d\t",(*it).second->users.size()); printf("\n"); } return 0; }
ReturnCode control( struct Global *global, int *counter ) /* Pending newline counter */ { /* * Process #control lines. Simple commands are processed inline, * while complex commands have their own subroutines. * * The counter is used to force out a newline before #line, and * #pragma commands. This prevents these commands from ending up at * the end of the previous line if cpp is invoked with the -C option. */ int c; char *tp; int hash; char *ep; ReturnCode ret; c = skipws( global ); if( c == '\n' || c == EOF_CHAR ) { (*counter)++; return(FPP_OK); } if( !isdigit(c) ) scanid( global, c ); /* Get #word to tokenbuf */ else { unget( global ); /* Hack -- allow #123 as a */ strcpy( global->tokenbuf, "line" ); /* synonym for #line 123 */ } hash = (global->tokenbuf[1] == EOS) ? L_nogood : (global->tokenbuf[0] + (global->tokenbuf[2] << 1)); switch( hash ) { case L_assert: tp = "assert"; break; case L_define: tp = "define"; break; case L_elif: tp = "elif"; break; case L_else: tp = "else"; break; case L_endif: tp = "endif"; break; case L_error: tp = "error"; break; case L_if: tp = "if"; break; case L_ifdef: tp = "ifdef"; break; case L_ifndef: tp = "ifndef"; break; case L_include: tp = "include"; break; case L_line: tp = "line"; break; case L_pragma: tp = "pragma"; break; case L_undef: tp = "undef"; break; default: hash = L_nogood; case L_nogood: tp = ""; break; } if( !streq( tp, global->tokenbuf ) ) hash = L_nogood; /* * hash is set to a unique value corresponding to the * control keyword (or L_nogood if we think it's nonsense). */ if( global->infile->fp == NULL ) cwarn( global, WARN_CONTROL_LINE_IN_MACRO, global->tokenbuf ); if( !compiling ) { /* Not compiling now */ switch( hash ) { case L_if: /* These can't turn */ case L_ifdef: /* compilation on, but */ case L_ifndef: /* we must nest #if's */ if( ++global->ifptr >= &global->ifstack[BLK_NEST] ) { cfatal( global, FATAL_TOO_MANY_NESTINGS, global->tokenbuf ); return( FPP_TOO_MANY_NESTED_STATEMENTS ); } *global->ifptr = 0; /* !WAS_COMPILING */ case L_line: /* Many */ /* * Are pragma's always processed? */ case L_pragma: /* options */ case L_include: /* are uninteresting */ case L_define: /* if we */ case L_undef: /* aren't */ case L_assert: /* compiling. */ case L_error: dump_line( global, counter ); /* Ignore rest of line */ return(FPP_OK); } } /* * Make sure that #line and #pragma are output on a fresh line. */ if( *counter > 0 && (hash == L_line || hash == L_pragma) ) { Putchar( global, '\n' ); (*counter)--; } switch( hash ) { case L_line: /* * Parse the line to update the line number and "progname" * field and line number for the next input line. * Set wrongline to force it out later. */ c = skipws( global ); global->workp = global->work; /* Save name in work */ while( c != '\n' && c != EOF_CHAR ) { if( (ret = save( global, c )) ) return(ret); c = get( global ); } unget( global ); if( (ret = save( global, EOS )) ) return(ret); /* * Split #line argument into <line-number> and <name> * We subtract 1 as we want the number of the next line. */ global->line = atoi(global->work) - 1; /* Reset line number */ for( tp = global->work; isdigit(*tp) || type[(unsigned)*tp] == SPA; tp++) ; /* Skip over digits */ if( *tp != EOS ) { /* Got a filename, so: */ if( *tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL ) { tp++; /* Skip over left quote */ *ep = EOS; /* And ignore right one */ } if( global->infile->progname != NULL ) /* Give up the old name if it's allocated. */ free( global->infile->progname ); global->infile->progname = savestring( global, tp ); } global->wrongline = TRUE; /* Force output later */ break; case L_include: ret = doinclude( global ); if( ret ) return(ret); break; case L_define: ret = dodefine( global ); if( ret ) return(ret); break; case L_undef: doundef( global ); break; case L_else: if( global->ifptr == &global->ifstack[0] ) { cerror( global, ERROR_STRING_MUST_BE_IF, global->tokenbuf ); dump_line( global, counter ); return( FPP_OK ); } else if( (*global->ifptr & ELSE_SEEN) != 0 ) { cerror( global, ERROR_STRING_MAY_NOT_FOLLOW_ELSE, global->tokenbuf ); dump_line( global, counter ); return( FPP_OK ); } *global->ifptr |= ELSE_SEEN; if( (*global->ifptr & WAS_COMPILING) != 0 ) { if( compiling || (*global->ifptr & TRUE_SEEN) != 0 ) compiling = FALSE; else { compiling = TRUE; } } break; case L_elif: if( global->ifptr == &global->ifstack[0] ) { cerror( global, ERROR_STRING_MUST_BE_IF, global->tokenbuf ); dump_line( global, counter ); return( FPP_OK ); } else if( (*global->ifptr & ELSE_SEEN) != 0 ) { cerror( global, ERROR_STRING_MAY_NOT_FOLLOW_ELSE, global->tokenbuf ); dump_line( global, counter ); return( FPP_OK ); } if( (*global->ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING ) { compiling = FALSE; /* Done compiling stuff */ dump_line( global, counter ); /* Skip this clause */ return( FPP_OK ); } ret = doif( global, L_if ); if( ret ) return(ret); break; case L_error: cerror(global, ERROR_ERROR); break; case L_if: case L_ifdef: case L_ifndef: if( ++global->ifptr < &global->ifstack[BLK_NEST] ) { *global->ifptr = WAS_COMPILING; ret = doif( global, hash ); if( ret ) return(ret); break; } cfatal( global, FATAL_TOO_MANY_NESTINGS, global->tokenbuf ); return( FPP_TOO_MANY_NESTED_STATEMENTS ); case L_endif: if( global->ifptr == &global->ifstack[0] ) { cerror( global, ERROR_STRING_MUST_BE_IF, global->tokenbuf ); dump_line( global, counter ); return(FPP_OK); } if( !compiling && (*global->ifptr & WAS_COMPILING) != 0 ) global->wrongline = TRUE; compiling = ((*global->ifptr & WAS_COMPILING) != 0); --global->ifptr; break; case L_assert: { int result; ret = eval( global, &result ); if(ret) return(ret); if( result == 0 ) cerror( global, ERROR_PREPROC_FAILURE ); } break; case L_pragma: /* * #pragma is provided to pass "options" to later * passes of the compiler. cpp doesn't have any yet. */ Putstring( global, "#pragma " ); while( (c = get( global ) ) != '\n' && c != EOF_CHAR ) Putchar( global, c ); unget( global ); Putchar( global, '\n' ); break; default: /* * Undefined #control keyword. * Note: the correct behavior may be to warn and * pass the line to a subsequent compiler pass. * This would allow #asm or similar extensions. */ if( global->warnillegalcpp ) cwarn( global, WARN_ILLEGAL_COMMAND, global->tokenbuf ); Putchar( global, '#' ); Putstring( global, global->tokenbuf ); Putchar( global, ' ' ); while( (c = get( global ) ) != '\n' && c != EOF_CHAR ) Putchar( global, c ); unget( global ); Putchar( global, '\n' ); break; } if( hash != L_include ) { #if OLD_PREPROCESSOR /* * Ignore the rest of the #control line so you can write * #if foo * #endif foo */ dump_line( global, counter ); /* Take common exit */ return( FPP_OK ); #else if (skipws(global) != '\n') { cwarn( global, WARN_UNEXPECTED_TEXT_IGNORED ); skipnl( global ); } #endif } (*counter)++; return( FPP_OK ); }
INLINE FILE_LOCAL ReturnCode doinclude( struct Global *global ) { /* * Process the #include control line. * There are three variations: * * #include "file" search somewhere relative to the * current source file, if not found, * treat as #include <file>. * * #include <file> Search in an implementation-dependent * list of places. * * #include token Expand the token, it must be one of * "file" or <file>, process as such. * * Note: the November 12 draft forbids '>' in the #include <file> format. * This restriction is unnecessary and not implemented. */ int c; int delim; ReturnCode ret; delim = skipws( global ); if( (ret = macroid( global, &delim )) ) return(ret); if( delim != '<' && delim != '"' ) { cerror( global, ERROR_INCLUDE_SYNTAX ); return( FPP_OK ); } if( delim == '<' ) delim = '>'; global->workp = global->work; while( (c = get(global)) != '\n' && c != EOF_CHAR ) if( (ret = save( global, c )) ) /* Put it away. */ return( ret ); unget( global ); /* Force nl after include */ /* * The draft is unclear if the following should be done. */ while( --global->workp >= global->work && (*global->workp == ' ' || *global->workp == '\t' || *global->workp == '\r') ) ; /* Trim blanks from filename */ if( *global->workp != delim ) { cerror( global, ERROR_INCLUDE_SYNTAX ); return(FPP_OK); } *global->workp = EOS; /* Terminate filename */ ret = openinclude( global, global->work, (delim == '"') ); if( ret && global->warnnoinclude ) { /* * Warn if #include file isn't there. */ cwarn( global, WARN_CANNOT_OPEN_INCLUDE, global->work ); } return( FPP_OK ); }
const char * set_encoding( char * name, /* Name of encoding specified */ char * env, /* Name of environment variable */ int pragma /* 2: #pragma setlocale, 1: #pragma __setlocale, 0: not #pragma */ ) /* * Search the encoding specified and re-initialize mbchar settings. */ { const char * unknown_encoding = "Unknown encoding: %s%.0ld%.0s"; /* _W1_ */ const char * too_long = "Too long encoding name: %s%.0ld%.0s"; /* _E_ */ const char * loc = ""; int alias; char norm[ NAMLEN]; /* * Normalized name (removed 'xxxxx.', stripped '_', '-', '.' * and lowered. */ if (strlen( name) >= NAMLEN) { if ((env || pragma) && (warn_level & 1)) { cwarn( too_long, name, 0L, NULL); } else { mcpp_fprintf( ERR, too_long, name); mcpp_fputc( '\n', ERR); } } strcpy( norm, name); if (norm[ 5] == '.') memmove( norm, norm + 5, strlen( norm + 5) + 1); /* Remove initial 'xxxxx.' as 'ja_JP.', 'en_US.' or any other */ conv_case( norm, norm + strlen( norm), LOWER); strip_bar( norm); if (strlen( name) == 0) { /* "" */ mbchar = MBCHAR; /* Restore to the default encoding */ } else if (memcmp( norm, "iso8859", 7) == 0 /* iso8859* */ || memcmp( norm, "latin", 5) == 0 /* latin* */ || memcmp( norm, "en", 2) == 0) { /* en* */ mbchar = 0; /* No multi-byte character */ } else { alias = 2; #if COMPILER == MSC if (pragma == SETLOCALE) /* #pragma setlocale */ alias = 0; #endif loc = search_encoding( norm, alias); /* Search the name */ } if (loc == NULL) { if ((env || pragma) && (warn_level & 1)) { cwarn( unknown_encoding, name, 0L, NULL); } else { /* -m option */ mcpp_fprintf( ERR, unknown_encoding, name); mcpp_fputc( '\n', ERR); } } else { mb_init(); /* Re-initialize */ } return loc; }