/**
* mds — A micro-display server
* Copyright © 2014 Mattias Andrée (maandree@member.fsf.org)
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef MDS_MDS_KBDC_INCLUDE_STACK_H
#define MDS_MDS_KBDC_INCLUDE_STACK_H
#include "parsed.h"
/**
* Add an error to the error list
*
* @param NODE:const mds_kbdc_tree_t* The node the triggered the error
* @param SEVERITY:identifier * in `MDS_KBDC_PARSE_ERROR_*` to indicate severity
* @param ...:const char*, ... Error description format string and arguments
* @scope error:mds_kbdc_parse_error_t* Variable where the new error will be stored
*/
#define NEW_ERROR_WITHOUT_INCLUDES(NODE, SEVERITY, ...) \
NEW_ERROR_(result, SEVERITY, 1, (NODE)->loc_line, \
(NODE)->loc_start, (NODE)->loc_end, 1, __VA_ARGS__)
/**
* Add “included from here”-notes
*
* @param PTR:size_t The number of “included from here”-notes
*/
#define DUMP_INCLUDE_STACK(PTR) \
fail_if (mds_kbdc_include_stack_dump(PTR))
/**
* Add an error with “included from here”-notes to the error list
*
* @param NODE:const mds_kbdc_tree_t* The node the triggered the error
* @param PTR:size_t The number of “included from here”-notes
* @param SEVERITY:identifier * in `MDS_KBDC_PARSE_ERROR_*` to indicate severity
* @param ...:const char*, ... Error description format string and arguments
* @scope error:mds_kbdc_parse_error_t* Variable where the new error will be stored
*/
#define NEW_ERROR_WITH_INCLUDES(NODE, PTR, SEVERITY, ...) \
do \
{ \
NEW_ERROR_WITHOUT_INCLUDES(NODE, SEVERITY, __VA_ARGS__); \
DUMP_INCLUDE_STACK(PTR); \
} \
while (0)
/**
* A saved state of the include stack
*/
typedef struct mds_kbdc_include_stack
{
/**
* Stack of visited include-statements
*/
const mds_kbdc_tree_include_t** stack;
/**
* The number elements stored in `stack` (do not edit)
*/
size_t ptr;
/**
* The number of duplicates there are of this object
*/
size_t duplicates;
} mds_kbdc_include_stack_t;
/**
* The number elements stored by `mds_kbdc_include_stack_push`
* but not removed by `mds_kbdc_include_stack_pop`
*/
extern size_t includes_ptr;
/**
* Add “included from here”-notes
*
* @param ptr The number of “included from here”-notes
* @return Zero on success, -1 on error
*/
int mds_kbdc_include_stack_dump(size_t ptr);
/**
* Mark the root of the tree as included
*
* @param result The `result` parameter of root procedure that requires the include stack
*/
void mds_kbdc_include_stack_begin(mds_kbdc_parsed_t* restrict result);
/**
* Mark the root of the tree as no longer being visited,
* and release clean up after the use of this module
*/
void mds_kbdc_include_stack_end(void);
/**
* Mark an include-statement as visited
*
* @param tree The visisted include-statement
* @param data Output parameter with stack information that should be passed to
* the corresponding call to `mds_kbdc_include_stack_pop`, `*data`
* is undefined on error
* @return Zero on success, -1 on error
*/
int mds_kbdc_include_stack_push(const mds_kbdc_tree_include_t* restrict tree, void** data);
/**
* Undo the lasted not-undone call to `mds_kbdc_include_stack_push`
*
* This function is guaranteed not to modify `errno`
*
* @param data `*data` from `mds_kbdc_include_stack_push`
*/
void mds_kbdc_include_stack_pop(void* data);
/**
* Save the current include-stack
*
* @return The include-stack, `NULL` on error
*/
mds_kbdc_include_stack_t* mds_kbdc_include_stack_save(void);
/**
* Restore a previous include-stack
*
* @param stack The include-stack
* @return Zero on success, -1 on error
*/
int mds_kbdc_include_stack_restore(mds_kbdc_include_stack_t* restrict stack);
/**
* Destroy a previous include-stack and free its allocation
*
* @param stack The include-stack
*/
void mds_kbdc_include_stack_free(mds_kbdc_include_stack_t* restrict stack);
#endif