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