/src/wml_backend/p2_mp4h/src/builtin.c
C | 5049 lines | 3787 code | 642 blank | 620 comment | 918 complexity | 5d8c9d6158cf1d6e7a702cb8ec102c2a MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- /* mp4h -- A macro processor for HTML documents
- Copyright 2000-2002, Denis Barbier
- All rights reserved.
- 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 2, or (at your option)
- any later version.
- This program is a work based on GNU m4 version 1.4n. Below is the
- original copyright.
- */
- /* GNU m4 -- A simple macro processor
- Copyright (C) 1989, 90, 91, 92, 93, 94, 98 Free Software Foundation, Inc.
- 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 2, 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, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- /* Code for all builtin macros, initialisation of symbol table, and
- expansion of user defined macros. */
- #define MP4H_MODULE
- #include "mp4h.h"
- #undef MP4H_MODULE
- #include "builtin.h"
- #define CHECK_SAFETY_LEVEL(sl) \
- if (safety_level > sl) \
- { \
- MP4HERROR ((warning_status, 0, \
- _("Warning:%s:%d: `<%s>' ignored due to -S flag"), \
- CURRENT_FILE_LINE, ARG (0))); \
- return; \
- }
- /* Initialisation of builtin and predefined macros. The table
- "builtin_tab" is both used for initialisation, and by the "builtin"
- builtin. */
- DECLARE (mp4h_bp___file__);
- DECLARE (mp4h_bp___line__);
- DECLARE (mp4h_bp___version__);
- DECLARE (mp4h_bp_lb);
- DECLARE (mp4h_bp_rb);
- DECLARE (mp4h_bp_dq);
- DECLARE (mp4h_bp_bs);
- DECLARE (mp4h_bp_timer);
- #ifdef HAVE_LOCALE_H
- DECLARE (mp4h_bp_mp4h_l10n);
- #endif
- DECLARE (mp4h_bp_mp4h_output_radix);
- #if !defined(HAVE_FILE_FUNCS) || !defined (HAVE_LOCALE_H) || !defined(WITH_MODULES)
- DECLARE (mp4h_bp_unsupported);
- #endif
- /* debug functions */
- DECLARE (mp4h_bp_debugmode);
- DECLARE (mp4h_bp_debugfile);
- DECLARE (mp4h_bp_function_def);
- DECLARE (mp4h_bp_debugging_off);
- DECLARE (mp4h_bp_debugging_on);
- /* file functions */
- #ifdef HAVE_FILE_FUNCS
- DECLARE (mp4h_bp_get_file_properties);
- DECLARE (mp4h_bp_directory_contents);
- DECLARE (mp4h_bp_file_exists);
- DECLARE (mp4h_bp_real_path);
- #endif /* HAVE_FILE_FUNCS */
- DECLARE (mp4h_bp_date);
- /* flow functions */
- DECLARE (mp4h_bp_group);
- DECLARE (mp4h_bp_compound);
- DECLARE (mp4h_bp_disjoin);
- DECLARE (mp4h_bp_noexpand);
- DECLARE (mp4h_bp_expand);
- DECLARE (mp4h_bp_if);
- DECLARE (mp4h_bp_ifeq);
- DECLARE (mp4h_bp_ifneq);
- DECLARE (mp4h_bp_when);
- DECLARE (mp4h_bp_while);
- DECLARE (mp4h_bp_foreach);
- DECLARE (mp4h_bp_var_case);
- DECLARE (mp4h_bp_break);
- DECLARE (mp4h_bp_return);
- DECLARE (mp4h_bp_warning);
- DECLARE (mp4h_bp_exit);
- DECLARE (mp4h_bp_at_end_of_file);
- /* macro functions */
- DECLARE (mp4h_bp_define_tag);
- DECLARE (mp4h_bp_provide_tag);
- DECLARE (mp4h_bp_let);
- DECLARE (mp4h_bp_undef);
- DECLARE (mp4h_bp_set_hook);
- DECLARE (mp4h_bp_get_hook);
- DECLARE (mp4h_bp_attributes_quote);
- DECLARE (mp4h_bp_attributes_remove);
- DECLARE (mp4h_bp_attributes_extract);
- DECLARE (mp4h_bp_define_entity);
- /* math functions */
- DECLARE (mp4h_bp_add);
- DECLARE (mp4h_bp_substract);
- DECLARE (mp4h_bp_multiply);
- DECLARE (mp4h_bp_divide);
- DECLARE (mp4h_bp_modulo);
- DECLARE (mp4h_bp_min);
- DECLARE (mp4h_bp_max);
- DECLARE (mp4h_bp_gt);
- DECLARE (mp4h_bp_lt);
- DECLARE (mp4h_bp_eq);
- DECLARE (mp4h_bp_neq);
- /* page functions */
- DECLARE (mp4h_bp_include);
- DECLARE (mp4h_bp___include);
- DECLARE (mp4h_bp_use);
- #ifdef WITH_MODULES
- DECLARE (mp4h_bp_load);
- #endif
- DECLARE (mp4h_bp_comment);
- DECLARE (mp4h_bp_set_eol_comment);
- DECLARE (mp4h_bp_set_quotes);
- DECLARE (mp4h_bp_dnl);
- DECLARE (mp4h_bp_frozen_dump);
- /* relational operators */
- DECLARE (mp4h_bp_not);
- DECLARE (mp4h_bp_and);
- DECLARE (mp4h_bp_or);
- /* string functions */
- DECLARE (mp4h_bp_downcase);
- DECLARE (mp4h_bp_upcase);
- DECLARE (mp4h_bp_capitalize);
- DECLARE (mp4h_bp_string_length);
- DECLARE (mp4h_bp_substring);
- DECLARE (mp4h_bp_string_eq);
- DECLARE (mp4h_bp_string_neq);
- DECLARE (mp4h_bp_string_compare);
- DECLARE (mp4h_bp_char_offsets);
- DECLARE (mp4h_bp_printf);
- /* regexp functions */
- DECLARE (mp4h_bp_subst_in_string);
- DECLARE (mp4h_bp_subst_in_var);
- DECLARE (mp4h_bp_match);
- /* variable functions */
- DECLARE (mp4h_bp_get_var);
- DECLARE (mp4h_bp_get_var_once);
- DECLARE (mp4h_bp_set_var_x);
- DECLARE (mp4h_bp_set_var);
- DECLARE (mp4h_bp_unset_var);
- DECLARE (mp4h_bp_preserve);
- DECLARE (mp4h_bp_restore);
- DECLARE (mp4h_bp_var_exists);
- DECLARE (mp4h_bp_increment);
- DECLARE (mp4h_bp_decrement);
- DECLARE (mp4h_bp_symbol_info);
- DECLARE (mp4h_bp_copy_var);
- DECLARE (mp4h_bp_defvar);
- /* array functions */
- DECLARE (mp4h_bp_array_size);
- DECLARE (mp4h_bp_array_add_unique);
- DECLARE (mp4h_bp_array_member);
- DECLARE (mp4h_bp_array_push);
- DECLARE (mp4h_bp_array_pop);
- DECLARE (mp4h_bp_array_topvalue);
- DECLARE (mp4h_bp_array_shift);
- DECLARE (mp4h_bp_array_concat);
- DECLARE (mp4h_bp_sort);
- /* diversion functions */
- DECLARE (mp4h_bp_divert);
- DECLARE (mp4h_bp_divnum);
- DECLARE (mp4h_bp_undivert);
- #undef DECLARE
- static builtin
- builtin_tab[] =
- {
- /* name container expand function
- attributes */
- { "__file__", FALSE, TRUE, mp4h_bp___file__ },
- { "__line__", FALSE, TRUE, mp4h_bp___line__ },
- { "__version__", FALSE, TRUE, mp4h_bp___version__ },
- { "lb", FALSE, TRUE, mp4h_bp_lb },
- { "rb", FALSE, TRUE, mp4h_bp_rb },
- { "dq", FALSE, TRUE, mp4h_bp_dq },
- { "bs", FALSE, TRUE, mp4h_bp_bs },
- { "timer", FALSE, TRUE, mp4h_bp_timer },
- #ifdef HAVE_LOCALE_H
- { "mp4h-l10n", FALSE, TRUE, mp4h_bp_mp4h_l10n },
- #else
- { "mp4h-l10n", FALSE, TRUE, mp4h_bp_unsupported },
- #endif
- { "mp4h-output-radix",FALSE, TRUE, mp4h_bp_mp4h_output_radix },
- { "date", FALSE, TRUE, mp4h_bp_date },
- /* debug functions */
- { "debugmode", FALSE, TRUE, mp4h_bp_debugmode },
- { "debugfile", FALSE, TRUE, mp4h_bp_debugfile },
- { "function-def", FALSE, TRUE, mp4h_bp_function_def },
- { "debugging-off", FALSE, TRUE, mp4h_bp_debugging_off },
- { "debugging-on", FALSE, TRUE, mp4h_bp_debugging_on },
- /* file functions */
- #ifdef HAVE_FILE_FUNCS
- { "get-file-properties", FALSE, TRUE, mp4h_bp_get_file_properties },
- { "directory-contents", FALSE, TRUE, mp4h_bp_directory_contents },
- { "file-exists", FALSE, TRUE, mp4h_bp_file_exists },
- { "real-path", FALSE, TRUE, mp4h_bp_real_path },
- #else
- { "get-file-properties", FALSE, TRUE, mp4h_bp_unsupported },
- { "directory-contents", FALSE, TRUE, mp4h_bp_unsupported },
- { "file-exists", FALSE, TRUE, mp4h_bp_unsupported },
- { "real-path", FALSE, TRUE, mp4h_bp_unsupported },
- #endif /* HAVE_FILE_FUNCS */
- /* flow functions */
- { "group", FALSE, TRUE, mp4h_bp_group },
- { "compound", TRUE, TRUE, mp4h_bp_compound },
- { "disjoin", FALSE, TRUE, mp4h_bp_disjoin },
- { "noexpand", FALSE, FALSE, mp4h_bp_noexpand },
- { "expand", FALSE, TRUE, mp4h_bp_expand },
- { "if", FALSE, FALSE, mp4h_bp_if },
- { "ifeq", FALSE, FALSE, mp4h_bp_ifeq },
- { "ifneq", FALSE, FALSE, mp4h_bp_ifneq },
- { "when", TRUE, TRUE, mp4h_bp_when },
- { "while", TRUE, FALSE, mp4h_bp_while },
- { "foreach", TRUE, TRUE, mp4h_bp_foreach },
- { "var-case", FALSE, FALSE, mp4h_bp_var_case },
- { "break", FALSE, TRUE, mp4h_bp_break },
- { "return", FALSE, TRUE, mp4h_bp_return },
- { "warning", FALSE, TRUE, mp4h_bp_warning },
- { "exit", FALSE, TRUE, mp4h_bp_exit },
- { "at-end-of-file", TRUE, TRUE, mp4h_bp_at_end_of_file },
- /* macro functions */
- { "define-tag", TRUE, TRUE, mp4h_bp_define_tag },
- { "provide-tag", TRUE, TRUE, mp4h_bp_provide_tag },
- { "let", FALSE, TRUE, mp4h_bp_let },
- { "undef", FALSE, TRUE, mp4h_bp_undef },
- { "set-hook", TRUE, TRUE, mp4h_bp_set_hook },
- { "get-hook", FALSE, TRUE, mp4h_bp_get_hook },
- { "attributes-quote", FALSE, TRUE, mp4h_bp_attributes_quote },
- { "attributes-remove", FALSE, TRUE, mp4h_bp_attributes_remove },
- { "attributes-extract", FALSE, TRUE, mp4h_bp_attributes_extract },
- { "define-entity", TRUE, TRUE, mp4h_bp_define_entity },
- /* numerical relational operators */
- { "gt", FALSE, TRUE, mp4h_bp_gt },
- { "lt", FALSE, TRUE, mp4h_bp_lt },
- { "eq", FALSE, TRUE, mp4h_bp_eq },
- { "neq", FALSE, TRUE, mp4h_bp_neq },
- /* math functions */
- { "add", FALSE, TRUE, mp4h_bp_add },
- { "substract", FALSE, TRUE, mp4h_bp_substract },
- { "multiply", FALSE, TRUE, mp4h_bp_multiply },
- { "divide", FALSE, TRUE, mp4h_bp_divide },
- { "modulo", FALSE, TRUE, mp4h_bp_modulo },
- { "min", FALSE, TRUE, mp4h_bp_min },
- { "max", FALSE, TRUE, mp4h_bp_max },
- /* page functions */
- { "include", FALSE, FALSE, mp4h_bp_include },
- { "__include", TRUE, TRUE, mp4h_bp___include },
- { "use", FALSE, TRUE, mp4h_bp_use },
- #ifdef WITH_MODULES
- { "load", FALSE, TRUE, mp4h_bp_load },
- #else
- { "load", FALSE, TRUE, mp4h_bp_unsupported },
- #endif
- { "comment", TRUE, TRUE, mp4h_bp_comment },
- { "set-eol-comment", FALSE, TRUE, mp4h_bp_set_eol_comment },
- { "set-quotes", FALSE, TRUE, mp4h_bp_set_quotes },
- { "dnl", FALSE, TRUE, mp4h_bp_dnl },
- { "frozen-dump", FALSE, TRUE, mp4h_bp_frozen_dump },
- /* relational operators */
- { "not", FALSE, TRUE, mp4h_bp_not },
- { "and", FALSE, TRUE, mp4h_bp_and },
- { "or", FALSE, TRUE, mp4h_bp_or },
- /* string functions */
- { "downcase", FALSE, TRUE, mp4h_bp_downcase },
- { "upcase", FALSE, TRUE, mp4h_bp_upcase },
- { "capitalize", FALSE, TRUE, mp4h_bp_capitalize },
- { "string-length", FALSE, TRUE, mp4h_bp_string_length },
- { "substring", FALSE, TRUE, mp4h_bp_substring },
- { "string-eq", FALSE, TRUE, mp4h_bp_string_eq },
- { "string-neq", FALSE, TRUE, mp4h_bp_string_neq },
- { "string-compare", FALSE, TRUE, mp4h_bp_string_compare },
- { "char-offsets", FALSE, TRUE, mp4h_bp_char_offsets },
- { "printf", FALSE, TRUE, mp4h_bp_printf },
- /* regexp functions */
- { "subst-in-string", FALSE, TRUE, mp4h_bp_subst_in_string },
- { "subst-in-var", FALSE, TRUE, mp4h_bp_subst_in_var },
- { "match", FALSE, TRUE, mp4h_bp_match },
- /* variable functions */
- { "get-var", FALSE, TRUE, mp4h_bp_get_var },
- { "get-var-once", FALSE, TRUE, mp4h_bp_get_var_once },
- { "set-var-x", TRUE, TRUE, mp4h_bp_set_var_x },
- { "set-var", FALSE, TRUE, mp4h_bp_set_var },
- { "set-var-verbatim", FALSE, FALSE, mp4h_bp_set_var },
- { "unset-var", FALSE, TRUE, mp4h_bp_unset_var },
- { "preserve", FALSE, TRUE, mp4h_bp_preserve },
- { "restore", FALSE, TRUE, mp4h_bp_restore },
- { "var-exists", FALSE, TRUE, mp4h_bp_var_exists },
- { "increment", FALSE, TRUE, mp4h_bp_increment },
- { "decrement", FALSE, TRUE, mp4h_bp_decrement },
- { "symbol-info", FALSE, TRUE, mp4h_bp_symbol_info },
- { "copy-var", FALSE, TRUE, mp4h_bp_copy_var },
- { "defvar", FALSE, TRUE, mp4h_bp_defvar },
- /* array functions */
- { "array-size", FALSE, TRUE, mp4h_bp_array_size },
- { "array-add-unique", FALSE, TRUE, mp4h_bp_array_add_unique },
- { "array-member", FALSE, TRUE, mp4h_bp_array_member },
- { "array-push", FALSE, TRUE, mp4h_bp_array_push },
- { "array-pop", FALSE, TRUE, mp4h_bp_array_pop },
- { "array-topvalue", FALSE, TRUE, mp4h_bp_array_topvalue },
- { "array-shift", FALSE, TRUE, mp4h_bp_array_shift },
- { "array-concat", FALSE, TRUE, mp4h_bp_array_concat },
- { "sort", FALSE, TRUE, mp4h_bp_sort },
- /* diversion functions */
- { "divert", FALSE, TRUE, mp4h_bp_divert },
- { "divnum", FALSE, TRUE, mp4h_bp_divnum },
- { "undivert", FALSE, TRUE, mp4h_bp_undivert },
- { 0, FALSE, FALSE, 0 },
- };
- /* Local functions */
- static void push_builtin_table __P ((builtin *));
- static void set_trace __P ((symbol *, const char *));
- static void generic_set_hook __P ((MP4H_BUILTIN_PROTO, boolean, int));
- static void math_relation __P ((MP4H_BUILTIN_PROTO, mathrel_type));
- static void mathop_functions __P ((MP4H_BUILTIN_PROTO, mathop_type));
- static void updowncase __P ((struct obstack *, int, token_data **, boolean));
- static void varstack_check __P ((void));
- static boolean safe_strtod __P ((const char *, const char *, double *));
- static boolean safe_strtol __P ((const char *, const char *, long int *));
- static void quote_name_value __P ((struct obstack *, char *));
- static void matching_attributes __P ((struct obstack *, int, token_data **, boolean, char *));
- static char * utf8char_skip __P ((char *, int));
- static int utf8char_strlen __P ((char *));
- static int encoding_strlen __P ((char *));
- static void substitute __P ((struct obstack *, const char *, const char *, int *));
- static void string_regexp __P ((struct obstack *, int, token_data **, int, const char *));
- static void subst_in_string __P ((struct obstack *, int, token_data **, int));
- static void generic_variable_lookup __P ((MP4H_BUILTIN_PROTO, boolean));
- static int array_size __P ((symbol *));
- static char *array_value __P ((symbol *, int, int *));
- static int array_member __P ((const char *, symbol *, boolean));
- static int sort_function __P ((const void *, const void *));
- static void logical_to_physical_paths __P ((char **));
- /* This symbol controls breakings of flow statements. */
- static symbol varbreak;
- /* Stack preserve/restore variables. */
- static var_stack *vs = NULL;
- /* Global variables needed by sort algorithms. */
- static boolean sort_caseless;
- static boolean sort_sortorder;
- static boolean sort_numeric;
- /* Localization */
- struct lconv *my_locale;
- /* Table of characters used by PCRE with non-C locales */
- static const unsigned char *re_tableptr = NULL;
- /* Timer */
- static struct tms elapsed_time;
- /* Pointer to a string containig the decimal point used
- with locales. */
- #ifdef HAVE_LOCALE_H
- static const char *decimal_point;
- #else
- #define decimal_point "."
- #endif
- /* Output radix */
- static int output_radix = 6;
- /*------------------------------------------------------------------.
- | If dynamic modules are enabled, more builtin tables can be active |
- | at a time. This implements a list of tables of builtins. |
- `------------------------------------------------------------------*/
- struct builtin_table
- {
- struct builtin_table *next;
- builtin *table;
- };
- typedef struct builtin_table builtin_table;
- static builtin_table *builtin_tables = NULL;
- static void
- push_builtin_table (builtin *table)
- {
- builtin_table *bt;
- bt = (builtin_table *) xmalloc (sizeof (struct builtin_table));
- bt->next = builtin_tables;
- bt->table = table;
- builtin_tables = bt;
- }
- /*----------------------------------------.
- | Find the builtin, which lives on ADDR. |
- `----------------------------------------*/
- const builtin *
- find_builtin_by_addr (builtin_func *func)
- {
- const builtin_table *bt;
- const builtin *bp;
- for (bt = builtin_tables; bt != NULL; bt = bt->next)
- for (bp = bt->table; bp->name != NULL; bp++)
- if (bp->func == func)
- return bp;
- return NULL;
- }
- /*-----------------------------------.
- | Find the builtin, which has NAME. |
- `-----------------------------------*/
- const builtin *
- find_builtin_by_name (const char *name)
- {
- const builtin_table *bt;
- const builtin *bp;
- /* This is necessary to load frozen files */
- if (builtin_tables == NULL)
- push_builtin_table (builtin_tab);
- for (bt = builtin_tables; bt != NULL; bt = bt->next)
- for (bp = bt->table; bp->name != NULL; bp++)
- if (strcasecmp (bp->name, name) == 0)
- return bp;
- return NULL;
- }
- /*-----------------------.
- | Initialize a symbol. |
- `-----------------------*/
- void
- initialize_builtin (symbol *sym)
- {
- SYMBOL_TYPE (sym) = TOKEN_VOID;
- SYMBOL_TRACED (sym) = FALSE;
- SYMBOL_CONTAINER (sym) = FALSE;
- SYMBOL_EXPAND_ARGS (sym) = FALSE;
- SYMBOL_HOOK_BEGIN (sym) = NULL;
- SYMBOL_HOOK_END (sym) = NULL;
- }
- /*-------------------------------------------------------------------------.
- | Install a builtin macro with name NAME, bound to the C function given in |
- | BP. TRACED defines whether NAME is to be traced. |
- `-------------------------------------------------------------------------*/
- void
- define_builtin (const char *name, const builtin *bp, boolean traced)
- {
- symbol *sym;
- sym = lookup_symbol (name, SYMBOL_INSERT);
- if (SYMBOL_TYPE (sym) == TOKEN_TEXT)
- xfree ((voidstar) SYMBOL_TEXT (sym));
- SYMBOL_TYPE (sym) = TOKEN_FUNC;
- SYMBOL_FUNC (sym) = bp->func;
- SYMBOL_TRACED (sym) = traced;
- SYMBOL_CONTAINER (sym) = bp->container;
- SYMBOL_EXPAND_ARGS (sym) = bp->expand_args;
- SYMBOL_HOOK_BEGIN (sym) = NULL;
- SYMBOL_HOOK_END (sym) = NULL;
- }
- /*------------------------------.
- | Install a new builtin_table. |
- `------------------------------*/
- void
- install_builtin_table (builtin *table)
- {
- const builtin *bp;
- push_builtin_table (table);
- for (bp = table; bp->name != NULL; bp++)
- define_builtin (bp->name, bp, FALSE);
- }
- void
- break_init (void) {
- initialize_builtin (&varbreak);
- SYMBOL_TYPE (&varbreak) = TOKEN_TEXT;
- SYMBOL_TEXT (&varbreak) = xstrdup ("");
- }
- void
- break_deallocate (void) {
- xfree ((voidstar) SYMBOL_TEXT (&varbreak));
- SYMBOL_TYPE (&varbreak) = TOKEN_VOID;
- }
- /*-------------------------------------------------------------------------.
- | Define a predefined or user-defined macro, with name NAME, and expansion |
- | TEXT. MODE destinguishes between the "define" and the "pushdef" case. |
- | It is also used from main (). |
- `-------------------------------------------------------------------------*/
- void
- define_user_macro (const char *name, char *text, symbol_lookup mode,
- boolean container, boolean expand_args, boolean space_delete)
- {
- symbol *s;
- char *begin, *cp;
- int offset, bracket_level = 0;
- s = lookup_symbol (name, mode);
- xfree ((voidstar) SYMBOL_HOOK_BEGIN (s));
- xfree ((voidstar) SYMBOL_HOOK_END (s));
- if (SYMBOL_TYPE (s) == TOKEN_TEXT)
- xfree ((voidstar) SYMBOL_TEXT (s));
- initialize_builtin (s);
- SYMBOL_TYPE (s) = TOKEN_TEXT;
- if (space_delete)
- {
- for (begin=text; *begin != '\0' && IS_SPACE(*begin); begin++)
- ;
- SYMBOL_TEXT (s) = xstrdup (begin);
- offset = 0;
- for (cp=SYMBOL_TEXT (s); *cp != '\0'; cp++)
- {
- switch (*cp)
- {
- case '<':
- bracket_level++;
- *(cp-offset) = *cp;
- break;
- case '>':
- bracket_level--;
- *(cp-offset) = *cp;
- break;
- case '\\':
- *(cp-offset) = *cp;
- if (*(cp+1) != '\0')
- {
- cp++;
- *(cp-offset) = *cp;
- }
- break;
- case '\n':
- if (bracket_level>0)
- *(cp-offset) = *cp;
- else
- {
- offset++;
- while (IS_SPACE(*(cp+1)))
- {
- cp++;
- offset++;
- }
- }
- break;
- default:
- *(cp-offset) = *cp;
- break;
- }
- }
- *(cp-offset) = '\0';
- }
- else
- SYMBOL_TEXT (s) = xstrdup (text);
- SYMBOL_CONTAINER (s) = container;
- SYMBOL_EXPAND_ARGS (s) = expand_args;
- #ifdef DEBUG_INPUT
- fprintf (stderr, "Define: %s\nText: %s\nContainer: %d\n",
- SYMBOL_NAME (s), SYMBOL_TEXT (s), SYMBOL_CONTAINER (s));
- #endif
- }
- /*--------------------------------------------------------------------------.
- | Define a predefined or user-defined entity, with name NAME, and expansion |
- | TEXT. MODE destinguishes between the "define" and the "pushdef" case. |
- | It is also used from main (). |
- `--------------------------------------------------------------------------*/
- static void
- define_user_entity (const char *name, char *text, symbol_lookup mode)
- {
- symbol *s;
- s = lookup_entity (name, mode);
- if (SYMBOL_TYPE (s) == TOKEN_TEXT)
- {
- xfree ((voidstar) SYMBOL_HOOK_BEGIN (s));
- xfree ((voidstar) SYMBOL_HOOK_END (s));
- xfree ((voidstar) SYMBOL_TEXT (s));
- }
- initialize_builtin (s);
- SYMBOL_TYPE (s) = TOKEN_TEXT;
- SYMBOL_TEXT (s) = xstrdup (text);
- #ifdef DEBUG_INPUT
- fprintf (stderr, "Define: %s\nText: %s\n",
- SYMBOL_NAME (s), SYMBOL_TEXT (s));
- #endif
- }
- /*-----------------------------------------------.
- | Initialise all builtin and predefined macros. |
- `-----------------------------------------------*/
- void
- builtin_init (void)
- {
- install_builtin_table (builtin_tab);
- pcre_malloc = xmalloc;
- pcre_free = xfree;
- }
- /*-----------------------------------------------.
- | Deallocate all builtin and predefined macros. |
- `-----------------------------------------------*/
- void
- builtin_deallocate (void)
- {
- builtin_table *bt, *bt_next;
- for (bt = builtin_tables; bt != NULL; )
- {
- bt_next = bt->next;
- xfree ((voidstar) bt);
- bt = bt_next;
- }
- varstack_check ();
- }
- static pcre *
- xre_compile (const char *pattern, int cflags)
- {
- pcre *patcomp;
- const char *errbuf;
- int erroffset;
- if (document_encoding == ENCODING_UTF8)
- cflags |= PCRE_UTF8;
- patcomp = pcre_compile (pattern, cflags, &errbuf, &erroffset, re_tableptr);
- if (patcomp == 0)
- {
- MP4HERROR ((warning_status, 0,
- _("Warning:%s:%d: Bad regular expression `%s' at position %d: %s"),
- CURRENT_FILE_LINE, pattern, erroffset, errbuf));
- }
- return patcomp;
- }
- static boolean
- safe_strtod (const char *name, const char *nptr, double *value)
- {
- char *endp;
- double result;
- result = strtod (nptr, &endp);
- if (nptr == NULL || *endp != '\0')
- {
- if (nptr == NULL)
- nptr = endp;
- MP4HERROR ((warning_status, 0,
- _("Warning:%s:%d: Argument `%s' non-numeric in <%s>"),
- CURRENT_FILE_LINE, nptr, name));
- return FALSE;
- }
- *value = result;
- return TRUE;
- }
- static boolean
- safe_strtol (const char *name, const char *nptr, long int *value)
- {
- char *endp;
- long int result;
- result = strtol (nptr, &endp, 10);
- if (nptr == NULL || *endp != '\0')
- {
- if (nptr == NULL)
- nptr = endp;
- MP4HERROR ((warning_status, 0,
- _("Warning:%s:%d: Argument `%s' non-numeric in <%s>"),
- CURRENT_FILE_LINE, nptr, name));
- return FALSE;
- }
- *value = result;
- return TRUE;
- }
- /*----------------------------------------------------------------.
- | Quote name=value pair. This function must be called only when |
- | text is sent to output. |
- `----------------------------------------------------------------*/
- static void
- quote_name_value (struct obstack *obs, char *pair)
- {
- char *equal_ptr, *cp;
- int special_chars;
- boolean valid;
- equal_ptr = strchr (pair, '=');
- if (equal_ptr == NULL)
- {
- obstack_grow (obs, pair, strlen (pair));
- return;
- }
- /* Skip special characters */
- special_chars = 0;
- cp = pair;
- while (IS_GROUP (*cp))
- {
- cp++;
- special_chars++;
- }
- valid = TRUE;
- while (cp < equal_ptr)
- {
- if (IS_SPACE (*cp) || IS_CLOSE (*cp))
- {
- valid = FALSE;
- break;
- }
- cp++;
- }
- if (!valid)
- {
- obstack_grow (obs, pair, strlen (pair));
- return;
- }
- if (special_chars)
- obstack_grow (obs, pair, special_chars);
- *equal_ptr = '\0';
- obstack_grow (obs, pair+special_chars, strlen (pair)-special_chars);
- *equal_ptr = '=';
- obstack_1grow (obs, '=');
- if (*(equal_ptr+1) != '"' && *(equal_ptr+1) != CHAR_QUOTE)
- obstack_1grow (obs, CHAR_QUOTE);
- obstack_grow (obs, equal_ptr+1, strlen (equal_ptr+1)-special_chars);
- if (*(equal_ptr+1) != '"' && *(equal_ptr+1) != CHAR_QUOTE)
- obstack_1grow (obs, CHAR_QUOTE);
- if (special_chars)
- obstack_grow (obs, equal_ptr+1+strlen (equal_ptr+1)-special_chars,
- special_chars);
- }
- /*---------------------------------------------------------------.
- | Extract from ARGV attributes from a list of attributes names. |
- | When MATCH is true, matching attributes are printed, otherwise |
- | non matching attributes are printed. |
- | First argument is a comma-separated list of attributes names, |
- | which may contain regular expressions. |
- `---------------------------------------------------------------*/
- static void
- matching_attributes (struct obstack *obs, int argc, token_data **argv,
- boolean match, char *list)
- {
- register char *cp;
- char *name;
- int i, j, special_chars;
- pcre *re;
- pcre_extra *re_extra = NULL;
- const char *errptr = NULL;
- int rc, max_subexps;
- int *match_ptr = NULL;
- boolean first = TRUE;
- /* Replace comma-separated list by a regular expression */
- for (cp=list; *cp != '\0'; cp++)
- {
- if (*cp == ',')
- *cp = '|';
- }
- name = (char *) xmalloc (strlen (list) + 3);
- sprintf (name, "^%s$", list);
- /* Compile this expression once */
- re = xre_compile (name, PCRE_CASELESS);
- xfree ((voidstar) name);
- if (re == NULL)
- return;
- if (argc>2)
- {
- re_extra = pcre_study (re, 0, &errptr);
- if (errptr != NULL)
- {
- MP4HERROR ((warning_status, 0,
- _("Error:%s:%d: Bad regular expression `%s': %s"),
- CURRENT_FILE_LINE, list, errptr));
- return;
- }
- }
- for (i=1; i<argc; i++)
- {
- special_chars = 0;
- cp = ARG (i);
- while (IS_GROUP (*cp))
- {
- cp++;
- special_chars++;
- }
- if (*(ARG (i)+special_chars) != '\0')
- {
- cp = strchr (ARG (i)+special_chars, '=');
- if (cp)
- *cp = '\0';
- }
- /* Ensure that all subexpressions are stored */
- max_subexps = 0;
- do
- {
- max_subexps += 10;
- match_ptr = (int *)
- xrealloc ((voidstar) match_ptr, sizeof (int) * max_subexps * 3);
- rc = pcre_exec (re, re_extra, ARG (i)+special_chars,
- strlen (ARG (i)+special_chars), 0,
- 0, match_ptr, max_subexps * 3);
- }
- while (rc == PCRE_ERROR_NOMEMORY);
- max_subexps -= 10;
- if (rc > 0 && match)
- {
- if (!first)
- obstack_1grow (obs, ' ');
- first = FALSE;
- obstack_1grow (obs, CHAR_BGROUP);
- if (special_chars)
- obstack_grow (obs, ARG (i), special_chars);
- if (rc == 1)
- {
- obstack_grow (obs, ARG (i)+special_chars,
- strlen (ARG (i)+special_chars));
- }
- else
- {
- for (j=1; j<rc; j++)
- obstack_grow (obs, ARG (i)+special_chars+match_ptr[j*2],
- match_ptr[j*2+1] - match_ptr[j*2]);
- }
- if (cp)
- {
- obstack_1grow (obs, '=');
- obstack_grow (obs, cp+1, strlen (cp+1));
- }
- obstack_1grow (obs, CHAR_EGROUP);
- }
- else if (rc == PCRE_ERROR_NOMATCH && !match)
- {
- if (cp)
- *cp = '=';
- if (!first)
- obstack_1grow (obs, ' ');
- first = FALSE;
- obstack_1grow (obs, CHAR_BGROUP);
- obstack_grow (obs, ARG (i), strlen (ARG (i)));
- obstack_1grow (obs, CHAR_EGROUP);
- }
- }
- pcre_free (re);
- pcre_free (re_extra);
- xfree ((voidstar) match_ptr);
- }
- /*
- The rest of this file is the code for builtins and expansion of user
- defined macros. All the functions for builtins have a prototype as:
- void mp4h_bp_MACRONAME (
- struct obstack *obs,
- int argc,
- char *argv[],
- read_type expansion
- );
- The function are expected to leave their expansion on the obstack OBS,
- as an unfinished object. ARGV is a table of ARGC pointers to the
- individual arguments to the macro. Please note that in general
- argv[argc] != NULL.
- For container tags, argv[argc] contains the body function.
- */
- /* Notes for hackers :
- o Execution must not depend on argv[0]. Indeed, user may define
- synonyms with <let myfunc primitive>
- o Last argument is removed by collect_arguments () if it is empty.
- For this reason, it does not make sense to define a mimimal
- number of arguments.
- */
- /* Miscellaneous builtins -- "__file__" and "__line__". */
- static void
- mp4h_bp___file__ (MP4H_BUILTIN_ARGS)
- {
- if (argc == 1)
- shipout_string (obs, current_file, 0);
- else
- {
- xfree ((voidstar) current_file);
- current_file = xstrdup (ARG (1));
- }
- }
- static void
- mp4h_bp___line__ (MP4H_BUILTIN_ARGS)
- {
- if (argc == 1)
- shipout_int (obs, current_line);
- else
- numeric_arg (argv[0], ARG (1), FALSE, ¤t_line);
- }
- /*-----------------------------.
- | Initialize character table. |
- `-----------------------------*/
- void
- pcre_init (void)
- {
- re_tableptr = pcre_maketables ();
- }
- void
- pcre_deallocate (void)
- {
- pcre_free ((voidstar) re_tableptr);
- }
- /*---------------------.
- | Initialize locales. |
- `---------------------*/
- #ifdef HAVE_LOCALE_H
- void
- locale_init (int category, char *value)
- {
- setlocale (category, value);
- my_locale = localeconv ();
- decimal_point = my_locale->decimal_point;
- }
- /*---------------------------.
- | Change locale attributes. |
- `---------------------------*/
- static void
- mp4h_bp_mp4h_l10n (MP4H_BUILTIN_ARGS)
- {
- char *cp;
- int i;
- int category;
- for (i=1; i<argc; i++)
- {
- category = -1;
- cp = strchr (ARG (i), '=');
- if (cp)
- {
- *cp = '\0';
- if (strcmp (ARG (i), "LC_ALL") == 0)
- category = LC_ALL;
- else if (strcmp (ARG (i), "LC_COLLATE") == 0)
- category = LC_COLLATE;
- else if (strcmp (ARG (i), "LC_CTYPE") == 0)
- category = LC_CTYPE;
- else if (strcmp (ARG (i), "LC_MESSAGES") == 0)
- category = LC_MESSAGES;
- else if (strcmp (ARG (i), "LC_MONETARY") == 0)
- category = LC_MONETARY;
- else if (strcmp (ARG (i), "LC_NUMERIC") == 0)
- category = LC_NUMERIC;
- else if (strcmp (ARG (i), "LC_TIME") == 0)
- category = LC_TIME;
- }
- if (category == -1)
- MP4HERROR ((warning_status, 0,
- _("Warning:%s:%d: Unknown locale `%s'"), CURRENT_FILE_LINE, ARG (i)));
- else
- {
- locale_init (category, cp+1);
- pcre_deallocate ();
- pcre_init ();
- }
- }
- /* Compute syntax table */
- syntax_init ();
- }
- #endif /* HAVE_LOCALE_H */
- /*----------------------------------------------.
- | Set output radix used when printing numbers. |
- `----------------------------------------------*/
- static void
- mp4h_bp_mp4h_output_radix (MP4H_BUILTIN_ARGS)
- {
- if (bad_argc (argv[0], argc, 0, 2))
- return;
- safe_strtol (ARG (0), ARG (1), (long int *) &output_radix);
- }
- static void
- mp4h_bp_timer (MP4H_BUILTIN_ARGS)
- {
- char buf[128];
- times(&elapsed_time);
- sprintf (buf, "user %d\nsys %d\n", (int) elapsed_time.tms_utime,
- (int) elapsed_time.tms_stime);
- obstack_grow (obs, buf, strlen (buf));
- }
- #if !defined(HAVE_FILE_FUNCS) || !defined (HAVE_LOCALE_H) || !defined(WITH_MODULES)
- static void
- mp4h_bp_unsupported (MP4H_BUILTIN_ARGS)
- {
- MP4HERROR ((warning_status, 0,
- _("Warning:%s:%d: The <%s> tag is not implemented on your OS\n"),
- CURRENT_FILE_LINE, ARG (0)));
- }
- #endif
- static void
- mp4h_bp___version__ (MP4H_BUILTIN_ARGS)
- {
- obstack_grow (obs, PACKAGE_VERSION, strlen (PACKAGE_VERSION));
- }
- static void
- add_1char_protected (struct obstack *obs, char ch)
- {
- obstack_1grow (obs, CHAR_LQUOTE);
- obstack_1grow (obs, ch);
- obstack_1grow (obs, CHAR_RQUOTE);
- }
- static void
- mp4h_bp_lb (MP4H_BUILTIN_ARGS)
- {
- add_1char_protected (obs, '<');
- }
- static void
- mp4h_bp_rb (MP4H_BUILTIN_ARGS)
- {
- add_1char_protected (obs, '>');
- }
- static void
- mp4h_bp_dq (MP4H_BUILTIN_ARGS)
- {
- obstack_1grow (obs, CHAR_QUOTE);
- }
- static void
- mp4h_bp_bs (MP4H_BUILTIN_ARGS)
- {
- add_1char_protected (obs, '\\');
- }
- /* Enable tracing of all specified macros, or all, if none is specified.
- Tracing is disabled by default, when a macro is defined. This can be
- overridden by the "t" debug flag. */
- /*-----------------------------------------------------------------------.
- | Set_trace () is used by "debugging-on" and "debugging-off" to enable |
- | and disable tracing of a macro. It disables tracing if DATA is NULL, |
- | otherwise it enable tracing. |
- `-----------------------------------------------------------------------*/
- static void
- set_trace (symbol *sym, const char *data)
- {
- SYMBOL_TRACED (sym) = (boolean) (data != NULL);
- }
- static void
- mp4h_bp_debugging_on (MP4H_BUILTIN_ARGS)
- {
- symbol *s;
- int i;
- if (argc == 1)
- hack_all_symbols (set_trace, (char *) obs);
- else
- for (i = 1; i < argc; i++)
- {
- s = lookup_symbol (ARG (i), SYMBOL_LOOKUP);
- if (s != NULL)
- set_trace (s, (char *) obs);
- else
- MP4HERROR ((warning_status, 0,
- _("Warning:%s:%d: Undefined name %s"),
- CURRENT_FILE_LINE, ARG (i)));
- }
- }
- /*------------------------------------------------------------------------.
- | Disable tracing of all specified macros, or all, if none is specified. |
- `------------------------------------------------------------------------*/
- static void
- mp4h_bp_debugging_off (MP4H_BUILTIN_ARGS)
- {
- symbol *s;
- int i;
- if (argc == 1)
- hack_all_symbols (set_trace, NULL);
- else
- for (i = 1; i < argc; i++)
- {
- s = lookup_symbol (ARG (i), SYMBOL_LOOKUP);
- if (s != NULL)
- set_trace (s, NULL);
- else
- MP4HERROR ((warning_status, 0,
- _("Warning:%s:%d: Undefined name %s"),
- CURRENT_FILE_LINE, ARG (i)));
- }
- }
- /*----------------------------------------------------------------------.
- | On-the-fly control of the format of the tracing output. It takes one |
- | argument, which is a character string like given to the -d option, or |
- | none in which case the debug_level is zeroed. |
- `----------------------------------------------------------------------*/
- static void
- mp4h_bp_debugmode (MP4H_BUILTIN_ARGS)
- {
- int new_debug_level;
- int change_flag;
- if (bad_argc (argv[0], argc, 0, 2))
- return;
- if (argc == 1)
- debug_level = 0;
- else
- {
- if (ARG (1)[0] == '+' || ARG (1)[0] == '-')
- {
- change_flag = ARG (1)[0];
- new_debug_level = debug_decode (ARG (1) + 1);
- }
- else
- {
- change_flag = 0;
- new_debug_level = debug_decode (ARG (1));
- }
- if (new_debug_level < 0)
- MP4HERROR ((warning_status, 0,
- _("Warning:%s:%d: Bad debug flags: `%s'"),
- CURRENT_FILE_LINE, ARG (1)));
- else
- {
- switch (change_flag)
- {
- case 0:
- debug_level = new_debug_level;
- break;
- case '+':
- debug_level |= new_debug_level;
- break;
- case '-':
- debug_level &= ~new_debug_level;
- break;
- }
- }
- }
- }
- /*-------------------------------------------------------------------------.
- | Specify the destination of the debugging output. With one argument, the |
- | argument is taken as a file name, with no arguments, revert to stderr. |
- `-------------------------------------------------------------------------*/
- static void
- mp4h_bp_debugfile (MP4H_BUILTIN_ARGS)
- {
- if (bad_argc (argv[0], argc, 1, 2))
- return;
- if (argc == 1)
- debug_set_output (NULL);
- else if (!debug_set_output (ARG (1)))
- MP4HERROR ((warning_status, errno,
- _("Warning:%s:%d: Cannot set error file: %s"),
- CURRENT_FILE_LINE, ARG (1)));
- }
- /*---------------------------------------------------------.
- | Print the replacement text for a builtin or user macro. |
- `---------------------------------------------------------*/
- static void
- mp4h_bp_function_def (MP4H_BUILTIN_ARGS)
- {
- symbol *s;
- if (bad_argc (argv[0], argc, 2, 2))
- return;
- s = lookup_symbol (ARG (1), SYMBOL_LOOKUP);
- if (s == NULL)
- return;
- switch (SYMBOL_TYPE (s))
- {
- case TOKEN_TEXT:
- obstack_1grow (obs, CHAR_LQUOTE);
- shipout_string (obs, SYMBOL_TEXT (s), strlen (SYMBOL_TEXT (s)));
- obstack_1grow (obs, CHAR_RQUOTE);
- break;
- case TOKEN_FUNC:
- push_macro (SYMBOL_FUNC (s), SYMBOL_TRACED (s));
- break;
- case TOKEN_VOID:
- break;
- default:
- MP4HERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad symbol type in mp4h_bp_function_def ()"));
- exit (1);
- }
- }
- /* file functions */
- #ifdef HAVE_FILE_FUNCS
- /*-----------------------------------------------------------------.
- | Informations on a file. A newline separated string is printed: |
- | Line 1: file size |
- | Line 2: file type |
- | Line 3: time of last change |
- | Line 4: time of last modification |
- | Line 5: time of last modification |
- | Line 6: time of last access |
- | Line 7: name of the owner of this file |
- | Line 8: name of the group of this file |
- `-----------------------------------------------------------------*/
- static void
- mp4h_bp_get_file_properties (MP4H_BUILTIN_ARGS)
- {
- struct stat buf;
- struct passwd *user;
- struct group *group;
- CHECK_SAFETY_LEVEL(1);
- if (bad_argc (argv[0], argc, 2, 2))
- return;
- if (stat (ARG (1), &buf))
- {
- MP4HERROR ((warning_status, errno,
- _("Warning:%s:%d: Could not stat `%s'"),
- CURRENT_FILE_LINE, ARG (1)));
- return;
- }
- shipout_long (obs, (long) buf.st_size);
- obstack_1grow (obs, '\n');
- if (S_ISLNK(buf.st_mode))
- obstack_grow (obs, "LINK", 4);
- else if (S_ISREG(buf.st_mode))
- obstack_grow (obs, "FILE", 4);
- else if (S_ISDIR(buf.st_mode))
- obstack_grow (obs, "DIR", 3);
- else
- obstack_grow (obs, "UNKNOWN", 7);
- obstack_1grow (obs, '\n');
- shipout_long (obs, (long) buf.st_ctime);
- obstack_1grow (obs, '\n');
- shipout_long (obs, (long) buf.st_mtime);
- obstack_1grow (obs, '\n');
- shipout_long (obs, (long) buf.st_atime);
- obstack_1grow (obs, '\n');
- user = getpwuid (buf.st_uid);
- if (user)
- obstack_grow (obs, user->pw_name, strlen (user->pw_name));
- else
- obstack_grow (obs, "(UNKNOWN)", 9);
- obstack_1grow (obs, '\n');
- group = getgrgid (buf.st_gid);
- if (group)
- obstack_grow (obs, group->gr_name, strlen (group->gr_name));
- else
- obstack_grow (obs, "(UNKNOWN)", 9);
- obstack_1grow (obs, '\n');
- }
- /*-----------------------------------------------------------------.
- | Prints a directory contents. A pattern can be specified with |
- | the ``matching'' attribute. This pattern is a regexp one, |
- | not a shell expansion. |
- `-----------------------------------------------------------------*/
- static void
- mp4h_bp_directory_contents (MP4H_BUILTIN_ARGS)
- {
- DIR *dir;
- struct dirent *entry;
- int length;
- const char *matching;
- pcre *re = NULL;
- pcre_extra *re_extra = NULL;
- const char *errptr = NULL;
- int *match_ptr = NULL;
- boolean first = TRUE;
- CHECK_SAFETY_LEVEL(1);
- matching = predefined_attribute ("matching", &argc, argv, FALSE);
- if (bad_argc (argv[0], argc, 2, 2))
- return;
- /* First, opens directory. */
- dir = opendir (ARG (1));
- if (dir == NULL)
- return;
- if (matching)
- {
- re = xre_compile (matching, 0);
- if (re == NULL)
- return;
- match_ptr = (int *)
- xrealloc ((voidstar) match_ptr, sizeof (int) * 3);
- re_extra = pcre_study (re, 0, &errptr);
- if (errptr != NULL)
- {
- MP4HERROR ((warning_status, 0,
- _("Error:%s:%d: Bad regular expression `%s': %s"),
- CURRENT_FILE_LINE, matching, errptr));
- return;
- }
- }
- while ((entry = readdir (dir)) != (struct dirent *)NULL)
- {
- length = strlen (entry->d_name);
- if (!matching ||
- (pcre_exec (re, re_extra, entry->d_name, length, 0,
- 0, match_ptr, 3) > 0
- && match_ptr[1] - match_ptr[0] == length))
- {
- if (!first)
- obstack_1grow (obs, '\n');
- obstack_grow (obs, entry->d_name, length);
- first = FALSE;
- }
- }
- if (matching)
- {
- pcre_free (re);
- pcre_free (re_extra);
- xfree ((voidstar) match_ptr);
- }
- closedir (dir);
- }
- /*--------------------------------.
- | Returns "true" if file exists. |
- `--------------------------------*/
- static void
- mp4h_bp_file_exists (MP4H_BUILTIN_ARGS)
- {
- struct stat file;
- CHECK_SAFETY_LEVEL(1);
- if (bad_argc (argv[0], argc, 2, 2))
- return;
- if ((stat (ARG (1), &file)) != -1)
- obstack_grow (obs, "true", 4);
- }
- /*------------------------------------.
- | Returns a real (absolute) path name |
- `------------------------------------*/
- static void
- mp4h_bp_real_path (MP4H_BUILTIN_ARGS)
- {
- const char *pathname;
- char resolvedname[MAXPATHLEN];
- CHECK_SAFETY_LEVEL(1);
- pathname = predefined_attribute ("pathname", &argc, argv, FALSE);
- if (!pathname)
- MP4HERROR ((warning_status, 0,
- _("Warning:%s:%d: In <%s>, required attribute `%s' is not specified"),
- CURRENT_FILE_LINE, ARG (0), "pathname"));
- else
- if (!realpath(pathname, resolvedname))
- MP4HERROR ((warning_status, errno,
- _("Error:%s:%d: Cannot form real path for `%s'"),
- CURRENT_FILE_LINE, pathname));
- else
- obstack_grow(obs, resolvedname, strlen(resolvedname));
- }
- #endif /* HAVE_FILE_FUNCS */
- /*------------------------------------------------------------.
- | Converts an epoch to a readable string. |
- | If no argument is given, current date and time is printed. |
- `------------------------------------------------------------*/
- static void
- mp4h_bp_date (MP4H_BUILTIN_ARGS)
- {
- time_t epoch_time = (time_t)0;
- char *ascii_time;
- const char *format, *timespec;
- struct tm *timeptr;
- char *endp = NULL;
- format = predefined_attribute ("format", &argc, argv, FALSE);
- timespec = predefined_attribute ("time", &argc, argv, FALSE);
- if (!format && !timespec)
- /* backwards compatible... */
- if (argc > 1)
- timespec = ARG (1);
- if (timespec)
- {
- epoch_time = strtol (timespec, &endp, 10);
- if (!endp)
- {
- MP4HERROR ((warning_status, 0,
- _("Warning:%s:%d: Invalid value in date: %s"),
- CURRENT_FILE_LINE, ARG (1)));
- return;
- }
- }
- else
- epoch_time = time ((time_t *)NULL);
- timeptr = (struct tm *) localtime (&epoch_time);
- if (format)
- {
- ascii_time = (char *)xmalloc(1000);
- strftime(ascii_time, 1000, format, timeptr);
- obstack_grow (obs, ascii_time, strlen (ascii_time));
- xfree((voidstar) ascii_time);
- }
- else
- {
- ascii_time = (char *) asctime (timeptr);
- /* Remove newline. */
- LAST_CHAR (ascii_time) = '\0';
- obstack_grow (obs, ascii_time, strlen (ascii_time));
- }
- }
- /* Flow functions: these functions allow complex structures
- There are 2 different kinds of conditions : numerical and
- string tests. A numerical test is false if result is null
- and right if non null. String-based tests are false if
- followed by a null string, and right otherwise. */
- /*----------------------------------------------------------.
- | Group multiple tags into one. This is useful when |
- | combined with tests like <if>, <ifeq>, .... |
- `----------------------------------------------------------*/
- static void
- mp4h_bp_group (MP4H_BUILTIN_ARGS)
- {
- const char *separator;
- separator = predefined_attribute ("separator", &argc, argv, FALSE);
- obstack_1grow (obs, CHAR_BGROUP);
- /* separator = NULL is handled by dump_args */
- dump_args (obs, argc, argv, separator);
- obstack_1grow (obs, CHAR_EGROUP);
- }
- /*------------------------------------------------.
- | Like <group>, but this one is a container tag. |
- `------------------------------------------------*/
- static void
- mp4h_bp_compound (MP4H_BUILTIN_ARGS)
- {
- const char *separator;
- separator = predefined_attribute ("separator", &argc, argv, FALSE);
- obstack_1grow (obs, CHAR_BGROUP);
- /* separator = NULL is handled by dump_args */
- dump_args (obs, argc, argv, separator);
- obstack_grow (obs, ARGBODY, strlen (ARGBODY));
- obstack_1grow (obs, CHAR_EGROUP);
- }
- /*------------------------------------------------.
- | Allow breaking an object into several pieces. |
- `------------------------------------------------*/
- static void
- mp4h_bp_disjoin (MP4H_BUILTIN_ARGS)
- {
- obstack_1grow (obs, CHAR_EGROUP);
- obstack_grow (obs, ARG(1), strlen (ARG(1)));
- obstack_1grow (obs, CHAR_BGROUP);
- }
- /*-------------------------------------------.
- | Prevent further expansion of attributes. |
- `-------------------------------------------*/
- static void
- mp4h_bp_noexpand (MP4H_BUILTIN_ARGS)
- {
- obstack_1grow (obs, CHAR_LQUOTE);
- dump_args (obs, argc, argv, NULL);
- obstack_1grow (obs, CHAR_RQUOTE);
- }
- /*----------------------------------------------------------.
- | Remove special characters which forbid expansion. |
- `----------------------------------------------------------*/
- static void
- mp4h_bp_expand (MP4H_BUILTIN_ARGS)
- {
- int i, offset;
- register char *cp;
- for (i=1; i<argc; i++)
- {
- offset = 0;
- for (cp=ARG (i); *cp != '\0'; cp++)
- {
- if (*cp == CHAR_LQUOTE || *cp == CHAR_RQUOTE)
- offset++;
- else
- *(cp-offset) = *cp;
- }
- *(cp-offset) = '\0';
- }
- dump_args (obs, argc, argv, NULL);
- }
- /*--------------------------------------------------------------.
- | If followed by a non-empty string, second argument is |
- | expanded, otherwise 3rd argument is read. |
- `--------------------------------------------------------------*/
- static void
- mp4h_bp_if (MP4H_BUILTIN_ARGS)
- {
- symbol *var;
- if (bad_argc (argv[0], argc, 0, 4))
- return;
- if (argc == 1)
- return;
- /* The ``natural'' way to implement <if/> is with
- obstack_grow (obs, "<when ", 6);
- obstack_grow (obs, ARG (1), strlen (ARG (1)));
- obstack_grow (obs, " >", 2);
- obstack_grow (obs, ARG (2), strlen (ARG (2)));
- obstack_grow (obs, "</when>", 7);
- and a similar else-clause.
- But this is broken, because ARG(2) may change the condition, and
- then else-clause could be run too.
- For this reason, the following implementation is preferred.
- */
- var = lookup_variable ("__cond_cnt", SYMBOL_LOOKUP);
- if (var == NULL)
- {
- var = lookup_variable ("__cond_cnt", SYMBOL_INSERT);
- SYMBOL_TEXT (var) = (char *) xstrdup ("0");
- SYMBOL_TYPE (var) = TOKEN_TEXT;
- }
- obstack_grow (obs, "<increment __cond_cnt />", 24);
- obstack_grow (obs, "<set-var __cond_var<get-var __cond_cnt />=", 42);
- obstack_1grow (obs, CHAR_BGROUP);
- obstack_grow (obs, ARG (1), strlen (ARG (1)));
- obstack_1grow (obs, CHAR_EGROUP);
- obstack_grow (obs, " />", 3);
- obstack_grow (obs, "<when <get-var __cond_var<get-var __cond_cnt /> /> >", 52);
- obstack_grow (obs, ARG (2), strlen (ARG (2)));
- obstack_grow (obs, "</when>", 7);
- if (argc>3)
- {
- obstack_grow (obs, "<when <not <get-var __cond_var<get-var __cond_cnt /> /> /> >", 60);
- obstack_grow (obs, ARG (3), strlen (ARG (3)));
- obstack_grow (obs, "</when>", 7);
- }
- obstack_grow (obs, "<decrement __cond_cnt />", 24);
- }
- /*------------------------------------------------------.
- | String comparisons. |
- | If 2nd and 3rd arguments are equal, 4th argumeā¦
Large files files are truncated, but you can click here to view the full file