1 /*
2  * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #ifndef SHARE_COMPILER_DIRECTIVESPARSER_HPP
26 #define SHARE_COMPILER_DIRECTIVESPARSER_HPP
27 
28 #include "utilities/json.hpp"
29 #include "compiler/compilerDirectives.hpp"
30 
31 enum FlagType {
32   boolFlag,
33   intxFlag,
34   uintxFlag,
35   doubleFlag,
36   ccstrFlag,
37   ccstrlistFlag,
38   UnknownFlagType
39 };
40 
41 static const char* flag_type_names[] = {
42     "bool",
43     "int",
44     "uint",
45     "double",
46     "string",
47     "string list",
48     "unknown"
49 };
50 
51 class DirectivesParserTest;
52 
53 class DirectivesParser : public JSON {
54  friend class DirectivesParserTest;
55  public:
56   static bool has_file();
57   static bool parse_from_flag();
58   static bool parse_from_file(const char* filename, outputStream* st);
59   static int  parse_string(const char* string, outputStream* st);
60   int install_directives();
61 
62  private:
63   DirectivesParser(const char* text, outputStream* st, bool silent);
64   ~DirectivesParser();
65 
66   bool callback(JSON_TYPE t, JSON_VAL* v, uint level);
67   static bool parse_from_file_inner(const char* filename, outputStream* st);
68 
69   // types of "keys". i.e recognized <key>:<value> pairs in our JSON syntax
70   typedef enum {
71      type_c1,
72      type_c2,
73      type_enable,
74      type_preset,
75      type_match,
76      type_inline,
77 
78      // After here, there is no correlation between
79      // keytype and keys array
80      //type_strategy,
81      type_flag,
82      //type_dir,
83 
84      // Synthetic.
85      type_dir_array,
86      type_directives,
87      type_value_array
88   } keytype;
89 
90   // name, type, dtd info and maybe a setter
91   // this is how we map key-values
92   typedef struct {
93      const char *name;
94      keytype     type;
95      uint    allow_array_value : 1;
96      uint    allowedmask;
97      void (DirectiveSet::*set)(void* arg);
98      FlagType flag_type;
99   } key;
100 
101   // Array with valid keys for the directive file
102   static const key keys[];
103   // Marker for outermost moosewings/array
104   static const key dir_array_key;
105   // Marker for a directives set (these are "implicit" objects, as in not named)
106   static const key dir_key;
107   // Marker for a multi value
108   static const key value_array_key;
109 
110   // A compiler directive shouldn't be able to use more than 5 stack slots.
111   // Example of max stack usage:
112   // depth 1: type_dir_array  [
113   // depth 2: type_directives   {
114   // depth 3: type_c1             c1: {
115   // depth 4: type_inline           inline:
116   // depth 5: type_value_array      [ ...
117   static const uint MAX_DEPTH = 5;
118   const key* stack[MAX_DEPTH];
119   uint depth;
120 
121   bool push_key(const char* str, size_t len);
122   bool push_key(const key* k);
123   const key* current_key();
124   const key* pop_key();
125   static const key* lookup_key(const char* s, size_t len);
126 
127   bool set_option(JSON_TYPE t, JSON_VAL* v);
128   bool set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set);
129 
130   CompilerDirectives* current_directive;
131   DirectiveSet*       current_directiveset;
132 
133   void push_tmp(CompilerDirectives* dir);
134   void clean_tmp();
135   CompilerDirectives* pop_tmp();
136   CompilerDirectives* _tmp_top; // temporary storage for dirs while parsing
137   int _tmp_depth;               // Number of directives that has been parsed but not installed.
138 
139   static uint mask(keytype kt);
140 };
141 
142 #endif // SHARE_COMPILER_DIRECTIVESPARSER_HPP
143