All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			changed multiple open functions to accept hawk_errinfo_t* instead of hawk_errnum_t*
		
			
				
	
	
		
			935 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			935 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|     Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved.
 | |
| 
 | |
|     Redistribution and use in source and binary forms, with or without
 | |
|     modification, are permitted provided that the following conditions
 | |
|     are met:
 | |
|     1. Redistributions of source code must retain the above copyright
 | |
|        notice, this list of conditions and the following disclaimer.
 | |
|     2. Redistributions in binary form must reproduce the above copyright
 | |
|        notice, this list of conditions and the following disclaimer in the
 | |
|        documentation and/or other materials provided with the distribution.
 | |
| 
 | |
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
 | |
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 | |
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | |
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | |
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | |
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | |
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #ifndef _HAWK_SED_H_
 | |
| #define _HAWK_SED_H_
 | |
| 
 | |
| #include <hawk-cmn.h>
 | |
| #include <hawk-gem.h>
 | |
| #include <hawk-sio.h>
 | |
| 
 | |
| /** \file
 | |
|  * This file defines data types and functions to use for creating a custom
 | |
|  * stream editor commonly available on many platforms. A stream editor is
 | |
|  * a non-interactive text editing tool that reads text from an input stream,
 | |
|  * stores it to pattern space, manipulates the pattern space by applying a set
 | |
|  * of editing commands, and writes the pattern space to an output stream.
 | |
|  * Typically, the input and output streams are a console or a file.
 | |
|  *
 | |
|  * \code
 | |
|  * sed = hawk_sed_open ();
 | |
|  * hawk_sed_comp (sed);
 | |
|  * hawk_sed_exec (sed);
 | |
|  * hawk_sed_close (sed);
 | |
|  * \endcode
 | |
|  */
 | |
| 
 | |
| /** \struct hawk_sed_t
 | |
|  * The hawk_sed_t type defines a stream editor. The structural details are
 | |
|  * hidden as it is a relatively complex data type and fragile to external
 | |
|  * changes. To use a stream editor, you typically can:
 | |
|  *
 | |
|  * - create a stream editor object with hawk_sed_open().
 | |
|  * - compile stream editor commands with hawk_sed_comp().
 | |
|  * - execute them over input and output streams with hawk_sed_exec().
 | |
|  * - destroy it with hawk_sed_close() when done.
 | |
|  *
 | |
|  * The input and output streams needed by hawk_sed_exec() are implemented in
 | |
|  * the form of callback functions. You should implement two functions
 | |
|  * conforming to the ::hawk_sed_io_impl_t type.
 | |
|  */
 | |
| typedef struct hawk_sed_t hawk_sed_t;
 | |
| 
 | |
| #define HAWK_SED_HDR \
 | |
| 	hawk_oow_t _instsize; \
 | |
| 	hawk_gem_t _gem
 | |
| 
 | |
| typedef struct hawk_sed_alt_t hawk_sed_alt_t;
 | |
| struct hawk_sed_alt_t
 | |
| {
 | |
| 	/* ensure that hawk_sed_alt_t matches the beginning part of hawk_sed_t */
 | |
| 	HAWK_SED_HDR;
 | |
| };
 | |
| 
 | |
| typedef struct hawk_sed_adr_t hawk_sed_adr_t;
 | |
| typedef struct hawk_sed_cmd_t hawk_sed_cmd_t;
 | |
| 
 | |
| struct hawk_sed_adr_t
 | |
| {
 | |
| 	enum
 | |
| 	{
 | |
| 		HAWK_SED_ADR_NONE,     /* no address */
 | |
| 		HAWK_SED_ADR_DOL,      /* $ - last line */
 | |
| 		HAWK_SED_ADR_LINE,     /* specified line */
 | |
| 		HAWK_SED_ADR_REX,      /* lines matching regular expression */
 | |
| 		HAWK_SED_ADR_STEP,     /* line steps - only in the second address */
 | |
| 		HAWK_SED_ADR_RELLINE,  /* relative line - only in second address */
 | |
| 		HAWK_SED_ADR_RELLINEM  /* relative line in the multiples - only in second address */
 | |
| 	} type;
 | |
| 
 | |
| 	union
 | |
| 	{
 | |
| 		hawk_oow_t lno;
 | |
| 		void*      rex;
 | |
| 	} u;
 | |
| };
 | |
| 
 | |
| typedef struct hawk_sed_cut_sel_t hawk_sed_cut_sel_t;
 | |
| 
 | |
| struct hawk_sed_cut_sel_t
 | |
| {
 | |
| 	hawk_oow_t len;
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		enum
 | |
| 		{
 | |
| 			HAWK_SED_CUT_SEL_CHAR = HAWK_T('c'),
 | |
| 			HAWK_SED_CUT_SEL_FIELD = HAWK_T('f')
 | |
| 		} id;
 | |
| 		hawk_oow_t start;
 | |
| 		hawk_oow_t end;
 | |
| 	} range[128];
 | |
| 
 | |
| 	hawk_sed_cut_sel_t* next;
 | |
| };
 | |
| 
 | |
| #define HAWK_SED_CMD_NOOP            HAWK_T('\0')
 | |
| #define HAWK_SED_CMD_QUIT            HAWK_T('q')
 | |
| #define HAWK_SED_CMD_QUIT_QUIET      HAWK_T('Q')
 | |
| #define HAWK_SED_CMD_APPEND          HAWK_T('a')
 | |
| #define HAWK_SED_CMD_INSERT          HAWK_T('i')
 | |
