/* * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
bool DirectivesParser::parse_from_file(constchar* filename, outputStream* st) {
assert(filename != NULL, "Test before calling this"); if (!parse_from_file_inner(filename, st)) {
st->print_cr("Could not load file: %s", filename); returnfalse;
} returntrue;
}
bool DirectivesParser::parse_from_file_inner(constchar* filename, outputStream* stream) { struct stat st;
ResourceMark rm; if (os::stat(filename, &st) == 0) { // found file, open it int file_handle = os::open(filename, 0, 0); if (file_handle != -1) { // read contents into resource array char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1);
ssize_t num_read = ::read(file_handle, (char*) buffer, st.st_size); if (num_read >= 0) {
buffer[num_read] = '\0'; // close file
::close(file_handle); return parse_string(buffer, stream) > 0;
}
}
} returnfalse;
}
int DirectivesParser::install_directives() { // Check limit if (!DirectivesStack::check_capacity(_tmp_depth, _st)) {
clean_tmp(); return 0;
}
// Pop from internal temporary stack and push to compileBroker.
CompilerDirectives* tmp = pop_tmp(); int i = 0; while (tmp != NULL) {
i++;
DirectivesStack::push(tmp);
tmp = pop_tmp();
} if (i == 0) {
_st->print_cr("No directives in file"); return 0;
} else {
_st->print_cr("%i compiler directives added", i); if (CompilerDirectivesPrint) { // Print entire directives stack after new has been pushed.
DirectivesStack::print(_st);
} return i;
}
}
const DirectivesParser::key DirectivesParser::dir_array_key = { "top level directives array", type_dir_array, 0, 1 // Lowest bit means allow at top level
}; const DirectivesParser::key DirectivesParser::dir_key = { "top level directive", type_directives, 0, mask(type_dir_array) | 1 // Lowest bit means allow at top level
}; const DirectivesParser::key DirectivesParser::value_array_key = { "value array", type_value_array, 0, UINT_MAX // Allow all, checked by allow_array on other keys, not by allowed_mask from this key
};
const DirectivesParser::key* DirectivesParser::lookup_key(constchar* str, size_t len) { for (size_t i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) { if (strncasecmp(keys[i].name, str, len) == 0) { return &keys[i];
}
} return NULL;
}
// Exceeding the stack should not be possible with a valid compiler directive, // and an invalid should abort before this happens
assert(depth < MAX_DEPTH, "exceeded stack depth"); if (depth >= MAX_DEPTH) {
error(INTERNAL_ERROR, "Stack depth exceeded."); returnfalse;
}
assert(stack[depth] == NULL, "element not nulled, something is wrong");
if (depth == 0 && !(k->allowedmask & 1)) {
error(KEY_ERROR, "Key '%s' not allowed at top level.", k->name); returnfalse;
}
if (depth > 0) { const key* prev = stack[depth - 1]; if (!(k->allowedmask & mask(prev->type))) {
error(KEY_ERROR, "Key '%s' not allowed after '%s' key.", k->name, prev->name); returnfalse;
}
}
void (DirectiveSet::*test)(void *args);
test = option_key->set;
switch (t) { case JSON_TRUE: if (option_key->flag_type != boolFlag) {
error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]); returnfalse;
} else { bool val = true;
(set->*test)((void *)&val);
} break;
case JSON_FALSE: if (option_key->flag_type != boolFlag) {
error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]); returnfalse;
} else { bool val = false;
(set->*test)((void *)&val);
} break;
case JSON_NUMBER_INT: if (option_key->flag_type == intxFlag) {
intx ival = v->int_value;
(set->*test)((void *)&ival);
} elseif (option_key->flag_type == uintxFlag) {
uintx ival = v->uint_value;
(set->*test)((void *)&ival);
} elseif (option_key->flag_type == doubleFlag) { double dval = (double)v->int_value;
(set->*test)((void *)&dval);
} else {
error(VALUE_ERROR, "Cannot use int value for an %s flag", flag_type_names[option_key->flag_type]); returnfalse;
} break;
case JSON_NUMBER_FLOAT: if (option_key->flag_type != doubleFlag) {
error(VALUE_ERROR, "Cannot use double value for an %s flag", flag_type_names[option_key->flag_type]); returnfalse;
} else { double dval = v->double_value;
(set->*test)((void *)&dval);
} break;
case JSON_STRING: if (option_key->flag_type != ccstrFlag && option_key->flag_type != ccstrlistFlag) {
error(VALUE_ERROR, "Cannot use string value for a %s flag", flag_type_names[option_key->flag_type]); returnfalse;
} else { char* s = NEW_C_HEAP_ARRAY(char, v->str.length+1, mtCompiler);
strncpy(s, v->str.start, v->str.length + 1);
s[v->str.length] = '\0';
(set->*test)((void *)&s);
if (strncmp(option_key->name, "ControlIntrinsic", 16) == 0) {
ControlIntrinsicValidator validator(s, false/*disabled_all*/);
if (option_key->type == value_array_key.type) { // Multi value array, we are really setting the value // for the key one step further up.
option_key = pop_key();
enclosing_key = current_key();
// Repush option_key and multi value marker, since // we need to keep them until all multi values are set.
push_key(option_key);
push_key(&value_array_key);
}
switch (option_key->type) { case type_flag:
{ if (current_directiveset == NULL) {
assert(depth == 2, "Must not have active directive set");
if (!set_option_flag(t, v, option_key, current_directive->_c1_store)) { returnfalse;
} if (!set_option_flag(t, v, option_key, current_directive->_c2_store)) { returnfalse;
}
} else {
assert(depth > 2, "Must have active current directive set"); if (!set_option_flag(t, v, option_key, current_directiveset)) { returnfalse;
}
} break;
}
case type_match: if (t != JSON_STRING) {
error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name); returnfalse;
} if (enclosing_key->type != type_directives) {
error(SYNTAX_ERROR, "Match keyword can only exist inside a directive"); returnfalse;
}
{ char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
strncpy(s, v->str.start, v->str.length);
s[v->str.length] = '\0';
case type_inline: if (t != JSON_STRING) {
error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name); returnfalse;
}
{ //char* s = strndup(v->str.start, v->str.length); char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
strncpy(s, v->str.start, v->str.length);
s[v->str.length] = '\0';
case type_c1:
current_directiveset = current_directive->_c1_store; if (t != JSON_TRUE && t != JSON_FALSE) {
error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name); returnfalse;
} break;
case type_c2:
current_directiveset = current_directive->_c2_store; if (t != JSON_TRUE && t != JSON_FALSE) {
error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name); returnfalse;
} break;
if (depth == 0) { switch (t) { case JSON_ARRAY_BEGIN: return push_key(&dir_array_key);
case JSON_OBJECT_BEGIN: // push synthetic dir_array
push_key(&dir_array_key);
assert(depth == 1, "Make sure the stack are aligned with the directives"); break;
default:
error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive."); returnfalse;
}
} if (depth == 1) { switch (t) { case JSON_OBJECT_BEGIN: // Parsing a new directive.
current_directive = new CompilerDirectives(); return push_key(&dir_key);
case JSON_ARRAY_END:
k = pop_key();
if (k->type != type_dir_array) {
error(SYNTAX_ERROR, "Expected end of directives array"); returnfalse;
} returntrue;
default:
error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive."); returnfalse;
}
} else { switch (t) { case JSON_OBJECT_BEGIN:
k = current_key(); switch (k->type) { case type_c1:
current_directiveset = current_directive->_c1_store; returntrue; case type_c2:
current_directiveset = current_directive->_c2_store; returntrue;
case type_dir_array: return push_key(&dir_key);
default:
error(SYNTAX_ERROR, "The key '%s' does not allow an object to follow.", k->name); returnfalse;
} returnfalse;
case JSON_OBJECT_END:
k = pop_key(); switch (k->type) { case type_c1: case type_c2: // This is how we now if options apply to a single or both directive sets
current_directiveset = NULL; break;
case type_directives: // Check, finish and push to stack! if (current_directive->match() == NULL) {
error(INTERNAL_ERROR, "Directive missing required match."); returnfalse;
}
current_directive->finalize(_st);
push_tmp(current_directive);
current_directive = NULL; break;
default:
error(INTERNAL_ERROR, "Object end with wrong key type on stack: %s.", k->name);
ShouldNotReachHere(); returnfalse;
} returntrue;
case JSON_ARRAY_BEGIN:
k = current_key(); if (!(k->allow_array_value)) { if (k->type == type_dir_array) {
error(SYNTAX_ERROR, "Array not allowed inside top level array, expected directive object.");
} else {
error(VALUE_ERROR, "The key '%s' does not allow an array of values.", k->name);
} returnfalse;
} return push_key(&value_array_key);
case JSON_ARRAY_END:
k = pop_key(); // Pop multi value marker
assert(k->type == value_array_key.type, "array end for level != 0 should terminate multi value");
k = pop_key(); // Pop key for option that was set returntrue;
case JSON_KEY: return push_key(v->str.start, v->str.length);
case JSON_STRING: case JSON_NUMBER_INT: case JSON_NUMBER_FLOAT: case JSON_TRUE: case JSON_FALSE: case JSON_NULL: return set_option(t, v);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.