1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
|
/*
* Copyright (C) 1997-2004, Michael Jennings
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file libast_internal.h
* LibAST header file for internal-use-only stuff.
*
* This file contains all macros, structure definitions, etc. which
* are restricted to internal LibAST use only.
*
* @author Michael Jennings <mej@eterm.org>
* @version $Revision: 1.21 $
* @date $Date: 2004/07/21 22:17:49 $
*/
#ifndef _LIBAST_INTERNAL_H_
#define _LIBAST_INTERNAL_H_
/* This GNU goop has to go before the system headers */
#ifdef __GNUC__
# ifndef __USE_GNU
# define __USE_GNU
# endif
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
# ifndef _DEFAULT_SOURCE
# define _DEFAULT_SOURCE
# endif
#endif
#include "config.h"
#include "libast.h"
#ifdef HAVE_STDARG_H
# include <stdarg.h>
#endif
/******************************** MSGS GOOP ***********************************/
extern spif_charptr_t libast_program_name, libast_program_version;
/********************************* MEM GOOP ***********************************/
/**
* Filename length limit.
*
* This is used to limit the maximum length of a source filename.
* When tracking memory allocation, the filename and line number for
* each MALLOC()/REALLOC()/CALLOC()/FREE() call is recorded. A small
* buffer of static length is used to speed things up.
*
* @see MALLOC(), REALLOC(), CALLOC(), FREE()
* @ingroup DOXGRP_MEM
*/
#define LIBAST_FNAME_LEN 20
/**
* Pointer tracking structure.
*
* This structure is used by LibAST's memory management system to keep
* track of what pointers have been allocated, where they were
* allocated, and how much space was requested.
*
* @see MALLOC(), REALLOC(), CALLOC(), FREE()
* @ingroup DOXGRP_MEM
*/
typedef struct ptr_t_struct {
/** The allocated pointer. The allocated pointer. */
void *ptr;
/** The pointer's size, in bytes. The pointer's size, in bytes. */
size_t size;
/** Filename. The file which last (re)allocated the pointer. */
spif_char_t file[LIBAST_FNAME_LEN + 1];
/** Line number. The line number where the pointer was last (re)allocated. */
spif_uint32_t line;
} ptr_t;
/**
* Pointer list structure.
*
* This structure is used by LibAST's memory management system to hold
* the list of pointers being tracked. This list is maintained as an
* array for simplicity.
*
* @see MALLOC(), REALLOC(), CALLOC(), FREE(), ptr_t_struct
* @ingroup DOXGRP_MEM
*/
typedef struct memrec_t_struct {
/** Pointer count. The number of pointers being tracked. */
size_t cnt;
/** Pointer list. The list of tracked pointers. */
ptr_t *ptrs;
} memrec_t;
/******************************** CONF GOOP ***********************************/
/**
* Convert context name to ID.
*
* This macro converts a context name as read from a config file into
* the corresponding ID number. If the context name is not found, an
* error message is printed, and the ID number of 0 (the "null"
* context) is returned.
*
* @bug This probably should not be a macro.
* @bug The @a i parameter really isn't needed.
*
* @param the_id The return value -- the context ID.
* @param n The name of the context.
* @param i An arbitrary counter variable.
*
* @see @link DOXGRP_CONF_CTX Context Handling @endlink
* @ingroup DOXGRP_CONF_CTX
*/
#define ctx_name_to_id(the_id, n, i) do { \
for ((i)=0; (i) <= ctx_idx; (i)++) { \
if (!strcasecmp(SPIF_CAST_C(char *) (n), \
SPIF_CAST_C(char *) context[(i)].name)) { \
(the_id) = (i); \
break; \
} \
} \
if ((i) > ctx_idx) { \
libast_print_error("Parsing file %s, line %lu: No such context \"%s\"\n", \
file_peek_path(), file_peek_line(), (n)); \
(the_id) = 0; \
} \
} while (0)
/**
* Convert context ID to name.
*
* This macro converts a context ID to its name.
*
* @param id The context ID number.
* @return The name of the context.
*
* @see @link DOXGRP_CONF_CTX Context Handling @endlink
* @ingroup DOXGRP_CONF_CTX
*/
#define ctx_id_to_name(id) (context[(id)].name)
/**
* Convert context ID to handler.
*
* This macro returns the function pointer (a ctx_handler_t)
* corresponding to the assigned handler function for the given
* context.
*
* @param id The context ID number.
* @return The name of the context.
*
* @see @link DOXGRP_CONF_CTX Context Handling @endlink
* @ingroup DOXGRP_CONF_CTX
*/
#define ctx_id_to_func(id) (context[(id)].handler)
/*@{*/
/**
* @name Internal Context State Stack Manipulation Macros
* Facilitate use of the context state stack.
*
* These macros provide a function-style interface to the CSS.
*
* @bug All this goop will be replaced with a spif object class.
* @ingroup DOXGRP_CONF_CTX
*/
/**
* Pushes a context onto the stack. Pushes a context onto the stack.
*
* @param ctx The context ID for the new context.
*/
#define ctx_push(ctx) spifconf_register_context_state(ctx)
/**
* Pops a context structure off the stack. Pops a context structure
* off the stack.
*/
#define ctx_pop() (ctx_state_idx--)
/**
* Returns the context structure atop the stack. Returns the context
* structure atop the stack.
*
* @return The current context.
*/
#define ctx_peek() (ctx_state[ctx_state_idx])
/**
* Returns the context ID from the context structure atop the stack.
* Returns the context ID from the context structure atop the stack.
*
* @return The current context ID.
*/
#define ctx_peek_id() (ctx_state[ctx_state_idx].ctx_id)
/**
* Returns the context state from the context structure atop the
* stack. Returns the context state from the context structure atop
* the stack.
*
* @return The current context state.
*/
#define ctx_peek_state() (ctx_state[ctx_state_idx].state)
/**
* Returns the context ID from the context structure one level below
* the top of the stack. Returns the context ID from the context
* structure one level below the top of the stack.
*
* @return The previous context ID.
*/
#define ctx_peek_last_id() (ctx_state[(ctx_state_idx?ctx_state_idx-1:0)].ctx_id)
/**
* Returns the context state from the context structure one level
* below the top of the stack. Returns the context state from the
* context structure one level below the top of the stack.
*
* @return The previous context state.
*/
#define ctx_peek_last_state() (ctx_state[(ctx_state_idx?ctx_state_idx-1:0)].state)
/**
* Sets the current context state. Sets the current context state.
*
* @param q The new state for the current context.
*/
#define ctx_poke_state(q) ((ctx_state[ctx_state_idx].state) = (q))
/**
* Gets the current depth of the context stack. Gets the current
* depth of the context stack.
*
* @return The current context stack depth.
*/
#define ctx_get_depth() (ctx_state_idx)
/**
* Convenience macro for beginning a new context.
*
* This macro simplifies the beginning of a new context. The name
* read from the config file is turned into a context ID which is then
* registered with the parser. The context handler for the new
* context is called with CONF_BEGIN_STRING. The returned state is
* saved in the context structure atop the stack.
*
* @param idx The word number of the context name.
*/
#define ctx_begin(idx) do { \
spif_charptr_t name; \
name = spiftool_get_word(idx, buff); \
ctx_name_to_id(id, name, i); \
ctx_push(id); \
state = (*ctx_id_to_func(id))(SPIF_CAST(charptr) SPIFCONF_BEGIN_STRING, \
ctx_peek_last_state()); \
ctx_poke_state(state); \
FREE(name); \
} while (0)
/**
* Convenience macro for ending a context.
*
* This macro simplifies the ending of a context. The context handler
* for the context is called with SPIFCONF_END_STRING. The old context is
* then popped off the stack, and the returned state is saved for the
* parent context.
*
*/
#define ctx_end() do { \
if (ctx_get_depth()) { \
state = (*ctx_id_to_func(id))(SPIF_CAST(charptr) SPIFCONF_END_STRING, \
ctx_peek_state()); \
ctx_poke_state(NULL); \
ctx_pop(); \
id = ctx_peek_id(); \
ctx_poke_state(state); \
file_poke_skip(0); \
} \
} while (0)
/*@}*/
/**
* Context structure.
*
* This structure is used to hold context names and their respective
* handlers (#ctx_handler_t).
*
* @bug This needs to be turned into a spif object class.
* @see @link DOXGRP_CONF_CTX Context Handling @endlink
* @ingroup DOXGRP_CONF_CTX
*/
typedef struct ctx_t_struct {
/**
* Context name.
*
* The string representation of the context name. The word
* immediately after the keyword @c begin is compared with this
* value to find the handler for the requested context. This
* comparison is case-insensitive.
*/
spif_charptr_t name;
/**
* Context handler.
*
* Pointer to the function which will handle this context.
* Context handlers must accept two parameters, a spif_charptr_t
* containing either the config file line or a begin/end magic
* string, and a void * containing state information; they must
* return a void * which will be passed to the next invocation of
* the handler as the aforementioned state information parameter.
*/
ctx_handler_t handler;
} ctx_t;
/**
* Context state structure.
*
* This structure is used as part of the context stack to track the
* current context and its state information.
*
* @bug This needs to be turned into a spif object class.
* @see @link DOXGRP_CONF_CTX Context Handling @endlink
* @ingroup DOXGRP_CONF_CTX
*/
typedef struct ctx_state_t_struct {
/**
* Context ID.
*
* The ID number of the context.
*/
unsigned char ctx_id;
/**
* Context state.
*
* The state for the context. This holds the state variable in
* between calls to the handler (ctx_t_struct#handler).
*/
void *state;
} ctx_state_t;
/**
* Built-in config file function.
*
* This structure holds the name and a pointer to the handler for
* built-in config file functions (%get(), %random(), etc.).
*
* @bug This needs to be turned into a spif object class.
* @see @link DOXGRP_CONF_CTX Context Handling @endlink
* @ingroup DOXGRP_CONF_CTX
*/
typedef struct spifconf_func_t_struct {
/**
* Function name.
*
* The string representation of the built-in function name, not
* including the leading percent sign ('%').
*/
spif_charptr_t name;
/**
* Function handler pointer.
*
* Pointer to the handler for the built-in function.
*/
spifconf_func_ptr_t ptr;
} spifconf_func_t;
/**
* Linked list for user-defined config file variables.
*
* This structure holds the name and value for user-defined config
* file variables set/retrieved using the %get() and %put() built-in
* functions.
*
* @bug This needs to be turned into a spif object class.
* @see @link DOXGRP_CONF_CTX Context Handling @endlink, builtin_get(), builtin_put()
* @ingroup DOXGRP_CONF_CTX
*/
typedef struct spifconf_var_t_struct {
/**
* Variable name.
*
* The string representation of the variable name. Variable names
* ARE case-sensitive!
*/
spif_charptr_t var;
/**
* Variable value.
*
* The value of the user-defined variable. The value must be a
* text string (obviously, since the config files are text-based.
*/
spif_charptr_t value;
/**
* Linked list pointer.
*
* Pointer to the next variable in the list.
*/
struct spifconf_var_t_struct *next;
} spifconf_var_t;
/******************************* OPTIONS GOOP **********************************/
/**
* Increment and check bad option counter.
*
* This is a convenience macro which is invoked each time an option
* parsing error is encountered. This macro increments the bad option
* count within the parser and checks to see if the count has now
* exceeded the threshold. If so, the registered help handler
* (spifopt_settings_t_struct#help_handler) via the
* #SPIFOPT_HELPHANDLER() macro. If not, an error message is printed
* noting that behavior may be abnormal but that parsing will
* continue.
*
* @see @link DOXGRP_OPT Command Line Option Parser @endlink
* @ingroup DOXGRP_OPT
*/
#define CHECK_BAD() do { \
SPIFOPT_BADOPTS_SET(SPIFOPT_BADOPTS_GET() + 1); \
if (SPIFOPT_BADOPTS_GET() > SPIFOPT_ALLOWBAD_GET()) { \
libast_print_error("Error threshold exceeded, giving up.\n"); \
SPIFOPT_HELPHANDLER(); \
} else { \
libast_print_error("Attempting to continue, but strange things may happen.\n"); \
} \
} while(0)
#endif /* _LIBAST_INTERNAL_H_ */
|