| #define HAWK_SED_CMD_CHANGE          HAWK_T('c')
 | |
| #define HAWK_SED_CMD_DELETE          HAWK_T('d')
 | |
| #define HAWK_SED_CMD_DELETE_FIRSTLN  HAWK_T('D')
 | |
| #define HAWK_SED_CMD_PRINT_LNNUM     HAWK_T('=')
 | |
| #define HAWK_SED_CMD_PRINT           HAWK_T('p')
 | |
| #define HAWK_SED_CMD_PRINT_FIRSTLN   HAWK_T('P')
 | |
| #define HAWK_SED_CMD_PRINT_CLEARLY   HAWK_T('l')
 | |
| #define HAWK_SED_CMD_HOLD            HAWK_T('h')
 | |
| #define HAWK_SED_CMD_HOLD_APPEND     HAWK_T('H')
 | |
| #define HAWK_SED_CMD_RELEASE         HAWK_T('g')
 | |
| #define HAWK_SED_CMD_RELEASE_APPEND  HAWK_T('G')
 | |
| #define HAWK_SED_CMD_EXCHANGE        HAWK_T('x')
 | |
| #define HAWK_SED_CMD_NEXT            HAWK_T('n')
 | |
| #define HAWK_SED_CMD_NEXT_APPEND     HAWK_T('N')
 | |
| #define HAWK_SED_CMD_READ_FILE       HAWK_T('r')
 | |
| #define HAWK_SED_CMD_READ_FILELN     HAWK_T('R')
 | |
| #define HAWK_SED_CMD_WRITE_FILE      HAWK_T('w')
 | |
| #define HAWK_SED_CMD_WRITE_FILELN    HAWK_T('W')
 | |
| #define HAWK_SED_CMD_BRANCH          HAWK_T('b')
 | |
| #define HAWK_SED_CMD_BRANCH_COND     HAWK_T('t')
 | |
| #define HAWK_SED_CMD_SUBSTITUTE      HAWK_T('s')
 | |
| #define HAWK_SED_CMD_TRANSLATE       HAWK_T('y')
 | |
| #define HAWK_SED_CMD_CLEAR_PATTERN   HAWK_T('z')
 | |
| #define HAWK_SED_CMD_CUT             HAWK_T('C')
 | |
| 
 | |
| struct hawk_sed_cmd_t
 | |
| {
 | |
| 	hawk_ooch_t type;
 | |
| 
 | |
| 	const hawk_ooch_t* lid;
 | |
| 	hawk_loc_t     loc;
 | |
| 
 | |
| 	int negated;
 | |
| 
 | |
| 	hawk_sed_adr_t a1; /* optional start address */
 | |
| 	hawk_sed_adr_t a2; /* optional end address */
 | |
| 
 | |
| 	union
 | |
| 	{
 | |
| 		/* text for the a, i, c commands */
 | |
| 		hawk_oocs_t text;
 | |
| 
 | |
| 		/* file name for r, w, R, W */
 | |
| 		hawk_oocs_t file;
 | |
| 
 | |
| 		/* data for the s command */
 | |
| 		struct
 | |
| 		{
 | |
| 			void* rex; /* regular expression */
 | |
| 			hawk_oocs_t rpl;  /* replacement */
 | |
| 
 | |
| 			/* flags */
 | |
| 			hawk_oocs_t file; /* file name for w */
 | |
| 			unsigned short occ;
 | |
| 			unsigned short g: 1; /* global */
 | |
| 			unsigned short p: 1; /* print */
 | |
| 			unsigned short i: 1; /* case insensitive */
 | |
| 			unsigned short k: 1; /* kill unmatched portion */
 | |
| 		} subst;
 | |
| 
 | |
| 		/* translation set for the y command */
 | |
| 		hawk_oocs_t transet;
 | |
| 
 | |
| 		/* branch target for b and t */
 | |
| 		struct
 | |
| 		{
 | |
| 			hawk_oocs_t label;
 | |
| 			hawk_sed_cmd_t* target;
 | |
| 		} branch;
 | |
| 
 | |
| 		/* cut command information */
 | |
| 		struct
 | |
| 		{
 | |
| 			hawk_sed_cut_sel_t* fb;/**< points to the first block */
 | |
| 			hawk_sed_cut_sel_t* lb; /**< points to the last block */
 | |
| 
 | |
| 			hawk_ooch_t         delim[2]; /**< input/output field delimiters */
 | |
| 			unsigned short     w: 1; /* whitespace for input delimiters. ignore delim[0]. */
 | |
| 			unsigned short     f: 1; /* fold delimiters */
 | |
| 			unsigned short     d: 1; /* delete if not delimited */
 | |
| 
 | |
| 			hawk_oow_t         count;
 | |
| 			hawk_oow_t         fcount;
 | |
| 			hawk_oow_t         ccount;
 | |
| 		} cut;
 | |
| 	} u;
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		int a1_matched;
 | |
| 		hawk_oow_t a1_match_line;
 | |
| 
 | |
| 		int c_ready;
 | |
| 
 | |
| 		/* points to the next command for fast traversal and
 | |
| 		 * fast random jumps */
 | |
| 		hawk_sed_cmd_t* next;
 | |
| 	} state;
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_opt_t type defines various option types.
 | |
|  */
 | |
| enum hawk_sed_opt_t
 | |
