spec_syntax.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. /**
  2. * Copyright (C) 2011 Anders Sundman <anders@4zm.org>
  3. *
  4. * This file is part of mfterm.
  5. *
  6. * mfterm is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * mfterm is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with mfterm. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <stdio.h>
  22. #include "util.h"
  23. #include "spec_syntax.h"
  24. // Forward declarations
  25. int sp_parse();
  26. extern FILE* sp_in;
  27. // Parse the input file and set up type_root and instance_root.
  28. // Return 0 on success.
  29. int spec_import(FILE* input) {
  30. // Parse the input to build a type hierarchy
  31. sp_in = input;
  32. if (sp_parse()) {
  33. printf("Syntax Error: Specification not imported\n");
  34. goto error;
  35. }
  36. // Check for missing definitions
  37. type_t* partial = tt_contains_partial_types();
  38. if (partial) {
  39. printf("Error: Incomplete declaration '%s' in specification.\n",
  40. partial->composite_extras->name);
  41. goto error;
  42. }
  43. // Make sure we have a root type defined
  44. if (type_root == NULL) {
  45. printf("Error: No root type '.' found in specification.\n");
  46. goto error;
  47. }
  48. // Create the instance tree
  49. instance_root = make_instance_tree(type_root);
  50. printf("Specification sucessfully imported.\n");
  51. return 0;
  52. error:
  53. clear_instance_tree();
  54. tt_clear();
  55. return 1;
  56. }
  57. // The primitive Byte type
  58. type_t byte_type = {
  59. .type_category = BYTE_TYPE,
  60. .composite_extras = NULL,
  61. };
  62. // The primitive Bit type
  63. type_t bit_type = {
  64. .type_category = BIT_TYPE,
  65. .composite_extras = NULL,
  66. };
  67. // Allocate and return a composite type instance. The type will assume
  68. // ownership of the heap allocated name.
  69. type_t* make_composite_type(char* name) {
  70. type_t* t = malloc(sizeof(type_t));
  71. t->type_category = COMPOSITE_TYPE;
  72. t->composite_extras = (composite_type_extras_t*)
  73. malloc(sizeof(composite_type_extras_t));
  74. if (name)
  75. t->composite_extras->name = name;
  76. else
  77. t->composite_extras->name = NULL; // Anonymous type
  78. t->composite_extras->fields = NULL;
  79. return t;
  80. }
  81. // Free a composite type. This function will also free it's fields.
  82. void free_composite_type(type_t* t) {
  83. // Free the fields
  84. field_list_t* iter = t->composite_extras->fields;
  85. while (iter) {
  86. field_list_t* tmp = iter;
  87. iter = iter->next_;
  88. free_field(tmp->field);
  89. free(tmp);
  90. }
  91. // Free the type data
  92. free(t->composite_extras->name);
  93. free(t->composite_extras);
  94. free(t);
  95. }
  96. // Allocate a new field with the given parameters. Anonymous '-'
  97. // filler fields use NULL as name. The field will assume ownership of
  98. // the heap allocated name.
  99. field_t* make_field(char* name, type_t* type, size_t length) {
  100. field_t* f = (field_t*) malloc(sizeof(field_t));
  101. f->name = name; // NULL for fillers
  102. f->type = type;
  103. f->length = length;
  104. return f;
  105. }
  106. // Free the memory used by a field.
  107. void free_field(field_t* field) {
  108. if (field == NULL)
  109. return;
  110. free(field->name);
  111. free(field);
  112. }
  113. // Add a field to an existing list of fields or, if the field_list
  114. // parameter is NULL, create a new field list. The order of fields is
  115. // significant and this function will append the field to the end of
  116. // the field_list.
  117. field_list_t* append_field(field_list_t* field_list, field_t* field) {
  118. // Create the list node
  119. field_list_t* flist = (field_list_t*) malloc(sizeof(field_list_t));
  120. flist->field = field;
  121. flist->next_ = NULL;
  122. // Create the list or append to the end
  123. if (field_list != NULL) {
  124. field_list_t* it = field_list;
  125. while(it->next_)
  126. it = it->next_;
  127. it->next_ = flist;
  128. }
  129. else {
  130. field_list = flist; // Won't effect the inarg
  131. }
  132. // Return the start of the list
  133. return field_list;
  134. }
  135. // Search the field list for a field with the given name
  136. field_t* get_field(field_list_t* field_list, const char* name) {
  137. if (name == NULL || field_list == NULL)
  138. return NULL;
  139. field_list_t* it = field_list;
  140. while(it) {
  141. field_t* f = it->field;
  142. if (f && f->name && strcmp(f->name, name) == 0)
  143. return f;
  144. it = it->next_;
  145. }
  146. // Not found
  147. return NULL;
  148. }
  149. // The global instance of the type table. If there isn't any, the
  150. // variable will be NULL. All the type table operations (tt_) operate
  151. // on this global variable.
  152. type_table_t* type_table = NULL;
  153. // The root type of the type hierarchy
  154. type_t* type_root = NULL;
  155. // Internal functions for allocating and freeing type table list nodes.
  156. type_table_t* tt_make_node_(type_t* t);
  157. void tt_free_node_(type_table_t* tt);
  158. // Clear the type table - freeing the memory used by the table and by
  159. // all the types.
  160. void tt_clear() {
  161. // Reset the root
  162. type_root = NULL;
  163. // Free all types and the table itself
  164. type_table_t* it = type_table;
  165. while(it) {
  166. type_table_t* next = it->next_;
  167. free_composite_type(it->type);
  168. tt_free_node_(it);
  169. it = next;
  170. };
  171. type_table = NULL;
  172. }
  173. // Add a type to the type table.
  174. type_t* tt_add_type(type_t* t) {
  175. if (type_table == NULL) {
  176. type_table = tt_make_node_(t);
  177. }
  178. else {
  179. type_table_t* it = type_table;
  180. while(it->next_)
  181. it = it->next_;
  182. it->next_ = tt_make_node_(t);
  183. }
  184. return t;
  185. }
  186. // Search the type table for a type with the given name. The first
  187. // type found will be returned. If no type is found, NULL is returned.
  188. type_t* tt_get_type(const char* type_name) {
  189. if (type_name == NULL)
  190. return NULL;
  191. type_table_t* it = type_table;
  192. while(it) {
  193. // Anonymous types (name == NULL) will never match
  194. if (it->type->composite_extras->name &&
  195. strcmp(type_name, it->type->composite_extras->name) == 0)
  196. return it->type; // Type was found!
  197. it = it->next_;
  198. }
  199. // Not found
  200. return NULL;
  201. }
  202. // Check if there are any partially declared types in the type
  203. // table. Return a pointer to the first incomplete type or NULL if
  204. // none exists.
  205. type_t* tt_contains_partial_types() {
  206. type_table_t* it = type_table;
  207. while(it) {
  208. if (it->type->composite_extras->decl_status == PARTIAL_DECL)
  209. return it->type;
  210. it = it->next_;
  211. }
  212. return NULL;
  213. }
  214. // Allocate a new list entry for the type table
  215. type_table_t* tt_make_node_(type_t* t) {
  216. type_table_t* tt = malloc(sizeof(type_table_t));
  217. tt->type = t;
  218. tt->next_ = NULL;
  219. return tt;
  220. }
  221. // Free a type table list entry (this won't free the type)
  222. void tt_free_node_(type_table_t* tt) {
  223. free(tt);
  224. }
  225. // The global variable representing the root instance; it is an
  226. // instanciation of the '.' type.
  227. instance_t* instance_root = NULL;
  228. // Forward decls of internal functions used during creation and
  229. // destruction of the instance tree.
  230. void clear_instance_tree_(instance_t* root);
  231. void make_instance_(instance_t* root,
  232. size_t* obytes, size_t* obits,
  233. size_t* sbytes, size_t* sbits);
  234. instance_t* make_byte_instance_(field_t* field, size_t* obytes, size_t* obits);
  235. instance_t* make_bit_instance_(field_t* field, size_t* obytes, size_t* obits);
  236. instance_t* make_composite_instance_(field_t* field,
  237. size_t* obytes, size_t* obits);
  238. instance_list_t* append_instance_(instance_list_t** end_ptr,
  239. instance_t* new_field);
  240. // Create an instance tree matching the type tree starting at
  241. // type_root. The global instance tree is constructed with type_root '.'.
  242. instance_t* make_instance_tree(type_t* type_root) {
  243. instance_t* root = malloc(sizeof(instance_t));
  244. root->offset_bytes = 0;
  245. root->offset_bits = 0;
  246. root->size_bytes = 0;
  247. root->size_bits = 0;
  248. root->field = make_field(strdup("."), type_root, 1);
  249. root->fields = NULL;
  250. size_t obytes = 0;
  251. size_t obits = 0;
  252. make_instance_(root, &obytes, &obits,
  253. &(root->size_bytes), &(root->size_bits));
  254. return root;
  255. }
  256. // Clear the global instance tree. Free it and set instance_root NULL
  257. void clear_instance_tree() {
  258. if (instance_root == NULL)
  259. return;
  260. clear_instance_tree_(instance_root);
  261. instance_root = NULL;
  262. }
  263. /* Get the child instance with a given name. Only look to children, */
  264. /* not grand children. If no child with the given name exists, return */
  265. /* null. */
  266. instance_t* get_instance_child(instance_t* inst, const char* name) {
  267. if (name == NULL)
  268. return NULL;
  269. return get_instance_child_n(inst, name, strlen(name));
  270. }
  271. /**
  272. * Like get_instance_child(inst, name), but name does not have to be
  273. * null terminated. Instead the length of the name string is given by
  274. * the last argument.
  275. */
  276. instance_t* get_instance_child_n(instance_t* inst,
  277. const char* name,
  278. size_t nlen) {
  279. if (inst == NULL || name == NULL || nlen == 0)
  280. return NULL;
  281. instance_list_t* iter = inst->fields;
  282. while(iter) {
  283. field_t* f = iter->instance->field;
  284. // Make sure the field has a name (isn't anaonymous) before comparing.
  285. if (f && f->name &&
  286. strlen(f->name) == nlen &&
  287. strncmp(f->name, name, nlen) == 0)
  288. return iter->instance;
  289. iter = iter->next_;
  290. }
  291. return NULL;
  292. }
  293. /**
  294. * Parse a specification path of the form '.fu.bar.baz' and return the
  295. * instance pointed to by baz. In case the path doesn't point to a
  296. * loaded instance, return NULL. */
  297. instance_t* parse_spec_path(const char* path) {
  298. const char* lastpath;
  299. instance_t* inst;
  300. // Parse the path up to the last instance
  301. if (parse_partial_spec_path(path, &lastpath, &inst) != 0)
  302. return NULL;
  303. // Find and return the leaf node
  304. return get_instance_child(inst, lastpath);
  305. }
  306. /**
  307. * Parse the path to produce a parent section and an instance that
  308. * points to the head of the parent.
  309. *
  310. * The format is .fu.bar.ba(z). Where .fu.bar.ba is the path, fu, bar
  311. * and baz are nested fields. The function should return parent_end
  312. * pointing into path to the point after the last '.', i.e. to the 'b'
  313. * in the last 'ba'. parent_inst will point to bar.
  314. *
  315. * The function returns 0 on success.
  316. */
  317. int parse_partial_spec_path(const char* path,
  318. const char** parent_end,
  319. instance_t** parent_inst) {
  320. // Check input. Paths start with '.'
  321. if (path == NULL || path[0] != '.')
  322. return 1;
  323. instance_t* inst = instance_root;
  324. const char* remaining_path = path + 1;
  325. char* tok_end;
  326. while((tok_end = strchr(remaining_path, '.')) != NULL) {
  327. // There is still a part of the path before the last '.'
  328. inst = get_instance_child_n(inst, remaining_path,
  329. tok_end - remaining_path);
  330. // Exit early (error in ancestor path)
  331. if (inst == NULL)
  332. return 1;
  333. // Remove the token and the '.' from the start of remaining string
  334. remaining_path = tok_end + 1;
  335. }
  336. // Set the output arguments
  337. if (parent_end != NULL)
  338. *parent_end = remaining_path;
  339. if (parent_inst != NULL)
  340. *parent_inst = inst;
  341. return 0;
  342. }
  343. // Count the number of fields in the instance
  344. int instance_fields_count(instance_t* inst) {
  345. if (inst == NULL)
  346. return 0;
  347. int count = 0;
  348. instance_list_t* it = inst->fields;
  349. while (it) {
  350. ++count;
  351. it = it->next_;
  352. }
  353. return count;
  354. }
  355. void clear_instance_tree_(instance_t* root) {
  356. instance_list_t* iter = root->fields;
  357. while (iter) {
  358. instance_list_t* tmp = iter->next_;
  359. clear_instance_tree_(iter->instance);
  360. free(iter);
  361. iter = tmp;
  362. }
  363. free(root);
  364. }
  365. void make_instance_(instance_t* root,
  366. size_t* obytes, size_t* obits,
  367. size_t* sbytes, size_t* sbits) {
  368. // Pointers to the matching type field and instance field beign processed.
  369. field_list_t* tf_iter = root->field->type->composite_extras->fields;
  370. instance_list_t* if_iter = root->fields;
  371. // Iterate over all the type fields and add matching instance fields.
  372. while(tf_iter) {
  373. field_t* f = tf_iter->field;
  374. // Create the child sub-tree or instance.
  375. instance_t* child;
  376. // Byte
  377. if (f->type == &byte_type) {
  378. child = make_byte_instance_(f, obytes, obits);
  379. }
  380. // Bit
  381. else if (f->type == &bit_type) {
  382. child = make_bit_instance_(f, obytes, obits);
  383. }
  384. // Composite type
  385. else {
  386. child = make_composite_instance_(f, obytes, obits);
  387. child->size_bytes = 0;
  388. child->size_bits = 0;
  389. make_instance_(child, obytes, obits,
  390. &(child->size_bytes), &(child->size_bits));
  391. // Update size with bits % 8
  392. child->size_bytes =
  393. child->size_bytes * f->length +
  394. (child->size_bits * f->length) / 8;
  395. child->size_bits = (child->size_bits * f->length) % 8;
  396. }
  397. // Add the new instance or instance tree, to the root instance
  398. // field list.
  399. if_iter = if_iter == NULL ?
  400. append_instance_(&(root->fields), child) :
  401. append_instance_(&(if_iter->next_), child);
  402. // Note that we are changing the value of the input parameters here
  403. // this is part of the 'return value' of the function. Wrap the
  404. // bit size mod 8.
  405. *sbytes = *sbytes + child->size_bytes + (*sbits + child->size_bits) / 8;
  406. *sbits = (*sbits + child->size_bits) % 8;
  407. tf_iter = tf_iter->next_;
  408. }
  409. }
  410. instance_t* make_byte_instance_(field_t* field, size_t* obytes, size_t* obits) {
  411. instance_t* i = malloc(sizeof(instance_t));
  412. i->field = field;
  413. i->fields = NULL;
  414. i->offset_bytes = *obytes;
  415. i->offset_bits = *obits;
  416. i->size_bytes = field->length;
  417. i->size_bits = 0;
  418. *obytes += i->size_bytes;
  419. // *obits += 0;
  420. return i;
  421. }
  422. instance_t* make_bit_instance_(field_t* field, size_t* obytes, size_t* obits) {
  423. instance_t* i = malloc(sizeof(instance_t));
  424. i->field = field;
  425. i->fields = NULL;
  426. i->offset_bytes = *obytes;
  427. i->offset_bits = *obits;
  428. // Bits % 8, overflow in bytes field
  429. i->size_bytes = field->length / 8;
  430. i->size_bits = field->length % 8;
  431. *obytes += i->size_bytes + (*obits + i->size_bits) / 8;
  432. *obits = (*obits + i->size_bits) % 8;
  433. return i;
  434. }
  435. instance_t* make_composite_instance_(field_t* field,
  436. size_t* obytes, size_t* obits) {
  437. instance_t* i = malloc(sizeof(instance_t));
  438. i->field = field;
  439. i->fields = NULL;
  440. i->offset_bytes = *obytes;
  441. i->offset_bits = *obits;
  442. // The size will be updated later, after recusion into all child fields.
  443. i->size_bytes = 0;
  444. i->size_bits = 0;
  445. return i;
  446. }
  447. instance_list_t* append_instance_(instance_list_t** end_ptr,
  448. instance_t* new_field) {
  449. instance_list_t* il = (instance_list_t*) malloc(sizeof(instance_list_t));
  450. il->instance = new_field;
  451. il->next_ = NULL;
  452. *end_ptr = il;
  453. return il;
  454. }
  455. // Forward declaration
  456. void print_instance_tree_(instance_t* i, int indent);
  457. void print_instance_(instance_t* i);
  458. void print_instance_tree() {
  459. if (instance_root == NULL) {
  460. printf("No specification loaded.\n");
  461. return;
  462. }
  463. printf("[%d, %d] [%d, %d] -- . (root)\n",
  464. instance_root->offset_bytes,
  465. instance_root->offset_bits,
  466. instance_root->size_bytes,
  467. instance_root->size_bits);
  468. print_instance_tree_(instance_root, 1);
  469. }
  470. void print_instance_tree_(instance_t* root, int indent) {
  471. // For each field of the root instance
  472. instance_list_t* il = root->fields;
  473. while(il) {
  474. // Indent
  475. int count = (indent - 1) * 2;
  476. while(count--)
  477. printf(" ");
  478. printf("+- ");
  479. // Print instance field
  480. instance_t* inst = il->instance;
  481. print_instance_(inst);
  482. if (inst->field->type->composite_extras != NULL)
  483. print_instance_tree_(inst, indent + 1);
  484. il = il->next_;
  485. }
  486. }
  487. void print_instance_(instance_t* i) {
  488. if (i->field->type == &byte_type) {
  489. printf("[%d, %d] [%d, %d] -- Byte[%d] %s\n",
  490. i->offset_bytes,
  491. i->offset_bits,
  492. i->size_bytes,
  493. i->size_bits,
  494. i->field->length,
  495. i->field->name);
  496. }
  497. else if (i->field->type == &bit_type) {
  498. printf("[%d, %d] [%d, %d] -- Bit[%d] %s\n",
  499. i->offset_bytes,
  500. i->offset_bits,
  501. i->size_bytes,
  502. i->size_bits,
  503. i->field->length,
  504. i->field->name);
  505. }
  506. else {
  507. printf("[%d, %d] [%d, %d] -- %s[%d] %s\n",
  508. i->offset_bytes,
  509. i->offset_bits,
  510. i->size_bytes,
  511. i->size_bits,
  512. i->field->type->composite_extras->name,
  513. i->field->length,
  514. i->field->name);
  515. }
  516. }