/** * Count the number of characters in a word. * The first character is already valid for a keyword * * @param pc The structure to update, str is an input. * @return Whether a word was parsed (always true) */ bool parse_word(tok_ctx &ctx, chunk_t &pc, bool skipcheck) { int ch; static unc_text intr_txt("@interface"); /* The first character is already valid */ pc.str.clear(); pc.str.append(ctx.get()); while (ctx.more()) { ch = ctx.peek(); if (CharTable::IsKw2(ch)) { pc.str.append(ctx.get()); } else if ((ch == '\\') && (unc_tolower(ctx.peek(1)) == 'u')) { pc.str.append(ctx.get()); pc.str.append(ctx.get()); skipcheck = true; } else { break; } /* HACK: Non-ASCII character are only allowed in identifiers */ if (ch > 0x7f) { skipcheck = true; } } pc.type = CT_WORD; if (skipcheck) { return(true); } /* Detect pre-processor functions now */ if ((cpd.in_preproc == CT_PP_DEFINE) && (cpd.preproc_ncnl_count == 1)) { if (ctx.peek() == '(') { pc.type = CT_MACRO_FUNC; } else { pc.type = CT_MACRO; } } else { /* '@interface' is reserved, not an interface itself */ if ((cpd.lang_flags & LANG_JAVA) && pc.str.startswith("@") && !pc.str.equals(intr_txt)) { pc.type = CT_ANNOTATION; } else { /* Turn it into a keyword now */ pc.type = find_keyword_type(pc.text(), pc.str.size()); } } return(true); } // parse_word
/** * Skips the next bit of whatever and returns the type of block. * * pc.str is the input text. * pc.len in the output length. * pc.type is the output type * pc.column is output column * * @param pc The structure to update, str is an input. * @return true/false - whether anything was parsed */ static bool parse_next(tok_ctx& ctx, chunk_t& pc) { const chunk_tag_t *punc; int ch, ch1; if (!ctx.more()) { //fprintf(stderr, "All done!\n"); return(false); } /* Save off the current column */ pc.orig_line = ctx.c.row; pc.column = ctx.c.col; pc.orig_col = ctx.c.col; pc.type = CT_NONE; pc.nl_count = 0; pc.flags = 0; /* If it is turned off, we put everything except newlines into CT_UNKNOWN */ if (cpd.unc_off) { if (parse_ignored(ctx, pc)) { return(true); } } /** * Parse whitespace */ if (parse_whitespace(ctx, pc)) { return(true); } /** * Handle unknown/unhandled preprocessors */ if ((cpd.in_preproc > CT_PP_BODYCHUNK) && (cpd.in_preproc <= CT_PP_OTHER)) { pc.str.clear(); tok_info ss; ctx.save(ss); /* Chunk to a newline or comment */ pc.type = CT_PREPROC_BODY; int last = 0; while (ctx.more()) { int ch = ctx.peek(); if ((ch == '\n') || (ch == '\r')) { /* Back off if this is an escaped newline */ if (last == '\\') { ctx.restore(ss); pc.str.pop_back(); } break; } /* Quit on a C++ comment start */ if ((ch == '/') && (ctx.peek(1) == '/')) { break; } last = ch; ctx.save(ss); pc.str.append(ctx.get()); } if (pc.str.size() > 0) { return(true); } } /** * Detect backslash-newline */ if ((ctx.peek() == '\\') && parse_bs_newline(ctx, pc)) { return(true); } /** * Parse comments */ if (parse_comment(ctx, pc)) { return(true); } /* Parse code placeholders */ if (parse_code_placeholder(ctx, pc)) { return(true); } /* Check for C# literal strings, ie @"hello" and identifiers @for*/ if ((cpd.lang_flags & LANG_CS) && (ctx.peek() == '@')) { if (ctx.peek(1) == '"') { parse_cs_string(ctx, pc); return(true); } /* check for non-keyword identifiers such as @if @switch, etc */ if (CharTable::IsKw1(ctx.peek(1))) { parse_word(ctx, pc, true); return(true); } } /* Check for C# Interpolated strings */ if ((cpd.lang_flags & LANG_CS) && (ctx.peek() == '$') && (ctx.peek(1) == '"')) { parse_cs_interpolated_string(ctx, pc); return(true); } /* handle VALA """ strings """ */ if ((cpd.lang_flags & LANG_VALA) && (ctx.peek() == '"') && (ctx.peek(1) == '"') && (ctx.peek(2) == '"')) { parse_verbatim_string(ctx, pc); return(true); } /* handle C++0x strings u8"x" u"x" U"x" R"x" u8R"XXX(I'm a "raw UTF-8" string.)XXX" */ ch = ctx.peek(); if ((cpd.lang_flags & LANG_CPP) && ((ch == 'u') || (ch == 'U') || (ch == 'R'))) { int idx = 0; bool is_real = false; if ((ch == 'u') && (ctx.peek(1) == '8')) { idx = 2; } else if (unc_tolower(ch) == 'u') { idx++; } if (ctx.peek(idx) == 'R') { idx++; is_real = true; } if (ctx.peek(idx) == '"') { if (is_real) { if (parse_cr_string(ctx, pc, idx)) { return(true); } } else { if (parse_string(ctx, pc, idx, true)) { parse_suffix(ctx, pc, true); return(true); } } } } /* PAWN specific stuff */ if (cpd.lang_flags & LANG_PAWN) { if ((cpd.preproc_ncnl_count == 1) && ((cpd.in_preproc == CT_PP_DEFINE) || (cpd.in_preproc == CT_PP_EMIT))) { parse_pawn_pattern(ctx, pc, CT_MACRO); return(true); } /* Check for PAWN strings: \"hi" or !"hi" or !\"hi" or \!"hi" */ if ((ctx.peek() == '\\') || (ctx.peek() == '!')) { if (ctx.peek(1) == '"') { parse_string(ctx, pc, 1, (ctx.peek() == '!')); return(true); } else if (((ctx.peek(1) == '\\') || (ctx.peek(1) == '!')) && (ctx.peek(2) == '"')) { parse_string(ctx, pc, 2, false); return(true); } } /* handle PAWN preprocessor args %0 .. %9 */ if ((cpd.in_preproc == CT_PP_DEFINE) && (ctx.peek() == '%') && unc_isdigit(ctx.peek(1))) { pc.str.clear(); pc.str.append(ctx.get()); pc.str.append(ctx.get()); pc.type = CT_WORD; return(true); } } /** * Parse strings and character constants */ if (parse_number(ctx, pc)) { return(true); } if (cpd.lang_flags & LANG_D) { /* D specific stuff */ if (d_parse_string(ctx, pc)) { return(true); } } else { /* Not D stuff */ /* Check for L'a', L"abc", 'a', "abc", <abc> strings */ ch = ctx.peek(); ch1 = ctx.peek(1); if ((((ch == 'L') || (ch == 'S')) && ((ch1 == '"') || (ch1 == '\''))) || (ch == '"') || (ch == '\'') || ((ch == '<') && (cpd.in_preproc == CT_PP_INCLUDE))) { parse_string(ctx, pc, unc_isalpha(ch) ? 1 : 0, true); return(true); } if ((ch == '<') && (cpd.in_preproc == CT_PP_DEFINE)) { if (chunk_get_tail()->type == CT_MACRO) { /* We have "#define XXX <", assume '<' starts an include string */ parse_string(ctx, pc, 0, false); return(true); } } } /* Check for Objective C literals and VALA identifiers ('@1', '@if')*/ if ((cpd.lang_flags & (LANG_OC | LANG_VALA)) && (ctx.peek() == '@')) { int nc = ctx.peek(1); if ((nc == '"') || (nc == '\'')) { /* literal string */ parse_string(ctx, pc, 1, true); return(true); } else if ((nc >= '0') && (nc <= '9')) { /* literal number */ pc.str.append(ctx.get()); /* store the '@' */ parse_number(ctx, pc); return(true); } } /* Check for pawn/ObjectiveC/Java and normal identifiers */ if (CharTable::IsKw1(ctx.peek()) || ((ctx.peek() == '@') && CharTable::IsKw1(ctx.peek(1)))) { parse_word(ctx, pc, false); return(true); } /* see if we have a punctuator */ char punc_txt[4]; punc_txt[0] = ctx.peek(); punc_txt[1] = ctx.peek(1); punc_txt[2] = ctx.peek(2); punc_txt[3] = ctx.peek(3); if ((punc = find_punctuator(punc_txt, cpd.lang_flags)) != NULL) { int cnt = strlen(punc->tag); while (cnt--) { pc.str.append(ctx.get()); } pc.type = punc->type; pc.flags |= PCF_PUNCTUATOR; return(true); } /* throw away this character */ pc.type = CT_UNKNOWN; pc.str.append(ctx.get()); LOG_FMT(LWARN, "%s:%d Garbage in col %d: %x\n", cpd.filename, pc.orig_line, (int)ctx.c.col, pc.str[0]); cpd.error_count++; return(true); } // parse_next
/** * Check the backup-md5 file and copy the input file to a backup if needed. */ int backup_copy_file(const char *filename, const vector<UINT8> &data) { char newpath[1024]; char buffer[128]; char md5_str_in[33]; char md5_str[33]; UINT8 dig[16]; md5_str_in[0] = 0; MD5::Calc(&data[0], data.size(), dig); snprintf(md5_str, sizeof(md5_str), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", dig[0], dig[1], dig[2], dig[3], dig[4], dig[5], dig[6], dig[7], dig[8], dig[9], dig[10], dig[11], dig[12], dig[13], dig[14], dig[15]); /* Create the backup-md5 filename, open it and read the md5 */ snprintf(newpath, sizeof(newpath), "%s%s", filename, UNC_BACKUP_MD5_SUFFIX); FILE *thefile = fopen(newpath, "rb"); if (thefile != NULL) { if (fgets(buffer, sizeof(buffer), thefile) != NULL) { for (int i = 0; buffer[i] != 0; i++) { if (unc_isxdigit(buffer[i])) { md5_str_in[i] = unc_tolower(buffer[i]); } else { md5_str_in[i] = 0; break; } } } fclose(thefile); } /* if the MD5s match, then there is no need to back up the file */ if (memcmp(md5_str, md5_str_in, 32) == 0) { LOG_FMT(LNOTE, "%s: MD5 match for %s\n", __func__, filename); return(SUCCESS); } LOG_FMT(LNOTE, "%s: MD5 mismatch - backing up %s\n", __func__, filename); /* Create the backup file */ snprintf(newpath, sizeof(newpath), "%s%s", filename, UNC_BACKUP_SUFFIX); thefile = fopen(newpath, "wb"); if (thefile != NULL) { int retval = fwrite(&data[0], data.size(), 1, thefile); int my_errno = errno; fclose(thefile); if (retval == 1) { return(SUCCESS); } LOG_FMT(LERR, "fwrite(%s) failed: %s (%d)\n", newpath, strerror(my_errno), my_errno); cpd.error_count++; } else { LOG_FMT(LERR, "fopen(%s) failed: %s (%d)\n", newpath, strerror(errno), errno); cpd.error_count++; } return(FAILURE); } // backup_copy_file