| {
 | |
| 	HAWK_SED_TRAIT,      /**< trait */
 | |
| 	HAWK_SED_TRACER,     /**< tracer hook */
 | |
| 	HAWK_SED_LFORMATTER, /**< formatter for the 'l' command */
 | |
| 
 | |
| 	HAWK_SED_DEPTH_REX_BUILD,
 | |
| 	HAWK_SED_DEPTH_REX_MATCH
 | |
| };
 | |
| typedef enum hawk_sed_opt_t hawk_sed_opt_t;
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_trait_t type defines various trait codes for a stream editor.
 | |
|  * Options can be OR'ed with each other and be passed to a stream editor with
 | |
|  * the hawk_sed_setopt() function.
 | |
|  */
 | |
| enum hawk_sed_trait_t
 | |
| {
 | |
| 	HAWK_SED_STRIPLS      = (1 << 0), /**< strip leading spaces from text */
 | |
| 	HAWK_SED_KEEPTBS      = (1 << 1), /**< keep an trailing backslash */
 | |
| 	HAWK_SED_ENSURENL     = (1 << 2), /**< ensure NL at the text end */
 | |
| 	HAWK_SED_QUIET        = (1 << 3), /**< do not print pattern space */
 | |
| 	HAWK_SED_STRICT       = (1 << 4), /**< do strict address and label check */
 | |
| 	HAWK_SED_EXTENDEDADR  = (1 << 5), /**< allow start~step , addr1,+line, addr1,~line */
 | |
| 	HAWK_SED_SAMELINE     = (1 << 7), /**< allow text on the same line as c, a, i */
 | |
| 	HAWK_SED_EXTENDEDREX  = (1 << 8), /**< use extended regex */
 | |
| 	HAWK_SED_NONSTDEXTREX = (1 << 9)  /**< enable non-standard extensions to regex */
 | |
| };
 | |
| typedef enum hawk_sed_trait_t hawk_sed_trait_t;
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_io_cmd_t type defines I/O command codes. The code indicates
 | |
|  * the action to take in an I/O handler.
 | |
|  */
 | |
| enum hawk_sed_io_cmd_t
 | |
| {
 | |
| 	HAWK_SED_IO_OPEN  = 0,
 | |
| 	HAWK_SED_IO_CLOSE = 1,
 | |
| 	HAWK_SED_IO_READ  = 2,
 | |
| 	HAWK_SED_IO_WRITE = 3
 | |
| };
 | |
| typedef enum hawk_sed_io_cmd_t hawk_sed_io_cmd_t;
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_io_arg_t type defines a data structure required by
 | |
|  * an I/O handler.
 | |
|  */
 | |
| struct hawk_sed_io_arg_t
 | |
| {
 | |
| 	void*             handle; /**< I/O handle */
 | |
| 	const hawk_ooch_t* path;   /**< file path. HAWK_NULL for a console */
 | |
| };
 | |
| typedef struct hawk_sed_io_arg_t hawk_sed_io_arg_t;
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_io_impl_t type defines an I/O handler. I/O handlers are called by
 | |
|  * hawk_sed_exec().
 | |
|  */
 | |
