/**
* mds — A micro-display server
* Copyright © 2014, 2015, 2016, 2017 Mattias Andrée (m@maandree.se)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef MDS_MDS_KBDC_TREE_H
#define MDS_MDS_KBDC_TREE_H
/* TODO add information field for layout mods */
#include "raw-data.h"
#include "string.h"
#include
#include
#include
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_information_t`
*/
#define MDS_KBDC_TREE_TYPE_INFORMATION 0
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_information_language_t`
*/
#define MDS_KBDC_TREE_TYPE_INFORMATION_LANGUAGE 1
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_information_country_t`
*/
#define MDS_KBDC_TREE_TYPE_INFORMATION_COUNTRY 2
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_information_variant_t`
*/
#define MDS_KBDC_TREE_TYPE_INFORMATION_VARIANT 3
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_include_t`
*/
#define MDS_KBDC_TREE_TYPE_INCLUDE 4
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_function_t`
*/
#define MDS_KBDC_TREE_TYPE_FUNCTION 5
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_macro_t`
*/
#define MDS_KBDC_TREE_TYPE_MACRO 6
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_assumption`
*/
#define MDS_KBDC_TREE_TYPE_ASSUMPTION 7
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_assumption_have_t`
*/
#define MDS_KBDC_TREE_TYPE_ASSUMPTION_HAVE 8
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_assumption_have_chars_t`
*/
#define MDS_KBDC_TREE_TYPE_ASSUMPTION_HAVE_CHARS 9
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_assumption_have_range_t`
*/
#define MDS_KBDC_TREE_TYPE_ASSUMPTION_HAVE_RANGE 10
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_for_t`
*/
#define MDS_KBDC_TREE_TYPE_FOR 11
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_if_t`
*/
#define MDS_KBDC_TREE_TYPE_IF 12
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_let_t`
*/
#define MDS_KBDC_TREE_TYPE_LET 13
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_map_t`
*/
#define MDS_KBDC_TREE_TYPE_MAP 14
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_array_t`
*/
#define MDS_KBDC_TREE_TYPE_ARRAY 15
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_keys_t`
*/
#define MDS_KBDC_TREE_TYPE_KEYS 16
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_string_t`
*/
#define MDS_KBDC_TREE_TYPE_STRING 17
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_compiled_keys_t`
*/
#define MDS_KBDC_TREE_TYPE_COMPILED_KEYS 18
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_compiled_string_t`
*/
#define MDS_KBDC_TREE_TYPE_COMPILED_STRING 19
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_nothing_t`
*/
#define MDS_KBDC_TREE_TYPE_NOTHING 20
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_alternation_t`
*/
#define MDS_KBDC_TREE_TYPE_ALTERNATION 21
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_unordered_t`
*/
#define MDS_KBDC_TREE_TYPE_UNORDERED 22
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_ordered_t`
*/
#define MDS_KBDC_TREE_TYPE_ORDERED 23
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_macro_call_t`
*/
#define MDS_KBDC_TREE_TYPE_MACRO_CALL 24
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_return_t`
*/
#define MDS_KBDC_TREE_TYPE_RETURN 25
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_break_t`
*/
#define MDS_KBDC_TREE_TYPE_BREAK 26
/**
* Value of `mds_kbdc_tree_t.type` for `mds_kbdc_tree_continue_t`
*/
#define MDS_KBDC_TREE_TYPE_CONTINUE 27
/**
* Keyboard layout syntax tree
*/
union mds_kbdc_tree __attribute__((transparent_union));
/**
* Keyboard layout syntax tree
*/
typedef union mds_kbdc_tree mds_kbdc_tree_t;
/**
* This macro is used in this header file, and is then
* undefined. It defined the common members for these
* tree structures.
*
* It defines:
* - int type; -- Integer that specifies which structure is used
* - mds_kbdc_tree_t* next; -- The next node in the tree, at the same level; a sibling
* - size_t loc_line; -- The line in the source code where this is found
* - size_t loc_start; -- The first byte in the source code where this is found, inclusive
* - size_t loc_end; -- The last byte in the source code where this is found, exclusive
* - long processed; -- The lasted step where the statement has already been processed once
*/
#define MDS_KBDC_TREE_COMMON\
int type;\
mds_kbdc_tree_t *next;\
size_t loc_line;\
size_t loc_start;\
size_t loc_end;\
long processed
/**
* This macro is used in this header file, and is then
* undefined. It defined padding of a tree structure.
*
* @param S:size_t The size of the data structure excluding this padding and
* the members defined by the macro `MDS_KBDC_TREE_COMMON`
*/
#define MDS_KBDC_TREE_PADDING_(S) char _padding[(5 * sizeof(void*) - (S)) / sizeof(char)]
/**
* This macro is used in this header file, and is then
* undefined. It defined padding of a tree structure.
*
* @param N The number of sizeof(void*) sized memebers defined data
* structure excluding this padding and the members defined
* by the macro `MDS_KBDC_TREE_COMMON`
*/
#define MDS_KBDC_TREE_PADDING(N) MDS_KBDC_TREE_PADDING_((N) * sizeof(void*))
/**
* This datastructure is not meant to be
* used directly, it is a common definition
* for tree structurs that only have, beside
* the common members, a pointer to the first
* node on next level in the tree
*/
struct mds_kbdc_tree_nesting {
MDS_KBDC_TREE_COMMON;
/**
* The first child node, `.inner.next`
* is used to access the second child node.
*/
mds_kbdc_tree_t *inner;
MDS_KBDC_TREE_PADDING(1);
};
/**
* Tree structure for the "information"-keyword
*/
typedef struct mds_kbdc_tree_nesting mds_kbdc_tree_information_t;
/**
* This datastructure is not meant to be
* used directly, it is a common definition
* for the tree structurs for the information
* entries: the children of `mds_kbdc_tree_information_t`
*/
struct mds_kbdc_tree_information_data {
MDS_KBDC_TREE_COMMON;
/**
* The value of the information entry
*/
char *data;
MDS_KBDC_TREE_PADDING(1);
};
/**
* Declaration of one of the languages for which the layout is designed
*/
typedef struct mds_kbdc_tree_information_data mds_kbdc_tree_information_language_t;
/**
* Declaration of one of the country for which the layout is designed
*/
typedef struct mds_kbdc_tree_information_data mds_kbdc_tree_information_country_t;
/**
* Declaration of which variant of the language–country the layout is
*/
typedef struct mds_kbdc_tree_information_data mds_kbdc_tree_information_variant_t;
/**
* Leaf structure for inclusion of a file
*/
typedef struct mds_kbdc_tree_include {
MDS_KBDC_TREE_COMMON;
/**
* The included layout code tree
*/
mds_kbdc_tree_t *inner;
/**
* The filename of the file to include
*/
char *filename;
/**
* The source code of the file included by this statement
*/
mds_kbdc_source_code_t* source_code;
MDS_KBDC_TREE_PADDING(3);
} mds_kbdc_tree_include_t;
/**
* This datastructure is not meant to be
* used directly, it is a common definition
* for tree structurs that define a callable
* element
*/
struct mds_kbdc_tree_callable {
MDS_KBDC_TREE_COMMON;
/**
* The first child node, `.inner.next`
* is used to access the second child node
*/
mds_kbdc_tree_t *inner;
/* It is important that `.inner` is first because
* it is first in `struct mds_kbdc_tree_nesting`
* too which means that `.inner` has to same
* offset everyever (except in `mds_kbdc_tree_if_t`).
*/
/**
* The name of the callable
*/
char *name;
MDS_KBDC_TREE_PADDING(2);
};
/**
* Tree structure for a function
*/
typedef struct mds_kbdc_tree_callable mds_kbdc_tree_function_t;
/**
* Tree structure for a macro
*/
typedef struct mds_kbdc_tree_callable mds_kbdc_tree_macro_t;
/**
* Tree structure for the "assumption"-keyword
*/
typedef struct mds_kbdc_tree_nesting mds_kbdc_tree_assumption_t;
/**
* Tree structure for making the assumption
* that there is a mapping to a key or string
*/
typedef struct mds_kbdc_tree_assumption_have {
MDS_KBDC_TREE_COMMON;
/**
* The key or string
*/
mds_kbdc_tree_t *data;
MDS_KBDC_TREE_PADDING(1);
} mds_kbdc_tree_assumption_have_t;
/**
* Leaf structure for making the assumption
* that there are mappings to a set of characters
*/
typedef struct mds_kbdc_tree_assumption_have_chars {
MDS_KBDC_TREE_COMMON;
/**
* The characters
*/
char *chars;
MDS_KBDC_TREE_PADDING(1);
} mds_kbdc_tree_assumption_have_chars_t;
/**
* Leaf structure for making the assumption
* that there are mappings to a range of characters
*/
typedef struct mds_kbdc_tree_assumption_have_range {
MDS_KBDC_TREE_COMMON;
/**
* The first character, inclusive
*/
char *first;
/**
* The last character, inclusive
*/
char *last;
MDS_KBDC_TREE_PADDING(2);
} mds_kbdc_tree_assumption_have_range_t;
/**
* Tree structure for a "for"-loop
*/
typedef struct mds_kbdc_tree_for {
MDS_KBDC_TREE_COMMON;
/**
* The first child node, `.inner.next` is
* used to access the second child node.
* This is what should be done inside the loop.
*/
mds_kbdc_tree_t *inner;
/* It is important that `.inner` is first because
* it is first in `struct mds_kbdc_tree_nesting`
* too which means that `.inner` has to same
* offset everyever (except in `mds_kbdc_tree_if_t`).
*/
/**
* The first value to variable should take, inclusive
*/
char *first;
/**
* The last value the variable should take, inclusive
*/
char *last;
/**
* The variable
*/
char *variable;
MDS_KBDC_TREE_PADDING(4);
} mds_kbdc_tree_for_t;
/**
* Tree structure for a "if"-statement
*/
typedef struct mds_kbdc_tree_if {
MDS_KBDC_TREE_COMMON;
/**
* The condition
*/
char *condition;
/**
* This is what should be done inside
* if the condition is satisfied
*/
mds_kbdc_tree_t *inner;
/**
* This is what should be done inside
* if the condition is not satisfied
*/
mds_kbdc_tree_t *otherwise;
MDS_KBDC_TREE_PADDING(3);
} mds_kbdc_tree_if_t;
/**
* Tree structure for assigning a value to a variable,
* possibly declaring the variable in the process
*/
typedef struct mds_kbdc_tree_let {
MDS_KBDC_TREE_COMMON;
/**
* The variable
*/
char *variable;
/**
* The value to assign to the variable
*/
mds_kbdc_tree_t *value;
MDS_KBDC_TREE_PADDING(2);
} mds_kbdc_tree_let_t;
/**
* Tree structure for mapping a (possible single element)
* sequence of key combinations or strings to another
* combination or string or sequence thereof
*
* Inside functions this can be used for the return value,
* in such case `sequence` should not be `NULL` but
* `sequence.next` and `result` should be `NULL`
*/
typedef struct mds_kbdc_tree_map {
MDS_KBDC_TREE_COMMON;
/**
* The input sequence
*/
mds_kbdc_tree_t *sequence;
/**
* The output sequence
*/
mds_kbdc_tree_t *result;
/*
* These are ordered so that `mds_kbdc_tree_t.macro_call.arguments`
* and `mds_kbdc_tree_t.map.sequence` have the same address.
*/
MDS_KBDC_TREE_PADDING(2);
} mds_kbdc_tree_map_t;
/**
* Tree structure for an array of values
*/
typedef struct mds_kbdc_tree_array {
MDS_KBDC_TREE_COMMON;
/**
* The first value, `.elements.next`
* is used to access the second value.
*/
mds_kbdc_tree_t *elements;
MDS_KBDC_TREE_PADDING(1);
} mds_kbdc_tree_array_t;
/**
* Leaf structure for a key-combination
*/
typedef struct mds_kbdc_tree_keys {
MDS_KBDC_TREE_COMMON;
/**
* The key-combination
*/
char *keys;
MDS_KBDC_TREE_PADDING(1);
} mds_kbdc_tree_keys_t;
/**
* Leaf structure for a string
*/
typedef struct mds_kbdc_tree_string {
MDS_KBDC_TREE_COMMON;
/**
* The string
*/
char *string;
/*
* `evaluate_element` in "compile-layout.c" utilises
* that `mds_kbdc_tree_string.string` has the same
* offset as `mds_kbdc_tree_keys.keys`.
*/
MDS_KBDC_TREE_PADDING(1);
} mds_kbdc_tree_string_t;
/**
* Leaf structure for a compiled key-combination
*/
typedef struct mds_kbdc_tree_compiled_keys {
MDS_KBDC_TREE_COMMON;
/**
* The key-combination
*
* Strictly terminated by -1
*/
char32_t *keys;
MDS_KBDC_TREE_PADDING(1);
} mds_kbdc_tree_compiled_keys_t;
/**
* Leaf structure for a compiled string
*/
typedef struct mds_kbdc_tree_compiled_string {
MDS_KBDC_TREE_COMMON;
/**
* The string
*/
char32_t *string;
/*
* `evaluate_element` in "compile-layout.c" utilises
* that `mds_kbdc_tree_string.compiled_string` has the
* same offset as `mds_kbdc_tree_keys.compiled_keys`.
*/
MDS_KBDC_TREE_PADDING(1);
} mds_kbdc_tree_compiled_string_t;
/**
* Leaf structure for nothing (a dot in the layout code)
*
* Other leaf structures without any content may `typedef`
* this structure
*/
typedef struct mds_kbdc_tree_nothing {
MDS_KBDC_TREE_COMMON;
MDS_KBDC_TREE_PADDING(0);
} mds_kbdc_tree_nothing_t;
/**
* Tree structure for an alternation
*/
typedef struct mds_kbdc_tree_nesting mds_kbdc_tree_alternation_t;
/**
* Tree structure for an unordered sequence
*/
typedef struct mds_kbdc_tree_nesting mds_kbdc_tree_unordered_t;
/**
* Tree structure for an ordered sequence
*
* This is intended has an auxiliary type for
* simplifying trees
*/
typedef struct mds_kbdc_tree_nesting mds_kbdc_tree_ordered_t;
/**
* Tree structure for a macro call
*/
typedef struct mds_kbdc_tree_macro_call {
MDS_KBDC_TREE_COMMON;
/**
* The first input argument for the
* macro call, the second is accessed
* using `.arguments.next`
*/
mds_kbdc_tree_t *arguments;
/**
* The name of the macro
*/
char *name;
/*
* These are ordered so that `mds_kbdc_tree_t.macro_call.arguments`
* and `mds_kbdc_tree_t.map.sequence` have the same address.
*/
MDS_KBDC_TREE_PADDING(2);
} mds_kbdc_tree_macro_call_t;
/**
* Leaf structure for "return"-keyword
*/
typedef struct mds_kbdc_tree_nothing mds_kbdc_tree_return_t;
/**
* Leaf structure for "break"-keyword
*/
typedef struct mds_kbdc_tree_nothing mds_kbdc_tree_break_t;
/**
* Leaf structure for "continue"-keyword
*/
typedef struct mds_kbdc_tree_nothing mds_kbdc_tree_continue_t;
/**
* Keyboard layout syntax tree
*/
union mds_kbdc_tree {
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wpedantic" /* unnamed struct */
#endif
struct {
MDS_KBDC_TREE_COMMON;
MDS_KBDC_TREE_PADDING(0);
};
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif
mds_kbdc_tree_information_t information;
mds_kbdc_tree_information_language_t language;
mds_kbdc_tree_information_country_t country;
mds_kbdc_tree_information_variant_t variant;
mds_kbdc_tree_include_t include;
mds_kbdc_tree_function_t function;
mds_kbdc_tree_macro_t macro;
mds_kbdc_tree_assumption_t assumption;
mds_kbdc_tree_assumption_have_t have;
mds_kbdc_tree_assumption_have_chars_t have_chars;
mds_kbdc_tree_assumption_have_range_t have_range;
mds_kbdc_tree_for_t for_;
mds_kbdc_tree_if_t if_;
mds_kbdc_tree_let_t let;
mds_kbdc_tree_map_t map;
mds_kbdc_tree_array_t array;
mds_kbdc_tree_keys_t keys;
mds_kbdc_tree_string_t string;
mds_kbdc_tree_compiled_keys_t compiled_keys;
mds_kbdc_tree_compiled_string_t compiled_string;
mds_kbdc_tree_nothing_t nothing;
mds_kbdc_tree_alternation_t alternation;
mds_kbdc_tree_unordered_t unordered;
mds_kbdc_tree_ordered_t ordered;
mds_kbdc_tree_macro_call_t macro_call;
mds_kbdc_tree_return_t return_;
mds_kbdc_tree_break_t break_;
mds_kbdc_tree_continue_t continue_;
};
/**
* Initialise a tree node
*
* @param this The memory slot for the tree node
* @param type The type of the node
*/
void mds_kbdc_tree_initialise(mds_kbdc_tree_t *restrict this, int type);
/**
* Create a tree node
*
* @param type The type of the node
* @return The tree node, `NULL` on error
*/
mds_kbdc_tree_t *mds_kbdc_tree_create(int type);
/**
* Release all resources stored in a tree node,
* without freeing the node itself or freeing
* or destroying inner `mds_kbdc_tree_t*`:s
*
* @param this The tree node
*/
void mds_kbdc_tree_destroy_nonrecursive(mds_kbdc_tree_t *restrict this);
/**
* Release all resources stored in a tree node,
* without freeing or destroying inner
* `mds_kbdc_tree_t*`:s, but free this node's
* allocation
*
* @param this The tree node
*/
void mds_kbdc_tree_free_nonrecursive(mds_kbdc_tree_t *restrict this);
/**
* Release all resources stored in a tree node
* recursively, but do not free the allocation
* of the tree node
*
* @param this The tree node
*/
void mds_kbdc_tree_destroy(mds_kbdc_tree_t *restrict this);
/**
* Release all resources stored in a tree node
* recursively, and free the allocation
* of the tree node
*
* @param this The tree node
*/
void mds_kbdc_tree_free(mds_kbdc_tree_t *restrict this);
/**
* Create a duplicate of a tree node and
* its children
*
* @param this The tree node
* @return A duplicate of `this`, `NULL` on error
*/
mds_kbdc_tree_t *mds_kbdc_tree_dup(const mds_kbdc_tree_t *restrict this);
/**
* Print a tree into a file
*
* @param this The tree node
* @param output The output file
*/
void mds_kbdc_tree_print(const mds_kbdc_tree_t *restrict this, FILE *output);
#undef MDS_KBDC_TREE_PADDING
#undef MDS_KBDC_TREE_PADDING_
#undef MDS_KBDC_TREE_COMMON
#endif