9506a1 | 2016-08-20 | Martin Nilsson | | /* -*- mode: c; encoding: utf-8; -*-
|
e576bb | 2002-10-11 | Martin Nilsson | | || This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information.
*/
|
24ddc7 | 1998-03-28 | Henrik Grubbström (Grubba) | |
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | #include "global.h"
#include "stralloc.h"
#include "module_support.h"
#include "interpret.h"
#include "svalue.h"
#include "pike_macros.h"
#include "program.h"
|
142073 | 2017-02-08 | Henrik Grubbström (Grubba) | | #include "pike_compiler.h"
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | #include "object.h"
|
b2d3e4 | 2000-12-01 | Fredrik Hübinette (Hubbe) | | #include "pike_error.h"
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | #include "array.h"
#include "mapping.h"
#include "builtin_functions.h"
#include "operators.h"
#include "constants.h"
#include "time.h"
|
f0950a | 1999-03-27 | Henrik Grubbström (Grubba) | | #include "version.h"
|
a0180b | 2003-11-14 | Martin Stjernholm | | #include "pike_types.h"
|
b964fd | 2004-04-16 | Martin Stjernholm | | #include "cpp.h"
|
bdd37a | 2004-11-02 | Martin Stjernholm | | #include "lex.h"
|
9d1f54 | 2017-01-25 | Henrik Grubbström (Grubba) | | #include "sprintf.h"
|
f0950a | 1999-03-27 | Henrik Grubbström (Grubba) | |
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | #include <ctype.h>
|
3b8741 | 2016-07-27 | Henrik Grubbström (Grubba) | | #define DEFAULT_CMOD_STORAGE
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | #define CPP_NO_OUTPUT 1 /* Inside false section of #if/#else */
#define CPP_EXPECT_ELSE 2 /* Expect #else/#elif/#elseif. */
#define CPP_EXPECT_ENDIF 4 /* Expect #endif */
#define CPP_REALLY_NO_OUTPUT 8 /* Entire preprocessor is in false section. */
#define CPP_END_AT_NEWLINE 16 /* Halt at end of line. */
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | #define CPP_DO_IF 32
|
0d52dd | 1998-01-16 | Fredrik Hübinette (Hubbe) | | #define CPP_NO_EXPAND 64
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
#define OUTP() (!(flags & (CPP_NO_OUTPUT | CPP_REALLY_NO_OUTPUT)))
|
d9ac33 | 1999-02-22 | Henrik Grubbström (Grubba) | | #define PUTNL() string_builder_putchar(&this->buf, '\n')
|
74966e | 2014-05-12 | Per Hedbor | | #define GOBBLE(X) (INDEX_PCHARP(data,pos)==(X)?++pos,1:0)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | #define PUTC(C) do { \
|
d9ac33 | 1999-02-22 | Henrik Grubbström (Grubba) | | int c_=(C); if(OUTP() || c_=='\n') string_builder_putchar(&this->buf, c_); }while(0)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
#define MAX_ARGS 255
#define DEF_ARG_STRINGIFY 0x100000
#define DEF_ARG_NOPRESPACE 0x200000
#define DEF_ARG_NOPOSTSPACE 0x400000
|
9b52e5 | 2011-10-24 | Tobias S. Josefowitz | | #define DEF_ARG_NEED_COMMA 0x800000
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | #define DEF_ARG_MASK 0x0fffff
|
58efb8 | 2014-05-12 | Per Hedbor | | #ifdef __GNUC__
#pragma GCC optimize "-Os"
#endif
|
7050b7 | 2014-02-25 | Per Hedbor | |
/* Return true if compat version is equal or less than MAJOR.MINOR */
#define CPP_TEST_COMPAT(THIS,MAJOR,MINOR) \
(THIS->compat_major < (MAJOR) || \
(THIS->compat_major == (MAJOR) && \
THIS->compat_minor <= (MINOR)))
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | #if 0
#define CALC_DUMPPOS(X) DUMPPOS(X)
#else /* !0 */
#define CALC_DUMPPOS(X)
#endif /* 0 */
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
516482 | 2004-11-14 | Martin Stjernholm | | static struct pike_string *efun_str;
static struct pike_string *constant_str;
static struct pike_string *defined_str;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | struct pike_predef_s
{
struct pike_predef_s *next;
char *name;
char *value;
};
|
b584b1 | 2001-12-20 | Martin Stjernholm | | static int use_initial_predefs;
static struct pike_predef_s *first_predef = NULL, *last_predef = NULL;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | struct define_argument {
|
2dc009 | 1999-02-27 | Henrik Grubbström (Grubba) | | PCHARP arg;
|
f49e47 | 2000-08-10 | Henrik Grubbström (Grubba) | | ptrdiff_t len;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | };
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | struct CPP_struct;
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct;
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | typedef void (*magic_define_fun)(struct CPP_struct *,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *,
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *,
|
d9ac33 | 1999-02-22 | Henrik Grubbström (Grubba) | | struct string_builder *);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
be65c5 | 2016-09-02 | Henrik Grubbström (Grubba) | | DECLARATIONS;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
7db6bc | 2016-09-08 | Henrik Grubbström (Grubba) | | #define CPP_MACRO_DISABLED 1 /* Don't expand. */
#define CPP_MACRO_IN_USE 2 /* In use. */
|
347b10 | 2018-04-19 | Henrik Grubbström (Grubba) | | #define CPP_MACRO_VARARGS 4 /* Varargs. */
|
7db6bc | 2016-09-08 | Henrik Grubbström (Grubba) | |
|
6e5cb6 | 2018-03-08 | Henrik Grubbström (Grubba) | | /*! @class Stack
*! This class implements a simple stack. Instead of adding and removing
*! elements to an array, and thus making it vary in size for every push
*! and pop operation, this stack tries to keep the stack size constant.
*! If however the stack risks to overflow, it will allocate double its
*! current size, i.e. pushing an element on an full 32 slot stack will
*! result in a 64 slot stack with 33 elements.
*/
PIKECLASS Stack
{
PIKEVAR array arr;
/*! @decl void push(mixed val)
*! Push an element on the top of the stack.
*/
PIKEFUN void push(mixed val)
{
if (!THIS->arr) {
THIS->arr = real_allocate_array(1, 31);
array_set_index_no_free(THIS->arr, 0, val);
} else {
THIS->arr = array_insert(THIS->arr, val, THIS->arr->size);
}
push_int(0);
}
/*! @decl mixed top()
*! Returns the top element from the stack, without
*! popping it.
*! @throws
*! Throws an error if called on an empty stack.
*/
PIKEFUN mixed top()
{
if (THIS->arr && THIS->arr->size) {
push_svalue(ITEM(THIS->arr) + THIS->arr->size - 1);
return;
}
Pike_error("Stack underflow\n");
}
/*! @decl mixed pop(void|int val)
*! Pops and returns entry @[val] from the stack, counting
*! from the top. If no value is given the top element is
*! popped and returned. All popped entries are freed from
*! the stack.
*/
PIKEFUN mixed pop(void|int val)
{
if (!THIS->arr || !THIS->arr->size) {
Pike_error("Stack underflow\n");
}
if (val && (val->u.integer > 0)) {
ptrdiff_t new_size;
ptrdiff_t old_size;
new_size = THIS->arr->size - val->u.integer;
if (new_size < 0) new_size = 0;
/* NB: Steal reference from the array element. */
*Pike_sp = ITEM(THIS->arr)[new_size];
old_size = THIS->arr->size;
THIS->arr->size = new_size;
Pike_sp++;
free_svalues(ITEM(THIS->arr) + new_size + 1, old_size - (new_size + 1),
THIS->arr->type_field);
} else {
/* NB: Steal reference from the array element. */
THIS->arr->size--;
*Pike_sp = ITEM(THIS->arr)[THIS->arr->size];
Pike_sp++;
}
}
/*! @decl void quick_pop(void|int val)
*! Pops @[val] entries from the stack, or one entry
*! if no value is given. The popped entries are not
*! returned.
*/
PIKEFUN void quick_pop(void|int val)
{
apply_current(f_Stack_quick_pop_fun_num, args);
push_int(0);
}
/*! @decl void reset(int|void initial_size)
*! Empties the stack, resets the stack pointer
*! and shrinks the stack size to the given value
*! or 32 if none is given.
*! @seealso
*! @[create]
*/
PIKEFUN void reset(int|void initial_size)
{
ptrdiff_t size = 32;
if (initial_size && (initial_size->u.integer > 0)) {
size = initial_size->u.integer;
}
if (THIS->arr) {
free_array(THIS->arr);
THIS->arr = NULL;
}
/* NB: The initial size MUST != 0 else the empty array will be returned. */
THIS->arr = real_allocate_array(1, size-1);
THIS->arr->size = 0;
}
/*! @decl void create(int|void initial_size)
*! An initial stack size can be given when
*! a stack is cloned. The default value is
*! 32.
*/
PIKEFUN void create(int|void initial_size)
{
apply_current(f_Stack_reset_fun_num, args);
}
/*! @decl void set_stack(array stack)
*! Sets the stacks content to the provided array.
*/
PIKEFUN void set_stack(array stack)
{
if (THIS->arr) {
free_array(THIS->arr);
}
add_ref(THIS->arr = stack);
}
/*! @decl int _sizeof()
*! @[sizeof] on a stack returns the number of entries
*! in the stack.
*/
PIKEFUN int _sizeof()
flags ID_PROTECTED;
{
push_int(THIS->arr ? THIS->arr->size : 0);
}
/*! @decl array _values()
*! @[values] on a stack returns all the entries in
*! the stack, in order.
*/
PIKEFUN array _values()
flags ID_PROTECTED;
{
if (THIS->arr) {
push_array(copy_array(THIS->arr));
} else {
ref_push_array(&empty_array);
}
}
/*! @decl int _search(mixed item)
*! Return the stack-depth to @[item].
*!
*! This function makes it possible to use
*! eg @[search()] and @[has_value()] on the stack.
*/
PIKEFUN int _search(mixed item)
flags ID_PROTECTED;
{
if (!THIS->arr || !THIS->arr->size) {
push_int(-1);
} else {
push_int(array_search(THIS->arr, item, 0));
}
}
/*! @decl this_program `+(this_program s)
*! A stack added with another stack yields a new
*! stack with all the elements from both stacks,
*! and the elements from the second stack at the
*! top of the new stack.
*/
PIKEFUN Stack `+(Stack s)
flags ID_PROTECTED;
{
struct Stack_struct *other_st = get_storage(s, Stack_program);
int cnt = 0;
if (!other_st) {
SIMPLE_BAD_ARG_ERROR("`+", 1, "Stack");
}
if (THIS->arr) {
ref_push_array(THIS->arr);
cnt++;
}
if (other_st->arr) {
ref_push_array(THIS->arr);
cnt++;
}
if (cnt == 1) {
ref_push_array(&empty_array);
}
if (cnt) {
f_add(2);
#ifdef PIKE_DEBUG
if (TYPEOF(Pike_sp[-1]) != PIKE_T_ARRAY) {
Pike_fatal("Stack addition failure.\n");
}
#endif
push_object(s = fast_clone_object(Stack_program));
other_st = get_storage(s, Stack_program);
#ifdef PIKE_DEBUG
if (!other_st) {
Pike_fatal("Stack lost storage.\n");
}
#endif
add_ref(other_st->arr = Pike_sp[-2].u.array);
return;
}
push_object(clone_object(Stack_program, 0));
}
PIKEFUN mixed cast(string to)
flags ID_PROTECTED;
{
if( to == MK_STRING("array") ) {
apply_current(f_Stack_cq__values_fun_num, 0);
} else {
push_undefined();
}
}
PIKEFUN string _sprintf(int t)
flags ID_PROTECTED;
{
if (t != '0') {
push_undefined();
}
push_constant_text("%O%O");
ref_push_program(Pike_fp->current_program);
apply_current(f_Stack_cq__values_fun_num, 0);
f_sprintf(3);
}
}
/*! @endclass
*/
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | /* Consider
*
* class Preprocessor
* {
* class Macro
* {
* }
*
* mapping(string:Macro) macros;
*
* class Context
* {
* inherit String.Buffer;
*
* string current_file;
* int current_line;
*
* string directive_*(...);
*
* void cpp(string data);
*
* Context clone();
* }
* }
*
* string cpp(...)
* {
* Preprocessor p = Preprocessor();
* p->init();
* Preprocessor.Context ctx = p->Context();
* ctx->cpp(data);
* return ctx->get();
* }
*/
static void insert_callback_define(struct CPP_struct *this,
struct define_struct *def,
struct pike_string *arg,
struct string_builder *tmp);
static void insert_callback_define_no_args(struct CPP_struct *this,
struct define_struct *def,
struct pike_string *arg,
struct string_builder *tmp);
static void insert_pragma(struct CPP_struct *this,
struct define_struct *def,
struct pike_string *arg,
struct string_builder *tmp);
/*! @class define
*/
|
be65c5 | 2016-09-02 | Henrik Grubbström (Grubba) | | PIKECLASS define
{
|
279a4f | 2016-09-03 | Henrik Grubbström (Grubba) | | PIKEVAR string name flags ID_PRIVATE|ID_PROTECTED;
|
7a6120 | 2016-09-04 | Henrik Grubbström (Grubba) | | PIKEVAR array(string|int) parts flags ID_PRIVATE|ID_PROTECTED;
|
be65c5 | 2016-09-02 | Henrik Grubbström (Grubba) | | CVAR magic_define_fun magic;
CVAR int args;
|
7db6bc | 2016-09-08 | Henrik Grubbström (Grubba) | | CVAR short flags; /* CPP_MACRO_* */
|
be65c5 | 2016-09-02 | Henrik Grubbström (Grubba) | |
|
2e060f | 2018-04-04 | Henrik Grubbström (Grubba) | | CVAR struct svalue self;
|
be65c5 | 2016-09-02 | Henrik Grubbström (Grubba) | | DECLARE_STORAGE;
|
f8a633 | 2016-09-02 | Henrik Grubbström (Grubba) | | INIT
{
|
b46752 | 2017-06-25 | Martin Nilsson | | struct define_struct *def = (struct define_struct *)CURRENT_STORAGE;
|
2e060f | 2018-04-04 | Henrik Grubbström (Grubba) | | /* NB: NO reference for def->self! */
SET_SVAL(def->self, T_OBJECT,
Pike_fp->context - Pike_fp->current_program->inherits,
object, Pike_fp->current_object);
|
f8a633 | 2016-09-02 | Henrik Grubbström (Grubba) | | def->args=-1;
|
b46752 | 2017-06-25 | Martin Nilsson | | #ifdef PIKE_NULL_IS_SPECIAL
def->magic=0;
|
7db6bc | 2016-09-08 | Henrik Grubbström (Grubba) | | def->flags = 0;
|
b46752 | 2017-06-25 | Martin Nilsson | | #endif
|
f8a633 | 2016-09-02 | Henrik Grubbström (Grubba) | | }
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | |
PIKEFUN void create(string name, int num_args,
array(string|int|function(mixed|void...:string)) parts)
flags ID_PROTECTED;
{
if (THIS->name) free_string(THIS->name);
add_ref(THIS->name = name);
/* FIXME: Validate the arguments. */
THIS->args = num_args;
THIS->flags = 0;
if (THIS->parts) {
free_array(THIS->parts);
}
add_ref(THIS->parts = parts);
}
#ifndef tObjImpl_CPP
#define tObjImpl_CPP tObj
#endif
|
e21e1a | 2018-04-07 | Henrik Grubbström (Grubba) | | /*! @decl string `()(array(string)|void arguments, CPP|void context, int|void flags)
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | *!
*! @param arguments
*! Array of arguments to the macro. Zero if no parenthesis.
*!
*! @param context
*! CPP context we are evaluating in.
*!
*! @returns
*! Returns the expansion of the macro.
*/
|
e21e1a | 2018-04-07 | Henrik Grubbström (Grubba) | | PIKEFUN string `()(array(string)|void arguments, object(CPP)|void context_obj,
int|void flags_sval)
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | flags ID_PROTECTED;
{
struct define_struct *d = THIS;
struct string_builder s;
struct array *parts = THIS->parts;
INT32 i;
|
e21e1a | 2018-04-07 | Henrik Grubbström (Grubba) | | INT_TYPE flags = flags_sval?flags_sval->u.integer:0;
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | |
init_string_builder(&s, 0);
if(d->magic)
{
struct pike_string *a = NULL;
struct CPP_struct *this = get_storage(context_obj, CPP_program);
if (d->args > 0) {
a = ITEM(arguments)[0].u.string;
}
d->magic(this, d, a, &s);
/* NB: The variable 'a' does not holdany refs. */
if (d->magic == insert_callback_define ||
d->magic == insert_callback_define_no_args ||
d->magic == insert_pragma) {
goto keep_new_lines;
}
goto remove_new_lines;
}
for (i = 0; i < parts->size; i++) {
struct svalue *sval = &parts->item[i];
switch (TYPEOF(*sval)) {
case PIKE_T_STRING:
string_builder_shared_strcat(&s, sval->u.string);
break;
case PIKE_T_INT:
{
int raw_arg = sval->u.integer;
int arg = raw_arg & DEF_ARG_MASK;
struct pike_string *str;
if (!arguments || (arg >= arguments->size)) {
yyerror("Too few arguments to macro.");
break;
}
str = arguments->item[arg].u.string;
if (raw_arg & DEF_ARG_NEED_COMMA) {
|
347b10 | 2018-04-19 | Henrik Grubbström (Grubba) | | if (!(d->flags & CPP_MACRO_VARARGS) ||
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | (arg != d->args-1) ||
str->len) {
/* Don't add the comma if the varargs argument and empty. */
string_builder_putchar(&s, ',');
string_builder_putchar(&s, ' ');
}
}
if (!(raw_arg & DEF_ARG_NOPRESPACE)) {
string_builder_putchar(&s, ' ');
}
if (raw_arg & DEF_ARG_STRINGIFY) {
string_builder_putchar(&s, '\"');
string_builder_quote_string(&s, str, 0, 0x7fffffff,
|
397d78 | 2018-04-09 | Henrik Grubbström (Grubba) | | QUOTE_NO_STRING_CONCAT|
QUOTE_NORMALIZE_WS|
QUOTE_TOKENIZE);
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | string_builder_putchar(&s, '\"');
} else {
if (raw_arg & (DEF_ARG_NOPRESPACE|DEF_ARG_NOPOSTSPACE)) {
PCHARP a = MKPCHARP_STR(str);
ptrdiff_t len = str->len;
if (raw_arg & DEF_ARG_NOPRESPACE) {
while(len && wide_isspace(EXTRACT_PCHARP(a))) {
INC_PCHARP(a, 1);
len--;
}
}
if (raw_arg & DEF_ARG_NOPOSTSPACE) {
while(len && wide_isspace(INDEX_PCHARP(a, len-1))) {
len--;
}
}
string_builder_append(&s, a, len);
} else {
|
e21e1a | 2018-04-07 | Henrik Grubbström (Grubba) | | /* NB: Evaluate the argument before insertion. */
int save_flags = d->flags;
|
52791d | 2018-04-15 | Henrik Grubbström (Grubba) | | d->flags |= CPP_MACRO_IN_USE;
|
e21e1a | 2018-04-07 | Henrik Grubbström (Grubba) | |
ref_push_string(str);
push_int(flags & ~(CPP_EXPECT_ENDIF | CPP_EXPECT_ELSE));
safe_apply(context_obj, "cpp", 2);
string_builder_shared_strcat(&s, Pike_sp[-1].u.string);
pop_stack();
d->flags = save_flags;
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | }
}
|
e21e1a | 2018-04-07 | Henrik Grubbström (Grubba) | | if (!(raw_arg & DEF_ARG_NOPOSTSPACE)) {
string_builder_putchar(&s, ' ');
}
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | }
break;
default:
/* FIXME: Check that we have a callable. */
if (arguments) {
push_array_items(arguments);
apply_svalue(sval, arguments->size);
} else {
apply_svalue(sval, 0);
}
if (TYPEOF(Pike_sp[-1]) != T_STRING) {
my_yyerror("Invalid return value from macro: %s (expected string).",
get_name_of_type(TYPEOF(Pike_sp[-1])));
pop_stack();
break;
}
string_builder_shared_strcat(&s, Pike_sp[-1].u.string);
pop_stack();
break;
}
}
remove_new_lines:
/* Remove any newlines from the completed expression. */
for(i=0; i< (ptrdiff_t)s.s->len; i++)
if(index_shared_string(s.s, i) == '\n')
SET_INDEX_CHARP(s.s->str, i, s.s->size_shift, ' ');
keep_new_lines:
pop_n_elems(args);
push_string(finish_string_builder(&s));
}
|
be65c5 | 2016-09-02 | Henrik Grubbström (Grubba) | | }
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | /*! @endclass define
*/
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
0732a5 | 2018-03-30 | Henrik Grubbström (Grubba) | | /*! @class CPP
*!
*! The state for an instance of the preprocessor.
*!
*! @seealso
*! @[predef::cpp()]
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | PIKECLASS CPP
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | PIKEVAR mapping(string:object(define)) defines flags ID_PRIVATE|ID_PROTECTED;
PIKEVAR int current_line;
PIKEVAR int compile_errors;
PIKEVAR string current_file;
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | | PIKEVAR string charset;
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | CVAR struct string_builder buf;
PIKEVAR object handler;
PIKEVAR object compat_handler;
PIKEVAR int compat_major;
PIKEVAR int compat_minor;
PIKEVAR string prefix;
PIKEVAR int picky_cpp;
PIKEVAR int keep_comments;
PIKEVAR int dependencies_fail;
|
e19aca | 2018-01-06 | Henrik Grubbström (Grubba) | | PIKEVAR int auto_convert;
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | |
|
86bc4e | 2018-01-12 | Henrik Grubbström (Grubba) | | PIKEVAR mapping(string:function(string:string)) directives flags ID_PROTECTED;
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | INIT
{
init_string_builder(&THIS->buf, 0);
}
EXIT
{
/* NOTE: Most of the fields are mapped, and thus freed automatically. */
if (THIS->buf.s) {
free_string_builder(&THIS->buf);
}
}
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
350169 | 2018-03-31 | Henrik Grubbström (Grubba) | | PIKEFUN string _sprintf(int c, mapping|void opts)
flags ID_PROTECTED;
{
struct CPP_struct *this = THIS;
ref_push_string(MK_STRING("CPP(%s:%d)"));
if (this->current_file) {
ref_push_string(this->current_file);
} else {
ref_push_string(MK_STRING("-"));
}
push_int(this->current_line);
f_sprintf(2);
}
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | #define FIND_DEFINE(N) find_define(this, (N))
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static struct define_struct *find_define(struct CPP_struct *this, struct pike_string *n)
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | {
struct svalue *s;
if (!this->defines) return NULL;
if (!(s = low_mapping_string_lookup(this->defines, n))) return NULL;
if (TYPEOF(*s) != T_OBJECT) return NULL;
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | return (struct define_struct *)get_storage(s->u.object, define_program);
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | }
|
f6abaa | 2018-02-27 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
ptrdiff_t tmp, int flags);
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void cpp_error(struct CPP_struct *this, const char *err) ATTRIBUTE((noinline));
static void cpp_error_vsprintf (struct CPP_struct *this, const char *fmt,
|
1ebec6 | 2014-05-13 | Martin Nilsson | | va_list args) ATTRIBUTE((noinline));
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void cpp_error_sprintf(struct CPP_struct *this, const char *fmt, ...) ATTRIBUTE((noinline));
static void cpp_handle_exception(struct CPP_struct *this,
|
1ebec6 | 2014-05-13 | Martin Nilsson | | const char *cpp_error_fmt, ...) ATTRIBUTE((noinline));
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void cpp_warning(struct CPP_struct *this, const char *cpp_warn_fmt, ...) ATTRIBUTE((noinline));
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *defined_macro = NULL;
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | static struct svalue defined_macro_sval;
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | |
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void cpp_error(struct CPP_struct *this, const char *err)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
this->compile_errors++;
if(this->compile_errors > 10) return;
|
739f9d | 1999-11-04 | Henrik Grubbström (Grubba) | | if((this->handler && this->handler->prog) || get_master())
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
ref_push_string(this->current_file);
push_int(this->current_line);
push_text(err);
|
9036e8 | 2001-08-16 | Martin Stjernholm | | low_safe_apply_handler("compile_error", this->handler,
this->compat_handler, 3);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | pop_stack();
}else{
|
1154dc | 1998-05-05 | Fredrik Hübinette (Hubbe) | | (void)fprintf(stderr, "%s:%ld: %s\n",
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | this->current_file->str,
(long)this->current_line,
err);
fflush(stderr);
}
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void cpp_error_vsprintf (struct CPP_struct *this, const char *fmt,
|
404563 | 2004-06-29 | Martin Nilsson | | va_list args)
|
9036e8 | 2001-08-16 | Martin Stjernholm | | {
|
b20284 | 2007-10-22 | Henrik Grubbström (Grubba) | | struct string_builder s;
struct pike_string *msg;
this->compile_errors++;
if (this->compile_errors > 10) return;
init_string_builder(&s, 0);
string_builder_vsprintf(&s, fmt, args);
msg = finish_string_builder(&s);
if((this->handler && this->handler->prog) || get_master())
{
ref_push_string(this->current_file);
push_int(this->current_line);
push_string(msg);
low_safe_apply_handler("compile_error", this->handler,
this->compat_handler, 3);
pop_stack();
return;
}
if (this->current_file->size_shift) {
fprintf(stderr, "WIDE:%ld: ", (long)this->current_line);
} else {
fprintf(stderr, "%s:%ld: ",
this->current_file->str, (long)this->current_line);
}
if (!msg->size_shift) {
fprintf(stderr, "%s\n", msg->str);
} else {
fprintf(stderr, "WIDE (fmt: %s)\n", fmt);
}
free_string(msg);
fflush(stderr);
|
37338b | 2003-11-14 | Martin Stjernholm | | }
|
9036e8 | 2001-08-16 | Martin Stjernholm | |
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void cpp_error_sprintf(struct CPP_struct *this, const char *fmt, ...)
|
37338b | 2003-11-14 | Martin Stjernholm | | {
va_list args;
|
9036e8 | 2001-08-16 | Martin Stjernholm | | va_start(args,fmt);
|
37338b | 2003-11-14 | Martin Stjernholm | | cpp_error_vsprintf (this, fmt, args);
|
9036e8 | 2001-08-16 | Martin Stjernholm | | va_end(args);
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void cpp_handle_exception(struct CPP_struct *this,
|
404563 | 2004-06-29 | Martin Nilsson | | const char *cpp_error_fmt, ...)
|
9036e8 | 2001-08-16 | Martin Stjernholm | | {
|
37338b | 2003-11-14 | Martin Stjernholm | | struct svalue thrown;
move_svalue (&thrown, &throw_value);
|
1ab4ac | 2008-01-26 | Martin Stjernholm | | mark_free_svalue (&throw_value);
|
37338b | 2003-11-14 | Martin Stjernholm | |
if (cpp_error_fmt) {
va_list args;
va_start (args, cpp_error_fmt);
cpp_error_vsprintf (this, cpp_error_fmt, args);
va_end (args);
|
9036e8 | 2001-08-16 | Martin Stjernholm | | }
|
37338b | 2003-11-14 | Martin Stjernholm | | push_svalue(&thrown);
|
38dfa0 | 2008-04-12 | Henrik Grubbström (Grubba) | | low_safe_apply_handler("compile_exception",
this->handler, this->compat_handler, 1);
|
37338b | 2003-11-14 | Martin Stjernholm | |
|
19961b | 2017-04-08 | Martin Nilsson | | if (SAFE_IS_ZERO(Pike_sp-1)) {
|
37338b | 2003-11-14 | Martin Stjernholm | | struct pike_string *s = format_exception_for_error_msg (&thrown);
|
715e55 | 2003-11-14 | Martin Stjernholm | | if (s) {
|
404563 | 2004-06-29 | Martin Nilsson | | cpp_error_sprintf(this, "%S", s);
|
715e55 | 2003-11-14 | Martin Stjernholm | | free_string (s);
}
|
9036e8 | 2001-08-16 | Martin Stjernholm | | }
|
37338b | 2003-11-14 | Martin Stjernholm | |
pop_stack();
free_svalue(&thrown);
|
9036e8 | 2001-08-16 | Martin Stjernholm | | }
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void cpp_warning(struct CPP_struct *this, const char *cpp_warn_fmt, ...)
|
fb59d2 | 2004-02-07 | Martin Nilsson | | {
|
0a5cb7 | 2011-03-19 | Martin Stjernholm | | struct string_builder sb;
|
f6da7b | 2004-06-27 | Martin Nilsson | | va_list args;
|
0a5cb7 | 2011-03-19 | Martin Stjernholm | | init_string_builder (&sb, 0);
|
f6da7b | 2004-06-27 | Martin Nilsson | | va_start(args, cpp_warn_fmt);
|
0a5cb7 | 2011-03-19 | Martin Stjernholm | | string_builder_vsprintf (&sb, cpp_warn_fmt, args);
|
f6da7b | 2004-06-27 | Martin Nilsson | | va_end(args);
|
fb59d2 | 2004-02-07 | Martin Nilsson | | if((this->handler && this->handler->prog) || get_master())
{
ref_push_string(this->current_file);
push_int(this->current_line);
|
0a5cb7 | 2011-03-19 | Martin Stjernholm | | push_string (finish_string_builder (&sb));
|
fb59d2 | 2004-02-07 | Martin Nilsson | | low_safe_apply_handler("compile_warning", this->handler,
this->compat_handler, 3);
pop_stack();
}else{
(void)fprintf(stderr, "%s:%ld: %s\n",
this->current_file->str,
(long)this->current_line,
|
0a5cb7 | 2011-03-19 | Martin Stjernholm | | sb.s->str);
|
fb59d2 | 2004-02-07 | Martin Nilsson | | fflush(stderr);
|
0a5cb7 | 2011-03-19 | Martin Stjernholm | | free_string_builder (&sb);
|
fb59d2 | 2004-02-07 | Martin Nilsson | | }
}
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | /*! @class MasterObject
*/
/*! @decl inherit CompilationHandler
*!
*! The master object acts as fallback compilation handler for
*! @[compile()] and @[cpp()].
*/
/*! @decl CompilationHandler get_compilation_handler(int major, int minor)
*!
*! Get compilation handler for simulation of Pike v@[major].@[minor].
*!
*! This function is called by @[cpp()] when it encounters
|
cbe8c9 | 2003-04-07 | Martin Nilsson | | *! @expr{#pike@} directives.
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | *!
*! @param major
*! Major version.
*!
*! @param minor
*! Minor version.
*!
*! @returns
*! Returns a compilation handler for Pike >= @[major].@[minor].
*/
/*! @decl string decode_charset(string raw, string charset)
*!
*! Convert @[raw] from encoding @[charset] to UNICODE.
*!
*! This function is called by @[cpp()] when it encounters
|
cbe8c9 | 2003-04-07 | Martin Nilsson | | *! @expr{#charset@} directives.
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | *!
*! @param raw
*! String to convert.
*!
*! @param charset
*! Name of encoding that @[raw] uses.
*!
*! @returns
|
cbe8c9 | 2003-04-07 | Martin Nilsson | | *! @[raw] decoded to UNICODE, or @expr{0@} (zero) if the decoding failed.
|
2ee381 | 2002-12-08 | Henrik Grubbström (Grubba) | | *!
*! @seealso
|
0b8d2f | 2013-06-17 | Martin Nilsson | | *! @[Charset]
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | */
/*! @endclass
*/
/*! @class CompilationHandler
|
e290f3 | 2006-01-27 | Henrik Grubbström (Grubba) | | *!
*! Objects used by the compiler to handle references to global symbols,
*! modules, external files, etc.
*!
|
c0fa4e | 2006-03-25 | Henrik Grubbström (Grubba) | | *! There can be up to three compilation handlers active at the same
*! time during a compilation. They are in order of precedence:
|
e290f3 | 2006-01-27 | Henrik Grubbström (Grubba) | | *!
*! @ol
|
c0fa4e | 2006-03-25 | Henrik Grubbström (Grubba) | | *! @item
*! The error handler
*!
|
e290f3 | 2006-01-27 | Henrik Grubbström (Grubba) | | *! This is the object passed to @[compile()] as
*! the second argument (if any). This object is returned by
*! @[get_active_error_handler()] during a compilation.
*!
|
c0fa4e | 2006-03-25 | Henrik Grubbström (Grubba) | | *! @item
*! The compatibility handler
*!
|
e290f3 | 2006-01-27 | Henrik Grubbström (Grubba) | | *! This is the object returned by
*! @[master()->get_compilation_handler()] (if any), which
*! the compiler calls when it sees @tt{#pike@}-directives,
*! or expressions using the version scope
*! (eg @expr{7.4::rusage@}). This object is returned by
*! @[get_active_compilation_handler()] during a compilation.
*!
|
c0fa4e | 2006-03-25 | Henrik Grubbström (Grubba) | | *! @item
*! The master object.
*!
|
e290f3 | 2006-01-27 | Henrik Grubbström (Grubba) | | *! This is returned by @[master()] at any time.
*! @endol
*!
*! Any of the objects may implement a subset of the @[CompilationHandler]
*! functions, and the first object that implements a function will be
*! used. The error handler object can thus be used to block certain
*! functionality (eg to restrict the number of available functions).
*!
*! @seealso
*! @[master()->get_compilation_handler()], @[get_active_error_handler()],
*! @[get_active_compilation_handler()], @[compile()]
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | */
|
9c1e6f | 2002-12-08 | Henrik Grubbström (Grubba) | | /*! @decl void compile_error(string filename, int line, string msg)
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | *!
*! Called by @[compile()] and @[cpp()] when they encounter
*! errors in the code they compile.
*!
|
9c1e6f | 2002-12-08 | Henrik Grubbström (Grubba) | | *! @param filename
*! File where the error was detected.
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | *!
*! @param line
*! Line where the error was detected.
*!
|
9c1e6f | 2002-12-08 | Henrik Grubbström (Grubba) | | *! @param msg
*! Description of error.
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | *!
*! @seealso
*! @[compile_warning()].
*/
/*! @decl void compile_exception(mixed exception)
*!
*! Called by @[compile()] and @[cpp()] if they trigger
*! exceptions.
*/
/*! @decl mapping(string:mixed) get_predefines()
*!
|
bd537b | 2002-12-10 | Martin Stjernholm | | *! Called by @[cpp()] to get the set of global symbols.
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | *!
*! @returns
*! Returns a mapping from symbol name to symbol value.
*! Returns zero on failure.
*!
*! @seealso
|
bd537b | 2002-12-10 | Martin Stjernholm | | *! @[resolv()], @[get_default_module()]
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | */
/*! @decl mixed resolv(string symbol, string filename, @
*! CompilationHandler handler)
*!
*! Called by @[compile()] and @[cpp()] to resolv
*! module references.
*!
*! @returns
*! Returns the resolved value, or @[UNDEFINED] on failure.
*!
*! @seealso
*! @[get_predefines()]
*/
/*! @decl mixed handle_import(string path, string filename, @
*! CompilationHandler handler)
*!
*! Called by @[compile()] and @[cpp()] to handle import
*! directives specifying specific paths.
*!
*! @returns
*! Returns the resolved value, or @[UNDEFINED] on failure.
*/
|
915e53 | 2002-12-08 | Henrik Grubbström (Grubba) | | /*! @decl string handle_include(string header_file, string current_file, @
*! int(0..1) is_local_ref)
*!
|
cbe8c9 | 2003-04-07 | Martin Nilsson | | *! Called by @[cpp()] to resolv @expr{#include@} and @expr{#string@}
*! directives.
|
915e53 | 2002-12-08 | Henrik Grubbström (Grubba) | | *!
*! @param header_file
*! File that was requested for inclusion.
*!
*! @param current_file
|
548652 | 2002-12-08 | Henrik Grubbström (Grubba) | | *! File where the directive was found.
|
915e53 | 2002-12-08 | Henrik Grubbström (Grubba) | | *!
*! @param is_local_ref
*! Specifies reference method.
*! @int
*! @value 0
|
cbe8c9 | 2003-04-07 | Martin Nilsson | | *! Directive was @expr{#include <header_file>@}.
|
915e53 | 2002-12-08 | Henrik Grubbström (Grubba) | | *! @value 1
|
cbe8c9 | 2003-04-07 | Martin Nilsson | | *! Directive was @expr{#include "header_file"@}.
|
915e53 | 2002-12-08 | Henrik Grubbström (Grubba) | | *! @endint
*!
*! @returns
*! Returns the filename to pass to @[read_include()] if found,
|
cbe8c9 | 2003-04-07 | Martin Nilsson | | *! and @expr{0@} (zero) on failure.
|
915e53 | 2002-12-08 | Henrik Grubbström (Grubba) | | *!
*! @seealso
*! @[read_include()]
*/
/*! @decl string read_include(string filename)
*!
*! Called by @[cpp()] to read included files.
*!
*! @param filename
*! Filename as returned by @[handle_include()].
*!
*! @returns
*! Returns a string with the content of the header file on success,
|
cbe8c9 | 2003-04-07 | Martin Nilsson | | *! and @expr{0@} (zero) on failure.
|
915e53 | 2002-12-08 | Henrik Grubbström (Grubba) | | *!
*! @seealso
*! @[handle_include()]
*/
|
bbeddc | 2002-12-07 | Henrik Grubbström (Grubba) | | /*! @endclass
*/
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @namespace predef:: */
/*! @decl import cpp:: */
/*! @endnamespace */
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | /* #pike handling. */
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | void cpp_change_compat(struct CPP_struct *this, int major, int minor)
|
ac8715 | 2000-09-25 | Fredrik Hübinette (Hubbe) | | {
if(this->compat_major == major &&
this->compat_minor == minor) return;
if(this->compat_handler)
{
free_object(this->compat_handler);
this->compat_handler=0;
}
if((major == PIKE_MAJOR_VERSION &&
minor == PIKE_MINOR_VERSION) || major < 0)
{
this->compat_major=PIKE_MAJOR_VERSION;
this->compat_minor=PIKE_MINOR_VERSION;
return; /* Our work here is done */
}
push_int(major);
push_int(minor);
SAFE_APPLY_MASTER("get_compilation_handler",2);
|
19961b | 2017-04-08 | Martin Nilsson | | if(TYPEOF(Pike_sp[-1]) == T_OBJECT)
|
ac8715 | 2000-09-25 | Fredrik Hübinette (Hubbe) | | {
|
19961b | 2017-04-08 | Martin Nilsson | | if (SUBTYPEOF(Pike_sp[-1])) {
|
f54c78 | 2004-12-22 | Henrik Grubbström (Grubba) | | cpp_error(this,
"#pike: Subtyped compilation handlers are not supported yet.");
}
|
19961b | 2017-04-08 | Martin Nilsson | | this->compat_handler=Pike_sp[-1].u.object;
|
50ea68 | 2003-03-14 | Henrik Grubbström (Grubba) | | dmalloc_touch_svalue(Pike_sp-1);
|
19961b | 2017-04-08 | Martin Nilsson | | Pike_sp--;
|
9e1a9b | 2018-03-02 | Henrik Grubbström (Grubba) | | } else {
pop_stack();
|
ac8715 | 2000-09-25 | Fredrik Hübinette (Hubbe) | | }
this->compat_major=major;
this->compat_minor=minor;
}
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | /* #if macros and functions. */
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @namespace cpp::
*!
*! Pike has a builtin C-style preprocessor. It works similar to the
*! ANSI-C preprocessor but has a few extra features. These and the
*! default set of preprocessor macros are described here.
*/
/*! @directive #!
*!
*! All lines beginning with @[#!] will be regarded as comments,
*! to enable shell integration. It is recommended that Pike applications
*! begin with the line @tt{"#! /usr/bin/env pike"@} for maximum cross
*! platform compatibility.
*/
/*! @directive #charset
*!
|
0b8d2f | 2013-06-17 | Martin Nilsson | | *! Inform the preprocessor about which charset the file is encoded
*! with. The Charset module is called with this string to decode
*! the remainder of the file.
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | */
/*! @directive #if
*!
*! The @[#if] directive can evaluate simple expressions and, if
*! the expression is evaluates to true, "activate" the code block that
*! follows. The code block ends when an @[#endif], @[#else],
*! @[#elseif] or @[#elif] block is encountered at the same
*! nesting depth.
*!
*! The @[#if] expressions may include defines, integer, string
*! and float constants, @tt{?:@}, @tt{||@} and @tt{&&@} operations,
*! @tt{~@}, @tt{^@}, @tt{!@}, @tt{|@} and @tt{&@} operations,
*! @tt{<@}, @tt{>@}, @tt{<=@}, @tt{>=@}, @tt{==@} and @tt{!=@} operations,
*! @tt{+@}, @tt{-@}, @tt{*@}, @tt{/@}, @tt{<<@} and @tt{>>@} operations
*! and paranthesis.
*!
*! Strings may also be indexed with the @tt{[]@} index operator.
*! Finally there are three special "functions" available in @[#if]
*! expressions; @[defined()], @[efun()] and @[constant()].
*!
*! @seealso
*! @[#ifdef], @[#ifndef], @[#elif], @[#else], @[#endif],
*! @[defined()], @[constant()], @[efun()]
*/
/*! @directive #ifdef
*!
*! Check whether an identifier is a macro.
*!
*! The directive
*!
*! @tt{#ifdef @i{<identifier>@}@}
*!
|
bf2c0d | 2018-01-12 | Stephen R. van den Berg | | *! is equivalent to
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | *!
*! @tt{#if @[defined](@i{<identifier>@})@}
*!
*! @seealso
*! @[#if], @[#ifndef], @[defined]
*/
/*! @directive #ifndef
*!
*! Check whether an identifier is not a macro.
*!
*! This is the inverse of @[#ifdef].
*!
*! The directive
*!
*! @tt{#ifndef @i{<identifier>@}@}
*!
|
bf2c0d | 2018-01-12 | Stephen R. van den Berg | | *! is equivalent to
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | *!
*! @tt{#if !@[defined](@i{<identifier>@})@}
*!
*! @seealso
*! @[#if], @[#ifdef], @[defined]
*/
|
956513 | 2014-02-14 | Martin Nilsson | | /*! @directive #require
*!
*! If the directive evaluates to false, the source file will be
*! considered to have failed dependencies, and will not be found by
*! the resolver. In practical terms the @[cpp()] call will return
*! zero.
*!
*! @seealso
*! @[#if]
*/
|
f6abaa | 2018-02-27 | Henrik Grubbström (Grubba) | | PIKEFUN string(0..0) directive_require(int flags, string line)
{
struct CPP_struct *this = THIS;
if (OUTP()) {
ref_push_string(line);
push_int(CPP_DO_IF);
apply_current(f_CPP_cpp_fun_num, 2);
if (TYPEOF(Pike_sp[-1]) == PIKE_T_STRING) {
calc(this, MKPCHARP_STR(Pike_sp[-1].u.string),
Pike_sp[-1].u.string->len, 0, 0);
if(SAFE_IS_ZERO(Pike_sp-1)) this->dependencies_fail=1;
} else {
this->dependencies_fail=1;
}
pop_stack();
}
push_empty_string();
}
|
956513 | 2014-02-14 | Martin Nilsson | |
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @directive #endif
*!
*! End a block opened with @[#if], @[#ifdef], @[#ifndef],
*! @[#else], @[#elseif] or @[#elif].
*!
*! @example
*! @code
*! #ifdef DEBUG
*! do_debug_stuff();
*! #endif // DEBUG
*! @endcode
*/
/*! @directive #else
*!
*! This directive is used to divide the current code block into another
*! code block with inverse activation.
*!
*! @example
*! @code
*! #ifdef FAST_ALGORITHM
*! do_fast_algorithm();
*! #elif defined(EXPERIMENTAL_ALGORITHM)
*! do_experimental_algorithm();
*! #else
*! do_default_algorithm();
*! #endif
*! @endcode
*/
/*! @directive #elif
*! @directive #elseif
*!
*! These work as a combined @[#else] and @[#if] without
*! adding an extra level of nesting.
*!
*! @example
*!
|
bf2c0d | 2018-01-12 | Stephen R. van den Berg | | *! The following two are equivalent:
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | *!
*! @code
*! #ifdef A
*! // Code for A.
*! #else
*! #ifdef B
*! // Code for B.
*! #else
*! #ifdef C
*! // Code for C.
*! #else
*! // Code for D.
*! #endif
*! #endif
*! #endif
*! @endcode
*!
*! And
*!
*! @code
*! #ifdef A
*! // Code for A.
*! #elif defined(B)
*! // Code for B.
*! #elseif defined(C)
*! // Code for C.
*! #else
*! // Code for D.
*! #endif
*! @endcode
*!
*! @seealso
*! @[#if], @[#ifdef], @[#else], @[defined()], @[constant()]
*/
/*! @directive #error
*!
*! Throw an error during preprocessing.
*!
*! This directive causes a cpp error. It can be used to notify
*! the user that certain functions are missing and similar things.
*!
*! @note
*! Note that this directive will cause @[cpp()] to throw
*! an error at the end of preprocessing, which will cause
*! any compilation to fail.
*!
*! @example
*! @code
*! #if !constant(Yp)
*! #error Support for NIS not available.
*! #endif
*! @endcode
*!
*! @seealso
*! @[#warning]
*/
|
78b796 | 2018-01-15 | Henrik Grubbström (Grubba) | | PIKEFUN string(0..0) directive_error(int flags, string line)
{
struct CPP_struct *this = THIS;
if (OUTP()) {
cpp_error_sprintf(this, "%O", Pike_sp - 1);
}
push_empty_string();
}
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | |
/*! @directive #warning
*!
*! Generate a warning during preprocessing.
*!
*! This directive causes a cpp warning, it can be used to notify
*! the user that certain functions are missing and similar things.
*!
*! @example
*! @code
*! #if !constant(Yp)
*! #warning Support for NIS not available. Some features may not work.
*! #endif
*! @endcode
*!
*! @seealso
*! @[#error]
*/
|
78b796 | 2018-01-15 | Henrik Grubbström (Grubba) | | PIKEFUN string(0..0) directive_warning(int flags, string line)
{
struct CPP_struct *this = THIS;
if (OUTP()) {
cpp_warning(this, "%O", Pike_sp - 1);
}
push_empty_string();
}
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | |
/*! @directive #include
*!
*! @[#include] is used to insert the contents of another file into
*! the processed file at the place of the include directive.
*!
*! Files can be referenced either by absolute or relative path from the
*! source file, or searched for in the include paths.
*!
*! To include a file with absolute or relative path, use double quotes,
*! e.g. @tt{#include "constants.pike"@} or @tt{#include "../debug.h"@}.
*!
*! To include from the include paths, use less than and greater than,
*! e.g. @tt{#include <profiling.h>@}.
*!
*! It is also possible to include a file whose path is defined in a
*! preprocessor macro, e.g. @tt{#include USER_SETTINGS@}.
*/
/*! @directive #line
*! @directive #<integer>
*!
*! A hash character followed by a number or by the string
*! @tt{"line"@} and a number will make the preprocessor line counter
*! set this number as the line number for the next line and adjust the
*! following lines accordingly.
*!
*! All error messages from Pike will use these line numbers.
*!
*! Optionally the number may be followed by a file name, e.g.
*! @tt{#line 1 "/home/pike/program.pike.in"@}. Then this
*! filename will be used instead of the current file for error
*! messages.
*/
/*! @directive #pike
*!
*! Set the Pike compiler backward compatibility level.
*!
*! This tells the compiler which version of Pike it should
*! attempt to emulate from this point on in the current
*! compilation unit.
*!
*! This is typically used to "quick-fix" old code to work
*! with more recent versions of Pike.
*!
*! @example
*! @code
*! // This code was written for Pike 7.2, and depends on
|
640b82 | 2016-09-10 | Henrik Grubbström (Grubba) | | *! // the old behaviour for @expr{7.2::dirname()@}.
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | *! #pike 7.2
*!
*! // ... Code that uses @[dirname()] ...
*! @endcode
*!
*! This directive is also needed for Pike modules that
*! have been installed globally, and might be used by
*! a Pike that has been started with the @tt{-V@} flag.
*!
*! @example
*! @code
*! // Pike modules that are bundled with Pike are
*! // typically written for the same version of Pike.
*! #pike __REAL_VERSION__
*! @endcode
*/
|
a361fc | 2018-02-28 | Henrik Grubbström (Grubba) | | PIKEFUN string(0..0) directive_pike(int flags, string line)
{
struct CPP_struct *this = THIS;
if (OUTP()) {
int major, minor;
ptrdiff_t tmp;
PCHARP ptr;
string_builder_strcat(&this->buf, "#pike ");
ref_push_string(line);
push_int(CPP_DO_IF);
apply_current(f_CPP_cpp_fun_num, 2);
if (TYPEOF(Pike_sp[-1]) == PIKE_T_STRING) {
line = Pike_sp[-1].u.string;
ptr = MKPCHARP_STR(line);
major = STRTOL_PCHARP(ptr, &ptr, 10);
if(INDEX_PCHARP(ptr,0) == '.')
{
INC_PCHARP(ptr, 1);
minor=STRTOL_PCHARP(ptr, &ptr, 10);
cpp_change_compat(this, major, minor);
}else{
cpp_error(this, "Missing '.' in #pike.");
this->compat_minor=0;
}
/* NB: The parsed line is already in place on the stack. */
return;
} else {
cpp_error(this, "Invalid #pike directive.");
}
}
push_empty_string();
}
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | |
/*! @directive #""
*! If a string literal is opened with @tt{#"@} newlines in the
*! string will end up in the string literal, instead of triggering a
*! @tt{"newline in string"@} error.
*!
*! @note
*! Newlines will be converted to @tt{\n@} characters in the string
*! even if the newlines in the file are something else.
*!
*! This preprocessor directive may appear anywhere a string may
*! appear.
*!
*! @seealso
*! @[#string]
*/
|
d6d2e5 | 2016-06-10 | Martin Nilsson | | /*! @directive #(#)
*! @directive #[#]
*! @directive #{#}
*! If a string literal is opened with @tt{#(@} all subsequent
*! characters until the closing @tt{#)@} will be treated as
*! literals, including newlines, @tt{\@}, @tt{"@} and @tt{'@}.
*!
*! There are three different pairs of start/end tokens for this
*! type of literals, #( and #), #[ and #], and #{ and #}.
*!
*! @example
*! @expr{#["\n\'##]@} is equivalent to @expr{"\"\\n\\'#"@}.
|
b6fef0 | 2016-06-10 | Martin Nilsson | | */
|
d6d2e5 | 2016-06-10 | Martin Nilsson | |
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @directive #string
*! The preprocessor directive @[#string] will load the file in the
*! string that follows and insert its contents as a string. This
*! preprocessor directive may appear anywhere a string may appear.
*!
*! @example
*! @code
*! do_something(#string "the_file.wks");
*! @endcode
*!
*! @seealso
*! @[#include]
*/
/*! @directive #pragma
*!
*! This is a generic directive for flags to the compiler.
*!
*! These are some of the flags that are available:
*! @string
*! @value "all_inline"
*! This is the same as adding the modifier @tt{inline@}
*! to all functions that follow.
*! @value "all_final"
*! Instructs the compiler to mark all symbols as @tt{final@}.
|
d3abb8 | 2015-02-10 | Henrik Grubbström (Grubba) | | *! @value "deprecation_warnings"
*! Enable warnings for use of deprecated symbols (default).
*! @value "no_deprecation_warnings"
*! Disable warnings for use of deprecated symbols. This is
*! typically used in code that implements the deprecated
*! symbols.
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | *! @value "save_parent"
*! Cause nested classes to save a reference to their
*! surrounding class even if not strictly needed.
*! @value "dont_save_parent"
*! Inverse of @tt{"save_parent"@}. This is needed to override
*! if the global symbol @[predef::__pragma_save_parent__]
*! has been set.
*! @value "strict_types"
*! Enable warnings for all cases where the compiler
*! isn't certain that the types are correct.
|
d3abb8 | 2015-02-10 | Henrik Grubbström (Grubba) | | *! @value "disassemble"
*! Enable disassembly output for the code being compiled.
*! Note that this option essentially has a function-level
*! scope, so enabling it for just a few lines is usually
*! a noop. This is similar to @[Debug.assembler_debug()]
|
fdde6b | 2017-01-16 | Henrik Grubbström (Grubba) | | *! level @expr{3@}.
|
d3abb8 | 2015-02-10 | Henrik Grubbström (Grubba) | | *! @value "no_disassemble"
*! Disable disassembly output (default).
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | *! @endstring
|
dddfca | 2018-02-22 | Henrik Grubbström (Grubba) | | */
PIKEFUN string(0..0) directive_pragma(int flags, string line)
{
struct CPP_struct *this = THIS;
if (OUTP()) {
/* FIXME: Prefix with this->prefix? */
string_builder_strcat(&this->buf, "#pragma ");
ref_push_string(line);
|
ff7085 | 2018-02-23 | Henrik Grubbström (Grubba) | | push_int(flags & ~CPP_EXPECT_ENDIF);
|
dddfca | 2018-02-22 | Henrik Grubbström (Grubba) | | apply_current(f_CPP_low_cpp_fun_num, 2);
pop_stack();
}
push_empty_string();
}
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | |
/*! @decl int(0..1) defined(mixed identifier)
*!
*! Check whether an identifier is a cpp macro or not.
*!
*! @returns
*! @[defined] returns true if the symbol given as argument
*! is defined.
*!
*! @note
|
bf2c0d | 2018-01-12 | Stephen R. van den Berg | | *! @tt{#if defined(MY_DEF)@} is equivalent to
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | *! @tt{#ifdef MY_DEF@}.
*!
*! @seealso
*! @[#if], @[#ifdef], @[constant()]
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void check_defined(struct CPP_struct *this,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *arg,
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | struct string_builder *tmp)
{
|
3d6a1d | 2016-08-21 | Martin Nilsson | | if(arg && FIND_DEFINE(arg))
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | string_builder_binary_strcat(tmp, " 1 ", 3);
|
6e5206 | 2014-05-12 | Martin Nilsson | | else
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | string_builder_binary_strcat(tmp, " 0 ", 3);
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static int do_safe_index_call(struct CPP_struct *this, struct pike_string *s)
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | {
int res;
JMP_BUF recovery;
if(!s) return 0;
if (SETJMP_SP(recovery, 1)) {
|
abe9fe | 2014-09-18 | Martin Nilsson | | if(this->picky_cpp)
|
7b2a53 | 2004-06-29 | Martin Nilsson | | cpp_warning (this, "Error indexing module with %S.", s);
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | res = 0;
push_undefined();
} else {
ref_push_string(s);
f_index(2);
|
13670c | 2015-05-25 | Martin Nilsson | |
|
19961b | 2017-04-08 | Martin Nilsson | | res=!(UNSAFE_IS_ZERO(Pike_sp-1) && SUBTYPEOF(Pike_sp[-1]) == NUMBER_UNDEFINED);
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | }
UNSETJMP(recovery);
return res;
}
|
d2ac22 | 2014-02-15 | Martin Nilsson | | /*! @decl int(0..1) constant(mixed identifier)
*! @decl __deprecated__ int(0..1) efun(mixed identifier)
*!
*! Check whether the argument resolves to a constant or not.
*!
*! @seealso
*! @[#if], @[defined()]
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void cpp_constant(struct CPP_struct *this, int value)
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | {
|
19961b | 2017-04-08 | Martin Nilsson | | struct svalue *save_stack=Pike_sp;
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | struct array *arr;
|
a1640e | 2010-09-18 | Marcus Comstedt | | INT_TYPE res = 0;
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | int n;
/* FIXME: Protection against errors. */
/* Remove extra whitespace. */
|
75367d | 2014-08-22 | Arne Goedeke | | push_static_text(" ");
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | o_subtract();
|
75367d | 2014-08-22 | Arne Goedeke | | push_static_text("\t");
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | o_subtract();
/* Split on . */
|
75367d | 2014-08-22 | Arne Goedeke | | push_static_text(".");
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | o_divide();
#ifdef PIKE_DEBUG
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | if (TYPEOF(Pike_sp[-1]) != T_ARRAY) {
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | Pike_fatal("Bad result from division in constant(): %s "
"(expected array(string)).\n",
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | get_name_of_type(TYPEOF(Pike_sp[-1])));
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | }
#endif /* PIKE_DEBUG */
arr = Pike_sp[-1].u.array;
#ifdef PIKE_DEBUG
if (!arr->size) {
Pike_fatal("Got an empty array from division in constant().\n");
}
if ((arr->type_field & ~BIT_STRING) &&
(array_fix_type_field(arr) & ~BIT_STRING)) {
Pike_fatal("Bad result from division in constant(): type_field: 0x%08x "
"(expected array(string)).\n",
arr->type_field & ~BIT_STRING);
}
#endif /* PIKE_DEBUG */
if (arr->item[0].u.string->len) {
struct pike_string *str = arr->item[0].u.string;
struct svalue *sv;
if((sv=low_mapping_string_lookup(get_builtin_constants(), str)))
{
/* efun */
push_svalue(sv);
res=1;
} else if(get_master()) {
/* Module. */
ref_push_string(str);
ref_push_string(this->current_file);
if (this->handler) {
ref_push_object(this->handler);
} else {
push_int(0);
}
if (safe_apply_handler("resolv", this->handler,
this->compat_handler, 3, 0)) {
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | if ((TYPEOF(Pike_sp[-1]) == T_OBJECT &&
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | Pike_sp[-1].u.object == placeholder_object) ||
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | (TYPEOF(Pike_sp[-1]) == T_PROGRAM &&
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | Pike_sp[-1].u.program == placeholder_program)) {
|
89f543 | 2004-06-29 | Martin Nilsson | | cpp_error_sprintf (this, "Got placeholder %s (resolver problem) "
"when resolving %S.",
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | get_name_of_type(TYPEOF(Pike_sp[-1])),
|
89f543 | 2004-06-29 | Martin Nilsson | | str);
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | }
else
|
19961b | 2017-04-08 | Martin Nilsson | | res = !(SAFE_IS_ZERO(Pike_sp-1) && SUBTYPEOF(Pike_sp[-1]) == NUMBER_UNDEFINED);
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | }
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | else if (TYPEOF(throw_value) == T_STRING &&
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | !throw_value.u.string->size_shift) {
cpp_error(this, throw_value.u.string->str);
free_svalue(&throw_value);
|
1ab4ac | 2008-01-26 | Martin Stjernholm | | mark_free_svalue (&throw_value);
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | res = 0;
|
91a2f6 | 2004-11-05 | Martin Nilsson | | } else if(this->picky_cpp) {
|
7b2a53 | 2004-06-29 | Martin Nilsson | | cpp_warning (this, "Error resolving %S.", str);
res = 0;
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | }
}
} else {
/* Handle constant(.foo) */
|
75367d | 2014-08-22 | Arne Goedeke | | push_static_text(".");
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | ref_push_string(this->current_file);
if (this->handler) {
ref_push_object(this->handler);
} else {
push_int(0);
}
if (safe_apply_handler("handle_import", this->handler,
this->compat_handler, 3,
BIT_MAPPING|BIT_OBJECT|BIT_PROGRAM))
|
19961b | 2017-04-08 | Martin Nilsson | | res = !(SAFE_IS_ZERO(Pike_sp-1) && SUBTYPEOF(Pike_sp[-1]) == NUMBER_UNDEFINED);
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | else {
cpp_handle_exception (this, "Error importing '.'.");
}
}
for (n = 1; res && (n < arr->size); n++) {
res = do_safe_index_call(this, arr->item[n].u.string);
}
|
a1640e | 2010-09-18 | Marcus Comstedt | | if (value && res) {
|
19961b | 2017-04-08 | Martin Nilsson | | if (TYPEOF(Pike_sp[-1]) == T_INT)
res = Pike_sp[-1].u.integer;
|
a1640e | 2010-09-18 | Marcus Comstedt | | else
res = 0;
}
|
19961b | 2017-04-08 | Martin Nilsson | | pop_n_elems(1 + Pike_sp - save_stack);
|
fbf6c9 | 2004-06-29 | Henrik Grubbström (Grubba) | | push_int(res);
}
|
0ca86e | 2005-04-09 | Henrik Grubbström (Grubba) | | static struct mapping *initial_predefs_mapping(void)
|
b584b1 | 2001-12-20 | Martin Stjernholm | | {
struct pike_predef_s *def;
struct mapping *map = allocate_mapping (0);
#ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if (!use_initial_predefs) Pike_fatal ("Initial predefs has been taken over.\n");
|
b584b1 | 2001-12-20 | Martin Stjernholm | | #endif
|
df9147 | 2016-10-21 | Henrik Grubbström (Grubba) | | for (def = first_predef; def; def = def->next) {
struct pike_string *name = make_shared_string(def->name);
struct pike_string *value = make_shared_string(def->value);
mapping_string_insert_string(map, name, value);
free_string(value);
free_string(name);
}
|
b584b1 | 2001-12-20 | Martin Stjernholm | | return map;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static p_wchar2 readchar( PCHARP data, ptrdiff_t *pos, struct CPP_struct *this )
|
1f57ef | 2014-05-10 | Per Hedbor | | {
ptrdiff_t l;
p_wchar2 C;
INC_PCHARP(data,*pos);
switch(parse_esc_seq_pcharp (data, &C, &l))
{
case 0:
*pos += l;
break;
case 1:
C = '\r';
*pos += 1;
break;
case 3:
/* The eof will get caught in the next round. */
C = 0;
*pos += 1;
break;
case 4: case 5: case 6:
cpp_error (this, "Too large character value in escape.");
C = (int) MAX_UINT32;
*pos += l;
break;
case 7:
cpp_error (this, "Too few hex digits in \\u escape.");
C = '\\';
break;
case 8:
cpp_error (this, "Too few hex digits in \\U escape.");
C = '\\';
break;
|
6e5206 | 2014-05-12 | Martin Nilsson | | #ifdef PIKE_DEBUG
case 2: Pike_fatal ("Not supposed to happen.\n");
default: Pike_fatal ("Unknown error from parse_esc_seq.\n");
#endif
|
1f57ef | 2014-05-10 | Per Hedbor | | }
return C;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t readstring( struct CPP_struct *this, const PCHARP data, ptrdiff_t len, ptrdiff_t pos,
|
1f57ef | 2014-05-10 | Per Hedbor | | struct string_builder*nf, int nl_ok)
{
while(1)
{
pos++;
if(pos>=len)
{
cpp_error(this,"End of file in string.");
break;
}
switch(INDEX_PCHARP(data,pos))
{
case '"': break;
case '\\':
{
pos++;
if(INDEX_PCHARP(data,pos)=='\n')
{
this->current_line++;
PUTNL();
continue;
}
if(INDEX_PCHARP(data,pos)=='\r' && INDEX_PCHARP(data,pos+1)=='\n')
{
pos++;
this->current_line++;
PUTNL();
continue;
}
string_builder_putchar(nf, readchar(data,&pos,this));
pos--;
continue;
}
case '\r':
continue; /* ignored */
case '\n':
this->current_line++;
if( nl_ok )
PUTNL();
else
cpp_error(this,"Newline in string.");
|
5f5084 | 2018-02-12 | Marcus Comstedt | | /* FALLTHRU */
|
1f57ef | 2014-05-10 | Per Hedbor | | default:
string_builder_putchar(nf, INDEX_PCHARP(data,pos));
continue;
}
pos++;
break;
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t readstring_lit( struct CPP_struct *this, const PCHARP data, ptrdiff_t len, ptrdiff_t pos,
|
2028f8 | 2014-07-21 | Per Hedbor | | struct string_builder*nf, INT32 ec)
{
INT32 ch;
|
b9a2a9 | 2015-07-06 | Arne Goedeke | | while(1) {
if(++pos>=len) {
|
2028f8 | 2014-07-21 | Per Hedbor | | cpp_error(this,"End of file in string.");
|
b9a2a9 | 2015-07-06 | Arne Goedeke | | break;
}
if((ch=INDEX_PCHARP(data,pos)) == '#' && INDEX_PCHARP(data,pos+1)==ec)
|
2028f8 | 2014-07-21 | Per Hedbor | | return pos + 2;
|
b9a2a9 | 2015-07-06 | Arne Goedeke | | else {
if (ch == '\n') {
this->current_line++;
PUTNL();
}
|
2028f8 | 2014-07-21 | Per Hedbor | | string_builder_putchar(nf, ch);
|
b9a2a9 | 2015-07-06 | Arne Goedeke | | }
}
|
2028f8 | 2014-07-21 | Per Hedbor | | return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t fixstring(struct CPP_struct *this, const PCHARP data, ptrdiff_t len,
|
efd97a | 2014-05-12 | Martin Nilsson | | ptrdiff_t pos, struct string_builder *nf, int outp)
|
1f57ef | 2014-05-10 | Per Hedbor | | {
int trailing_newlines=0;
if(outp) string_builder_putchar(nf, '"');
while(1)
{
if(pos>=len)
{
cpp_error(this,"End of file in string.");
break;
}
switch(INDEX_PCHARP(data,pos++))
{
case '\n':
cpp_error(this,"Newline in string.");
this->current_line++;
break;
case '"': break;
case '\\':
if(INDEX_PCHARP(data,pos)=='\n')
{
pos++;
trailing_newlines++;
this->current_line++;
continue;
}
if(INDEX_PCHARP(data,pos)=='\r' && INDEX_PCHARP(data,pos+1)=='\n')
{
pos+=2;
trailing_newlines++;
this->current_line++;
continue;
}
if(outp) string_builder_putchar(nf, '\\');
pos++;
/* Fall through. */
default:
if(outp) string_builder_putchar(nf, INDEX_PCHARP(data,pos-1));
continue;
}
break;
}
if(outp) string_builder_putchar(nf, '"');
while(trailing_newlines--) PUTNL();
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t find_end_of_line( struct CPP_struct *this, const PCHARP data,
|
efd97a | 2014-05-12 | Martin Nilsson | | ptrdiff_t len, ptrdiff_t pos, int emit )
|
1f57ef | 2014-05-10 | Per Hedbor | | {
while(pos < len) {
switch (INDEX_PCHARP(data,pos++)) {
case '\n':
return pos-1;
case '\\':
if (INDEX_PCHARP(data,pos) == '\n') {
pos+=2;
} else if ((INDEX_PCHARP(data,pos) == '\r') &&
(INDEX_PCHARP(data,pos+1) == '\n')) {
pos+=3;
} else {
pos++;
continue;
}
this->current_line++;
if( emit ) PUTNL();
}
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t find_end_of_comment( struct CPP_struct *this, const PCHARP data, ptrdiff_t len,
|
efd97a | 2014-05-12 | Martin Nilsson | | ptrdiff_t pos, int emit)
|
1f57ef | 2014-05-10 | Per Hedbor | | {
pos++;
while(INDEX_PCHARP(data,pos)!='*' || INDEX_PCHARP(data,pos+1)!='/')
|
13670c | 2015-05-25 | Martin Nilsson | | {
|
1f57ef | 2014-05-10 | Per Hedbor | | if(pos+2>=len)
{
cpp_error(this,"End of file in comment.");
break;
}
if(INDEX_PCHARP(data,pos)=='\n')
{
this->current_line++;
if( emit )PUTNL();
}
pos++;
}
return pos + 2;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t find_end_quote(struct CPP_struct *this, const PCHARP data,
|
fbd041 | 2016-10-01 | Henrik Grubbström (Grubba) | | ptrdiff_t len, ptrdiff_t pos,
p_wchar2 quote, int flags)
|
1f57ef | 2014-05-10 | Per Hedbor | | {
while(1)
{
|
fbd041 | 2016-10-01 | Henrik Grubbström (Grubba) | | p_wchar2 c;
|
1f57ef | 2014-05-10 | Per Hedbor | | if(pos>=len)
{
|
fbd041 | 2016-10-01 | Henrik Grubbström (Grubba) | | if (quote == '\'') {
cpp_error(this,"End of file in character constant.");
} else {
cpp_error(this,"End of file in string.");
}
|
1f57ef | 2014-05-10 | Per Hedbor | | break;
}
|
fbd041 | 2016-10-01 | Henrik Grubbström (Grubba) | | switch((c = INDEX_PCHARP(data,pos++)))
|
1f57ef | 2014-05-10 | Per Hedbor | | {
case '\n':
|
1238cd | 2016-09-29 | Henrik Grubbström (Grubba) | | if (flags & CPP_END_AT_NEWLINE) {
|
fbd041 | 2016-10-01 | Henrik Grubbström (Grubba) | | if (quote == '\'') {
cpp_error(this,"Newline in char.");
} else {
cpp_error(this,"Newline in string.");
}
|
1238cd | 2016-09-29 | Henrik Grubbström (Grubba) | | }
|
1f57ef | 2014-05-10 | Per Hedbor | | this->current_line++;
PUTNL();
break;
|
fbd041 | 2016-10-01 | Henrik Grubbström (Grubba) | | default:
if (c == quote) return pos;
|
1f57ef | 2014-05-10 | Per Hedbor | | break;
case '\\':
if(INDEX_PCHARP(data,pos)=='\n') {
this->current_line++;
PUTNL();
}
|
fbd041 | 2016-10-01 | Henrik Grubbström (Grubba) | | else if ((INDEX_PCHARP(data,pos) == '\r') && (INDEX_PCHARP(data,pos+1) == '\n')) {
|
1f57ef | 2014-05-10 | Per Hedbor | | this->current_line++;
pos++;
PUTNL();
}
pos++;
}
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t find_end_brace(struct CPP_struct *this,
|
1f57ef | 2014-05-10 | Per Hedbor | | PCHARP data,
ptrdiff_t len,
ptrdiff_t pos);
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t find_end_parenthesis(struct CPP_struct *this,
|
1f57ef | 2014-05-10 | Per Hedbor | | PCHARP data,
ptrdiff_t len,
ptrdiff_t pos)
/* pos is after the open paren. Returns the position after the close paren. */
{
INT_TYPE start_line = this->current_line;
while(1)
{
if(pos+1>=len)
{
INT_TYPE save_line = this->current_line;
this->current_line = start_line;
cpp_error(this, "End of file while looking for end parenthesis.");
this->current_line = save_line;
return pos;
}
switch(INDEX_PCHARP(data,pos++))
{
case '\n': PUTNL(); this->current_line++; break;
|
fbd041 | 2016-10-01 | Henrik Grubbström (Grubba) | | case '\'': pos=find_end_quote(this,data,len,pos,'\'',CPP_END_AT_NEWLINE); break;
case '"': pos=find_end_quote(this,data,len,pos,'\"',CPP_END_AT_NEWLINE); break;
|
1f57ef | 2014-05-10 | Per Hedbor | | case '(': pos=find_end_parenthesis(this, data, len, pos); break;
case '{': pos=find_end_brace(this, data, len, pos); break;
case ')': return pos;
case '/':
if (INDEX_PCHARP(data,pos) == '*') {
pos = find_end_of_comment(this,data,len,pos+1,0);
} else if (INDEX_PCHARP(data,pos) == '/') {
pos = find_end_of_line(this,data,len,pos+1,0);
}
}
}
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t find_end_brace(struct CPP_struct *this,
|
90e5e9 | 2014-05-13 | Martin Nilsson | | const PCHARP data,
|
1f57ef | 2014-05-10 | Per Hedbor | | ptrdiff_t len,
ptrdiff_t pos)
/* pos is after the open brace. Returns the position after the close brace. */
{
INT_TYPE start_line = this->current_line;
while(1)
{
if(pos+1>=len)
{
INT_TYPE save_line = this->current_line;
this->current_line = start_line;
cpp_error(this, "End of file while looking for end brace.");
this->current_line = save_line;
return pos;
}
switch(INDEX_PCHARP(data,pos++))
{
case '\n': PUTNL(); this->current_line++; break;
|
fbd041 | 2016-10-01 | Henrik Grubbström (Grubba) | | case '\'': pos=find_end_quote(this,data,len,pos,'\'',CPP_END_AT_NEWLINE); break;
case '"': pos=find_end_quote(this,data,len,pos,'\"',CPP_END_AT_NEWLINE); break;
|
1f57ef | 2014-05-10 | Per Hedbor | | case '{': pos=find_end_brace(this, data, len, pos); break;
case '}': return pos;
case '/':
if (INDEX_PCHARP(data,pos) == '*') {
pos=find_end_of_comment(this,data,len,pos,0);
} else if (INDEX_PCHARP(data,pos) == '/') {
pos=find_end_of_line(this,data,len,pos,0);
}
}
}
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static struct pike_string *gobble_identifier (struct CPP_struct *this, const PCHARP data, ptrdiff_t *pos)
|
1f57ef | 2014-05-10 | Per Hedbor | | {
ptrdiff_t p = *pos;
struct string_builder sb;
|
74966e | 2014-05-12 | Per Hedbor | | p_wchar2 tmp;
if( !wide_isidchar( tmp = INDEX_PCHARP(data,*pos)) && tmp != '\\' )
return NULL;
|
1f57ef | 2014-05-10 | Per Hedbor | | init_string_builder (&sb, 0); /* in fact, 0 is more likely than data.shift */
while (1) {
ptrdiff_t start = p;
|
13670c | 2015-05-25 | Martin Nilsson | | while (wide_isidchar (INDEX_PCHARP(data,p)))
|
1f57ef | 2014-05-10 | Per Hedbor | | p++;
if (p != start)
{
PCHARP x = data;
INC_PCHARP(x,start);
string_builder_append(&sb,x, p - start);
}
if (INDEX_PCHARP(data,p) != '\\') goto past_identifier;
switch (INDEX_PCHARP(data,p + 1)) {
case '\r':
if (INDEX_PCHARP(data,p + 2) != '\n')
goto past_identifier;
p++;
/* Fall through */
case '\n':
this->current_line++;
PUTNL();
p += 2;
break;
case 'u':
case 'U': {
/* Note: Code dup in parse_esc_seq in lexer.h. */
/* Don't have to bother checking for an even number of
* preceding backslashes since they aren't valid outside
* string and char literals in the lexer input. */
unsigned INT32 c = 0;
ptrdiff_t stop, q;
if (INDEX_PCHARP(data,p + 2) == INDEX_PCHARP(data,p + 1))
/* A quoted \u escape means we got "\uxxxx" dequoted here,
* and that can't be part of an identifier. */
goto past_identifier;
if (INDEX_PCHARP(data,p + 1) == 'u')
stop = p + 6;
else
stop = p + 10;
for (q = p + 2; q < stop; q++)
{
int tmp;
switch (tmp=INDEX_PCHARP(data,q)) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
c = 16 * c + tmp - '0';
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
c = 16 * c + tmp - 'a' + 10;
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
c = 16 * c + tmp - 'A' + 10;
break;
default:
cpp_error_sprintf (this, "Too few hex digits in \\%c escape.",
INDEX_PCHARP(data,p + 1));
goto past_identifier;
}
}
|
1585cf | 2014-05-10 | Per Hedbor | | if (!wide_isidchar (c)) goto past_identifier;
|
1f57ef | 2014-05-10 | Per Hedbor | | string_builder_putchar (&sb, c);
p = q;
break;
}
default:
goto past_identifier;
}
}
past_identifier:
if (p != *pos) {
*pos = p;
return finish_string_builder (&sb);
}
free_string_builder (&sb);
return NULL;
}
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | /* The reference to the define is held by the stack on return. */
|
7a6120 | 2016-09-04 | Henrik Grubbström (Grubba) | | static struct define_struct *alloc_empty_define(struct pike_string *name)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *def;
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | struct object *o;
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | push_object(o = fast_clone_object(define_program));
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | def = (struct define_struct *)get_storage(o, define_program);
|
500d46 | 2016-09-06 | Henrik Grubbström (Grubba) | | add_ref(def->name = name);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | return def;
}
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @directive #undef
*! @directive #undefine
*!
*! This removes the effect of a @[#define], all subsequent occurances of
*! the undefined identifier will not be replaced by anything.
*!
*! @note
*! Note that when undefining a macro, you just give the identifer,
*! not the arguments.
*!
*! @example
*! // Strip debug
*! #define werror(X ...) 0
*! #include "/home/someone/experimental/stuff.h"
*! #undef werror
*!
*! @seealso
*! @[#define], @[defined()]
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void undefine(struct CPP_struct *this, struct pike_string *name)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | ref_push_string(name);
push_int(0);
map_delete_no_free(this->defines, Pike_sp - 2, Pike_sp - 1);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | if (TYPEOF(Pike_sp[-1]) == PIKE_T_OBJECT) {
struct object *o = Pike_sp[-1].u.object;
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *def = (struct define_struct *)get_storage(o, define_program);
|
7db6bc | 2016-09-08 | Henrik Grubbström (Grubba) | | if (def->flags & (CPP_MACRO_IN_USE | CPP_MACRO_DISABLED)) {
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | /* Restore the #define. */
mapping_insert(this->defines, Pike_sp - 2, Pike_sp - 1);
cpp_error(this, "Illegal to undefine a macro during its expansion.");
pop_n_elems(2);
return;
}
|
853819 | 2001-05-29 | Henrik Grubbström (Grubba) | | }
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | pop_n_elems(2);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @directive #define
*!
*! This directive is used to define or redefine a cpp macro.
*!
*! The simplest way to use define is to write
*!
*! @code
*! #define @b{@i{<identifier>@}@} @i{<replacement string>@}
*! @endcode
*!
*! which will cause all subsequent occurances of @tt{@b{@i{<identifier@}@}@}
*! to be replaced with the @tt{@i{<replacement string>@}@}.
*!
*! Define also has the capability to use arguments, thus a line like
*!
*! @code
*! #define @b{@i{<identifier>@}@}(arg1, arg2) @i{<replacement string>@}
*! @endcode
*!
*! would cause @tt{@b{@i{<identifer>@}@}@} to be a macro. All occurances of
*! '@tt{@b{@i{<identifier>@}@}(something1,something2d)@}' would be replaced
*! with the @tt{@i{<replacement string>@}@}.
*! And in the @tt{@i{<replacement string>@}@}, @tt{arg1@} and @tt{arg2@}
*! will be replaced with @tt{something1@} and @tt{something2@}.
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static struct pike_string *make_define_name(struct CPP_struct *this,
|
a8e54c | 2016-09-06 | Martin Nilsson | | const char *name)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
|
16a6f7 | 2011-11-27 | Tobias S. Josefowitz | | if (this->prefix) {
struct string_builder s;
init_string_builder(&s, 0);
string_builder_append(&s, MKPCHARP_STR(this->prefix),
this->prefix->len);
string_builder_putchar(&s, '_');
|
75942b | 2018-01-12 | Martin Nilsson | | string_builder_strcat(&s, name);
|
a8e54c | 2016-09-06 | Martin Nilsson | | return finish_string_builder(&s);
}
return make_shared_string(name);
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static struct define_struct *do_magic_define(struct CPP_struct *this,
|
a8e54c | 2016-09-06 | Martin Nilsson | | const char *name,
magic_define_fun fun)
{
struct define_struct* def;
|
500d46 | 2016-09-06 | Henrik Grubbström (Grubba) | | struct pike_string *name_str = make_define_name(this, name);
def = alloc_empty_define(name_str);
free_string(name_str);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | def->magic=fun;
|
279a4f | 2016-09-03 | Henrik Grubbström (Grubba) | | mapping_string_insert(this->defines, def->name, Pike_sp-1);
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | pop_stack();
|
3c8ee5 | 2011-12-28 | Henrik Grubbström (Grubba) | | return def;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void add_define(struct CPP_struct *this,
|
b584b1 | 2001-12-20 | Martin Stjernholm | | struct pike_string *name,
struct pike_string *what)
{
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct* def;
|
7a6120 | 2016-09-04 | Henrik Grubbström (Grubba) | | def=alloc_empty_define(name);
ref_push_string(what);
f_aggregate(1);
def->parts = Pike_sp[-1].u.array;
Pike_sp--;
|
279a4f | 2016-09-03 | Henrik Grubbström (Grubba) | | mapping_string_insert(this->defines, def->name, Pike_sp-1);
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | pop_stack();
|
b584b1 | 2001-12-20 | Martin Stjernholm | | }
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void simple_add_define(struct CPP_struct *this,
|
90e5e9 | 2014-05-13 | Martin Nilsson | | const char *name,
const char *what)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
|
500d46 | 2016-09-06 | Henrik Grubbström (Grubba) | |
struct pike_string *name_str = make_define_name(this, name);
|
90314c | 2016-09-09 | Henrik Grubbström (Grubba) | | struct pike_string *what_str = make_shared_string(what);
add_define(this, name_str, what_str);
free_string(what_str);
|
500d46 | 2016-09-06 | Henrik Grubbström (Grubba) | | free_string(name_str);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static struct pike_string *recode_string(struct CPP_struct *this, struct pike_string *data)
|
1c8da5 | 1999-02-24 | Henrik Grubbström (Grubba) | | {
/* Observations:
*
* * At least a prefix of two bytes need to be 7bit in a valid
* Pike program.
*
* * NUL isn't valid in a Pike program.
*/
/* Heuristic:
*
* Index 0 | Index 1 | Interpretation
* --------+---------+------------------------------------------
* 0 | 0 | 32bit wide string.
* 0 | >0 | 16bit Unicode string.
* >0 | 0 | 16bit Unicode string reverse byte order.
* 0xfe | 0xff | 16bit Unicode string.
* 0xff | 0xfe | 16bit Unicode string reverse byte order.
* 0x7b | 0x83 | EBCDIC-US ("#c").
* 0x7b | 0x40 | EBCDIC-US ("# ").
* 0x7b | 0x09 | EBCDIC-US ("#\t").
* --------+---------+------------------------------------------
* Other | Other | 8bit standard string.
*
* Note that the tests below are more lenient than the table above.
* This shouldn't matter, since the other cases would be erroneus
* anyway.
*/
/* Add an extra reference to data, since we may return it as is. */
add_ref(data);
if ((!((unsigned char *)data->str)[0]) ||
(((unsigned char *)data->str)[0] == 0xfe) ||
(((unsigned char *)data->str)[0] == 0xff) ||
(!((unsigned char *)data->str)[1])) {
/* Unicode */
if ((!((unsigned char *)data->str)[0]) &&
(!((unsigned char *)data->str)[1])) {
/* 32bit Unicode (UCS4) */
|
bc861d | 1999-02-25 | Henrik Grubbström (Grubba) | | struct pike_string *new_str;
|
d0ad0a | 2000-08-08 | Henrik Grubbström (Grubba) | | ptrdiff_t len;
ptrdiff_t i;
ptrdiff_t j;
|
bc861d | 1999-02-25 | Henrik Grubbström (Grubba) | | p_wchar0 *orig = STR0(data);
p_wchar2 *dest;
if (data->len & 3) {
/* String len is not a multiple of 4 */
return data;
}
len = data->len/4;
new_str = begin_wide_shared_string(len, 2);
dest = STR2(new_str);
j = 0;
for(i=0; i<len; i++) {
dest[i] = (orig[j]<<24) | (orig[j+1]<<16) | (orig[j+2]<<8) | orig[j+3];
j += 4;
}
free_string(data);
return(end_shared_string(new_str));
|
1c8da5 | 1999-02-24 | Henrik Grubbström (Grubba) | | } else {
|
9aa6ec | 1999-02-25 | Henrik Grubbström (Grubba) | | /* 16bit Unicode (UCS2) */
|
bc861d | 1999-02-25 | Henrik Grubbström (Grubba) | | if (data->len & 1) {
/* String len is not a multiple of 2 */
return data;
}
|
1c8da5 | 1999-02-24 | Henrik Grubbström (Grubba) | | if ((!((unsigned char *)data->str)[1]) ||
(((unsigned char *)data->str)[1] == 0xfe)) {
/* Reverse Byte-order */
|
371abe | 1999-02-26 | Henrik Grubbström (Grubba) | | struct pike_string *new_str = begin_shared_string(data->len);
|
9aa6ec | 1999-02-25 | Henrik Grubbström (Grubba) | | int i;
for(i=0; i<data->len; i++) {
new_str->str[i^1] = data->str[i];
}
free_string(data);
|
bc861d | 1999-02-25 | Henrik Grubbström (Grubba) | | data = end_shared_string(new_str);
|
1c8da5 | 1999-02-24 | Henrik Grubbström (Grubba) | | }
|
9aa6ec | 1999-02-25 | Henrik Grubbström (Grubba) | | /* Note: We lose the extra reference to data here. */
|
1c8da5 | 1999-02-24 | Henrik Grubbström (Grubba) | | push_string(data);
f_unicode_to_string(1);
|
19961b | 2017-04-08 | Martin Nilsson | | add_ref(data = Pike_sp[-1].u.string);
|
1c8da5 | 1999-02-24 | Henrik Grubbström (Grubba) | | pop_stack();
|
bc861d | 1999-02-25 | Henrik Grubbström (Grubba) | | return data;
|
1c8da5 | 1999-02-24 | Henrik Grubbström (Grubba) | | }
|
371abe | 1999-02-26 | Henrik Grubbström (Grubba) | | } else if (data->str[0] == '{') {
|
1c8da5 | 1999-02-24 | Henrik Grubbström (Grubba) | | /* EBCDIC */
/* Notes on EBCDIC:
*
* * EBCDIC conversion needs to first convert the first line
* according to EBCDIC-US, and then the rest of the string
* according to the encoding specified by the first line.
*
|
a4a172 | 2000-12-05 | Per Hedbor | | * * It's an error for a program written in EBCDIC not to
|
1c8da5 | 1999-02-24 | Henrik Grubbström (Grubba) | | * start with a #charset directive.
*
* Obfuscation note:
*
* * This still allows the rest of the file to be written in
* another encoding than EBCDIC.
*/
|
371abe | 1999-02-26 | Henrik Grubbström (Grubba) | |
/* First split out the first line.
*
* Note that codes 0x00 - 0x1f are the same in ASCII and EBCDIC.
*/
struct pike_string *new_str;
char *p = strchr(data->str, '\n');
char *p2;
|
d0ad0a | 2000-08-08 | Henrik Grubbström (Grubba) | | size_t len;
|
371abe | 1999-02-26 | Henrik Grubbström (Grubba) | |
if (!p) {
return data;
}
len = p - data->str;
if (len < CONSTANT_STRLEN("#charset ")) {
return data;
}
new_str = begin_shared_string(len);
|
59fc9e | 2014-09-03 | Martin Nilsson | | memcpy(new_str->str, data->str, len);
|
371abe | 1999-02-26 | Henrik Grubbström (Grubba) | |
push_string(end_shared_string(new_str));
|
75367d | 2014-08-22 | Arne Goedeke | | push_static_text("ebcdic-us");
|
371abe | 1999-02-26 | Henrik Grubbström (Grubba) | |
|
715e55 | 2003-11-14 | Martin Stjernholm | | if (safe_apply_handler ("decode_charset", this->handler, this->compat_handler,
2, BIT_STRING)) {
/* Various consistency checks. */
|
19961b | 2017-04-08 | Martin Nilsson | | if ((Pike_sp[-1].u.string->size_shift) ||
(((size_t)Pike_sp[-1].u.string->len) < CONSTANT_STRLEN("#charset")) ||
(Pike_sp[-1].u.string->str[0] != '#')) {
|
715e55 | 2003-11-14 | Martin Stjernholm | | pop_stack();
return data;
}
}
else {
cpp_handle_exception (this, "Error decoding with charset 'ebcdic-us'");
|
371abe | 1999-02-26 | Henrik Grubbström (Grubba) | | return data;
}
/* At this point the decoded first line is on the stack. */
/* Extract the charset name */
|
19961b | 2017-04-08 | Martin Nilsson | | p = Pike_sp[-1].u.string->str + 1;
|
371abe | 1999-02-26 | Henrik Grubbström (Grubba) | | while (*p && isspace(*((unsigned char *)p))) {
p++;
}
if (strncmp(p, "charset", CONSTANT_STRLEN("charset")) ||
!isspace(((unsigned char *)p)[CONSTANT_STRLEN("charset")])) {
pop_stack();
return data;
}
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | p += CONSTANT_STRLEN("charset") + 1;
while (*p && isspace(*((unsigned char *)p))) {
p++;
}
if (!*p) {
pop_stack();
return data;
}
/* Build a string of the trailing data
* NOTE:
* Keep the newline, so the linenumber info stays correct.
*/
new_str = begin_shared_string(data->len - len);
|
59fc9e | 2014-09-03 | Martin Nilsson | | memcpy(new_str->str, data->str + len, data->len - len);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | |
push_string(end_shared_string(new_str));
stack_swap();
/* Build a string of the charset name */
p2 = p;
while(*p2 && !isspace(*((unsigned char *)p2))) {
p2++;
}
len = p2 - p;
new_str = begin_shared_string(len);
|
59fc9e | 2014-09-03 | Martin Nilsson | | memcpy(new_str->str, p, len);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | |
pop_stack();
|
20c006 | 2004-06-30 | Henrik Grubbström (Grubba) | | ref_push_string(new_str = end_shared_string(new_str));
|
b7df6e | 2014-05-12 | Per Hedbor | |
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | /* Decode the string */
|
715e55 | 2003-11-14 | Martin Stjernholm | | if (!safe_apply_handler ("decode_charset", this->handler, this->compat_handler,
2, BIT_STRING)) {
|
404563 | 2004-06-29 | Martin Nilsson | | cpp_handle_exception (this, "Error decoding with charset %S", new_str);
|
715e55 | 2003-11-14 | Martin Stjernholm | | free_string (new_str);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | return data;
}
|
715e55 | 2003-11-14 | Martin Stjernholm | | free_string (new_str);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | |
/* Accept the new string */
free_string(data);
|
19961b | 2017-04-08 | Martin Nilsson | | add_ref(data = Pike_sp[-1].u.string);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | pop_stack();
}
return data;
}
static struct pike_string *filter_bom(struct pike_string *data)
{
/* More notes:
*
* * Character 0xfeff (ZERO WIDTH NO-BREAK SPACE = BYTE ORDER MARK = BOM)
* needs to be filtered away before processing continues.
*/
|
7e1661 | 2000-08-10 | Henrik Grubbström (Grubba) | | ptrdiff_t i;
ptrdiff_t j = 0;
ptrdiff_t len = data->len;
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | struct string_builder buf;
/* Add an extra reference to data here, since we may return it as is. */
add_ref(data);
if (!data->size_shift) {
return(data);
}
|
13670c | 2015-05-25 | Martin Nilsson | |
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | init_string_builder(&buf, data->size_shift);
if (data->size_shift == 1) {
/* 16 bit string */
p_wchar1 *ptr = STR1(data);
for(i = 0; i<len; i++) {
if (ptr[i] == 0xfeff) {
if (i != j) {
|
13d2d3 | 2004-11-14 | Martin Stjernholm | | string_builder_binary_strcat1 (&buf, ptr + j, i - j);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | j = i+1;
}
}
}
if ((j) && (i != j)) {
/* Add the trailing string */
|
13d2d3 | 2004-11-14 | Martin Stjernholm | | string_builder_binary_strcat1 (&buf, ptr + j, i - j);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | free_string(data);
data = finish_string_builder(&buf);
} else {
/* String didn't contain 0xfeff */
free_string_builder(&buf);
}
} else {
/* 32 bit string */
p_wchar2 *ptr = STR2(data);
for(i = 0; i<len; i++) {
if (ptr[i] == 0xfeff) {
if (i != j) {
|
13d2d3 | 2004-11-14 | Martin Stjernholm | | string_builder_binary_strcat2 (&buf, ptr + j, i - j);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | j = i+1;
}
}
}
if ((j) && (i != j)) {
/* Add the trailing string */
|
13d2d3 | 2004-11-14 | Martin Stjernholm | | string_builder_binary_strcat2 (&buf, ptr + j, i - j);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | free_string(data);
data = finish_string_builder(&buf);
} else {
/* String didn't contain 0xfeff */
free_string_builder(&buf);
}
}
return(data);
}
|
7b73fb | 2014-05-10 | Per Hedbor | | #define PUSH_STRING0(X,Y,Z) add_quoted_string( X,Y,0,Z)
|
1585cf | 2014-05-10 | Per Hedbor | | #define PUSH_STRING_SHIFT(X,Y,Z,A) add_quoted_string(X,Y,Z,A)
|
48c4ef | 2016-12-17 | Martin Nilsson | |
|
b7df6e | 2014-05-12 | Per Hedbor | | /*
* Generic macros
*/
|
efd97a | 2014-05-12 | Martin Nilsson | | #define CHECK_WORD(X,LEN) (begins_with(X,ADD_PCHARP(data,pos),(LEN),len-pos,1))
#define GOBBLE_WORD(X) (CHECK_WORD(X,NELEM(X)) ? (pos+=NELEM(X)),1 : 0)
|
fbd041 | 2016-10-01 | Henrik Grubbström (Grubba) | | #define FIND_END_OF_STRING(FLAGS) (pos=find_end_quote(this,data,len,pos,'\"',FLAGS))
#define FIND_END_OF_CHAR() (pos=find_end_quote(this,data,len,pos,'\'',CPP_END_AT_NEWLINE))
|
b7df6e | 2014-05-12 | Per Hedbor | | #define FIND_EOL_PRETEND() (pos=find_end_of_line(this,data,len,pos,0))
#define FIND_EOL() (pos=find_end_of_line(this,data,len,pos,1))
#define SKIPCOMMENT_INC_LINES() (pos=find_end_of_comment(this,data,len,pos,0))
#define SKIPCOMMENT() (pos=find_end_of_comment(this,data,len,pos,1))
#define FIND_EOS() (pos=find_eos(this,data,len,pos))
/* Skips horizontal whitespace and newlines. */
#define SKIPWHITE() (pos=skipwhite(this,data,pos))
/* Skips horizontal whitespace and escaped newlines. */
#define SKIPSPACE() (pos=skipspace(this,data,pos,1))
#define SKIPSPACE_PRETEND() (pos=skipspace(this,data,pos,0))
/* At entry pos points past the start quote.
* At exit pos points past the end quote.
*/
#define READSTRING(nf) (pos=readstring(this,data,len,pos,&nf,0))
#define READSTRING2(nf) (pos=readstring(this,data,len,pos,&nf,1))
|
2028f8 | 2014-07-21 | Per Hedbor | | #define READSTRING3(nf,ec) (pos=readstring_lit(this,data,len,pos,&nf,ec))
|
b7df6e | 2014-05-12 | Per Hedbor | | #define FIXSTRING(nf,outp) (pos=fixstring(this,data,len,pos,&nf,outp))
/* Gobble an identifier at the current position. */
#define GOBBLE_IDENTIFIER() dmalloc_touch (struct pike_string *, gobble_identifier(this,data,&pos))
#define READCHAR(C) (C=readchar(data,&pos,this))
#define DATA(X) INDEX_PCHARP(data,X)
|
efd97a | 2014-05-12 | Martin Nilsson | | #define HAS_PREFIX(X) \
|
b7df6e | 2014-05-12 | Per Hedbor | | ((begins_with(X,ADD_PCHARP(data,pos),sizeof(X),len-pos,0)) ? (pos += NELEM(X)),1 : 0)
|
1585cf | 2014-05-10 | Per Hedbor | |
|
90e5e9 | 2014-05-13 | Martin Nilsson | | static void add_quoted_string( const void *str, ptrdiff_t len, int shift,
|
7b73fb | 2014-05-10 | Per Hedbor | | struct string_builder *dst )
{
struct pike_string *x = make_shared_binary_pcharp( MKPCHARP(str,shift), len );
string_builder_putchar( dst, '"' );
string_builder_quote_string( dst, x, 0, 0x7fffffff, 0 );
string_builder_putchar( dst, '"' );
free_string(x);
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t find_eos( struct CPP_struct *this, const PCHARP data, ptrdiff_t len, ptrdiff_t pos )
|
1585cf | 2014-05-10 | Per Hedbor | | {
while(pos < len)
{
|
b7df6e | 2014-05-12 | Per Hedbor | | switch (DATA(pos++)) {
|
1585cf | 2014-05-10 | Per Hedbor | | case '\n':
break;
case '/':
|
b7df6e | 2014-05-12 | Per Hedbor | | if (DATA(pos) == '/') {
|
1585cf | 2014-05-10 | Per Hedbor | | pos = find_end_of_line(this,data,len,pos,0);
break;
|
b7df6e | 2014-05-12 | Per Hedbor | | } else if (DATA(pos) == '*') {
|
1585cf | 2014-05-10 | Per Hedbor | | pos = find_end_of_comment(this,data,len,pos,0);
}
continue;
case '\\':
|
b7df6e | 2014-05-12 | Per Hedbor | | if (DATA(pos) == '\n') {
|
1585cf | 2014-05-10 | Per Hedbor | | pos+=1;
|
b7df6e | 2014-05-12 | Per Hedbor | | } else if ((DATA(pos) == '\r') &&
(DATA(pos+1) == '\n')) {
|
1585cf | 2014-05-10 | Per Hedbor | | pos+=2;
} else {
continue;
}
this->current_line++;
|
3595ea | 2018-02-12 | Marcus Comstedt | | /* FALLTHRU */
|
1585cf | 2014-05-10 | Per Hedbor | | default:
continue;
}
this->current_line++;
break;
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t skipwhite(struct CPP_struct *this, const PCHARP data, ptrdiff_t pos)
|
1585cf | 2014-05-10 | Per Hedbor | | {
|
13670c | 2015-05-25 | Martin Nilsson | | do
|
1585cf | 2014-05-10 | Per Hedbor | | {
int c;
|
b7df6e | 2014-05-12 | Per Hedbor | | if(!wide_isspace(c=DATA(pos)))
|
1585cf | 2014-05-10 | Per Hedbor | | {
|
13670c | 2015-05-25 | Martin Nilsson | | if (c == '\\')
|
1585cf | 2014-05-10 | Per Hedbor | | {
|
13670c | 2015-05-25 | Martin Nilsson | | if (DATA(pos+1) == '\n')
|
1585cf | 2014-05-10 | Per Hedbor | | {
pos += 2;
PUTNL();
this->current_line++;
continue;
|
b7df6e | 2014-05-12 | Per Hedbor | | } else if ((DATA(pos+1) == '\r') &&
(DATA(pos+2) == '\n')) {
|
1585cf | 2014-05-10 | Per Hedbor | | pos += 3;
PUTNL();
this->current_line++;
continue;
}
}
break;
}
|
13670c | 2015-05-25 | Martin Nilsson | | else if(c=='\n')
{
PUTNL(); this->current_line++;
|
1585cf | 2014-05-10 | Per Hedbor | | }
pos++;
} while(1);
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t skipspace(struct CPP_struct *this, const PCHARP data, ptrdiff_t pos, int emit)
|
1585cf | 2014-05-10 | Per Hedbor | | {
do {
int c;
|
b7df6e | 2014-05-12 | Per Hedbor | | while (wide_isspace(c=DATA(pos)) && c!='\n') {
|
1585cf | 2014-05-10 | Per Hedbor | | pos++;
}
if (c == '\\') {
|
b7df6e | 2014-05-12 | Per Hedbor | | if (DATA(pos+1) == '\n') {
|
1585cf | 2014-05-10 | Per Hedbor | | pos+=2;
|
b7df6e | 2014-05-12 | Per Hedbor | | } else if ((DATA(pos+1) == '\r') &&
(DATA(pos+2) == '\n')) {
|
1585cf | 2014-05-10 | Per Hedbor | | pos+=3;
} else {
break;
}
} else {
break;
}
if( emit )
{
PUTNL();
this->current_line++;
}
} while (1);
return pos;
}
static const char eq_[] = { '=', '=' };
static const char ne_[] = { '!', '=' };
static const char land_[] = { '&', '&' };
static const char lor_[] = { '|', '|' };
static const char string_recur_[] =
{ 's', 't', 'r', 'i', 'n', 'g', '_', 'r', 'e', 'c', 'u', 'r' };
static const char include_recur_[] =
{ 'i', 'n', 'c', 'l', 'u', 'd', 'e', '_', 'r', 'e', 'c', 'u', 'r' };
static const char line_[] = { 'l', 'i', 'n', 'e' };
static const char string_[] = { 's', 't', 'r', 'i', 'n', 'g' };
static const char include_[] = { 'i', 'n', 'c', 'l', 'u', 'd', 'e' };
static const char if_[] = { 'i', 'f' };
static const char ifdef_[] = { 'i', 'f', 'd', 'e', 'f' };
static const char ifndef_[] = { 'i', 'f', 'n', 'd', 'e', 'f' };
static const char endif_[] = { 'e', 'n', 'd', 'i', 'f' };
static const char else_[] = { 'e', 'l', 's', 'e' };
static const char elseif_[] = { 'e', 'l', 's', 'e', 'i', 'f' };
static const char elif_[] = { 'e', 'l', 'i', 'f' };
static const char define_[] = { 'd', 'e', 'f', 'i', 'n', 'e' };
static const char undef_[] = { 'u', 'n', 'd', 'e', 'f' };
static const char undefine_[] = { 'u', 'n', 'd', 'e', 'f', 'i', 'n', 'e' };
static const char charset_[] = { 'c', 'h', 'a', 'r', 's', 'e', 't' };
static const char pragma_[] = { 'p', 'r', 'a', 'g', 'm', 'a' };
static const char pike_[] = { 'p', 'i', 'k', 'e' };
static const char require_[] = { 'r', 'e', 'q', 'u', 'i', 'r', 'e' };
static const char lsh_[] = { '<', '<' };
static const char rsh_[] = { '>', '>' };
|
90e5e9 | 2014-05-13 | Martin Nilsson | | static int begins_with( const char *prefix, const PCHARP stack, int len, int remain, int whole )
|
1585cf | 2014-05-10 | Per Hedbor | | {
int i;
|
74966e | 2014-05-12 | Per Hedbor | | if( len > remain )
return 0;
|
1585cf | 2014-05-10 | Per Hedbor | | for( i=0; i<len; i++ )
if( INDEX_PCHARP(stack,i) != prefix[i] )
return 0;
|
74966e | 2014-05-12 | Per Hedbor | |
if( whole && len != remain && wide_isidchar(INDEX_PCHARP(stack,len)) )
return 0;
|
1585cf | 2014-05-10 | Per Hedbor | | return 1;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t low_cpp(struct CPP_struct *this,
|
58efb8 | 2014-05-12 | Per Hedbor | | PCHARP data,
ptrdiff_t len,
int flags,
struct pike_string *charset);
|
7b73fb | 2014-05-10 | Per Hedbor | |
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc1(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags);
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calcC(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
SKIPWHITE();
CALC_DUMPPOS("calcC");
|
b7df6e | 2014-05-12 | Per Hedbor | | switch(DATA(pos))
|
74966e | 2014-05-12 | Per Hedbor | | {
case '(':
pos=calc1(this,data,len,pos+1,flags);
SKIPWHITE();
if(!GOBBLE(')'))
cpp_error(this, "Missing ')'");
break;
|
b7df6e | 2014-05-12 | Per Hedbor | |
|
74966e | 2014-05-12 | Per Hedbor | | case '0':
|
b7df6e | 2014-05-12 | Per Hedbor | | if(DATA(pos+1)=='x' || DATA(pos+1)=='X')
|
74966e | 2014-05-12 | Per Hedbor | | {
PCHARP p = data;
INC_PCHARP(p,pos + 2);
push_int(0);
safe_wide_string_to_svalue_inumber(Pike_sp-1, p.ptr, &p.ptr, 16, 0, p.shift);
if(!OUTP()) pop_stack();
pos = SUBTRACT_PCHARP(p,data);
break;
}
|
3595ea | 2018-02-12 | Marcus Comstedt | | /* FALLTHRU */
|
b7df6e | 2014-05-12 | Per Hedbor | |
|
74966e | 2014-05-12 | Per Hedbor | | case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
PCHARP p1,p2;
PCHARP p;
double f;
long l;
/* FIXME: Support bignums. */
|
b7df6e | 2014-05-12 | Per Hedbor | |
|
74966e | 2014-05-12 | Per Hedbor | | p = ADD_PCHARP(data,pos);
f = STRTOD_PCHARP(p, &p1);
l = STRTOL_PCHARP(p, &p2, 0);
if(COMPARE_PCHARP(p1,>,p2))
{
if(OUTP())
|
bd6739 | 2015-10-14 | Martin Nilsson | | push_float((FLOAT_TYPE)f);
|
74966e | 2014-05-12 | Per Hedbor | | pos = SUBTRACT_PCHARP(p1,data);
}else{
if(OUTP())
push_int(l);
pos = SUBTRACT_PCHARP(p2,data);
}
break;
}
case '\'':
{
|
b7df6e | 2014-05-12 | Per Hedbor | | p_wchar2 tmp = DATA(++pos);
|
74966e | 2014-05-12 | Per Hedbor | | if (tmp == '\\') READCHAR(tmp);
pos++;
// FIXME: Multi char char constants here as well.
if(!GOBBLE('\''))
cpp_error(this, "Missing end quote in character constant.");
if(OUTP())
push_int(tmp);
break;
}
case '"':
{
struct string_builder s;
init_string_builder(&s, 0);
READSTRING(s);
if(OUTP())
push_string(finish_string_builder(&s));
else
free_string_builder(&s);
break;
}
|
b7df6e | 2014-05-12 | Per Hedbor | |
|
74966e | 2014-05-12 | Per Hedbor | | default: {
struct pike_string *func_name = gobble_identifier(this,data,&pos);
|
b7df6e | 2014-05-12 | Per Hedbor | | if (func_name || DATA(pos) == '.') {
/* NOTE: defined() can not be handled here,
|
74966e | 2014-05-12 | Per Hedbor | | * since the argument must not be expanded.
*/
SKIPWHITE();
if ( (func_name==constant_str || func_name==efun_str) &&
|
b7df6e | 2014-05-12 | Per Hedbor | | DATA(pos) == '(')
|
74966e | 2014-05-12 | Per Hedbor | | {
int start, end;
int arg = 0;
INT_TYPE start_line;
if( func_name==efun_str && !CPP_TEST_COMPAT(this,7,9) )
cpp_warning(this, "Directive efun() deprecated.");
pos++; /* GOBBLE('(') */
start_line = this->current_line;
SKIPWHITE();
start = end = pos;
|
b7df6e | 2014-05-12 | Per Hedbor | | while (DATA(pos) != ')') {
switch(DATA(pos++)) {
|
74966e | 2014-05-12 | Per Hedbor | | case '(':
pos = find_end_parenthesis(this, data, len, pos);
break;
case ',':
push_string(make_shared_binary_pcharp(ADD_PCHARP(data,start), end-start));
arg++;
start = pos;
break;
case '/':
|
b7df6e | 2014-05-12 | Per Hedbor | | if (DATA(pos) == '*') {
|
74966e | 2014-05-12 | Per Hedbor | | pos++;
if (this->keep_comments) {
start = pos - 2;
SKIPCOMMENT_INC_LINES();
|
13670c | 2015-05-25 | Martin Nilsson | | } else
|
74966e | 2014-05-12 | Per Hedbor | | SKIPCOMMENT();
|
b7df6e | 2014-05-12 | Per Hedbor | | } else if (DATA(pos) == '/') {
|
74966e | 2014-05-12 | Per Hedbor | | if (this->keep_comments) {
start = pos - 1;
FIND_EOL_PRETEND();
} else FIND_EOL();
}
break;
case '\0':
if (pos > len) {
INT_TYPE old_line = this->current_line;
this->current_line = start_line;
cpp_error_sprintf(this, "Missing ) in the meta function %S().",
func_name);
this->current_line = old_line;
free_string (func_name);
return pos-1;
}
|
5f5084 | 2018-02-12 | Marcus Comstedt | | /* FALLTHRU */
|
74966e | 2014-05-12 | Per Hedbor | | default:
|
a55090 | 2016-12-17 | Martin Nilsson | | if (wide_isspace(DATA(pos-1))) {
|
74966e | 2014-05-12 | Per Hedbor | | SKIPWHITE();
continue;
}
break;
}
end = pos;
}
|
b7df6e | 2014-05-12 | Per Hedbor | |
|
74966e | 2014-05-12 | Per Hedbor | | if (start != end) {
push_string(make_shared_binary_pcharp(ADD_PCHARP(data,start), end-start));
arg++;
}
if(!GOBBLE(')')) {
INT_TYPE old_line = this->current_line;
this->current_line = start_line;
cpp_error_sprintf(this, "Missing ) in the meta function %S().",
func_name);
this->current_line = old_line;
}
/* NOTE: cpp_func MUST protect against errors. */
if(OUTP())
{
if (arg != 1) {
cpp_error_sprintf(this, "Bad number of arguments to %S().",
func_name);
pop_n_elems(arg);
push_int(0);
}
else
cpp_constant(this, 0);
}
else
pop_n_elems(arg);
|
b7df6e | 2014-05-12 | Per Hedbor | | } else if (DATA(pos) == '.') {
|
74966e | 2014-05-12 | Per Hedbor | | if (func_name == NULL)
add_ref((func_name = empty_pike_string));
while (GOBBLE('.')) {
struct pike_string *ind_name;
SKIPWHITE();
ind_name = gobble_identifier(this,data,&pos);
if (ind_name == NULL) {
cpp_error_sprintf(this, "Syntax error in #if missing identifier after '.'.");
free_string (func_name);
func_name = NULL;
break;
}
if(OUTP()) {
push_string (func_name);
|
5e9fc0 | 2015-08-18 | Per Hedbor | | push_static_text (".");
|
74966e | 2014-05-12 | Per Hedbor | | push_string (ind_name);
f_add(3);
func_name = Pike_sp[-1].u.string;
--Pike_sp;
}
SKIPWHITE();
}
if (func_name == NULL)
break;
if(OUTP())
{
ref_push_string(func_name);
cpp_constant(this, 1);
}
} else {
if(OUTP())
push_int(0);
}
free_string (func_name);
break;
}
cpp_error_sprintf(this, "Syntax error in #if bad character %c (%d).",
|
b7df6e | 2014-05-12 | Per Hedbor | | DATA(pos), DATA(pos));
|
74966e | 2014-05-12 | Per Hedbor | | break;
}
}
SKIPWHITE();
while(GOBBLE('['))
{
CALC_DUMPPOS("inside calcC");
pos=calc1(this,data,len,pos,flags);
if(OUTP())
f_index(2);
SKIPWHITE();
if(!GOBBLE(']'))
cpp_error(this, "Missing ']'.");
}
CALC_DUMPPOS("after calcC");
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calcB(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calcB");
SKIPWHITE();
|
b7df6e | 2014-05-12 | Per Hedbor | | switch(DATA(pos))
|
74966e | 2014-05-12 | Per Hedbor | | {
case '-': pos++; pos=calcB(this,data,len,pos,flags);
if(OUTP()) o_negate(); break;
case '!': pos++; pos=calcB(this,data,len,pos,flags);
if(OUTP()) o_not(); break;
case '~': pos++; pos=calcB(this,data,len,pos,flags);
if(OUTP()) o_compl(); break;
default: pos=calcC(this,data,len,pos,flags);
}
CALC_DUMPPOS("after calcB");
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calcA(struct CPP_struct *this,PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calcA");
pos=calcB(this,data,len,pos,flags);
while(1)
{
CALC_DUMPPOS("inside calcA");
SKIPWHITE();
|
b7df6e | 2014-05-12 | Per Hedbor | | switch(DATA(pos))
|
74966e | 2014-05-12 | Per Hedbor | | {
case '/':
|
b7df6e | 2014-05-12 | Per Hedbor | | if(DATA(pos+1)=='/' ||
DATA(pos+1)=='*')
|
74966e | 2014-05-12 | Per Hedbor | | return pos;
pos++;
pos=calcB(this,data,len,pos,flags);
if(OUTP())
o_divide();
continue;
case '*':
pos++;
pos=calcB(this,data,len,pos,flags);
if(OUTP())
o_multiply();
continue;
case '%':
pos++;
pos=calcB(this,data,len,pos,flags);
if(OUTP())
o_mod();
continue;
}
break;
}
CALC_DUMPPOS("after calcA");
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc9(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calc9");
pos=calcA(this,data,len,pos,flags);
while(1)
{
CALC_DUMPPOS("inside calc9");
SKIPWHITE();
|
b7df6e | 2014-05-12 | Per Hedbor | | switch(DATA(pos))
|
74966e | 2014-05-12 | Per Hedbor | | {
case '+':
pos++;
pos=calcA(this,data,len,pos,flags);
if(OUTP())
f_add(2);
continue;
case '-':
pos++;
pos=calcA(this,data,len,pos,flags);
if(OUTP())
o_subtract();
continue;
}
break;
}
CALC_DUMPPOS("after calc9");
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc8(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calc8");
pos=calc9(this,data,len,pos,flags);
while(1)
{
CALC_DUMPPOS("inside calc8");
SKIPWHITE();
|
efd97a | 2014-05-12 | Martin Nilsson | | if(HAS_PREFIX(lsh_))
|
74966e | 2014-05-12 | Per Hedbor | | {
CALC_DUMPPOS("Found <<");
pos=calc9(this,data,len,pos,flags);
if(OUTP())
o_lsh();
break;
}
|
efd97a | 2014-05-12 | Martin Nilsson | | if(HAS_PREFIX(rsh_))
|
74966e | 2014-05-12 | Per Hedbor | | {
CALC_DUMPPOS("Found >>");
pos=calc9(this,data,len,pos,flags);
if(OUTP())
o_rsh();
break;
}
break;
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc7b(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calc7b");
pos=calc8(this,data,len,pos,flags);
while(1)
{
CALC_DUMPPOS("inside calc7b");
SKIPWHITE();
|
b7df6e | 2014-05-12 | Per Hedbor | |
switch(DATA(pos))
|
74966e | 2014-05-12 | Per Hedbor | | {
case '<':
|
b7df6e | 2014-05-12 | Per Hedbor | | if(DATA(pos+1) == '<') break;
|
74966e | 2014-05-12 | Per Hedbor | | pos++;
if(GOBBLE('='))
{
pos=calc8(this,data,len,pos,flags);
if(OUTP())
f_le(2);
}else{
pos=calc8(this,data,len,pos,flags);
if(OUTP())
f_lt(2);
}
continue;
case '>':
|
b7df6e | 2014-05-12 | Per Hedbor | | if(DATA(pos+1) == '>') break;
|
74966e | 2014-05-12 | Per Hedbor | | pos++;
if(GOBBLE('='))
{
pos=calc8(this,data,len,pos,flags);
if(OUTP())
f_ge(2);
}else{
pos=calc8(this,data,len,pos,flags);
if(OUTP())
f_gt(2);
}
continue;
}
break;
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc7(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calc7");
pos=calc7b(this,data,len,pos,flags);
while(1)
{
CALC_DUMPPOS("inside calc7");
SKIPWHITE();
|
efd97a | 2014-05-12 | Martin Nilsson | | if(HAS_PREFIX(eq_))
|
74966e | 2014-05-12 | Per Hedbor | | {
pos=calc7b(this,data,len,pos,flags);
if(OUTP())
f_eq(2);
continue;
}
|
efd97a | 2014-05-12 | Martin Nilsson | | if(HAS_PREFIX(ne_))
|
74966e | 2014-05-12 | Per Hedbor | | {
pos=calc7b(this,data,len,pos,flags);
if(OUTP())
f_ne(2);
continue;
}
break;
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc6(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calc6");
pos=calc7(this,data,len,pos,flags);
SKIPWHITE();
|
b7df6e | 2014-05-12 | Per Hedbor | | while(DATA(pos) == '&' && DATA(pos+1)!='&')
|
74966e | 2014-05-12 | Per Hedbor | | {
CALC_DUMPPOS("inside calc6");
pos++;
pos=calc7(this,data,len,pos,flags);
if(OUTP())
o_and();
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc5(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calc5");
pos=calc6(this,data,len,pos,flags);
SKIPWHITE();
while(GOBBLE('^'))
{
CALC_DUMPPOS("inside calc5");
pos=calc6(this,data,len,pos,flags);
if(OUTP())
o_xor();
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc4(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calc4");
pos=calc5(this,data,len,pos,flags);
SKIPWHITE();
|
b7df6e | 2014-05-12 | Per Hedbor | | while(DATA(pos) == '|' && DATA(pos+1)!='|')
|
74966e | 2014-05-12 | Per Hedbor | | {
CALC_DUMPPOS("inside calc4");
pos++;
pos=calc5(this,data,len,pos,flags);
if(OUTP())
o_or();
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc3(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calc3");
pos=calc4(this,data,len,pos,flags);
SKIPWHITE();
|
efd97a | 2014-05-12 | Martin Nilsson | | while(HAS_PREFIX(land_))
|
74966e | 2014-05-12 | Per Hedbor | | {
CALC_DUMPPOS("inside calc3");
if(OUTP()) {
check_destructed(Pike_sp-1);
if(UNSAFE_IS_ZERO(Pike_sp-1))
{
pos=calc4(this,data,len,pos,flags|CPP_REALLY_NO_OUTPUT);
}else{
pop_stack();
pos=calc4(this,data,len,pos,flags);
}
} else
pos=calc4(this,data,len,pos,flags);
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc2(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calc2");
pos=calc3(this,data,len,pos,flags);
SKIPWHITE();
|
efd97a | 2014-05-12 | Martin Nilsson | | while(HAS_PREFIX(lor_))
|
74966e | 2014-05-12 | Per Hedbor | | {
CALC_DUMPPOS("inside calc2");
if(OUTP()) {
check_destructed(Pike_sp-1);
if(!UNSAFE_IS_ZERO(Pike_sp-1))
{
pos=calc3(this,data,len,pos,flags|CPP_REALLY_NO_OUTPUT);
}else{
pop_stack();
pos=calc3(this,data,len,pos,flags);
}
} else
pos=calc3(this,data,len,pos,flags);
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc1(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t pos, int flags)
{
CALC_DUMPPOS("before calc1");
pos=calc2(this,data,len,pos,flags);
SKIPWHITE();
if(GOBBLE('?'))
{
int select = -1;
if(OUTP()) {
check_destructed(Pike_sp-1);
select = (UNSAFE_IS_ZERO(Pike_sp-1)?0:1);
pop_stack();
}
pos=calc1(this,data,len,pos,(select == 1? flags:(flags|CPP_REALLY_NO_OUTPUT)));
if(!GOBBLE(':'))
cpp_error(this, "Colon expected.");
pos=calc1(this,data,len,pos,(select == 0? flags:(flags|CPP_REALLY_NO_OUTPUT)));
}
return pos;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static ptrdiff_t calc(struct CPP_struct *this, PCHARP data, ptrdiff_t len,
|
74966e | 2014-05-12 | Per Hedbor | | ptrdiff_t tmp, int flags)
{
JMP_BUF recovery;
ptrdiff_t pos;
CALC_DUMPPOS("Calculating");
if (SETJMP(recovery))
{
cpp_handle_exception (this, "Error evaluating expression.");
pos=tmp;
FIND_EOL();
push_int(0);
}else{
pos=calc1(this,data,len,tmp,flags);
check_destructed(Pike_sp-1);
}
UNSETJMP(recovery);
CALC_DUMPPOS("Done");
return pos;
}
|
1835c5 | 2018-04-12 | Martin Nilsson | | #if 0
|
00c4a4 | 2016-09-25 | Henrik Grubbström (Grubba) | | static void string_builder_append_cpp_quoted_pcharp(struct string_builder *s,
PCHARP a,
size_t l)
{
size_t e;
for(e=0; e<l;) {
|
a55090 | 2016-12-17 | Martin Nilsson | | if (wide_isspace(INDEX_PCHARP(a, e)) ||
|
00c4a4 | 2016-09-25 | Henrik Grubbström (Grubba) | | INDEX_PCHARP(a, e)=='"' || INDEX_PCHARP(a, e)=='\\') {
if (e) {
string_builder_append(s, a, e);
}
if (INDEX_PCHARP(a, e) == '"' || INDEX_PCHARP(a, e)=='\\') {
/* String or quote. */
string_builder_putchar(s, '\\');
string_builder_putchar(s, INDEX_PCHARP(a, e));
if (INDEX_PCHARP(a, e) == '"') {
for (e++; e < l; e++) {
if (INDEX_PCHARP(a, e) == '"') {
e++;
break;
}
string_builder_putchar(s, INDEX_PCHARP(a, e));
if (INDEX_PCHARP(a, e) == '\\') {
string_builder_putchar(s, '\\');
e++;
if (INDEX_PCHARP(a, e) == '\\' ||
INDEX_PCHARP(a, e) == '"') {
string_builder_putchar(s, '\\');
}
string_builder_putchar(s, INDEX_PCHARP(a, e));
}
}
string_builder_putchar(s, '\\');
string_builder_putchar(s, '"');
}
} else {
/* White space. */
|
a55090 | 2016-12-17 | Martin Nilsson | | while ((e < l) && wide_isspace(INDEX_PCHARP(a, e))) {
|
00c4a4 | 2016-09-25 | Henrik Grubbström (Grubba) | | e++;
}
if (e != l) {
string_builder_putchar(s, ' ');
}
}
INC_PCHARP(a, e);
l -= e;
e = 0;
} else {
e++;
}
}
if (l) {
string_builder_append(s,a,l);
}
}
|
1835c5 | 2018-04-12 | Martin Nilsson | | #endif
|
00c4a4 | 2016-09-25 | Henrik Grubbström (Grubba) | |
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | /* NB: This function is only called from low_cpp(), which
* means that Pike_fp->current_object is an object(CPP).
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void apply_define(struct CPP_struct *this,
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | | struct define_struct *d,
struct define_argument *arguments,
|
e19aca | 2018-01-06 | Henrik Grubbström (Grubba) | | short flags,
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | | struct pike_string *charset)
{
|
b9d36a | 2018-04-11 | Henrik Grubbström (Grubba) | | #if 1
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | | struct svalue *save_sp = Pike_sp;
|
52791d | 2018-04-15 | Henrik Grubbström (Grubba) | | int save_flags;
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | |
/* Keep d around... */
push_svalue(&d->self);
if (d->args < 0) {
push_undefined();
} else {
int i;
BEGIN_AGGREGATE_ARRAY(d->args) {
for (i = 0; i < d->args; i++) {
push_string(make_shared_binary_pcharp(arguments[i].arg,
arguments[i].len));
DO_AGGREGATE_ARRAY(120);
}
} END_AGGREGATE_ARRAY;
}
ref_push_object(Pike_fp->current_object);
|
e21e1a | 2018-04-07 | Henrik Grubbström (Grubba) | | push_int(flags);
apply_lfun(d->self.u.object, LFUN_CALL, 3);
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | |
|
52791d | 2018-04-15 | Henrik Grubbström (Grubba) | | save_flags = d->flags;
d->flags |= CPP_MACRO_DISABLED;
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | |
/* NB: We're executing in the CPP context object. */
low_cpp(this, MKPCHARP_STR(Pike_sp[-1].u.string), Pike_sp[-1].u.string->len,
flags & ~(CPP_EXPECT_ENDIF | CPP_EXPECT_ELSE),
charset);
|
52791d | 2018-04-15 | Henrik Grubbström (Grubba) | | d->flags = save_flags;
|
42af9f | 2018-04-06 | Henrik Grubbström (Grubba) | |
pop_n_elems(Pike_sp - save_sp);
|
b9d36a | 2018-04-11 | Henrik Grubbström (Grubba) | | #else /* !1 */
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | | struct string_builder tmp;
init_string_builder(&tmp, 0);
if(d->magic)
{
int i;
struct pike_string *a = NULL;
if (d->args > 0) {
a = make_shared_binary_pcharp(arguments[0].arg, arguments[0].len);
}
d->magic(this, d, a, &tmp);
/* FIXME: Popping the stack should be moved to
* the magic functions.
*/
if (a) free_string(a);
}else{
struct array *parts = d->parts;
int e;
for(e = 0; e < parts->size; e++)
{
PCHARP a;
ptrdiff_t l;
switch(TYPEOF(parts->item[e])) {
case PIKE_T_INT:
{
int argument = parts->item[e].u.integer;
if((argument & DEF_ARG_MASK) >= d->args)
{
cpp_error(this, "Macro not expanded correctly.");
continue;
}
a = arguments[argument & DEF_ARG_MASK].arg;
l = arguments[argument & DEF_ARG_MASK].len;
if (argument & DEF_ARG_NEED_COMMA
|
347b10 | 2018-04-19 | Henrik Grubbström (Grubba) | | && !(d->flags & CPP_MACRO_VARARGS && d->args-1
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | | == (argument & DEF_ARG_MASK) && l == 0)) {
string_builder_putchar(&tmp, ',');
string_builder_putchar(&tmp, ' ');
}
if(!(argument & DEF_ARG_NOPRESPACE))
string_builder_putchar(&tmp, ' ');
if(argument & DEF_ARG_STRINGIFY)
{
/* NOTE: At entry a[0] is non white-space. */
string_builder_putchar(&tmp, '"');
|
00c4a4 | 2016-09-25 | Henrik Grubbström (Grubba) | | string_builder_append_cpp_quoted_pcharp(&tmp, a, l);
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | | string_builder_putchar(&tmp, '"');
}else{
|
a596ec | 2016-09-24 | Henrik Grubbström (Grubba) | | /* Strip leading and trailing white-space. */
|
a55090 | 2016-12-17 | Martin Nilsson | | while(l && wide_isspace(EXTRACT_PCHARP(a)))
|
a596ec | 2016-09-24 | Henrik Grubbström (Grubba) | | INC_PCHARP(a,1),l--;
|
a55090 | 2016-12-17 | Martin Nilsson | | while(l && wide_isspace(INDEX_PCHARP(a,l-1)))
|
a596ec | 2016-09-24 | Henrik Grubbström (Grubba) | | l--;
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | |
if(argument & (DEF_ARG_NOPRESPACE | DEF_ARG_NOPOSTSPACE))
{
string_builder_append( &tmp, a, l );
}else{
|
52791d | 2018-04-15 | Henrik Grubbström (Grubba) | | /* NB: Evaluate the argument before insertion. */
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | | struct string_builder save;
INT_TYPE line = this->current_line;
|
52791d | 2018-04-15 | Henrik Grubbström (Grubba) | | int save_flags;
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | | /* FIXME: Shouldn't we save current_file too? */
save=this->buf;
this->buf=tmp;
|
52791d | 2018-04-15 | Henrik Grubbström (Grubba) | | save_flags = d->flags;
d->flags |= CPP_MACRO_IN_USE;
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | | low_cpp(this, a, l,
flags & ~(CPP_EXPECT_ENDIF | CPP_EXPECT_ELSE),
|
e19aca | 2018-01-06 | Henrik Grubbström (Grubba) | | charset);
|
52791d | 2018-04-15 | Henrik Grubbström (Grubba) | | d->flags = save_flags;
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | | tmp=this->buf;
this->buf=save;
this->current_line=line;
}
}
if(!(argument & DEF_ARG_NOPOSTSPACE))
string_builder_putchar(&tmp, ' ');
}
break;
case PIKE_T_STRING:
string_builder_shared_strcat(&tmp, parts->item[e].u.string);
break;
}
}
}
/* Remove any newlines from the completed expression. */
if (!(d->magic == insert_callback_define ||
d->magic == insert_callback_define_no_args ||
d->magic == insert_pragma)) {
int e;
for(e=0; e< (ptrdiff_t)tmp.s->len; e++)
if(index_shared_string(tmp.s,e)=='\n')
SET_INDEX_CHARP(tmp.s->str,e,tmp.s->size_shift,' ');
}
d->flags = CPP_MACRO_DISABLED;
/* FIXME: Ought to add a ref to d here. */
string_builder_putchar(&tmp, 0);
tmp.s->len--;
low_cpp(this, MKPCHARP_STR(tmp.s),tmp.s->len,
flags & ~(CPP_EXPECT_ENDIF | CPP_EXPECT_ELSE),
|
e19aca | 2018-01-06 | Henrik Grubbström (Grubba) | | charset);
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | |
d->flags = flags;
/* FIXME: Ought to free the ref to d here. */
free_string_builder(&tmp);
|
b9d36a | 2018-04-11 | Henrik Grubbström (Grubba) | | #endif /* 1 */
|
e0b777 | 2016-09-21 | Henrik Grubbström (Grubba) | | }
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | | /*
* Preprocessor template.
*
|
671034 | 2018-02-21 | Henrik Grubbström (Grubba) | | * NB: There are two basic cases where this function is called:
*
* * Either when switching to a new input data string
* (eg macro expansion or #include). The result of
* this is added to the current buffer.
*
* * Or parsing to the end of the line after a directive.
* The result of this is added to a temporary buffer.
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | | */
static ptrdiff_t low_cpp(struct CPP_struct *this,
PCHARP data,
ptrdiff_t len,
int flags,
struct pike_string *charset)
{
ptrdiff_t pos, tmp, e;
int include_mode;
INT_TYPE first_line = this->current_line;
/* FIXME: What about this->current_file? */
for(pos=0; pos<len;)
{
ptrdiff_t old_pos = pos;
int c;
/* fprintf(stderr,"%c",DATA(pos));
fflush(stderr); */
switch(c = DATA(pos++))
{
case '\n':
if(flags & CPP_END_AT_NEWLINE) return pos-1;
/* fprintf(stderr,"CURRENT LINE: %d\n",this->current_line); */
this->current_line++;
PUTNL();
goto do_skipwhite;
case 0x1b: case 0x9b: /* ESC or CSI */
/* Assume ANSI/DEC escape sequence.
* Format supported:
* <ESC>[\040-\077]+[\100-\177]
* or
* <CSI>[\040-\077]*[\100-\177]
*/
/* FIXME: This place is far from enough to make these things
* behave as whitespace. /mast */
while ((tmp = DATA(pos)) && (tmp == ((tmp & 0x1f)|0x20))) {
pos++;
}
if (tmp == ((tmp & 0x3f)|0x40)) {
pos++;
} else {
/* FIXME: Warning here? */
}
PUTC(' ');
break;
case '\t':
case ' ':
case '\r':
PUTC(' ');
do_skipwhite:
while( wide_isspace(c=DATA(pos)) && c != '\n' && c != '\r' )
pos++;
break;
/* Minor optimization */
case '<': case '=': case '>':
if(DATA(pos)==c &&
DATA(pos+1)==c &&
DATA(pos+2)==c &&
DATA(pos+3)==c &&
DATA(pos+4)==c &&
DATA(pos+5)==c) {
cpp_error(this, "Merge conflict detected.");
PUTC(c);
do {
PUTC(c);
} while (DATA(++pos) == c);
continue;
}
|
5f5084 | 2018-02-12 | Marcus Comstedt | | /* FALLTHRU */
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | |
case '!': case '@': case '$': case '%': case '^': case '&':
case '*': case '(': case ')': case '-': case '+':
case '{': case '}': case ':': case '?': case '`': case ';':
case ',': case '.': case '~': case '[': case ']': case '|':
PUTC(DATA(pos-1));
break;
case '\\':
if(DATA(pos)=='\n') {
pos++;
this->current_line++;
PUTNL();
goto do_skipwhite;
}
else if ((DATA(pos) == '\r') && (DATA(pos+1) == '\n')) {
pos += 2;
this->current_line++;
PUTNL();
goto do_skipwhite;
}
/* Fall through - identifiers might begin with \uxxxx. */
default:
if(OUTP())
{
struct pike_string *s;
struct define_struct *d = NULL;
pos--;
s = GOBBLE_IDENTIFIER();
if (!s) {
PUTC (DATA(pos++));
break;
}
if(flags & CPP_DO_IF && s == defined_str)
{
/* NOTE: defined() must be handled here, since its argument
* must not be macro expanded.
*/
d = defined_macro;
}else{
d=FIND_DEFINE(s);
}
if(d && !(d->flags & CPP_MACRO_DISABLED))
{
int arg=0;
INT_TYPE start_line = this->current_line;
struct string_builder tmp;
struct define_argument arguments[ MAX_ARGS];
short flags = d->flags;
if (d == defined_macro) {
free_string (s);
s = NULL;
}
if(d->args>=0)
{
SKIPWHITE();
if(!GOBBLE('('))
{
if (s) {
string_builder_shared_strcat(&this->buf,s);
free_string(s);
}
/* Restore the post-whitespace. */
string_builder_putchar(&this->buf, ' ');
break;
}
for(arg=0;arg<d->args;arg++)
{
if(arg && DATA(pos)==',')
{
pos++;
SKIPWHITE();
}else{
SKIPWHITE();
if(DATA(pos)==')')
{
|
347b10 | 2018-04-19 | Henrik Grubbström (Grubba) | | if(((d->flags & CPP_MACRO_VARARGS) && (arg + 1 == d->args)) ||
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | | (!arg && (d->args == 1))) {
/* Allow varargs to be left out.
*
* Allow a single argument to be left out.
*/
arguments[arg].arg = ADD_PCHARP(data,pos);
arguments[arg].len=0;
continue;
}else{
cpp_error_sprintf(this,
"Too few arguments to macro %S, expected %d.",
d->name, d->args);
break;
}
}
}
arguments[arg].arg = ADD_PCHARP(data,pos);
while(1)
{
if(pos+1>len)
{
INT_TYPE save_line = this->current_line;
this->current_line = start_line;
cpp_error(this, "End of file in macro call.");
this->current_line = save_line;
break;
}
switch(DATA(pos++))
{
case '\n':
this->current_line++;
PUTNL();
|
3595ea | 2018-02-12 | Marcus Comstedt | | /* FALLTHRU */
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | | default: continue;
case '"':
/* Note: Strings may contain \-escaped newlines.
* They must be removed on insertion to
* avoid being counted twice.
*/
if(DATA(pos-2)!='#') {
FIND_END_OF_STRING(CPP_END_AT_NEWLINE);
}else{
FIND_END_OF_STRING(0); /* Newlines allowed */
}
continue;
case '\'':
FIND_END_OF_CHAR();
continue;
case '/':
if (DATA(pos) == '*') {
pos++;
if (this->keep_comments) {
SKIPCOMMENT_INC_LINES();
goto ADD_TO_BUFFER;
}
SKIPCOMMENT();
} else if (DATA(pos) == '/') {
if (this->keep_comments) {
FIND_EOL_PRETEND();
goto ADD_TO_BUFFER;
}
FIND_EOL();
}
continue;
case '(':
pos=find_end_parenthesis(this, data, len, pos);
continue;
case '{':
pos=find_end_brace(this, data, len, pos);
continue;
case ',':
|
347b10 | 2018-04-19 | Henrik Grubbström (Grubba) | | if((d->flags & CPP_MACRO_VARARGS) && (arg+1 == d->args)) continue;
|
5f5084 | 2018-02-12 | Marcus Comstedt | | /* FALLTHRU */
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | |
case ')':
pos--;
break;
}
break;
}
arguments[arg].len = SUBTRACT_PCHARP(ADD_PCHARP(data,pos),arguments[arg].arg);
}
SKIPWHITE();
if(!GOBBLE(')')) {
this->current_line = start_line;
cpp_error_sprintf(this, "Missing ) in the macro %S.", d->name);
}
}
if(d->args >= 0 && arg != d->args)
cpp_error(this, "Wrong number of arguments to macro.");
/* NB: If there have been errors in the loop above, arguments may
* remain (partially) uninitialized.
*/
if (!this->compile_errors) {
apply_define(this, d, arguments, flags, charset);
}
}else{
if (OUTP())
string_builder_shared_strcat (&this->buf, s);
}
if (s) {
free_string(s);
}
}
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
PUTC(DATA(pos-1));
while(DATA(pos)>='0' && DATA(pos)<='9') PUTC(DATA(pos++));
break;
case '"':
FIXSTRING(this->buf,OUTP());
break;
case '\'':
tmp=pos-1;
FIND_END_OF_CHAR();
if(OUTP())
string_builder_append( &this->buf, ADD_PCHARP(data, tmp), pos - tmp);
else
for (; tmp < pos; tmp++)
if (DATA(tmp) == '\n')
string_builder_putchar (&this->buf, '\n');
break;
case '/':
if(DATA(pos)=='/')
{
if (this->keep_comments) {
FIND_EOL_PRETEND();
goto ADD_TO_BUFFER;
}
FIND_EOL();
break;
}
if(DATA(pos)=='*')
{
if (this->keep_comments) {
SKIPCOMMENT_INC_LINES();
goto ADD_TO_BUFFER;
} else {
PUTC(' ');
SKIPCOMMENT();
}
break;
}
PUTC(DATA(pos-1));
break;
case '#':
if(GOBBLE('!'))
{
FIND_EOL();
break;
}
SKIPSPACE();
if (!CHECK_WORD(string_recur_, NELEM(string_recur_))
&& !CHECK_WORD(include_recur_, NELEM(include_recur_)))
{
if (this->prefix)
{
if( !begins_with( this->prefix->str, ADD_PCHARP(data,pos), this->prefix->len, len-pos, 0 ) ||
DATA(pos+this->prefix->len) != '_')
{
FIND_EOS();
goto ADD_TO_BUFFER;
}
pos += this->prefix->len + 1;
} else {
int i;
for (i = pos; i < len; i++) {
if (DATA(i) == '_') {
FIND_EOS();
goto ADD_TO_BUFFER;
} else if (!wide_isidchar(DATA(i)))
break;
}
}
}
switch(DATA(pos))
{
case 'l':
{
if(GOBBLE_WORD(line_))
{
/* FIXME: Why not use SKIPSPACE()? */
/* Because SKIPSPACE skips newlines? - Hubbe */
/* Actually, no - Per */
while(DATA(pos)==' ' || DATA(pos)=='\t') pos++;
}else{
goto unknown_preprocessor_directive;
}
}
|
5f5084 | 2018-02-12 | Marcus Comstedt | | /* FALLTHRU */
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | | case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
INT_TYPE new_lineno;
PCHARP foo = ADD_PCHARP(data,pos);
new_lineno=STRTOL_PCHARP(foo, &foo, 10)-1;
if(OUTP())
{
string_builder_binary_strcat(&this->buf, "#line ", 6);
string_builder_append(&this->buf, ADD_PCHARP(data,pos),
SUBTRACT_PCHARP(foo,ADD_PCHARP(data,pos)));
}
pos = SUBTRACT_PCHARP(foo,data);
SKIPSPACE();
if(DATA(pos)=='"')
{
struct string_builder nf;
init_string_builder(&nf, 0);
READSTRING(nf);
if(OUTP())
{
free_string(this->current_file);
this->current_file = finish_string_builder(&nf);
string_builder_putchar(&this->buf, ' ');
PUSH_STRING_SHIFT (this->current_file->str, this->current_file->len,
this->current_file->size_shift, &this->buf);
}else{
free_string_builder(&nf);
}
}
if (OUTP())
this->current_line = new_lineno;
FIND_EOL();
break;
}
case '"':
{
struct string_builder nf;
char end;
init_string_builder(&nf, 0);
READSTRING2(nf);
goto stringout;
case '(': end = ')'; goto litstring;
case '[': end = ']'; goto litstring;
case '{': end = '}';
litstring:
init_string_builder(&nf, 0);
READSTRING3(nf,end);
stringout:
if(OUTP())
PUSH_STRING_SHIFT(nf.s->str, nf.s->len,nf.s->size_shift, &this->buf);
free_string_builder(&nf);
break;
}
case 's':
{
if(GOBBLE_WORD(string_))
{
include_mode = 1;
goto do_include;
}
if(GOBBLE_WORD(string_recur_))
{
include_mode = 3;
goto do_include;
}
}
goto unknown_preprocessor_directive;
case 'i': /* include, if, ifdef */
{
int recur = 0;
if(GOBBLE_WORD(include_) || (recur = GOBBLE_WORD(include_recur_)))
{
if (recur) {
include_mode = 2;
} else {
include_mode = 0;
}
do_include:
{
struct svalue *save_sp=Pike_sp;
SKIPSPACE();
check_stack(3);
switch(DATA(pos++))
{
case '"':
{
struct string_builder nf;
init_string_builder(&nf, 0);
pos--;
READSTRING(nf);
push_string(finish_string_builder(&nf));
/* In Pike 7.7 and later filenames belonging to Pike
* are assumed to be encoded according to UTF-8.
*/
f_string_to_utf8(1);
ref_push_string(this->current_file);
push_int(1);
break;
}
case '<':
{
ptrdiff_t tmp = pos;
while(DATA(pos)!='>')
{
if(DATA(pos)=='\n')
{
cpp_error(this, "Expecting '>' in include.");
break;
}
pos++;
}
push_string(make_shared_binary_pcharp(ADD_PCHARP(data,tmp), pos-tmp));
/* In Pike 7.7 and later filenames belonging to Pike
* are assumed to be encoded according to UTF-8.
*/
f_string_to_utf8(1);
ref_push_string(this->current_file);
pos++;
push_int(0);
break;
}
default:
if (include_mode & 2) {
/* Macro expanding didn't help... */
cpp_error(this, "Expected file to include.");
break;
} else {
/* Try macro expanding (Bug 2440). */
struct string_builder save = this->buf, tmp;
INT_TYPE save_line = this->current_line;
init_string_builder(&this->buf, 0);
/* Prefix the buffer with the corresponding *_recur
* directive, to avoid infinite loops.
*/
if (include_mode & 1) {
string_builder_strcat(&this->buf, "#string_recur ");
} else {
string_builder_strcat(&this->buf, "#include_recur ");
}
pos--;
pos += low_cpp(this, ADD_PCHARP(data,pos), len - pos,
CPP_END_AT_NEWLINE,
charset);
string_builder_putchar(&this->buf, '\n');
tmp = this->buf;
this->buf = save;
/* We now have a #include-recur or #string-recur directive
* in tmp. Preprocess it.
*/
/* We're processing the line twice. */
this->current_line = save_line;
low_cpp(this, MKPCHARP_STR(tmp.s), tmp.s->len,
flags, charset);
free_string_builder(&tmp);
this->current_line = save_line;
string_builder_sprintf(&this->buf, "\n#line %ld ",
(long)save_line);
PUSH_STRING_SHIFT(this->current_file->str,
this->current_file->len,
this->current_file->size_shift,
&this->buf);
string_builder_putchar(&this->buf, '\n');
}
break;
}
if(Pike_sp==save_sp) {
break;
}
if(OUTP())
{
struct pike_string *new_file;
if (!safe_apply_handler ("handle_include",
this->handler, this->compat_handler,
3, BIT_STRING) ||
!(new_file=Pike_sp[-1].u.string) ) {
cpp_handle_exception (this, "Couldn't find include file.");
pop_n_elems(Pike_sp-save_sp);
break;
}
ref_push_string(new_file);
if (!safe_apply_handler ("read_include",
this->handler, this->compat_handler,
1, BIT_STRING|BIT_INT)) {
cpp_handle_exception (this, "Couldn't read include file.");
pop_n_elems(Pike_sp-save_sp);
break;
} else if (TYPEOF(Pike_sp[-1]) == PIKE_T_INT) {
cpp_error_sprintf(this, "Couldn't read include file \"%S\".",
new_file);
pop_n_elems(Pike_sp-save_sp);
break;
}
{
struct pike_string *save_current_file;
INT_TYPE save_current_line;
save_current_file=this->current_file;
save_current_line=this->current_line;
copy_shared_string(this->current_file,new_file);
this->current_line=1;
string_builder_binary_strcat(&this->buf, "#line 1 ", 8);
PUSH_STRING_SHIFT(new_file->str, new_file->len,
new_file->size_shift, &this->buf);
string_builder_putchar(&this->buf, '\n');
if(include_mode & 1)
{
/* #string */
struct pike_string *str = Pike_sp[-1].u.string;
PUSH_STRING_SHIFT(str->str, str->len, str->size_shift,
&this->buf);
}else{
/* #include */
if (this->auto_convert) {
struct pike_string *new_str =
recode_string(this, Pike_sp[-1].u.string);
free_string(Pike_sp[-1].u.string);
Pike_sp[-1].u.string = new_str;
} else if (charset) {
ref_push_string(charset);
if (!safe_apply_handler ("decode_charset",
this->handler, this->compat_handler,
2, BIT_STRING)) {
cpp_handle_exception (this,
"Charset decoding failed for included file.");
pop_n_elems(Pike_sp - save_sp);
break;
}
}
if (Pike_sp[-1].u.string->size_shift) {
/* Get rid of any byte order marks (0xfeff) */
struct pike_string *new_str = filter_bom(Pike_sp[-1].u.string);
free_string(Pike_sp[-1].u.string);
Pike_sp[-1].u.string = new_str;
}
low_cpp(this,
MKPCHARP_STR(Pike_sp[-1].u.string),
Pike_sp[-1].u.string->len,
flags&~(CPP_EXPECT_ENDIF | CPP_EXPECT_ELSE),
charset);
}
free_string(this->current_file);
this->current_file=save_current_file;
this->current_line=save_current_line;
|
75942b | 2018-01-12 | Martin Nilsson | | string_builder_sprintf(&this->buf, "\n#line %ld ", (long)this->current_line);
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | | PUSH_STRING_SHIFT(this->current_file->str,
this->current_file->len,
this->current_file->size_shift,
&this->buf);
string_builder_putchar(&this->buf, '\n');
if ((include_mode & 2) && (pos < len)) {
/* NOTE: The rest of the current buffer has already been
* expanded once.
*/
string_builder_append(&this->buf, ADD_PCHARP(data, pos), len - pos);
pos = len;
}
}
}
pop_n_elems(Pike_sp-save_sp);
break;
}
}
if(GOBBLE_WORD(if_))
{
struct string_builder save, tmp;
INT32 nflags = 0;
if(!OUTP())
nflags = CPP_REALLY_NO_OUTPUT;
save=this->buf;
init_string_builder(&this->buf, 0);
pos += low_cpp(this, ADD_PCHARP(data,pos), len-pos,
nflags | CPP_END_AT_NEWLINE | CPP_DO_IF,
charset);
tmp=this->buf;
this->buf=save;
string_builder_putchar(&tmp, 0);
tmp.s->len--;
if (!nflags) {
calc(this,MKPCHARP_STR(tmp.s),tmp.s->len,0,0);
if(SAFE_IS_ZERO(Pike_sp-1)) nflags|=CPP_NO_OUTPUT;
pop_stack();
}
free_string_builder(&tmp);
pos += low_cpp(this, ADD_PCHARP(data,pos), len-pos,
nflags | CPP_EXPECT_ELSE | CPP_EXPECT_ENDIF,
charset);
break;
}
if(GOBBLE_WORD(ifdef_))
{
INT32 nflags;
struct pike_string *s;
SKIPSPACE();
s = GOBBLE_IDENTIFIER();
if(!s)
cpp_error(this, "#ifdef what?");
nflags = CPP_EXPECT_ELSE | CPP_EXPECT_ENDIF | CPP_NO_OUTPUT;
if(!OUTP())
nflags|=CPP_REALLY_NO_OUTPUT;
if (s) {
if(FIND_DEFINE(s))
nflags&=~CPP_NO_OUTPUT;
free_string (s);
}
pos += low_cpp(this, ADD_PCHARP(data,pos), len-pos, nflags,
charset);
break;
}
if(GOBBLE_WORD(ifndef_))
{
INT32 nflags;
struct pike_string *s;
SKIPSPACE();
s = GOBBLE_IDENTIFIER();
if(!s)
cpp_error(this, "#ifndef what?");
nflags=CPP_EXPECT_ELSE | CPP_EXPECT_ENDIF;
if(!OUTP())
nflags|=CPP_REALLY_NO_OUTPUT;
if (s) {
if(FIND_DEFINE(s))
nflags|=CPP_NO_OUTPUT;
free_string (s);
}
pos += low_cpp(this, ADD_PCHARP(data,pos), len-pos, nflags,
charset);
break;
}
goto unknown_preprocessor_directive;
}
case 'e': /* endif, else, elif, error */
{
if(GOBBLE_WORD(endif_))
{
if(!(flags & CPP_EXPECT_ENDIF))
cpp_error(this, "Unmatched #endif.");
return pos;
}
if(GOBBLE_WORD(else_))
{
if(!(flags & CPP_EXPECT_ELSE))
cpp_error(this, "Unmatched #else.");
flags&=~CPP_EXPECT_ELSE;
flags|=CPP_EXPECT_ENDIF;
|
1fc5a9 | 2018-01-17 | Henrik Grubbström (Grubba) | | flags ^= CPP_NO_OUTPUT;
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | | break;
}
if(GOBBLE_WORD(elif_) || GOBBLE_WORD(elseif_))
{
if(!(flags & CPP_EXPECT_ELSE))
cpp_error(this, "Unmatched #elif.");
flags|=CPP_EXPECT_ENDIF;
if((flags & (CPP_NO_OUTPUT | CPP_REALLY_NO_OUTPUT)) == CPP_NO_OUTPUT)
{
struct string_builder save,tmp;
save=this->buf;
init_string_builder(&this->buf, 0);
pos += low_cpp(this, ADD_PCHARP(data,pos), len-pos,
CPP_END_AT_NEWLINE | CPP_DO_IF,
charset);
tmp=this->buf;
this->buf=save;
string_builder_putchar(&tmp, 0);
tmp.s->len--;
calc(this,MKPCHARP_STR(tmp.s),tmp.s->len,0,0);
free_string_builder(&tmp);
if(!SAFE_IS_ZERO(Pike_sp-1)) flags&=~CPP_NO_OUTPUT;
pop_stack();
} else {
FIND_EOL();
flags |= CPP_NO_OUTPUT | CPP_REALLY_NO_OUTPUT;
}
break;
}
}
goto unknown_preprocessor_directive;
case 'd': /* define */
{
if(GOBBLE_WORD(define_))
{
struct string_builder str;
INT32 argno=-1;
ptrdiff_t tmp3;
struct pike_string *def_name;
struct define_struct *def;
struct svalue *partbase,*argbase=Pike_sp;
int varargs=0;
SKIPSPACE();
def_name = GOBBLE_IDENTIFIER();
if(!def_name) {
cpp_error(this, "Define what?");
FIND_EOL();
break;
}
if(GOBBLE('('))
{
argno=0;
SKIPWHITE();
while(DATA(pos)!=')')
{
struct pike_string *arg_name;
if(argno)
{
if(!GOBBLE(','))
cpp_error(this,
"Expecting comma in macro definition.");
SKIPWHITE();
}
if(varargs)
cpp_error(this,"Expected ) after ...");
arg_name = GOBBLE_IDENTIFIER();
if(!arg_name)
{
cpp_error(this, "Expected argument for macro.");
break;
}
check_stack(1);
push_string(arg_name);
SKIPWHITE();
argno++;
if(argno>=MAX_ARGS)
{
cpp_error(this, "Too many arguments in macro definition.");
pop_stack();
argno--;
}
if(DATA(pos)=='.' && DATA(pos+1)=='.' && DATA(pos+2)=='.')
{
|
347b10 | 2018-04-19 | Henrik Grubbström (Grubba) | | varargs = CPP_MACRO_VARARGS;
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | | pos+=3;
SKIPWHITE();
}
}
if(!GOBBLE(')'))
cpp_error(this, "Missing ) in macro definition.");
}
SKIPSPACE();
partbase=Pike_sp;
init_string_builder(&str, 0);
while(1)
{
INT32 extra=0;
ptrdiff_t old_pos = pos;
switch(DATA(pos++))
{
case '/':
if(DATA(pos)=='/')
{
if (this->keep_comments) {
FIND_EOL_PRETEND();
string_builder_append( &str, ADD_PCHARP(data, old_pos), pos-old_pos );
continue;
}
string_builder_putchar(&str, ' ');
FIND_EOL();
continue;
}
if(DATA(pos)=='*')
{
if (this->keep_comments) {
SKIPCOMMENT_INC_LINES();
string_builder_append( &str, ADD_PCHARP(data, old_pos), pos-old_pos );
continue;
}
PUTC(' ');
SKIPCOMMENT();
continue;
}
string_builder_putchar(&str, '/');
continue;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
string_builder_putchar(&str, DATA(pos-1));
while(DATA(pos)>='0' && DATA(pos)<='9')
string_builder_putchar(&str, DATA(pos++));
continue;
case '\\':
if(GOBBLE('\n'))
{
this->current_line++;
PUTNL();
continue;
}
if (DATA(pos) == '\r' && DATA(pos+1) == '\n') {
pos += 2;
this->current_line++;
PUTNL();
continue;
}
/* Identifiers might start with \uxxxx, so try to parse
* an identifier now. */
goto gobble_identifier_in_define;
case ',':
{
int oldpos;
oldpos = pos;
SKIPSPACE_PRETEND();
if (DATA(pos) == '#' && DATA(pos+1) == '#') {
extra|= DEF_ARG_NEED_COMMA;
pos += 2;
goto concat_identifier;
} else {
pos = oldpos;
goto gobble_identifier_in_define;
}
}
case '#':
if(GOBBLE('#'))
{
extra= (extra & DEF_ARG_NEED_COMMA) | DEF_ARG_NOPRESPACE;
while(str.s->len && wide_isspace(index_shared_string(str.s,str.s->len-1)))
str.s->len--;
concat_identifier:
if(!str.s->len && Pike_sp-partbase>1)
{
#ifdef PIKE_DEBUG
if(TYPEOF(Pike_sp[-1]) != PIKE_T_INT)
Pike_fatal("Internal error in CPP\n");
#endif
Pike_sp[-1].u.integer|=DEF_ARG_NOPOSTSPACE;
}
}else{
extra=DEF_ARG_STRINGIFY;
}
SKIPSPACE();
pos++;
/* fall through */
gobble_identifier_in_define:
default: {
struct pike_string *s;
pos--;
s = GOBBLE_IDENTIFIER();
if (s)
{
tmp3=pos-1;
if(argno>0)
{
if (s->refs > 1)
{
for(e=0;e<argno;e++)
{
if(argbase[e].u.string == s)
{
check_stack(2);
push_string(finish_string_builder(&str));
init_string_builder(&str, 0);
push_int(e | extra);
extra=0;
break;
}
}
if(e!=argno) {
free_string (s);
continue;
}
}
}
string_builder_shared_strcat (&str, s);
free_string (s);
}else{
string_builder_putchar(&str, DATA(pos++));
}
extra=0;
continue;
}
case '"':
FIXSTRING(str, 1);
continue;
case '\'':
tmp3=pos-1;
FIND_END_OF_CHAR();
string_builder_append(&str, ADD_PCHARP(data, tmp3), pos - tmp3);
continue;
case '\n':
PUTNL();
this->current_line++;
/* Fallthrough */
case 0:
break;
}
push_string(finish_string_builder(&str));
break;
}
if(OUTP())
{
f_aggregate(Pike_sp - partbase);
def = alloc_empty_define(def_name);
def->args=argno;
|
347b10 | 2018-04-19 | Henrik Grubbström (Grubba) | | def->flags |= varargs;
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | |
add_ref(def->parts = Pike_sp[-2].u.array);
{
struct define_struct *d;
if ((d = FIND_DEFINE(def->name)) &&
(d->flags & (CPP_MACRO_IN_USE | CPP_MACRO_DISABLED))) {
cpp_error(this,
"Illegal to redefine a macro during its expansion.");
} else {
mapping_string_insert(this->defines, def->name, Pike_sp-1);
}
}
}
free_string (def_name);
pop_n_elems(Pike_sp-argbase);
break;
}
goto unknown_preprocessor_directive;
}
case 'u': /* undefine */
{
/* NOTE: Reuses undefine_ for undef_ */
if(GOBBLE_WORD(undefine_) || GOBBLE_WORD(undef_))
{
struct pike_string *s;
SKIPSPACE();
s = GOBBLE_IDENTIFIER();
if(!s) {
cpp_error(this, "Undefine what?");
break;
}
if(OUTP())
{
undefine(this,s);
}
free_string (s);
break;
}
goto unknown_preprocessor_directive;
}
case 'c': /* charset */
{
if (GOBBLE_WORD(charset_)) {
ptrdiff_t p;
struct pike_string *s;
if (flags & (CPP_EXPECT_ENDIF | CPP_EXPECT_ELSE)) {
/* Only allowed at the top-level */
cpp_error(this, "#charset directive inside #if/#endif.");
/* Skip to end of line */
while (DATA(pos) && DATA(pos) != '\n') {
pos++;
}
break;
}
SKIPSPACE();
p = pos;
while(DATA(pos) && !wide_isspace(DATA(pos))) {
pos++;
}
if (pos != p) {
/* The rest of the string. */
push_string( make_shared_binary_pcharp( ADD_PCHARP(data,pos), len-pos ) );
/* The charset name */
push_string( make_shared_binary_pcharp( ADD_PCHARP(data,p),pos-p));
if (!safe_apply_handler ("decode_charset", this->handler, this->compat_handler,
2, BIT_STRING)) {
cpp_handle_exception (this, NULL);
} else {
low_cpp(this, MKPCHARP_STR(Pike_sp[-1].u.string),Pike_sp[-1].u.string->len,
flags, charset);
pop_stack();
}
/* FIXME: Is this the correct thing to return? */
return len;
} else {
cpp_error(this, "What charset?");
}
break;
}
goto unknown_preprocessor_directive;
}
default:
|
86bc4e | 2018-01-12 | Henrik Grubbström (Grubba) | | unknown_preprocessor_directive:
{
struct pike_string *directive = GOBBLE_IDENTIFIER();
|
87fa59 | 2018-01-14 | Henrik Grubbström (Grubba) | | if (directive) {
struct svalue *fun = NULL;
struct svalue sv;
struct pike_string *directive_string =
add_shared_strings(MK_STRING("directive_"), directive);
int id = find_shared_string_identifier(directive_string,
Pike_fp->current_object->prog);
free_string(directive_string);
if (id >= 0) {
/* NB: This svalue holds no reference! */
SET_SVAL(sv, PIKE_T_FUNCTION, id, object, Pike_fp->current_object);
fun = &sv;
}
if(!fun && this->directives) {
/* Try a mapping lookup instead. */
fun = low_mapping_string_lookup(this->directives, directive);
}
|
86bc4e | 2018-01-12 | Henrik Grubbström (Grubba) | | if (fun) {
ptrdiff_t foo;
|
8f942d | 2018-02-26 | Martin Nilsson | | free_string(directive);
|
86bc4e | 2018-01-12 | Henrik Grubbström (Grubba) | |
|
e0c30f | 2018-02-26 | Martin Nilsson | | SKIPSPACE();
|
86bc4e | 2018-01-12 | Henrik Grubbström (Grubba) | | foo = pos;
FIND_EOL();
push_int(flags);
push_string(make_shared_binary_pcharp(ADD_PCHARP(data,foo), pos-foo));
safe_apply_svalue(fun, 2, 1);
if ((TYPEOF(Pike_sp[-1]) == PIKE_T_STRING) &&
Pike_sp[-1].u.string->len) {
/* We need to recurse. */
low_cpp(this, MKPCHARP_STR(Pike_sp[-1].u.string),
|
9e1a9b | 2018-03-02 | Henrik Grubbström (Grubba) | | Pike_sp[-1].u.string->len,
flags & ~CPP_EXPECT_ENDIF, charset);
|
86bc4e | 2018-01-12 | Henrik Grubbström (Grubba) | | }
pop_stack();
break;
}
|
ee311a | 2018-02-26 | Martin Nilsson | | }
if(!OUTP() && !this->picky_cpp)
|
8f942d | 2018-02-26 | Martin Nilsson | | {
if(directive) free_string(directive);
|
ee311a | 2018-02-26 | Martin Nilsson | | break;
|
8f942d | 2018-02-26 | Martin Nilsson | | }
|
ee311a | 2018-02-26 | Martin Nilsson | |
if (directive) {
cpp_error_sprintf(this, "Unknown preprocessor directive %S.",
directive);
free_string(directive);
} else {
cpp_error_sprintf(this, "Invalid preprocessor directive character at %d: '%c'.",
pos, DATA(pos));
}
}
|
e7bcc5 | 2018-01-11 | Henrik Grubbström (Grubba) | | }
}
continue;
ADD_TO_BUFFER:
// keep line
string_builder_append(&this->buf, ADD_PCHARP(data,old_pos), pos-old_pos);
}
if(flags & CPP_EXPECT_ENDIF) {
INT_TYPE saved_line = this->current_line;
this->current_line = first_line;
cpp_error(this, "End of file while searching for #endif.");
this->current_line = saved_line;
}
return pos;
}
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | |
|
671034 | 2018-02-21 | Henrik Grubbström (Grubba) | | PIKEFUN void low_cpp(string data, int flags)
|
6ae186 | 2018-01-13 | Henrik Grubbström (Grubba) | | {
low_cpp(THIS, MKPCHARP_STR(data), data->len, flags, THIS->charset);
}
|
671034 | 2018-02-21 | Henrik Grubbström (Grubba) | | PIKEFUN string cpp(string data, int flags)
{
struct CPP_struct *this = THIS;
struct string_builder save_buf = this->buf;
struct pike_string *save_file = this->current_file;
INT_TYPE save_line = this->current_line;
if (save_file) add_ref(save_file);
init_string_builder(&this->buf, 0);
low_cpp(this, MKPCHARP_STR(data), data->len, flags, THIS->charset);
push_string(finish_string_builder(&this->buf));
this->buf = save_buf;
if (this->current_file) free_string(this->current_file);
this->current_file = save_file;
this->current_line = save_line;
}
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | /*** Magic defines ***/
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | |
/*! @decl constant __LINE__
*!
*! This define contains the current line number, represented as an
*! integer, in the source file.
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_current_line(struct CPP_struct *this,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *UNUSED(arg),
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | struct string_builder *tmp)
{
|
c060b5 | 2004-11-14 | Henrik Grubbström (Grubba) | | string_builder_sprintf(tmp, " %ld ", (long)this->current_line);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | }
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @decl constant __FILE__
*!
*! This define contains the file path and name of the source file.
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_current_file_as_string(struct CPP_struct *this,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *UNUSED(arg),
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | struct string_builder *tmp)
{
PUSH_STRING_SHIFT(this->current_file->str, this->current_file->len,
this->current_file->size_shift, tmp);
}
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @decl constant __DIR__
*!
*! This define contains the directory path of the source file.
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_current_dir_as_string(struct CPP_struct *this,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *UNUSED(arg),
|
15107c | 2008-06-12 | Martin Nilsson | | struct string_builder *tmp)
{
|
d85cc3 | 2008-06-13 | Henrik Grubbström (Grubba) | | ref_push_string(this->current_file);
|
03b990 | 2009-03-08 | Henrik Grubbström (Grubba) | | /* FIXME: This isn't safe if the master hasn't been compiled yet. */
|
89b83e | 2008-06-29 | Marcus Comstedt | | SAFE_APPLY_MASTER("dirname",1);
|
15107c | 2008-06-12 | Martin Nilsson | | PUSH_STRING_SHIFT(Pike_sp[-1].u.string->str, Pike_sp[-1].u.string->len,
Pike_sp[-1].u.string->size_shift, tmp);
pop_stack();
}
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @decl constant __TIME__
*!
*! This define contains the current time at the time of compilation,
*! e.g. "12:20:51".
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_current_time_as_string(struct CPP_struct *UNUSED(this),
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *UNUSED(arg),
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | struct string_builder *tmp)
{
/* FIXME: Is this code safe? */
time_t tmp2;
char *buf;
time(&tmp2);
buf=ctime(&tmp2);
|
01a957 | 2000-02-03 | Henrik Grubbström (Grubba) | | PUSH_STRING0((p_wchar0 *)buf+11, 8, tmp);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | }
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @decl constant __DATE__
*!
*! This define contains the current date at the time of compilation,
*! e.g. "Jul 28 2001".
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_current_date_as_string(struct CPP_struct *UNUSED(this),
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *UNUSED(arg),
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | struct string_builder *tmp)
{
/* FIXME: Is this code safe? */
time_t tmp2;
char *buf;
time(&tmp2);
buf=ctime(&tmp2);
|
01a957 | 2000-02-03 | Henrik Grubbström (Grubba) | | PUSH_STRING0((p_wchar0 *)buf+4, 6, tmp);
|
e5fac4 | 2000-03-09 | Johan Sundström | | PUSH_STRING0((p_wchar0 *)buf+19, 5, tmp);
|
7bfa4f | 1999-03-09 | Henrik Grubbström (Grubba) | | }
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @decl constant __VERSION__
*!
*! This define contains the current Pike version as a float. If
*! another Pike version is emulated, this define is updated
*! accordingly.
*!
*! @seealso
*! @[__REAL_VERSION__]
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_current_version(struct CPP_struct *this,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *UNUSED(arg),
|
a580e1 | 2000-09-27 | Fredrik Hübinette (Hubbe) | | struct string_builder *tmp)
{
|
c060b5 | 2004-11-14 | Henrik Grubbström (Grubba) | | string_builder_sprintf(tmp, " %d.%d ", this->compat_major,
|
ce5d48 | 2004-11-14 | Martin Nilsson | | this->compat_minor);
|
a580e1 | 2000-09-27 | Fredrik Hübinette (Hubbe) | | }
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @decl constant __MINOR__
*! This define contains the minor part of the current Pike version,
*! represented as an integer. If another Pike version is emulated,
*! this define is updated accordingly.
*!
*! @seealso
*! @[__REAL_MINOR__]
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_current_minor(struct CPP_struct *this,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *UNUSED(arg),
|
a580e1 | 2000-09-27 | Fredrik Hübinette (Hubbe) | | struct string_builder *tmp)
{
|
c060b5 | 2004-11-14 | Henrik Grubbström (Grubba) | | string_builder_sprintf(tmp, " %d ", this->compat_minor);
|
a580e1 | 2000-09-27 | Fredrik Hübinette (Hubbe) | | }
|
ce261a | 2014-08-26 | Per Hedbor | | /*! @decl int(1..) __COUNTER__
*! This define contains a unique counter (unless it has been expanded
|
6a5998 | 2016-04-27 | Chris Angelico | | *! Int.NATIVE_MAX times) represented as an integer.
|
ce261a | 2014-08-26 | Per Hedbor | | *!
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_current_counter(struct CPP_struct *UNUSED(this),
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *UNUSED(arg),
|
ce261a | 2014-08-26 | Per Hedbor | | struct string_builder *tmp)
{
static int counter = 0;
string_builder_sprintf(tmp, " %d ", ++counter);
}
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @decl constant __MAJOR__
*!
*! This define contains the major part of the current Pike version,
*! represented as an integer. If another Pike version is emulated,
*! this define is updated accordingly.
*!
*! @seealso
*! @[__REAL_MAJOR__]
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_current_major(struct CPP_struct *this,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *UNUSED(arg),
|
a580e1 | 2000-09-27 | Fredrik Hübinette (Hubbe) | | struct string_builder *tmp)
{
|
c060b5 | 2004-11-14 | Henrik Grubbström (Grubba) | | string_builder_sprintf(tmp, " %d ", this->compat_major);
|
a580e1 | 2000-09-27 | Fredrik Hübinette (Hubbe) | | }
|
51d3f3 | 2011-12-28 | Henrik Grubbström (Grubba) | | /* _Pragma(STRING) */
|
4fa654 | 2012-03-24 | Henrik Grubbström (Grubba) | | /*! @decl void _Pragma(string directive)
*!
*! This macro inserts the corresponding @[#pragma] @[directive]
*! in the source.
*!
*! e.g. @expr{_Pragma("strict_types")@} is the same
*! as @expr{#pragma strict_types@} .
*!
*! @seealso
*! @[#pragma]
*/
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_pragma(struct CPP_struct *this,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *UNUSED(def),
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *arg,
|
51d3f3 | 2011-12-28 | Henrik Grubbström (Grubba) | | struct string_builder *tmp)
{
int i;
int in_string = 0;
/* Make some reasonable amount of space. */
|
3d6a1d | 2016-08-21 | Martin Nilsson | | string_build_mkspace(tmp, arg->len + 20, arg->size_shift);
|
51d3f3 | 2011-12-28 | Henrik Grubbström (Grubba) | |
string_builder_strcat(tmp, "\n#pragma ");
/* Destringize the argument. */
|
3d6a1d | 2016-08-21 | Martin Nilsson | | for (i = 0; i < arg->len; i++) {
p_wchar2 ch = index_shared_string(arg, i);
|
51d3f3 | 2011-12-28 | Henrik Grubbström (Grubba) | | switch(ch) {
case '\n': case '\r':
ch = ' ';
|
5f5084 | 2018-02-12 | Marcus Comstedt | | /* FALLTHRU */
|
51d3f3 | 2011-12-28 | Henrik Grubbström (Grubba) | | case ' ': case '\t':
if (in_string) {
string_builder_putchar(tmp, ch);
}
break;
case '\"':
in_string = !in_string;
break;
case '\\':
if (in_string) {
|
3d6a1d | 2016-08-21 | Martin Nilsson | | ch = (++i < arg->len) ? index_shared_string(arg, i) : '\0';
|
51d3f3 | 2011-12-28 | Henrik Grubbström (Grubba) | | if ((ch != '\\') && (ch != '\"')) {
cpp_error(this, "Invalid \\-escape in _Pragma().");
break;
}
}
|
5f5084 | 2018-02-12 | Marcus Comstedt | | /* FALLTHRU */
|
51d3f3 | 2011-12-28 | Henrik Grubbström (Grubba) | | default:
if (in_string) {
string_builder_putchar(tmp, ch);
} else {
cpp_error(this, "Invalid character outside of string.");
}
break;
}
}
if (in_string) {
cpp_error(this, "Unterminated string constant.");
}
|
e82c17 | 2012-07-22 | Arne Goedeke | | string_builder_sprintf(tmp, "\n#line %ld ", (long)this->current_line);
|
51d3f3 | 2011-12-28 | Henrik Grubbström (Grubba) | | PUSH_STRING_SHIFT(this->current_file->str,
this->current_file->len,
this->current_file->size_shift,
tmp);
string_builder_putchar(tmp, '\n');
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_callback_define(struct CPP_struct *this,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *def,
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *arg,
|
080e3a | 2011-11-04 | Per Hedbor | | struct string_builder *tmp)
{
|
279a4f | 2016-09-03 | Henrik Grubbström (Grubba) | | ref_push_string( def->name );
|
443182 | 2016-08-24 | Henrik Grubbström (Grubba) | | ref_push_string( arg );
|
819004 | 2011-12-28 | Henrik Grubbström (Grubba) | | if (safe_apply_handler( "evaluate_define",
this->handler, this->compat_handler, 2, 0 ) &&
|
19961b | 2017-04-08 | Martin Nilsson | | TYPEOF(Pike_sp[-1]) == T_STRING ) {
string_builder_shared_strcat(tmp, Pike_sp[-1].u.string);
|
7e5b17 | 2014-04-10 | Per Hedbor | | if( !this->prefix ){
int min;
|
19961b | 2017-04-08 | Martin Nilsson | | check_string_range( Pike_sp[-1].u.string, 0, &min, 0 );
|
7e5b17 | 2014-04-10 | Per Hedbor | | if( min < 32 )
{
string_builder_sprintf(tmp, "\n#line %ld ", (long)this->current_line);
|
3d6a1d | 2016-08-21 | Martin Nilsson | | insert_current_file_as_string( this,def,arg,tmp);
|
7e5b17 | 2014-04-10 | Per Hedbor | | string_builder_putchar(tmp, '\n');
}
}
|
75a9f6 | 2011-12-04 | Arne Goedeke | | pop_stack();
}
|
080e3a | 2011-11-04 | Per Hedbor | | }
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | static void insert_callback_define_no_args(struct CPP_struct *this,
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *def,
|
3d6a1d | 2016-08-21 | Martin Nilsson | | struct pike_string *UNUSED(arg),
|
080e3a | 2011-11-04 | Per Hedbor | | struct string_builder *tmp)
{
|
75a9f6 | 2011-12-04 | Arne Goedeke | | struct svalue *save_sp = Pike_sp;
|
279a4f | 2016-09-03 | Henrik Grubbström (Grubba) | | ref_push_string( def->name );
|
819004 | 2011-12-28 | Henrik Grubbström (Grubba) | | if (safe_apply_handler( "evaluate_define",
this->handler, this->compat_handler, 1, 0 ) &&
|
19961b | 2017-04-08 | Martin Nilsson | | TYPEOF(Pike_sp[-1]) == T_STRING )
string_builder_shared_strcat(tmp, Pike_sp[-1].u.string);
|
75a9f6 | 2011-12-04 | Arne Goedeke | | if (Pike_sp > save_sp) pop_n_elems(Pike_sp-save_sp);
|
080e3a | 2011-11-04 | Per Hedbor | | }
|
a580e1 | 2000-09-27 | Fredrik Hübinette (Hubbe) | |
|
676e41 | 2001-07-28 | Martin Nilsson | |
/*! @decl constant __REAL_VERSION__
*!
*! This define always contains the version of the current Pike,
*! represented as a float.
*!
*! @seealso
*! @[__VERSION__]
*/
/*! @decl constant __REAL_MAJOR__
*!
*! This define always contains the major part of the version of the
*! current Pike, represented as an integer.
*!
*! @seealso
*! @[__MAJOR__]
*/
/*! @decl constant __REAL_MINOR__
*!
*! This define always contains the minor part of the version of the
*! current Pike, represented as an integer.
*!
*! @seealso
*! @[__MINOR__]
*/
/*! @decl constant __BUILD__
*! This constant contains the build number of the current Pike version,
*! represented as an integer. If another Pike version is emulated,
*! this constant remains unaltered.
*!
*! @seealso
*! @[__REAL_MINOR__]
*/
/*! @decl constant __REAL_BUILD__
*!
*! This define always contains the minor part of the version of the
*! current Pike, represented as an integer.
*!
*! @seealso
*! @[__BUILD__]
*/
|
aba09a | 2011-12-28 | Henrik Grubbström (Grubba) | | /*! @decl constant static_assert
*!
*! This define expands to the symbol @[_Static_assert].
*!
*! It is the preferred way to perform static
*! (ie compile-time) assertions.
*!
*! @note
*! The macro can also be used to check for whether static assertions
*! are supported.
*!
*! @seealso
|
2d5df6 | 2013-05-04 | Henrik Grubbström (Grubba) | | *! @[predef::_Static_assert()]
|
aba09a | 2011-12-28 | Henrik Grubbström (Grubba) | | */
|
676e41 | 2001-07-28 | Martin Nilsson | | /*! @decl constant __PIKE__
*!
*! This define is always true.
*/
/*! @decl constant __AUTO_BIGNUM__
*!
*! This define is defined when automatic bignum conversion is enabled.
*! When enabled all integers will automatically be converted to
*! bignums when they get bigger than what can be represented by
*! an integer, hampering performance slightly instead of crashing
|
d6d2e5 | 2016-06-10 | Martin Nilsson | | *! the program. This define is always set since Pike 8.0.
|
676e41 | 2001-07-28 | Martin Nilsson | | */
/*! @decl constant __NT__
*!
*! This define is defined when the Pike is running on a Microsoft Windows OS,
*! not just Microsoft Windows NT, as the name implies.
*/
|
0c9594 | 2018-01-12 | Stephen R. van den Berg | | /*! @decl constant __amigaos__
*!
*! This define is defined when the Pike is running on Amiga OS.
*/
|
522042 | 2003-04-01 | Martin Nilsson | | /*! @endnamespace */
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | | PIKEFUN void create(mapping|string|void opts_or_file,
int|string|void charset_sv,
object|void handler,
int|void compat_major_sv,
int|void compat_minor_sv,
int|void picky_cpp_sv)
flags ID_PROTECTED;
{
struct CPP_struct *this = THIS;
struct pike_string *prefix = NULL;
struct pike_string *current_file = 0;
struct pike_string *charset = NULL;
int compat_major = compat_major_sv?compat_major_sv->u.integer:0;
int compat_minor = compat_minor_sv?compat_minor_sv->u.integer:0;
int picky_cpp = picky_cpp_sv?picky_cpp_sv->u.integer:0;
this->prefix = NULL;
this->current_line=1;
this->compile_errors=0;
this->defines = allocate_mapping(32);
this->keep_comments = 0;
this->dependencies_fail = 0;
this->auto_convert = 0;
if (opts_or_file) {
if (TYPEOF(*opts_or_file) == PIKE_T_MAPPING) {
struct svalue *tmp;
struct mapping *m = opts_or_file->u.mapping;
#define GET_TYPE(type, name) ((tmp = simple_mapping_string_lookup(m, name)) \
&& (TYPEOF(*(tmp)) == PIKE_T_##type || (Pike_error("Expected type %s,"\
"got type %s for " name ".", get_name_of_type(PIKE_T_##type), get_name_of_type(TYPEOF(*tmp))), 0)))
if (GET_TYPE(STRING, "current_file")) current_file = tmp->u.string;
if (GET_TYPE(STRING, "charset")) charset_sv = tmp;
if (GET_TYPE(OBJECT, "handler")) handler = tmp->u.object;
if (GET_TYPE(INT, "compat_major")) compat_major = tmp->u.integer;
if (GET_TYPE(INT, "compat_minor")) compat_minor = tmp->u.integer;
if (GET_TYPE(INT, "picky")) picky_cpp = tmp->u.integer;
if (GET_TYPE(STRING, "prefix")) prefix = tmp->u.string;
if (GET_TYPE(INT, "keep_comments")) this->keep_comments = tmp->u.integer;
#undef GET_TYPE
} else if (TYPEOF(*opts_or_file) == PIKE_T_STRING) {
current_file = opts_or_file->u.string;
}
}
if(current_file)
add_ref(current_file);
else
current_file = make_shared_string("-");
this->current_file = current_file;
this->compat_major=PIKE_MAJOR_VERSION;
this->compat_minor=PIKE_MINOR_VERSION;
this->compat_handler = 0;
this->handler = handler;
if(handler)
add_ref(handler);
if (prefix) {
int i;
if (prefix->size_shift) {
Pike_error("No widechars allowed in cpp prefix.\n");
}
for (i = 0; i < prefix->len; i++) {
if (!wide_isidchar(prefix->str[i])) {
Pike_error("Invalid char in prefix.\n");
}
}
this->prefix = prefix;
add_ref(prefix);
}
if(charset_sv) {
if(TYPEOF(*charset_sv) == T_STRING) {
this->charset = charset_sv->u.string;
add_ref(this->charset);
}
else if(TYPEOF(*charset_sv) == T_INT)
this->auto_convert = charset_sv->u.integer;
else {
SIMPLE_ARG_TYPE_ERROR("cpp", 3, "string|int");
}
}
if(compat_major)
cpp_change_compat(this, compat_major, compat_minor);
this->picky_cpp = picky_cpp;
|
3b25dd | 2018-01-12 | Martin Nilsson | | pop_n_elems(args);
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | | }
|
8c8da9 | 2018-01-09 | Henrik Grubbström (Grubba) | | PIKEFUN void define_ansi_macros()
{
struct CPP_struct *this = THIS;
/* These attempt to be compatible with the C standard. */
do_magic_define(this,"__LINE__",insert_current_line);
do_magic_define(this,"__FILE__",insert_current_file_as_string);
do_magic_define(this,"__DATE__",insert_current_date_as_string);
do_magic_define(this,"__TIME__",insert_current_time_as_string);
/* These are from the 201x C standard. */
do_magic_define(this,"_Pragma",insert_pragma)->args = 1;
simple_add_define(this, "static_assert", "_Static_assert");
}
PIKEFUN void define_pike_macros()
{
struct CPP_struct *this = THIS;
/* These are Pike extensions. */
do_magic_define(this,"__DIR__",insert_current_dir_as_string);
do_magic_define(this,"__VERSION__",insert_current_version);
do_magic_define(this,"__MAJOR__",insert_current_major);
do_magic_define(this,"__MINOR__",insert_current_minor);
simple_add_define(this, "__ARGS__", "__args__");
do_magic_define(this,"__COUNTER__",insert_current_counter);
#if 0
/* Left in place for documentation reference purposes. */
struct define_struct *def =
alloc_empty_define(make_shared_string("__deprecated__"), 1);
def->args = 1;
REF_MAKE_CONST_STRING(def->first, "__attribute__(\"deprecated\", ");
def->parts[0].argument = 0;
REF_MAKE_CONST_STRING(def->parts[0].postfix, ")");
mapping_string_insert(this->defines, def->name, Pike_sp-1);
pop_stack();
#endif /* 0 */
simple_add_define(this, "__PIKE__", " 1 ");
simple_add_define(this, "__REAL_VERSION__",
" " DEFINETOSTR(PIKE_MAJOR_VERSION) "."
DEFINETOSTR(PIKE_MINOR_VERSION) " ");
simple_add_define(this, "__REAL_MAJOR__",
" " DEFINETOSTR(PIKE_MAJOR_VERSION) " ");
simple_add_define(this, "__REAL_MINOR__",
" " DEFINETOSTR(PIKE_MINOR_VERSION) " ");
simple_add_define(this, "__BUILD__",
" " DEFINETOSTR(PIKE_BUILD_VERSION) " ");
simple_add_define(this, "__REAL_BUILD__",
" " DEFINETOSTR(PIKE_BUILD_VERSION) " ");
simple_add_define(this, "__AUTO_BIGNUM__", " 1 ");
#ifdef __NT__
simple_add_define(this, "__NT__", " 1 ");
#endif
|
0c9594 | 2018-01-12 | Stephen R. van den Berg | | #ifdef __amigaos__
simple_add_define(this, "__amigaos__", " 1 ");
#endif
|
8c8da9 | 2018-01-09 | Henrik Grubbström (Grubba) | | #ifdef __APPLE__
simple_add_define(this, "__APPLE__", " 1 ");
#endif
simple_add_define(this, "SIZEOF_INT",
" " DEFINETOSTR(SIZEOF_INT) " ");
simple_add_define(this, "SIZEOF_FLOAT",
" " DEFINETOSTR(SIZEOF_FLOAT) " ");
}
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | | }
|
0732a5 | 2018-03-30 | Henrik Grubbström (Grubba) | | /* ! @endclass CPP
*/
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | |
|
16a6f7 | 2011-11-27 | Tobias S. Josefowitz | | /*! @decl string cpp(string data, mapping|string|void current_file, @
|
7c0df7 | 2001-02-06 | Henrik Grubbström (Grubba) | | *! int|string|void charset, object|void handler, @
|
f6da7b | 2004-06-27 | Martin Nilsson | | *! void|int compat_major, void|int compat_minor, @
|
91a2f6 | 2004-11-05 | Martin Nilsson | | *! void|int picky_cpp)
|
7c0df7 | 2001-02-06 | Henrik Grubbström (Grubba) | | *!
*! Run a string through the preprocessor.
*!
*! Preprocesses the string @[data] with Pike's builtin ANSI-C look-alike
*! preprocessor. If the @[current_file] argument has not been specified,
|
cbe8c9 | 2003-04-07 | Martin Nilsson | | *! it will default to @expr{"-"@}. @[charset] defaults to @expr{"ISO-10646"@}.
|
7c0df7 | 2001-02-06 | Henrik Grubbström (Grubba) | | *!
|
16a6f7 | 2011-11-27 | Tobias S. Josefowitz | | *! If the second argument is a mapping, no other arguments may follow.
*! Instead, they have to be given as members of the mapping (if wanted).
*! The following members are recognized:
*!
*! @mapping
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | *! @member string "current_file"
|
edd972 | 2014-08-09 | Arne Goedeke | | *! Name of the current file. It is used for generating
*! #line directives and for locating include files.
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | *! @member int|string "charset"
|
edd972 | 2014-08-09 | Arne Goedeke | | *! Charset to use when processing @expr{data@}.
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | *! @member object "handler"
|
edd972 | 2014-08-09 | Arne Goedeke | | *! Compilation handler.
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | *! @member int "compat_major"
|
edd972 | 2014-08-09 | Arne Goedeke | | *! Sets the major pike version used for compat handling.
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | *! @member int "compat_minor"
|
edd972 | 2014-08-09 | Arne Goedeke | | *! Sets the minor pike version used for compat handling.
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | *! @member int "picky_cpp"
|
edd972 | 2014-08-09 | Arne Goedeke | | *! Generate more warnings.
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | *! @member int "keep_comments"
|
edd972 | 2014-08-09 | Arne Goedeke | | *! This option keeps @[cpp()] from removing comments.
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | *! Useful in combination with the prefix feature below.
*! @member string "prefix"
|
16a6f7 | 2011-11-27 | Tobias S. Josefowitz | | *! If a prefix is given, only prefixed directives will be
*! processed. For example, if the prefix is @expr{"foo"@}, then
*! @expr{#foo_ifdef COND@} and @expr{foo___LINE__@} would be
*! processed, @expr{#ifdef COND@} and @expr{__LINE__@} would not.
*! @endmapping
*!
|
7c0df7 | 2001-02-06 | Henrik Grubbström (Grubba) | | *! @seealso
*! @[compile()]
|
739f9d | 1999-11-04 | Henrik Grubbström (Grubba) | | */
|
e34dcf | 2004-05-22 | Martin Nilsson | |
|
3b8741 | 2016-07-27 | Henrik Grubbström (Grubba) | | PIKEFUN string cpp(string data,
mapping|string|void opts_or_file,
int|string|void charset_sv,
object|void handler,
int|void compat_major_sv,
int|void compat_minor_sv,
int|void picky_cpp_sv)
efun;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | | struct svalue *save_sp = Pike_sp - args;
struct object *cpp_obj = clone_object(CPP_program, args-1);
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | struct CPP_struct *this =
(struct CPP_struct *)get_storage(cpp_obj, CPP_program);
|
e34dcf | 2004-05-22 | Martin Nilsson | | struct mapping *predefs = NULL;
|
57cef7 | 1999-12-28 | Henrik Grubbström (Grubba) | | #ifdef PIKE_DEBUG
ONERROR tmp;
#endif /* PIKE_DEBUG */
|
770b6d | 1999-02-23 | Henrik Grubbström (Grubba) | |
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | push_object(cpp_obj);
|
b584b1 | 2001-12-20 | Martin Stjernholm | | if (use_initial_predefs)
/* Typically compiling the master here. */
predefs = initial_predefs_mapping();
else {
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | low_unsafe_apply_handler ("get_predefines", this->handler,
this->compat_handler, 0);
|
19961b | 2017-04-08 | Martin Nilsson | | if (!UNSAFE_IS_ZERO (Pike_sp - 1)) {
|
b584b1 | 2001-12-20 | Martin Stjernholm | | struct keypair *k;
int e, sprintf_args = 0;
|
19961b | 2017-04-08 | Martin Nilsson | | if (TYPEOF(Pike_sp[-1]) != T_MAPPING) {
|
5e9fc0 | 2015-08-18 | Per Hedbor | | push_static_text ("Invalid return value from get_predefines, got %O\n");
|
19961b | 2017-04-08 | Martin Nilsson | | push_svalue (Pike_sp - 3);
|
b584b1 | 2001-12-20 | Martin Stjernholm | | sprintf_args = 2;
}
else {
|
19961b | 2017-04-08 | Martin Nilsson | | predefs = copy_mapping (Pike_sp[-1].u.mapping);
|
b584b1 | 2001-12-20 | Martin Stjernholm | | NEW_MAPPING_LOOP (predefs->data) {
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | if (TYPEOF(k->ind) != T_STRING || !k->ind.u.string->len) {
|
5e9fc0 | 2015-08-18 | Per Hedbor | | push_static_text ("Expected nonempty string as predefine name, got %O\n");
|
b584b1 | 2001-12-20 | Martin Stjernholm | | push_svalue (&k->ind);
sprintf_args = 2;
free_mapping (predefs);
predefs = NULL;
goto predef_map_error;
|
75a9f6 | 2011-12-04 | Arne Goedeke | | } else if (!(TYPEOF(k->val) == T_INT && !k->val.u.integer)
&& TYPEOF(k->val) != T_STRING
&& TYPEOF(k->val) != T_FUNCTION
&& TYPEOF(k->val) != T_OBJECT) {
|
5e9fc0 | 2015-08-18 | Per Hedbor | | push_static_text ("expected zero, string or function value for"
|
75a9f6 | 2011-12-04 | Arne Goedeke | | " predefine %O\n");
push_svalue (&k->ind);
sprintf_args = 2;
free_mapping (predefs);
predefs = NULL;
goto predef_map_error;
|
b584b1 | 2001-12-20 | Martin Stjernholm | | }
}
}
if (!predefs) {
predef_map_error:
f_sprintf (sprintf_args);
|
19961b | 2017-04-08 | Martin Nilsson | | Pike_error("%S", Pike_sp[-1].u.string);
|
b584b1 | 2001-12-20 | Martin Stjernholm | | }
}
pop_stack();
}
|
8c8da9 | 2018-01-09 | Henrik Grubbström (Grubba) | | apply(cpp_obj, "define_ansi_macros", 0);
|
f0950a | 1999-03-27 | Henrik Grubbström (Grubba) | |
|
8c8da9 | 2018-01-09 | Henrik Grubbström (Grubba) | | apply(cpp_obj, "define_pike_macros", 0);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
b584b1 | 2001-12-20 | Martin Stjernholm | | if (predefs) {
struct keypair *k;
int e;
NEW_MAPPING_LOOP (predefs->data) {
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | if (TYPEOF(k->val) == T_STRING)
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | add_define (this, k->ind.u.string, k->val.u.string);
|
75a9f6 | 2011-12-04 | Arne Goedeke | | else if(TYPEOF(k->val) == T_FUNCTION || TYPEOF(k->val) == T_OBJECT)
|
080e3a | 2011-11-04 | Per Hedbor | | {
|
7962c0 | 2016-09-01 | Henrik Grubbström (Grubba) | | struct define_struct *def;
|
080e3a | 2011-11-04 | Per Hedbor | | if( index_shared_string( k->ind.u.string, k->ind.u.string->len-1) == ')' )
{
struct pike_string *s = string_slice( k->ind.u.string, 0, k->ind.u.string->len-2);
|
7a6120 | 2016-09-04 | Henrik Grubbström (Grubba) | | def = alloc_empty_define(s);
|
500d46 | 2016-09-06 | Henrik Grubbström (Grubba) | | free_string(s);
|
080e3a | 2011-11-04 | Per Hedbor | | def->magic = insert_callback_define;
|
347b10 | 2018-04-19 | Henrik Grubbström (Grubba) | | def->flags |= CPP_MACRO_VARARGS;
|
080e3a | 2011-11-04 | Per Hedbor | | def->args=1;
}
else
{
|
7a6120 | 2016-09-04 | Henrik Grubbström (Grubba) | | def = alloc_empty_define(k->ind.u.string);
|
080e3a | 2011-11-04 | Per Hedbor | | def->magic = insert_callback_define_no_args;
}
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | mapping_string_insert(this->defines, def->name, Pike_sp-1);
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | pop_stack();
|
080e3a | 2011-11-04 | Per Hedbor | | }
|
b584b1 | 2001-12-20 | Martin Stjernholm | | else
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | add_define (this, k->ind.u.string, empty_pike_string);
|
b584b1 | 2001-12-20 | Martin Stjernholm | | }
free_mapping (predefs);
}
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | | if (this->charset) {
|
bead0b | 2018-03-21 | Henrik Grubbström (Grubba) | | ref_push_string(data);
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | | ref_push_string(this->charset);
if (!safe_apply_handler ("decode_charset", this->handler,
this->compat_handler, 2, BIT_STRING)) {
cpp_handle_exception (this, "Error decoding with charset %S",
THIS->charset);
Pike_error("Unknown charset.\n");
}
|
bead0b | 2018-03-21 | Henrik Grubbström (Grubba) | | data = Pike_sp[-1].u.string;
/* NB: We let the stack hold the references to data.
* We don't need to keep track of the number of elements
* on the stack as we have the save_sp marker.
*/
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | | }
if (this->auto_convert && (!data->size_shift) && (data->len > 1)) {
/* Try to determine if we need to recode the string */
|
bead0b | 2018-03-21 | Henrik Grubbström (Grubba) | | data = recode_string(this, data);
push_string(data);
/* NB: We let the stack hold the references to data.
* We don't need to keep track of the number of elements
* on the stack as we have the save_sp marker.
*/
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | | }
if (data->size_shift) {
/* Get rid of any byte order marks (0xfeff) */
|
bead0b | 2018-03-21 | Henrik Grubbström (Grubba) | | data = filter_bom(data);
push_string(data);
/* NB: We let the stack hold the references to data.
* We don't need to keep track of the number of elements
* on the stack as we have the save_sp marker.
*/
|
7cb5e2 | 2018-01-07 | Henrik Grubbström (Grubba) | | }
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | string_builder_binary_strcat(&this->buf, "#line 1 ", 8);
PUSH_STRING_SHIFT(this->current_file->str, this->current_file->len,
this->current_file->size_shift, &this->buf);
string_builder_putchar(&this->buf, '\n');
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
57cef7 | 1999-12-28 | Henrik Grubbström (Grubba) | | #ifdef PIKE_DEBUG
SET_ONERROR(tmp, fatal_on_error, "Preprocessor exited with longjump!\n");
#endif /* PIKE_DEBUG */
|
6ae186 | 2018-01-13 | Henrik Grubbström (Grubba) | | ref_push_string(data); /* data */
push_int(0); /* flags */
|
671034 | 2018-02-21 | Henrik Grubbström (Grubba) | | apply(cpp_obj, "low_cpp", 2);
|
57cef7 | 1999-12-28 | Henrik Grubbström (Grubba) | |
#ifdef PIKE_DEBUG
UNSET_ONERROR(tmp);
#endif /* PIKE_DEBUG */
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | if(this->compile_errors)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
|
ab53cf | 2018-02-24 | Martin Nilsson | | throw_error_object(fast_clone_object(cpp_error_program), 0, 0,
|
010dc6 | 2001-08-16 | Martin Stjernholm | | "Cpp() failed\n");
|
956513 | 2014-02-14 | Martin Nilsson | | }
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | else if(this->dependencies_fail)
|
956513 | 2014-02-14 | Martin Nilsson | | {
push_int(0);
}
else
{
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | push_string(finish_string_builder(&this->buf));
/* NB: Make sure the buffer isn't freed twice. */
this->buf.s = NULL;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
6e2bb5 | 2018-01-05 | Henrik Grubbström (Grubba) | | stack_pop_n_elems_keep_top((Pike_sp - save_sp) - 1);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | /*! @module Builtin
*/
/*! @decl mapping(string:mixed) _take_over_initial_predefines()
|
4f395b | 2018-01-10 | Henrik Grubbström (Grubba) | | *!
*! Returns a mapping containing the set of predefined macros.
*! These are typically the macros defined via the @tt{-D@} option
*! when starting Pike.
*!
*! This function is typically called by the @[MasterObject] at
*! initialization, and may only be called once. After it has been called,
*! @[cpp()] will start calling @[CompilationHandler->get_predefines()] to
*! retrieve the set of predefined macros.
*!
*! @seealso
*! [cpp()], @[CompilationHandler->get_predefines()]
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | */
|
b584b1 | 2001-12-20 | Martin Stjernholm | | void f__take_over_initial_predefines (INT32 args)
{
pop_n_elems (args);
if (use_initial_predefs) {
struct pike_predef_s *tmp;
push_mapping (initial_predefs_mapping());
use_initial_predefs = 0;
while((tmp=first_predef))
{
free(tmp->name);
first_predef=tmp->next;
|
0ec752 | 2014-04-27 | Martin Nilsson | | free(tmp);
|
b584b1 | 2001-12-20 | Martin Stjernholm | | }
last_predef = 0;
}
else Pike_error ("Initial predefines already taken over.\n");
}
|
6c3a6f | 2013-11-20 | Henrik Grubbström (Grubba) | | /*! @endmodule
*/
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | void init_cpp()
{
|
b584b1 | 2001-12-20 | Martin Stjernholm | | struct svalue s;
|
516482 | 2004-11-14 | Martin Stjernholm | | efun_str = make_shared_string ("efun");
constant_str = make_shared_string ("constant");
defined_str = make_shared_string ("defined");
|
b584b1 | 2001-12-20 | Martin Stjernholm | | use_initial_predefs = 1;
|
3b8741 | 2016-07-27 | Henrik Grubbström (Grubba) | | INIT;
|
b584b1 | 2001-12-20 | Martin Stjernholm | |
|
500d46 | 2016-09-06 | Henrik Grubbström (Grubba) | | defined_macro = alloc_empty_define(defined_str);
|
be65c5 | 2016-09-02 | Henrik Grubbström (Grubba) | | defined_macro->magic=check_defined;
defined_macro->args=1;
defined_macro_sval = Pike_sp[-1];
Pike_sp--;
|
75a9f6 | 2011-12-04 | Arne Goedeke | | ADD_INT_CONSTANT("__HAVE_CPP_PREFIX_SUPPORT__", 1, 0);
|
b584b1 | 2001-12-20 | Martin Stjernholm | | /* Somewhat tricky to add a _constant_ function in _static_modules.Builtin. */
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(s, T_FUNCTION, FUNCTION_BUILTIN, efun,
make_callable (f__take_over_initial_predefines,
"_take_over_initial_predefines",
"function(void:mapping(string:string))",
OPT_SIDE_EFFECT, NULL, NULL));
|
b584b1 | 2001-12-20 | Martin Stjernholm | | simple_add_constant ("_take_over_initial_predefines", &s, 0);
free_svalue (&s);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
b678e3 | 2014-05-15 | Martin Nilsson | | void add_predefine(const char *s)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
struct pike_predef_s *tmp=ALLOC_STRUCT(pike_predef_s);
|
282a8a | 2018-01-04 | Henrik Grubbström (Grubba) | | size_t len = strlen(s);
char *pos=strchr(s,'=');
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | if(pos)
{
|
282a8a | 2018-01-04 | Henrik Grubbström (Grubba) | | tmp->name = xalloc(len+1);
memcpy(tmp->name, s, len+1);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | tmp->name[pos-s]=0;
|
282a8a | 2018-01-04 | Henrik Grubbström (Grubba) | | tmp->value = tmp->name + (pos-s) + 1;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }else{
|
282a8a | 2018-01-04 | Henrik Grubbström (Grubba) | | tmp->name = xalloc(len + 1 + 4);
memcpy(tmp->name,s,len + 1);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
282a8a | 2018-01-04 | Henrik Grubbström (Grubba) | | tmp->value = tmp->name + len + 1;
|
59fc9e | 2014-09-03 | Martin Nilsson | | memcpy(tmp->value," 1 ",4);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
b584b1 | 2001-12-20 | Martin Stjernholm | | tmp->next = NULL;
|
282a8a | 2018-01-04 | Henrik Grubbström (Grubba) | |
|
b584b1 | 2001-12-20 | Martin Stjernholm | | if (first_predef) {
last_predef->next = tmp;
last_predef = tmp;
}
else first_predef = last_predef = tmp;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
ae9503 | 1999-04-07 | Fredrik Hübinette (Hubbe) | | void exit_cpp(void)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
|
ae9503 | 1999-04-07 | Fredrik Hübinette (Hubbe) | | #ifdef DO_PIKE_CLEANUP
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | struct pike_predef_s *tmp;
|
3b8741 | 2016-07-27 | Henrik Grubbström (Grubba) | |
EXIT;
|
b584b1 | 2001-12-20 | Martin Stjernholm | | while((tmp=first_predef))
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
free(tmp->name);
|
b584b1 | 2001-12-20 | Martin Stjernholm | | first_predef=tmp->next;
|
0ec752 | 2014-04-27 | Martin Nilsson | | free(tmp);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | | free_svalue(&defined_macro_sval);
|
516482 | 2004-11-14 | Martin Stjernholm | |
free_string (efun_str);
free_string (constant_str);
free_string (defined_str);
|
e44282 | 2016-08-31 | Henrik Grubbström (Grubba) | |
|
ae9503 | 1999-04-07 | Fredrik Hübinette (Hubbe) | | #endif
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|