| typedef hawk_ooi_t (*hawk_sed_io_impl_t) (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	hawk_sed_io_cmd_t  cmd,
 | |
| 	hawk_sed_io_arg_t* arg,
 | |
| 	hawk_ooch_t*       data,
 | |
| 	hawk_oow_t         count
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_lformatter_t type defines a text formatter for the 'l' command.
 | |
|  */
 | |
| typedef int (*hawk_sed_lformatter_t) (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	const hawk_ooch_t* str,
 | |
| 	hawk_oow_t        len,
 | |
| 	int (*cwriter) (hawk_sed_t*, hawk_ooch_t)
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_ecb_close_t type defines the callback function
 | |
|  * called when an sed object is closed.
 | |
|  */
 | |
| typedef void (*hawk_sed_ecb_close_t) (
 | |
| 	hawk_sed_t* sed,  /**< sed */
 | |
| 	void*       ctx
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_ecb_t type defines an event callback set.
 | |
|  * You can register a callback function set with
 | |
|  * hawk_sed_pushecb().  The callback functions in the registered
 | |
|  * set are called in the reverse order of registration.
 | |
|  */
 | |
| typedef struct hawk_sed_ecb_t hawk_sed_ecb_t;
 | |
| struct hawk_sed_ecb_t
 | |
| {
 | |
| 	/**
 | |
| 	 * called by hawk_sed_close().
 | |
| 	 */
 | |
| 	hawk_sed_ecb_close_t close;
 | |
| 	void* ctx;
 | |
| 
 | |
| 	/* internal use only. don't touch this field */
 | |
| 	hawk_sed_ecb_t* next;
 | |
| };
 | |
| 
 | |
| enum hawk_sed_tracer_op_t
 | |
| {
 | |
| 	HAWK_SED_TRACER_READ,
 | |
| 	HAWK_SED_TRACER_WRITE,
 | |
| 	HAWK_SED_TRACER_MATCH,
 | |
| 	HAWK_SED_TRACER_EXEC
 | |
| };
 | |
| typedef enum hawk_sed_tracer_op_t hawk_sed_tracer_op_t;
 | |
| 
 | |
| typedef void (*hawk_sed_tracer_t) (
 | |
| 	hawk_sed_t*           sed,
 | |
| 	hawk_sed_tracer_op_t  op,
 | |
| 	const hawk_sed_cmd_t* cmd
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_space_t type defines the types of
 | |
|  * sed bufferspaces.
 | |
|  */
 | |
| enum hawk_sed_space_t
 | |
| {
 | |
| 	HAWK_SED_SPACE_HOLD,   /**< hold space */
 | |
| 	HAWK_SED_SPACE_PATTERN /**< pattern space */
 | |
| };
 | |
| typedef enum hawk_sed_space_t hawk_sed_space_t;
 | |
| 
 | |
| 
 | |
| /* ------------------------------------------------------------------------ */
 | |
| 
 | |
| /**
 | |
|  * This section defines easier-to-use helper interface for a stream editor.
 | |
|  * If you don't care about the details of memory management and I/O handling,
 | |
|  * you can choose to use the helper functions provided here. It is
 | |
|  * a higher-level interface that is easier to use as it implements
 | |
|  * default handlers for I/O and memory management.
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_iostd_type_t type defines types of standard
 | |
|  * I/O resources.
 | |
|  */
 | |
| enum hawk_sed_iostd_type_t
 | |
| {
 | |
| 	HAWK_SED_IOSTD_NULL,  /**< null resource type */
 | |
| 	HAWK_SED_IOSTD_FILE,  /**< file */
 | |
| 	HAWK_SED_IOSTD_FILEB, /**< file */
 | |
| 	HAWK_SED_IOSTD_FILEU, /**< file */
 | |
| 	HAWK_SED_IOSTD_OOCS,  /**< string  */
 | |
| 	HAWK_SED_IOSTD_BCS,
 | |
| 	HAWK_SED_IOSTD_UCS,
 | |
| 	HAWK_SED_IOSTD_SIO    /**< sio */
 | |
| };
 | |
| typedef enum hawk_sed_iostd_type_t hawk_sed_iostd_type_t;
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_iostd_t type defines a standard I/O resource.
 | |
|  */
 | |
| struct hawk_sed_iostd_t
 | |
| {
 | |
| 	/** resource type */
 | |
| 	hawk_sed_iostd_type_t type;
 | |
| 
 | |
| 	/** union describing the resource of the specified type */
 | |
| 	union
 | |
| 	{
 | |
| 		/** file path with character encoding */
 | |
| 		struct
 | |
| 		{
 | |
| 			/** file path to open. #HAWK_NULL or '-' for stdin/stdout. */
 | |
| 			const hawk_ooch_t* path;
 | |
| 			/** a stream created with the file path is set with this
 | |
| 			 * cmgr if it is not #HAWK_NULL. */
 | |
| 			hawk_cmgr_t* cmgr;
 | |
| 		} file;
 | |
| 
 | |
| 		struct
 | |
| 		{
 | |
| 			const hawk_bch_t* path;
 | |
| 			hawk_cmgr_t* cmgr;
 | |
| 		} fileb;
 | |
| 
 | |
| 		struct
 | |
| 		{
 | |
| 			const hawk_uch_t* path;
 | |
| 			hawk_cmgr_t* cmgr;
 | |
| 		} fileu;
 | |
| 
 | |
| 		/**
 | |
| 		 * input string or dynamically allocated output string
 | |
| 		 *
 | |
| 		 * For input, the ptr and the len field of str indicates the
 | |
| 		 * pointer and the length of a string to read. You must set
 | |
| 		 * these two fields before calling hawk_sed_execstd().
 | |
| 		 *
 | |
| 		 * For output, the ptr and the len field of str indicates the
 | |
| 		 * pointer and the length of produced output. The output
 | |
| 		 * string is dynamically allocated. You don't need to set these
 | |
| 		 * fields before calling hawk_sed_execstd() because they are
 | |
| 		 * set by hawk_sed_execstd() and valid while the relevant sed
 | |
| 		 * object is alive. You must free the memory chunk pointed to by
 | |
| 		 * the ptr field with hawk_sed_freemem() once you're done with it
 | |
| 		 * to avoid memory leaks.
 | |
| 		 */
 | |
| 		hawk_oocs_t        oocs;
 | |
| 		hawk_bcs_t         bcs;
 | |
| 		hawk_ucs_t         ucs;
 | |
| 
 | |
| 		/** pre-opened sio stream */
 | |
| 		hawk_sio_t*        sio;
 | |
| 	} u;
 | |
| };
 | |
| 
 | |
| typedef struct hawk_sed_iostd_t hawk_sed_iostd_t;
 | |
| 
 | |
| /* ------------------------------------------------------------------------ */
 | |
| 
 | |
| #if defined(__cplusplus)
 | |
| extern "C" {
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_open() function creates a stream editor object. A memory
 | |
|  * manager provided is used to allocate and destory the object and any dynamic
 | |
|  * data through out its lifetime. An extension area is allocated if an
 | |
|  * extension size greater than 0 is specified. You can access it with the
 | |
|  * hawk_sed_getxtn() function and use it to store arbitrary data associated
 | |
|  * with the object.  When done, you should destroy the object with the
 | |
|  * hawk_sed_close() function to avoid any resource leaks including memory.
 | |
|  * \return pointer to a stream editor on success, HAWK_NULL on failure
 | |
|  */
 | |
| HAWK_EXPORT hawk_sed_t* hawk_sed_open (
 | |
| 	hawk_mmgr_t*   mmgr,    /**< memory manager */
 | |
| 	hawk_oow_t     xtnsize, /**< extension size in bytes */
 | |
| 	hawk_cmgr_t*   cmgr,
 | |
| 	hawk_errinf_t* errinf
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_close() function destroys a stream editor.
 | |
|  */
 | |
| HAWK_EXPORT void hawk_sed_close (
 | |
| 	hawk_sed_t* sed /**< stream editor */
 | |
| );
 | |
| 
 | |
| #if defined(HAWK_HAVE_INLINE)
 | |
| /**
 | |
|  * The hawk_sed_getxtn() function returns the pointer to the extension area
 | |
|  * placed behind the actual sed object.
 | |
|  */
 | |
| static HAWK_INLINE void* hawk_sed_getxtn (hawk_sed_t* sed) { return (void*)((hawk_uint8_t*)sed + ((hawk_sed_alt_t*)sed)->_instsize); }
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_getgem() function gets the pointer to the gem structure of the
 | |
|  * sed object.
 | |
|  */
 | |
| static HAWK_INLINE hawk_gem_t* hawk_sed_getgem (hawk_sed_t* sed) { return &((hawk_sed_alt_t*)sed)->_gem; }
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_getmmgr() function gets the memory manager used in
 | |
|  * hawk_sed_open().
 | |
|  */
 | |
| static HAWK_INLINE hawk_mmgr_t* hawk_sed_getmmgr (hawk_sed_t* sed) { return ((hawk_sed_alt_t*)sed)->_gem.mmgr; }
 | |
| static HAWK_INLINE hawk_cmgr_t* hawk_sed_getcmgr (hawk_sed_t* sed) { return ((hawk_sed_alt_t*)sed)->_gem.cmgr; }
 | |
| static HAWK_INLINE void hawk_sed_setcmgr (hawk_sed_t* sed, hawk_cmgr_t* cmgr) { ((hawk_sed_alt_t*)sed)->_gem.cmgr = cmgr; }
 | |
| #else
 | |
| #define hawk_sed_getxtn(sed) ((void*)((hawk_uint8_t*)sed + ((hawk_sed_alt_t*)sed)->_instsize))
 | |
| #define hawk_sed_getgem(sed) (&((hawk_sed_alt_t*)(sed))->_gem)
 | |
| #define hawk_sed_getmmgr(sed) (((hawk_sed_alt_t*)(sed))->_gem.mmgr)
 | |
| #define hawk_sed_getcmgr(sed) (((hawk_sed_alt_t*)(sed))->_gem.cmgr)
 | |
| #define hawk_sed_setcmgr(sed,_cmgr) (((hawk_sed_alt_t*)(sed))->_gem.cmgr = (_cmgr))
 | |
| #endif /* HAWK_HAVE_INLINE */
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_getopt() function gets the value of an option
 | |
|  * specified by \a id into the buffer pointed to by \a value.
 | |
|  *
 | |
|  * The \a value field is dependent on \a id:
 | |
|  *  - #HAWK_SED_TRAIT - int*, 0 or bitwised-ORed of #hawk_sed_trait_t values
 | |
|  *  - #HAWK_SED_TRACER - hawk_sed_tracer_t*
 | |
|  *  - #HAWK_SED_LFORMATTER - hawk_sed_lformatter_t*
 | |
|  *
 | |
|  * \return 0 on success, -1 on failure
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_getopt (
 | |
| 	hawk_sed_t*    sed,
 | |
| 	hawk_sed_opt_t id,
 | |
| 	void*         value
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_setopt() function sets the value of an option
 | |
|  * specified by \a id to the value pointed to by \a value.
 | |
|  *
 | |
|  * The \a value field is dependent on \a id:
 | |
|  *  - #HAWK_SED_TRAIT - const int*, 0 or bitwised-ORed of #hawk_sed_trait_t values
 | |
|  *  - #HAWK_SED_TRACER - hawk_sed_tracer_t
 | |
|  *  - #HAWK_SED_LFORMATTER - hawk_sed_lformatter_t
 | |
|  *
 | |
|  * \return 0 on success, -1 on failure
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_setopt (
 | |
| 	hawk_sed_t*    sed,
 | |
| 	hawk_sed_opt_t id,
 | |
| 	const void*   value
 | |
| );
 | |
| 
 | |
| HAWK_EXPORT hawk_errstr_t hawk_sed_geterrstr (
 | |
| 	hawk_sed_t* sed
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_geterrnum() function returns the number of the last error
 | |
|  * occurred.
 | |
|  * \return error number
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_geterror() function gets an error number, an error location,
 | |
|  * and an error message. The information is set to the memory area pointed
 | |
|  * to by each parameter.
 | |
|  */
 | |
| #if defined(HAWK_HAVE_INLINE)
 | |
| static HAWK_INLINE hawk_errnum_t hawk_sed_geterrnum (hawk_sed_t* sed) { return hawk_gem_geterrnum(hawk_sed_getgem(sed)); }
 | |
| static HAWK_INLINE const hawk_loc_t* hawk_sed_geterrloc (hawk_sed_t* sed) { return hawk_gem_geterrloc(hawk_sed_getgem(sed)); }
 | |
| static HAWK_INLINE const hawk_bch_t* hawk_sed_geterrbmsg (hawk_sed_t* sed) { return hawk_gem_geterrbmsg(hawk_sed_getgem(sed)); }
 | |
| static HAWK_INLINE const hawk_uch_t* hawk_sed_geterrumsg (hawk_sed_t* sed) { return hawk_gem_geterrumsg(hawk_sed_getgem(sed)); }
 | |
| static HAWK_INLINE void hawk_sed_geterrbinf (hawk_sed_t* sed, hawk_errbinf_t* errinf) { return hawk_gem_geterrbinf(hawk_sed_getgem(sed), errinf); }
 | |
| static HAWK_INLINE void hawk_sed_geterruinf (hawk_sed_t* sed, hawk_erruinf_t* errinf) { return hawk_gem_geterruinf(hawk_sed_getgem(sed), errinf); }
 | |
| static HAWK_INLINE void hawk_sed_geterror (hawk_sed_t* sed, hawk_errnum_t* errnum, const hawk_ooch_t** errmsg, hawk_loc_t* errloc) { return hawk_gem_geterror(hawk_sed_getgem(sed), errnum, errmsg, errloc); }
 | |
| #else
 | |
| #define hawk_sed_geterrnum(sed) hawk_gem_geterrnum(hawk_sed_getgem(sed))
 | |
| #define hawk_sed_geterrloc(sed) hawk_gem_geterrloc(hawk_sed_getgem(sed))
 | |
| #define hawk_sed_geterrbmsg(sed) hawk_gem_geterrbmsg(hawk_sed_getgem(sed))
 | |
| #define hawk_sed_geterrumsg(sed) hawk_gem_geterrumsg(hawk_sed_getgem(sed))
 | |
| #define hawk_sed_geterrbinf(sed, errinf) (hawk_gem_geterrbinf(hawk_sed_getgem(sed), errinf))
 | |
| #define hawk_sed_geterruinf(sed, errinf) (hawk_gem_geterruinf(hawk_sed_getgem(sed), errinf))
 | |
| #define hawk_sed_geterror(sed, errnum, errmsg, errloc) (hawk_gem_geterror(hawk_sed_getgem(sed), errnum, errmsg, errloc))
 | |
| #endif
 | |
| 
 | |
| #if defined(HAWK_OOCH_IS_BCH)
 | |
| #	define hawk_sed_geterrmsg hawk_sed_geterrbmsg
 | |
| #	define hawk_sed_geterrinf hawk_sed_geterrbinf
 | |
| #else
 | |
| #	define hawk_sed_geterrmsg hawk_sed_geterrumsg
 | |
| #	define hawk_sed_geterrinf hawk_sed_geterruinf
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_seterrnum() function sets the error information omitting
 | |
|  * error location. You must pass a non-NULL for \a errarg if the specified
 | |
|  * error number \a errnum requires one or more arguments to format an
 | |
|  * error message.
 | |
|  */
 | |
| #if defined(HAWK_HAVE_INLINE)
 | |
| static HAWK_INLINE void hawk_sed_seterrnum (hawk_sed_t* sed, const hawk_loc_t* errloc, hawk_errnum_t errnum) { hawk_gem_seterrnum (hawk_sed_getgem(sed), errloc, errnum); }
 | |
| static HAWK_INLINE void hawk_sed_seterrinf (hawk_sed_t* sed, const hawk_errinf_t* errinf) { hawk_gem_seterrinf (hawk_sed_getgem(sed), errinf); }
 | |
| static HAWK_INLINE void hawk_sed_seterror (hawk_sed_t* sed, const hawk_loc_t*  errloc, hawk_errnum_t errnum, const hawk_oocs_t* errarg) { hawk_gem_seterror(hawk_sed_getgem(sed), errloc, errnum, errarg); }
 | |
| static HAWK_INLINE const hawk_ooch_t* hawk_sed_backuperrmsg (hawk_sed_t* sed) { return hawk_gem_backuperrmsg(hawk_sed_getgem(sed)); }
 | |
| #else
 | |
| #define hawk_sed_seterrnum(sed, errloc, errnum) hawk_gem_seterrnum(hawk_sed_getgem(sed), errloc, errnum)
 | |
| #define hawk_sed_seterrinf(sed, errinf) hawk_gem_seterrinf(hawk_sed_getgem(sed), errinf)
 | |
| #define hawk_sed_seterror(sed, errloc, errnum, errarg) hawk_gem_seterror(hawk_sed_getgem(sed), errloc, errnum, errarg)
 | |
| #define hawk_sed_backuperrmsg(sed) hawk_gem_backuperrmsg(hawk_sed_getgem(sed))
 | |
| #endif
 | |
| 
 | |
| 
 | |
| HAWK_EXPORT void hawk_sed_seterrbfmt (
 | |
| 	hawk_sed_t*       sed,
 | |
| 	const hawk_loc_t* errloc,
 | |
| 	hawk_errnum_t     errnum,
 | |
| 	const hawk_bch_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| HAWK_EXPORT void hawk_sed_seterrufmt (
 | |
| 	hawk_sed_t*       sed,
 | |
| 	const hawk_loc_t* errloc,
 | |
| 	hawk_errnum_t     errnum,
 | |
| 	const hawk_uch_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| 
 | |
| HAWK_EXPORT void hawk_sed_seterrbvfmt (
 | |
| 	hawk_sed_t*         sed,
 | |
| 	const hawk_loc_t*   errloc,
 | |
| 	hawk_errnum_t       errnum,
 | |
| 	const hawk_bch_t*   errfmt,
 | |
| 	va_list             ap
 | |
| );
 | |
| 
 | |
| HAWK_EXPORT void hawk_sed_seterruvfmt (
 | |
| 	hawk_sed_t*         sed,
 | |
| 	const hawk_loc_t*   errloc,
 | |
| 	hawk_errnum_t       errnum,
 | |
| 	const hawk_uch_t*   errfmt,
 | |
| 	va_list             ap
 | |
| );
 | |
| 
 | |
| 
 | |
| HAWK_EXPORT void hawk_sed_killecb (
 | |
| 	hawk_sed_t*     sed,
 | |
| 	hawk_sed_ecb_t* ecb
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_popecb() function pops an sed event callback set
 | |
|  * and returns the pointer to it. If no callback set can be popped,
 | |
|  * it returns #HAWK_NULL.
 | |
|  */
 | |
| HAWK_EXPORT hawk_sed_ecb_t* hawk_sed_popecb (
 | |
| 	hawk_sed_t* sed
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_pushecb() function register a runtime callback set.
 | |
|  */
 | |
| HAWK_EXPORT void hawk_sed_pushecb (
 | |
| 	hawk_sed_t*     sed,
 | |
| 	hawk_sed_ecb_t* ecb
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_comp() function compiles editing commands into an internal form.
 | |
|  * \return 0 on success, -1 on error
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_comp (
 | |
| 	hawk_sed_t*        sed, /**< stream editor */
 | |
| 	hawk_sed_io_impl_t  inf  /**< script stream reader */
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_exec() function executes the compiled commands.
 | |
|  * \return 0 on success, -1 on error
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_exec (
 | |
| 	hawk_sed_t*        sed,  /**< stream editor */
 | |
| 	hawk_sed_io_impl_t  inf,  /**< stream reader */
 | |
| 	hawk_sed_io_impl_t  outf  /**< stream writer */
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_halt() function breaks running loop in hawk_sed_exec().
 | |
|  * It doesn't affect blocking calls in stream handlers.
 | |
|  */
 | |
| HAWK_EXPORT void hawk_sed_halt (
 | |
| 	hawk_sed_t* sed   /**< stream editor */
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_ishalt() functions tests if hawk_sed_halt() is called.
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_ishalt (
 | |
| 	hawk_sed_t* sed   /**< stream editor */
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_getcompid() function returns the latest
 | |
|  * identifier successfully set with hawk_sed_setcompid().
 | |
|  */
 | |
| HAWK_EXPORT const hawk_ooch_t* hawk_sed_getcompid (
 | |
| 	hawk_sed_t* sed
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_setcompid() functions duplicates a string
 | |
|  * pointed to by \a id and stores it internally to identify
 | |
|  * the script currently being compiled. The lid field of the
 | |
|  * current command being compiled in the script is set to the
 | |
|  * lastest identifer successfully set with this function.
 | |
|  * If this function fails, the location set in the command
 | |
|  * may be wrong.
 | |
|  */
 | |
| #if defined(HAWK_OOCH_IS_BCH)
 | |
| #define hawk_sed_setcompid(sed, id) hawk_sed_setcompidwithbcstr(sed, id)
 | |
| #else
 | |
| #define hawk_sed_setcompid(sed, id) hawk_sed_setcompidwithucstr(sed, id)
 | |
| #endif
 | |
| 
 | |
| HAWK_EXPORT const hawk_ooch_t* hawk_sed_setcompidwithbcstr (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	const hawk_bch_t*  id
 | |
| );
 | |
| 
 | |
| HAWK_EXPORT const hawk_ooch_t* hawk_sed_setcompidwithucstr (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	const hawk_uch_t*  id
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_getlinnum() function gets the current input line number.
 | |
|  * \return current input line number
 | |
|  */
 | |
| HAWK_EXPORT hawk_oow_t hawk_sed_getlinenum (
 | |
| 	hawk_sed_t* sed /**< stream editor */
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_setlinenum() function changes the current input line number.
 | |
|  */
 | |
| HAWK_EXPORT void hawk_sed_setlinenum (
 | |
| 	hawk_sed_t* sed,   /**< stream editor */
 | |
| 	hawk_oow_t  num    /**< a line number */
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_getspace() function gets the pointer and the length
 | |
|  * to a buffer space specfied by \a space.
 | |
|  */
 | |
| HAWK_EXPORT void hawk_sed_getspace (
 | |
| 	hawk_sed_t*      sed,
 | |
| 	hawk_sed_space_t space,
 | |
| 	hawk_oocs_t*     str
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_allocmem() function allocates a chunk of memory using
 | |
|  * the memory manager of \a sed.
 | |
|  */
 | |
| HAWK_EXPORT void* hawk_sed_allocmem (
 | |
| 	hawk_sed_t* sed,
 | |
| 	hawk_oow_t  size
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_callocmem() function allocates a chunk of memory using
 | |
|  * the memory manager of \a sed and clears it to zeros.
 | |
|  */
 | |
| HAWK_EXPORT void* hawk_sed_callocmem (
 | |
| 	hawk_sed_t* sed,
 | |
| 	hawk_oow_t  size
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_reallocmem() function reallocates a chunk of memory using
 | |
|  * the memory manager of \a sed.
 | |
|  */
 | |
| HAWK_EXPORT void* hawk_sed_reallocmem (
 | |
| 	hawk_sed_t* sed,
 | |
| 	void*       ptr,
 | |
| 	hawk_oow_t  size
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_freemem() function frees a chunk of memory using
 | |
|  * the memory manager of \a sed.
 | |
|  */
 | |
| HAWK_EXPORT void hawk_sed_freemem (
 | |
| 	hawk_sed_t* sed,
 | |
| 	void*       ptr
 | |
| );
 | |
| 
 | |
| /* ------------------------------------------------------------------------ */
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_openstd() function creates a stream editor with the default
 | |
|  * memory manager and initializes it.
 | |
|  * \return pointer to a stream editor on success, #HAWK_NULL on failure.
 | |
|  */
 | |
| HAWK_EXPORT hawk_sed_t* hawk_sed_openstd (
 | |
| 	hawk_oow_t     xtnsize,  /**< extension size in bytes */
 | |
| 	hawk_errinf_t* errinf
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_openstdwithmmgr() function creates a stream editor with a
 | |
|  * user-defined memory manager. It is equivalent to hawk_sed_openstd(),
 | |
|  * except that you can specify your own memory manager.
 | |
|  * \return pointer to a stream editor on success, #HAWK_NULL on failure.
 | |
|  */
 | |
| HAWK_EXPORT hawk_sed_t* hawk_sed_openstdwithmmgr (
 | |
| 	hawk_mmgr_t*   mmgr,     /**< memory manager */
 | |
| 	hawk_oow_t     xtnsize,  /**< extension size in bytes */
 | |
| 	hawk_cmgr_t*   cmgr,
 | |
| 	hawk_errinf_t* errinf
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_compstd() function compiles sed scripts specified in
 | |
|  * an array of stream resources. The end of the array is indicated
 | |
|  * by an element whose type is #HAWK_SED_IOSTD_NULL. However, the type
 | |
|  * of the first element shall not be #HAWK_SED_IOSTD_NULL. The output
 | |
|  * parameter \a count is set to the count of stream resources
 | |
|  * opened on both success and failure. You can pass #HAWK_NULL to \a
 | |
|  * count if the count is not needed.
 | |
|  *
 | |
|  * \return 0 on success, -1 on failure
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_compstd (
 | |
| 	hawk_sed_t*        sed,  /**< stream editor */
 | |
| 	hawk_sed_iostd_t   in[], /**< input scripts */
 | |
| 	hawk_oow_t*        count /**< number of input scripts opened */
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_compstdfile() function compiles a sed script from
 | |
|  * a single file \a infile.  If \a infile is #HAWK_NULL, it reads
 | |
|  * the script from the standard input.
 | |
|  * When #HAWK_OOCH_IS_UCH is defined, it converts the multibyte
 | |
|  * sequences in the file \a infile to wide characters via the
 | |
|  * #hawk_cmgr_t interface \a cmgr. If \a cmgr is #HAWK_NULL, it uses
 | |
|  * the default interface. It calls cmgr->mbtowc() for conversion.
 | |
|  * \return 0 on success, -1 on failure
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_compstdfile (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	const hawk_ooch_t* infile,
 | |
| 	hawk_cmgr_t*       cmgr
 | |
| );
 | |
| 
 | |
| HAWK_EXPORT int hawk_sed_compstdfileb (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	const hawk_bch_t*  infile,
 | |
| 	hawk_cmgr_t*       cmgr
 | |
| );
 | |
| 
 | |
| HAWK_EXPORT int hawk_sed_compstdfileu (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	const hawk_uch_t*  infile,
 | |
| 	hawk_cmgr_t*       cmgr
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_compstdoocstr() function compiles a sed script stored
 | |
|  * in a null-terminated string pointed to by \a script.
 | |
|  * \return 0 on success, -1 on failure
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_compstdoocstr (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	const hawk_ooch_t* script
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_compstdoocs() function compiles a sed script of the
 | |
|  * length \a script->len pointed to by \a script->ptr.
 | |
|  * \return 0 on success, -1 on failure
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_compstdoocs (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	const hawk_oocs_t* script
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_execstd() function executes a compiled script
 | |
|  * over input streams \a in and an output stream \a out.
 | |
|  *
 | |
|  * If \a in is not #HAWK_NULL, it must point to an array of stream
 | |
|  * resources whose end is indicated by an element with #HAWK_SED_IOSTD_NULL
 | |
|  * type. However, the type of the first element \a in[0].type show not
 | |
|  * be #HAWK_SED_IOSTD_NULL. It requires at least 1 valid resource to be
 | |
|  * included in the array.
 | |
|  *
 | |
|  * If \a in is #HAWK_NULL, the standard console input is used.
 | |
|  * If \a out is #HAWK_NULL, the standard console output is used.
 | |
|  *
 | |
|  * \return 0 on success, -1 on failure
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_execstd (
 | |
| 	hawk_sed_t*       sed,
 | |
| 	hawk_sed_iostd_t  in[],
 | |
| 	hawk_sed_iostd_t* out
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_execstdfile() function executes a compiled script
 | |
|  * over a single input file \a infile and a single output file \a
 | |
|  * outfile.
 | |
|  *
 | |
|  * If \a infile is #HAWK_NULL, the standard console input is used.
 | |
|  * If \a outfile is #HAWK_NULL, the standard console output is used.
 | |
|  *
 | |
|  * \return 0 on success, -1 on failure
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_execstdfile (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	const hawk_ooch_t* infile,
 | |
| 	const hawk_ooch_t* outfile,
 | |
| 	hawk_cmgr_t*       cmgr
 | |
| );
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * The hawk_sed_execstdfile() function executes a compiled script
 | |
|  * over a single input string \a instr and a dynamically allocated buffer.
 | |
|  * It copies the buffer pointer and length to the location pointed to
 | |
|  * by \a outstr on success. The buffer pointer copied to \a outstr
 | |
|  * must be released with hawk_sed_freemem().
 | |
|  *
 | |
|  * \return 0 on success, -1 on failure
 | |
|  */
 | |
| HAWK_EXPORT int hawk_sed_execstdxstr (
 | |
| 	hawk_sed_t*        sed,
 | |
| 	const hawk_oocs_t* instr,
 | |
| 	hawk_oocs_t*       outstr,
 | |
| 	hawk_cmgr_t*       cmgr
 | |
| );
 | |
| 
 | |
| #if defined(__cplusplus)
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #endif
 |