1 #ifndef FREEHDL_KERNEL_ACL_H
2 #define FREEHDL_KERNEL_ACL_H
3 
4 #include <stdlib.h>
5 #include <string.h>
6 
7 #include <freehdl/kernel-error.hh>
8 
9 
10 #define MAX_ACL_DEPTH 100 // Max depth of acl objects
11 #define ACL_MARKER ((int)0x80000000) // This const is used to store an range
12 // value within an acl list and to mark the end of a list
13 #define ACL_RANGE ACL_MARKER
14 
15 
16 /* *************************************************************
17  *  Range directions
18  * ************************************************************* */
19 enum range_direction {to, downto};
20 
21 
22 
23 // The following macro is used to store a range value into a alc list.
24 // Note, are stord as 4 int values into the list. ACL_RANGE_MARKER
25 // marks the start of a range value. Thereafter the left, the direction
26 // and the right value are stored into the list. Note further, this
27 // macro is based on the "<<" operator of the acl class.
28 #define acl_range(left, direction ,right) ACL_RANGE << left << direction << right
29 
30 
31 class acl;
32 typedef acl *pacl;
33 extern acl *free_acl[MAX_ACL_DEPTH + 1]; // List of acl objects that are currently not in use
34 
35 
36 // acl are used to identify elements or set of elements of
37 // a composite object. It is simply a list of int values. The
38 // first element stores the maximum length and the number of items
39 // currently on the list. Note, an acl instance can be created
40 // with "new(x)" only, where "x" is the maximum length (number of
41 // items) of the list.
42 class acl {
43   struct _head { short index; short size; };
44   union _data { _head head; int value; acl *next; };
45   _data data;
get_header()46   _head &get_header() { return (&this->data)[-1].head; }
get_index() const47   int get_index() const { return (&this->data)[-1].head.index; }
48 public:
49   // Returns the number of items of an acl instance
get_size() const50   int get_size() const { return (&this->data)[-1].head.size; }
51 
52   // Allocate a new acl instance from the list of free acl
53   // objects.
operator new(size_t,int s)54   void *operator new(size_t, int s) {
55 #ifdef DEBUG
56     string deb;
57 #endif
58     // Test parameter s
59     v_assert(s >= MAX_ACL_DEPTH, "MAX_ACL_DEPTH too small");
60 #ifdef DEBUG
61     deb=s;
62     v_assert(s < 1, "Illegal acl size (" + deb + ")");
63 #endif
64     acl *new_acl;
65     if (free_acl[s] != NULL) {
66       // There is an unused object in free_acl with the
67       // correct length
68       new_acl = free_acl[s];
69       free_acl[s] = new_acl->data.next;
70     } else
71       // Otherwise create a new acl list. Two elementes are
72       // used to mark the end of the list and one element
73       // stores the length of the list. Note, the length
74       // is stored in the -1'st element!
75       new_acl = ((acl*)malloc((s + 3) * sizeof(_data)) + 1);
76 
77     // Mark the current as well as the absolute end of the list.
78     // Note, contrary to the current end the absolute end will
79     // be never overwritten!
80     (&new_acl->data)[0].value = ACL_MARKER;
81     (&new_acl->data)[1].value = ACL_MARKER;
82     (&new_acl->data)[s].value = ACL_MARKER;
83     (&new_acl->data)[s+1].value = ACL_MARKER;
84     // Store the current size of the list
85     new_acl->get_header().index = 0;
86     new_acl->get_header().size = s;
87     return new_acl;
88   }
89 
90   // Removes a acl item. The unused item is inserted into
91   // the free_acl array.
operator delete(void * a)92   void operator delete(void *a) {
93     // The size of the current acl list is stored in the -1'nd
94     // element
95     register int s = ((acl*)a)->get_header().size;
96     ((acl*)a)->data.next = free_acl[s];
97     free_acl[s] = (acl*)a;
98   }
99 
acl()100   acl() { };
101 
102   // Clear the current acl list, i.e. remove all entries.
clear()103   acl &clear() {
104     // Mark the current end of the list. Note that the it is not
105     // necessary to reset the absolute end of the list as it is not
106     // overwritten!
107     (&data)[0].value = ACL_MARKER;
108     (&data)[1].value = ACL_MARKER;
109     // Set the size of the current size to 0
110     get_header().index = 0;
111 
112     return *this;
113   }
114 
115   // Adds a single int value to the current acl list. The result
116   // is stored into the current acl list. Note, no range checking
117   // is done!
operator <<(const int i)118   acl &operator<<(const int i) {
119     ((int*)&data.value)[get_header().index++] = i;
120     // Mark end of list
121     ((int*)&data.value)[get_header().index + 1] = ACL_MARKER;
122     return *this;
123   }
124 
125   // Returns true if there are no more values
end() const126   bool end() const {
127     return (this == NULL)? true : (&data.value)[0] == ACL_MARKER && (&data.value)[1] == ACL_MARKER;
128   }
129 
130   // Compare operator
131   bool operator==(const acl &a);
132 
133   // Assigment operator
operator =(const acl & a)134   acl &operator=(const acl &a) {
135     memcpy(&data.value, &a.data.value, sizeof(int) * (a.get_index() + 2));
136     get_header().index = a.get_index();
137     return *this;
138   }
139 
140   // Creates a copy of the acl
clone()141   acl *clone() {
142     if (this == NULL) return (acl*)NULL;
143     acl *new_acl = new(get_size()) acl;
144     *new_acl = *this;
145     return new_acl;
146   }
147 
148   // Returns item number i of an acl instance
get(int i) const149   int get(int i) const { return ((int*)&data.value)[i]; }
150 
151   // Returns the current value the acl instance points to
get() const152   int get() const { return ((int*)&data.value)[0]; }
153 
154   // Set index i to value j
set(int i,int j)155   acl *set(int i, int j) {
156     ((int*)&data.value)[i] = j;
157     return (acl*)&data.value;
158   }
159 
160   // Returns the next acl instance
next()161   acl *next() { return (acl*)&((int*)&data.value)[1]; }
162 
163   // Return last entry in acl list. Note that an range entry is
164   // considered as a single entry!
back()165   acl *back() {
166     if (end()) return this;
167 
168     acl *current_acl = this;
169     acl *next_acl = current_acl->next();
170     // search for the last entry in the list
171     while (!next_acl->end()) {
172       current_acl = next_acl;
173       next_acl = next_acl->next();
174       // If the next acl is a range entry then skip over all elements
175       // of the range
176       if (!next_acl->end() &&
177 	  next_acl->get() == ACL_RANGE)
178 	for (int i = 0; i < 4; i++)
179 	  next_acl = next_acl->next();
180     }
181 
182     return current_acl;
183   }
184 
185 };
186 
187 
188 #ifdef KERNEL
189 // *****************************************************************
190 // Some function  which are used only within kernel code.
191 // *****************************************************************
192 
193 // Count levels an acl consists of. Note that a range is counted as a
194 // single level.
195 int
196 count_levels(const pacl a);
197 
198 // Get acl pointer associated with level "level". Note that a range is
199 // counted as a single level.
200 pacl
201 get_level(const pacl a, const int level);
202 
203 // Creates a new acl containing levels begin to end (not included)
204 // from original acl a
205 pacl
206 clone_levels(const pacl a, const int begin, const int end);
207 
208 // Returns current acl entry in left, dir and right. A single number
209 // is converted into a range "number" to "number". If no range or
210 // index is specified then a null range 1 to 0 is returned. Function
211 // returns a pointer to the next acl entry.
212 pacl
213 get_entry_data(pacl a, int &left, range_direction &dir, int &right);
214 
215 #endif
216 
217 extern pacl tmpacl;
218 extern pacl tmpacl1;
219 extern pacl tmpacl2;
220 
221 #endif
222