/* Lexes a string, character constant, or angle-bracketed header file name. The stored string contains the spelling, including opening quote and leading any leading 'L'. It returns the type of the literal, or CPP_OTHER if it was not properly terminated. The spelling is NUL-terminated, but it is not guaranteed that this is the first NUL since embedded NULs are preserved. */ static void lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) { bool saw_NUL = false; const uchar *cur; cppchar_t terminator; enum cpp_ttype type; cur = base; terminator = *cur++; if (terminator == 'L') terminator = *cur++; if (terminator == '\"') type = *base == 'L' ? CPP_WSTRING: CPP_STRING; else if (terminator == '\'') type = *base == 'L' ? CPP_WCHAR: CPP_CHAR; else terminator = '>', type = CPP_HEADER_NAME; for (;;) { cppchar_t c = *cur++; /* In #include-style directives, terminators are not escapable. */ if (c == '\\' && !pfile->state.angled_headers && *cur != '\n') cur++; else if (c == terminator) break; else if (c == '\n') { cur--; type = CPP_OTHER; break; } else if (c == '\0') saw_NUL = true; } if (saw_NUL && !pfile->state.skipping) cpp_error (pfile, CPP_DL_WARNING, "null character(s) preserved in literal"); pfile->buffer->cur = cur; create_literal (pfile, token, base, cur - base, type); }
/* Lex a token into pfile->cur_token, which is also incremented, to get diagnostics pointing to the correct location. Does not handle issues such as token lookahead, multiple-include optimization, directives, skipping etc. This function is only suitable for use by _cpp_lex_token, and in special cases like lex_expansion_token which doesn't care for any of these issues. When meeting a newline, returns CPP_EOF if parsing a directive, otherwise returns to the start of the token buffer if permissible. Returns the location of the lexed token. */ cpp_token * _cpp_lex_direct (cpp_reader *pfile) { cppchar_t c; cpp_buffer *buffer; const unsigned char *comment_start; cpp_token *result = pfile->cur_token++; fresh_line: result->flags = 0; buffer = pfile->buffer; if (buffer->need_line) { if (!_cpp_get_fresh_line (pfile)) { result->type = CPP_EOF; if (!pfile->state.in_directive) { /* Tell the compiler the line number of the EOF token. */ result->line = pfile->line; result->flags = BOL; } return result; } if (!pfile->keep_tokens) { pfile->cur_run = &pfile->base_run; result = pfile->base_run.base; pfile->cur_token = result + 1; } result->flags = BOL; if (pfile->state.parsing_args == 2) result->flags |= PREV_WHITE; } buffer = pfile->buffer; update_tokens_line: result->line = pfile->line; skipped_white: if (buffer->cur >= buffer->notes[buffer->cur_note].pos && !pfile->overlaid_buffer) { _cpp_process_line_notes (pfile, false); result->line = pfile->line; } c = *buffer->cur++; result->col = CPP_BUF_COLUMN (buffer, buffer->cur); switch (c) { case ' ': case '\t': case '\f': case '\v': case '\0': result->flags |= PREV_WHITE; skip_whitespace (pfile, c); goto skipped_white; case '\n': pfile->line++; buffer->need_line = true; goto fresh_line; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': result->type = CPP_NUMBER; lex_number (pfile, &result->val.str); break; case 'L': /* 'L' may introduce wide characters or strings. */ if (*buffer->cur == '\'' || *buffer->cur == '"') { lex_string (pfile, result, buffer->cur - 1); break; } /* Fall through. */ case '_': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': result->type = CPP_NAME; result->val.node = lex_identifier (pfile, buffer->cur - 1); /* Convert named operators to their proper types. */ if (result->val.node->flags & NODE_OPERATOR) { result->flags |= NAMED_OP; result->type = result->val.node->directive_index; } break; case '\'': case '"': lex_string (pfile, result, buffer->cur - 1); break; case '/': /* A potential block or line comment. */ comment_start = buffer->cur; c = *buffer->cur; if (c == '*') { if (_cpp_skip_block_comment (pfile)) cpp_error (pfile, CPP_DL_ERROR, "unterminated comment"); } else if (c == '/' && (CPP_OPTION (pfile, cplusplus_comments) || CPP_IN_SYSTEM_HEADER (pfile))) { /* Warn about comments only if pedantically GNUC89, and not in system headers. */ if (CPP_OPTION (pfile, lang) == CLK_GNUC89 && CPP_PEDANTIC (pfile) && ! buffer->warned_cplusplus_comments) { cpp_error (pfile, CPP_DL_PEDWARN, "C++ style comments are not allowed in ISO C90"); cpp_error (pfile, CPP_DL_PEDWARN, "(this will be reported only once per input file)"); buffer->warned_cplusplus_comments = 1; } if (skip_line_comment (pfile) && CPP_OPTION (pfile, warn_comments)) cpp_error (pfile, CPP_DL_WARNING, "multi-line comment"); } else if (c == '=') { buffer->cur++; result->type = CPP_DIV_EQ; break; } else { result->type = CPP_DIV; break; } if (!pfile->state.save_comments) { result->flags |= PREV_WHITE; goto update_tokens_line; } /* Save the comment as a token in its own right. */ save_comment (pfile, result, comment_start, c); break; case '<': if (pfile->state.angled_headers) { lex_string (pfile, result, buffer->cur - 1); break; } result->type = CPP_LESS; if (*buffer->cur == '=') buffer->cur++, result->type = CPP_LESS_EQ; else if (*buffer->cur == '<') { buffer->cur++; IF_NEXT_IS ('=', CPP_LSHIFT_EQ, CPP_LSHIFT); } else if (*buffer->cur == '?' && CPP_OPTION (pfile, cplusplus)) { buffer->cur++; IF_NEXT_IS ('=', CPP_MIN_EQ, CPP_MIN); } else if (CPP_OPTION (pfile, digraphs)) { if (*buffer->cur == ':') { buffer->cur++; result->flags |= DIGRAPH; result->type = CPP_OPEN_SQUARE; } else if (*buffer->cur == '%') { buffer->cur++; result->flags |= DIGRAPH; result->type = CPP_OPEN_BRACE; } } break; case '>': result->type = CPP_GREATER; if (*buffer->cur == '=') buffer->cur++, result->type = CPP_GREATER_EQ; else if (*buffer->cur == '>') { buffer->cur++; IF_NEXT_IS ('=', CPP_RSHIFT_EQ, CPP_RSHIFT); } else if (*buffer->cur == '?' && CPP_OPTION (pfile, cplusplus)) { buffer->cur++; IF_NEXT_IS ('=', CPP_MAX_EQ, CPP_MAX); } break; case '%': result->type = CPP_MOD; if (*buffer->cur == '=') buffer->cur++, result->type = CPP_MOD_EQ; else if (CPP_OPTION (pfile, digraphs)) { if (*buffer->cur == ':') { buffer->cur++; result->flags |= DIGRAPH; result->type = CPP_HASH; if (*buffer->cur == '%' && buffer->cur[1] == ':') buffer->cur += 2, result->type = CPP_PASTE; } else if (*buffer->cur == '>') { buffer->cur++; result->flags |= DIGRAPH; result->type = CPP_CLOSE_BRACE; } } break; case '.': result->type = CPP_DOT; if (ISDIGIT (*buffer->cur)) { result->type = CPP_NUMBER; lex_number (pfile, &result->val.str); } else if (*buffer->cur == '.' && buffer->cur[1] == '.') buffer->cur += 2, result->type = CPP_ELLIPSIS; else if (*buffer->cur == '*' && CPP_OPTION (pfile, cplusplus)) buffer->cur++, result->type = CPP_DOT_STAR; break; case '+': result->type = CPP_PLUS; if (*buffer->cur == '+') buffer->cur++, result->type = CPP_PLUS_PLUS; else if (*buffer->cur == '=') buffer->cur++, result->type = CPP_PLUS_EQ; break; case '-': result->type = CPP_MINUS; if (*buffer->cur == '>') { buffer->cur++; result->type = CPP_DEREF; if (*buffer->cur == '*' && CPP_OPTION (pfile, cplusplus)) buffer->cur++, result->type = CPP_DEREF_STAR; } else if (*buffer->cur == '-') buffer->cur++, result->type = CPP_MINUS_MINUS; else if (*buffer->cur == '=') buffer->cur++, result->type = CPP_MINUS_EQ; break; case '&': result->type = CPP_AND; if (*buffer->cur == '&') buffer->cur++, result->type = CPP_AND_AND; else if (*buffer->cur == '=') buffer->cur++, result->type = CPP_AND_EQ; break; case '|': result->type = CPP_OR; if (*buffer->cur == '|') buffer->cur++, result->type = CPP_OR_OR; else if (*buffer->cur == '=') buffer->cur++, result->type = CPP_OR_EQ; break; case ':': result->type = CPP_COLON; if (*buffer->cur == ':' && CPP_OPTION (pfile, cplusplus)) buffer->cur++, result->type = CPP_SCOPE; else if (*buffer->cur == '>' && CPP_OPTION (pfile, digraphs)) { buffer->cur++; result->flags |= DIGRAPH; result->type = CPP_CLOSE_SQUARE; } break; case '*': IF_NEXT_IS ('=', CPP_MULT_EQ, CPP_MULT); break; case '=': IF_NEXT_IS ('=', CPP_EQ_EQ, CPP_EQ); break; case '!': IF_NEXT_IS ('=', CPP_NOT_EQ, CPP_NOT); break; case '^': IF_NEXT_IS ('=', CPP_XOR_EQ, CPP_XOR); break; case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); break; case '?': result->type = CPP_QUERY; break; case '~': result->type = CPP_COMPL; break; case ',': result->type = CPP_COMMA; break; case '(': result->type = CPP_OPEN_PAREN; break; case ')': result->type = CPP_CLOSE_PAREN; break; case '[': result->type = CPP_OPEN_SQUARE; break; case ']': result->type = CPP_CLOSE_SQUARE; break; case '{': result->type = CPP_OPEN_BRACE; break; case '}': result->type = CPP_CLOSE_BRACE; break; case ';': result->type = CPP_SEMICOLON; break; /* @ is a punctuator in Objective-C. */ case '@': result->type = CPP_ATSIGN; break; case '$': case '\\': { const uchar *base = --buffer->cur; if (forms_identifier_p (pfile, true)) { result->type = CPP_NAME; result->val.node = lex_identifier (pfile, base); break; } buffer->cur++; } default: create_literal (pfile, result, buffer->cur - 1, 1, CPP_OTHER); break; } return result; }
// // SourceVariable::getData // VariableData::Pointer SourceVariable::getData() const { ObjectExpression::Pointer address; SourceExpression::Pointer arrbase; bigsint size = type->getSize(pos); if (expr) address = expr; else address = ObjectExpression::CreateValueSymbol(nameObj, pos); switch (store) { case STORE_NONE: Error_NP("STORE_NONE"); case STORE_FAR: Error_NP("STORE_FAR"); case STORE_STATIC: return VariableData::create_static(size, address); case STORE_AUTO: return VariableData::create_auto(size, address); case STORE_CONST: return VariableData::create_literal(size, address); case STORE_REGISTER: return VariableData::create_register (size, VariableData::SR_LOCAL, address); case STORE_MAPREGISTER: return VariableData::create_register (size, VariableData::SR_MAP, address); case STORE_WORLDREGISTER: return VariableData::create_register (size, VariableData::SR_WORLD, address); case STORE_GLOBALREGISTER: return VariableData::create_register (size, VariableData::SR_GLOBAL, address); case STORE_MAPARRAY: address = ObjectExpression::CreateValueSymbol(nameArr, pos); arrbase = SourceExpression::create_value_variable(create_literal( VariableType::get_bt_uns(), nameObj, pos), SourceContext::global_context, pos); return VariableData::create_array(size, VariableData::SA_MAP, address, arrbase); case STORE_WORLDARRAY: address = ObjectExpression::CreateValueSymbol(nameArr, pos); arrbase = SourceExpression::create_value_variable(create_literal( VariableType::get_bt_uns(), nameObj, pos), SourceContext::global_context, pos); return VariableData::create_array(size, VariableData::SA_WORLD, address, arrbase); case STORE_GLOBALARRAY: address = ObjectExpression::CreateValueSymbol(nameArr, pos); arrbase = SourceExpression::create_value_variable(create_literal( VariableType::get_bt_uns(), nameObj, pos), SourceContext::global_context, pos); return VariableData::create_array(size, VariableData::SA_GLOBAL, address, arrbase); case STORE_STRING: Error_NP("STORE_STRING"); } Error_NP("invalid store"); }