e576bb2002-10-11Martin 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. */
1b10db2002-10-08Martin Nilsson 
dfa0b61997-01-21Fredrik Hübinette (Hubbe) #include "global.h" #include "module_support.h" #include "interpret.h" #include "svalue.h" #include "stralloc.h"
e55d291997-03-23Niels Möller #include "pike_types.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
d7143b2000-12-13Fredrik Hübinette (Hubbe) #include "mapping.h" #include "object.h"
a466762003-11-14Martin Stjernholm #include "operators.h"
0ba1be2004-03-06Martin Nilsson #include "bignum.h"
dfa0b61997-01-21Fredrik Hübinette (Hubbe) 
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
3c04e81997-03-13Fredrik Hübinette (Hubbe) /* Checks that args_to_check arguments are OK. * Returns 1 if everything worked ok, zero otherwise. * If something went wrong, 'exepect_result' tells you what went wrong. * Make sure to finish the argument list with a zero.
e6fa8e1997-01-25Henrik Grubbström (Grubba)  */
3c04e81997-03-13Fredrik Hübinette (Hubbe) static int va_check_args(struct svalue *s, int args_to_check, struct expect_result *res, va_list arglist)
e6fa8e1997-01-25Henrik Grubbström (Grubba) {
3c04e81997-03-13Fredrik Hübinette (Hubbe)  res->error_type = ERR_NONE; res->expected = 0;
13670c2015-05-25Martin Nilsson 
3c04e81997-03-13Fredrik Hübinette (Hubbe)  for (res->argno=0; res->argno < args_to_check; res->argno++)
e6fa8e1997-01-25Henrik Grubbström (Grubba)  {
3c04e81997-03-13Fredrik Hübinette (Hubbe)  if(!(res->expected & BIT_MANY)) { res->expected = va_arg(arglist, unsigned int); if(!res->expected) { res->error_type = ERR_TOO_MANY; return 0; } }
e6fa8e1997-01-25Henrik Grubbström (Grubba) 
017b572011-10-28Henrik Grubbström (Grubba)  if (!((1UL << TYPEOF(s[res->argno])) & res->expected) &&
9c14572003-06-05Martin Stjernholm  !(res->expected & BIT_ZERO &&
017b572011-10-28Henrik Grubbström (Grubba)  TYPEOF(s[res->argno]) == T_INT && s[res->argno].u.integer == 0))
e6fa8e1997-01-25Henrik Grubbström (Grubba)  {
017b572011-10-28Henrik Grubbström (Grubba)  res->got = DO_NOT_WARN((unsigned char)TYPEOF(s[res->argno]));
3c04e81997-03-13Fredrik Hübinette (Hubbe)  res->error_type = ERR_BAD_ARG; return 0;
e6fa8e1997-01-25Henrik Grubbström (Grubba)  } }
3c04e81997-03-13Fredrik Hübinette (Hubbe)  if(!(res->expected & BIT_MANY)) res->expected = va_arg(arglist, unsigned int);
b122a71999-11-11Fredrik Hübinette (Hubbe)  if(!res->expected ||
56d9cd1999-12-11Martin Stjernholm  (res->expected & BIT_VOID)) return 1;
b122a71999-11-11Fredrik Hübinette (Hubbe)  res->error_type = ERR_TOO_FEW; return 0;
e6fa8e1997-01-25Henrik Grubbström (Grubba) } /* Returns the number of the first bad argument,
3c04e81997-03-13Fredrik Hübinette (Hubbe)  * -X if there were too few arguments
e6fa8e1997-01-25Henrik Grubbström (Grubba)  * or 0 if all arguments were OK. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT int check_args(int args, ...)
dfa0b61997-01-21Fredrik Hübinette (Hubbe) { va_list arglist;
3c04e81997-03-13Fredrik Hübinette (Hubbe)  struct expect_result tmp;
13670c2015-05-25Martin Nilsson 
3c04e81997-03-13Fredrik Hübinette (Hubbe)  va_start(arglist, args); va_check_args(sp - args, args, &tmp, arglist);
e6fa8e1997-01-25Henrik Grubbström (Grubba)  va_end(arglist);
dfa0b61997-01-21Fredrik Hübinette (Hubbe) 
3c04e81997-03-13Fredrik Hübinette (Hubbe)  if(tmp.error_type == ERR_NONE) return 0; return tmp.argno+1;
e6fa8e1997-01-25Henrik Grubbström (Grubba) }
dfa0b61997-01-21Fredrik Hübinette (Hubbe) 
9c14572003-06-05Martin Stjernholm /* This function generates errors if any of the args first arguments
e6fa8e1997-01-25Henrik Grubbström (Grubba)  * is not OK. */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT void check_all_args(const char *fnname, int args, ... )
e6fa8e1997-01-25Henrik Grubbström (Grubba) { va_list arglist;
3c04e81997-03-13Fredrik Hübinette (Hubbe)  struct expect_result tmp;
e6fa8e1997-01-25Henrik Grubbström (Grubba) 
3c04e81997-03-13Fredrik Hübinette (Hubbe)  va_start(arglist, args); va_check_args(sp - args, args, &tmp, arglist);
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  va_end(arglist);
e6fa8e1997-01-25Henrik Grubbström (Grubba) 
3c04e81997-03-13Fredrik Hübinette (Hubbe)  switch(tmp.error_type) { case ERR_NONE: return; case ERR_TOO_FEW:
f2e5251998-04-12Henrik Grubbström (Grubba)  new_error(fnname, "Too few arguments.\n", sp, args, NULL, 0);
d9d4b52015-05-05Henrik Grubbström (Grubba)  break;
3c04e81997-03-13Fredrik Hübinette (Hubbe)  case ERR_TOO_MANY:
f2e5251998-04-12Henrik Grubbström (Grubba)  new_error(fnname, "Too many arguments.\n", sp, args, NULL, 0);
d9d4b52015-05-05Henrik Grubbström (Grubba)  break;
3c04e81997-03-13Fredrik Hübinette (Hubbe)  case ERR_BAD_ARG: { char buf[1000];
a5cd6a2001-09-24Henrik Grubbström (Grubba)  int e;
3c04e81997-03-13Fredrik Hübinette (Hubbe)  buf[0]=0; for(e=0;e<16;e++) { if(tmp.expected & (1<<e)) { if(buf[0]) { if(tmp.expected & 0xffff & (0xffff << e)) strcat(buf,", "); else strcat(buf," or "); } strcat(buf, get_name_of_type(e)); } }
13670c2015-05-25Martin Nilsson  Pike_error("Bad argument %d to %s(), (expecting %s, got %s)\n",
3c04e81997-03-13Fredrik Hübinette (Hubbe)  tmp.argno+1, fnname, buf, get_name_of_type(tmp.got));
d9d4b52015-05-05Henrik Grubbström (Grubba)  break;
3c04e81997-03-13Fredrik Hübinette (Hubbe)  }
e6fa8e1997-01-25Henrik Grubbström (Grubba)  }
dfa0b61997-01-21Fredrik Hübinette (Hubbe) }
e4cdbe2004-02-29Martin Stjernholm /* get_args and get_all_args type specifiers: *
1e2c511999-03-21Henrik Grubbström (Grubba)  * %i: INT_TYPE
13670c2015-05-25Martin Nilsson  * %I: int or float -> INT_TYPE
2373c12003-02-17Mirar (Pontus Hagland)  * %d: int (the c type "int" which may vary from INT_TYPE) * %D: int of float -> int * %+: positive int -> INT_TYPE
b9ac222003-12-08Henrik Grubbström (Grubba)  * %l: int or bignum -> LONGEST
c3067c2008-03-31Martin Stjernholm  * %c: char * Only narrow (8 bit) strings without NUL. * %C: char * or NULL Only narrow (8 bit) strings without NUL.
e4cdbe2004-02-29Martin Stjernholm  * %n: struct pike_string * Only narrow (8 bit) strings. * %N: struct pike_string * or NULL Only narrow (8 bit) strings. * %t: struct pike_string * Any string width. (*) * %T: struct pike_string * or NULL Any string width. (*)
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  * %a: struct array *
be106c1999-04-03Henrik Grubbström (Grubba)  * %A: struct array * or NULL
3a19341999-12-06Mirar (Pontus Hagland)  * %f: float -> FLOAT_TYPE * %F: float or int -> FLOAT_TYPE
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  * %m: struct mapping *
e4cdbe2004-02-29Martin Stjernholm  * %G: struct mapping * or NULL (*) * %u: struct multiset * * %U: struct multiset * or NULL
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  * %o: struct object *
f014e21999-02-12Per Hedbor  * %O: struct object * or NULL
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  * %p: struct program *
e4cdbe2004-02-29Martin Stjernholm  * %P: struct program * or NULL
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  * %*: struct svalue *
e4cdbe2004-02-29Martin Stjernholm  * * For compatibility: *
c3067c2008-03-31Martin Stjernholm  * %s: char * Only 8 bit strings without NUL.
99c5382010-07-27Martin Stjernholm  * %S: struct pike_string * Only 8 bit strings
e4cdbe2004-02-29Martin Stjernholm  * %W: struct pike_string * Allow wide strings * %M: struct multiset * * * A period can be specified between type specifiers to mark the start
c3067c2008-03-31Martin Stjernholm  * of optional arguments. If the real arguments run out in the list of
99c5382010-07-27Martin Stjernholm  * optional arguments, or if a real argument is UNDEFINED in an * optional argument position, the corresponding pointer won't be * assigned at all. * * WARNING: If you use a period to parse optional arguments, then you * should _always_ initialize the corresponding variables before * calling get_args/get_all_args. Just looking at num_args afterwards * is not safe since the user might have passed UNDEFINED, in which * case the variable won't be assigned anyway.
c3067c2008-03-31Martin Stjernholm  *
e048d52008-04-25Henrik Grubbström (Grubba)  * Note: If there are more arguments than there are type specifiers * the excessive arguments will be silently ignored. This may change * in the future, in which case an extra marker must be added to get * this behaviour. *
c3067c2008-03-31Martin Stjernholm  * Note: A lowercase type specifier (i.e. one that doesn't accept * NULL) in the optional args list leads to behavior that breaks * common coding conventions. Try to avoid it.
e4cdbe2004-02-29Martin Stjernholm  * * *) Contrived letter since the logical one is taken for historical * reasons. :\
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  */
e4cdbe2004-02-29Martin Stjernholm /* Values for the info flag: */ #define ARGS_OK 0 /* At end of args and fmt. */ #define ARGS_OPT -1 /* At end of args but not fmt and has passed a period. */ #define ARGS_SHORT -2 /* At end of args but not fmt and has not passed a period. */ #define ARGS_LONG -3 /* At end of fmt but not args. */
7fd6b92008-03-31Martin Stjernholm #define ARGS_NUL_IN_STRING -4 /* 8 bit string got embedded NUL. */
781d7c2008-04-14Henrik Grubbström (Grubba) #define ARGS_SUBTYPED_OBJECT -5 /* An object with a subtype. */
e4cdbe2004-02-29Martin Stjernholm /* Positive values: Stopped at arg with invalid type. The value is the * format letter for the expected type. */ static int va_get_args_2(struct svalue *s, INT32 num_args, const char *fmt, va_list ap, int *info)
dfa0b61997-01-21Fredrik Hübinette (Hubbe) { int ret=0;
e4cdbe2004-02-29Martin Stjernholm  int optional = 0;
f014e21999-02-12Per Hedbor 
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  while(*fmt) {
8634d72007-12-24Henrik Grubbström (Grubba)  void *ptr;
e4cdbe2004-02-29Martin Stjernholm  if (*fmt == '.' && !optional) { fmt++; optional = 1; continue; }
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  if(*fmt != '%')
e4cdbe2004-02-29Martin Stjernholm  Pike_fatal("Error in format for get_args or get_all_args.\n");
dfa0b61997-01-21Fredrik Hübinette (Hubbe) 
e4cdbe2004-02-29Martin Stjernholm  if(ret == num_args) { if (optional) *info = ARGS_OPT; else *info = ARGS_SHORT; return ret; }
dfa0b61997-01-21Fredrik Hübinette (Hubbe) 
8634d72007-12-24Henrik Grubbström (Grubba)  ptr = va_arg(ap, void *); #define cast_arg(PTR, TYPE) ((TYPE)(PTR))
99c5382010-07-27Martin Stjernholm #ifdef PIKE_DEBUG /* Try to check that the caller has given the variable for every * optional argument a value, because otherwise the caller is * almost certainly doing something stupid. See the warning in the * blurb above. */ if (optional && PIKE_MEM_NOT_DEF (*cast_arg (ptr, char *))) Pike_fatal ("Detected undefined default value for optional argument.\n"); #endif
ccf6be2004-12-13Martin Stjernholm  if (optional && IS_UNDEFINED (s)) { /* An optional argument with an undefined value should be * treated as if it isn't given at all, i.e. don't assign this * argument. */ fmt++; } else switch(*++fmt)
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  { case 'd':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_INT) goto type_err;
0f97e92008-04-01Martin Stjernholm  /* FIXME: Range checks, including bignum objects. */
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, int *)=s->u.integer;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  break; case 'i':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_INT) goto type_err;
0f97e92008-04-01Martin Stjernholm  /* FIXME: Error reporting for bignum objects. */
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, INT_TYPE *)=s->u.integer;
19aaeb1998-05-25Fredrik Hübinette (Hubbe)  break;
08ab061999-12-05Mirar (Pontus Hagland)  case '+':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_INT) goto type_err;
e4cdbe2004-02-29Martin Stjernholm  if(s->u.integer<0) goto type_err;
0f97e92008-04-01Martin Stjernholm  /* FIXME: Error reporting for bignum objects. */
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, INT_TYPE *)=s->u.integer;
08ab061999-12-05Mirar (Pontus Hagland)  break;
e4cdbe2004-02-29Martin Stjernholm 
f014e21999-02-12Per Hedbor  case 'D':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) == T_INT)
0f97e92008-04-01Martin Stjernholm  /* FIXME: Range checks. */
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, int *)=s->u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  else if(TYPEOF(*s) == T_FLOAT)
0f97e92008-04-01Martin Stjernholm  /* FIXME: Range checks. */ *cast_arg(ptr, int *)=
61a8ec2000-08-11Henrik Grubbström (Grubba)  DO_NOT_WARN((int)s->u.float_number);
13670c2015-05-25Martin Nilsson  else
f014e21999-02-12Per Hedbor  {
b103b32001-02-20Henrik Grubbström (Grubba)  ref_push_type_value(int_type_string);
44bcbb1999-11-16Henrik Grubbström (Grubba)  push_svalue( s );
f014e21999-02-12Per Hedbor  f_cast( );
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-1]) == T_INT)
0f97e92008-04-01Martin Stjernholm  /* FIXME: Range checks. */
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, int *)=sp[-1].u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  else if(TYPEOF(*s) == T_FLOAT)
0f97e92008-04-01Martin Stjernholm  /* FIXME: Range checks. Btw, does this case occur? */
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, int *)=
61a8ec2000-08-11Henrik Grubbström (Grubba)  DO_NOT_WARN((int)sp[-1].u.float_number); else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cast to int failed.\n");
f014e21999-02-12Per Hedbor  pop_stack(); } break;
e4cdbe2004-02-29Martin Stjernholm 
f014e21999-02-12Per Hedbor  case 'I':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) == T_INT)
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, INT_TYPE *)=s->u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  else if(TYPEOF(*s) == T_FLOAT)
0f97e92008-04-01Martin Stjernholm  /* FIXME: Range checks. */ *cast_arg(ptr, INT_TYPE *) = DO_NOT_WARN((INT_TYPE)s->u.float_number);
13670c2015-05-25Martin Nilsson  else
f014e21999-02-12Per Hedbor  {
0f97e92008-04-01Martin Stjernholm  /* FIXME: Error reporting for bignum objects. */
b103b32001-02-20Henrik Grubbström (Grubba)  ref_push_type_value(int_type_string);
44bcbb1999-11-16Henrik Grubbström (Grubba)  push_svalue( s );
f014e21999-02-12Per Hedbor  f_cast( );
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-1]) == T_INT)
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, INT_TYPE *)=sp[-1].u.integer;
017b572011-10-28Henrik Grubbström (Grubba)  else if(TYPEOF(*s) == T_FLOAT)
0f97e92008-04-01Martin Stjernholm  /* FIXME: Range checks. Btw, does this case occur? */
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, INT_TYPE *)=
61a8ec2000-08-11Henrik Grubbström (Grubba)  DO_NOT_WARN((INT_TYPE)sp[-1].u.float_number); else
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Cast to int failed.\n");
f014e21999-02-12Per Hedbor  pop_stack(); } break;
e4cdbe2004-02-29Martin Stjernholm 
b9ac222003-12-08Henrik Grubbström (Grubba)  case 'l':
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s) == T_INT) {
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, LONGEST *)=s->u.integer;
b9ac222003-12-08Henrik Grubbström (Grubba)  break;
1acd0c2003-12-17Henrik Grubbström (Grubba)  } else if (is_bignum_object_in_svalue(s) &&
8634d72007-12-24Henrik Grubbström (Grubba)  int64_from_bignum(cast_arg(ptr, LONGEST *), s->u.object) == 1) {
1acd0c2003-12-17Henrik Grubbström (Grubba)  break;
b9ac222003-12-08Henrik Grubbström (Grubba)  }
0f97e92008-04-01Martin Stjernholm  /* FIXME: Error reporting for bignum objects. */
e4cdbe2004-02-29Martin Stjernholm  goto type_err;
c3067c2008-03-31Martin Stjernholm  case 'C':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_STRING && UNSAFE_IS_ZERO (s)) {
c3067c2008-03-31Martin Stjernholm  *cast_arg(ptr, char **) = NULL; break; } /* FALL THROUGH */ case 'c':
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  case 's':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_STRING) goto type_err;
e4cdbe2004-02-29Martin Stjernholm  if(s->u.string->size_shift) goto type_err;
ba7a1b2005-11-14Martin Nilsson 
7fd6b92008-03-31Martin Stjernholm  if(string_has_null(s->u.string)) { *info = ARGS_NUL_IN_STRING; return ret; }
ba7a1b2005-11-14Martin Nilsson 
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, char **)=s->u.string->str;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  break;
e4cdbe2004-02-29Martin Stjernholm  case 'N':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_STRING && UNSAFE_IS_ZERO (s)) {
b9ed5c2007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct pike_string **) = NULL;
e4cdbe2004-02-29Martin Stjernholm  break; } /* FALL THROUGH */ case 'n':
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  case 'S':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_STRING) goto type_err;
e4cdbe2004-02-29Martin Stjernholm  if(s->u.string->size_shift) goto type_err;
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct pike_string **)=s->u.string;
3389fd1998-10-10Henrik Grubbström (Grubba)  break;
e4cdbe2004-02-29Martin Stjernholm  case 'T':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_STRING && UNSAFE_IS_ZERO (s)) {
b9ed5c2007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct pike_string **) = NULL;
e4cdbe2004-02-29Martin Stjernholm  break; } /* FALL THROUGH */ case 't':
3389fd1998-10-10Henrik Grubbström (Grubba)  case 'W':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_STRING) goto type_err;
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct pike_string **)=s->u.string;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  break;
e4cdbe2004-02-29Martin Stjernholm  case 'A':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_ARRAY && UNSAFE_IS_ZERO (s)) {
b9ed5c2007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct array **) = NULL;
e4cdbe2004-02-29Martin Stjernholm  break; } /* FALL THROUGH */
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  case 'a':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_ARRAY) goto type_err;
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct array **)=s->u.array;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  break;
e4cdbe2004-02-29Martin Stjernholm 
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  case 'f':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_FLOAT) goto type_err;
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, FLOAT_TYPE *)=s->u.float_number;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  break;
ab2ead1999-01-24Mirar (Pontus Hagland)  case 'F':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) == T_FLOAT)
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, FLOAT_TYPE *)=s->u.float_number;
017b572011-10-28Henrik Grubbström (Grubba)  else if(TYPEOF(*s) == T_INT)
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, FLOAT_TYPE *)=(FLOAT_TYPE)s->u.integer;
13670c2015-05-25Martin Nilsson  else
f014e21999-02-12Per Hedbor  {
b103b32001-02-20Henrik Grubbström (Grubba)  ref_push_type_value(float_type_string);
44bcbb1999-11-16Henrik Grubbström (Grubba)  push_svalue( s );
f014e21999-02-12Per Hedbor  f_cast( );
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, FLOAT_TYPE *)=sp[-1].u.float_number;
f014e21999-02-12Per Hedbor  pop_stack(); }
ab2ead1999-01-24Mirar (Pontus Hagland)  break;
f014e21999-02-12Per Hedbor 
e4cdbe2004-02-29Martin Stjernholm  case 'G':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_MAPPING && UNSAFE_IS_ZERO (s)) {
b9ed5c2007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct mapping **) = NULL;
e4cdbe2004-02-29Martin Stjernholm  break; } /* FALL THROUGH */
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  case 'm':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_MAPPING) goto type_err;
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct mapping **)=s->u.mapping;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  break;
e4cdbe2004-02-29Martin Stjernholm  case 'U':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_MULTISET && UNSAFE_IS_ZERO (s)) {
b9ed5c2007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct multiset **) = NULL;
e4cdbe2004-02-29Martin Stjernholm  break; } /* FALL THROUGH */ case 'u':
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  case 'M':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_MULTISET) goto type_err;
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct multiset **)=s->u.multiset;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  break;
e4cdbe2004-02-29Martin Stjernholm  case 'O':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_OBJECT && UNSAFE_IS_ZERO (s)) {
b9ed5c2007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct object **) = NULL;
e4cdbe2004-02-29Martin Stjernholm  break; } /* FALL THROUGH */
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  case 'o':
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(*s) != T_OBJECT) goto type_err; if (SUBTYPEOF(*s)) {
781d7c2008-04-14Henrik Grubbström (Grubba)  *info = ARGS_SUBTYPED_OBJECT; return ret; }
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct object **)=s->u.object;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  break;
e4cdbe2004-02-29Martin Stjernholm  case 'P':
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  case 'p':
017b572011-10-28Henrik Grubbström (Grubba)  switch(TYPEOF(*s))
1994251999-09-06Fredrik Hübinette (Hubbe)  { case T_PROGRAM:
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct program **)=s->u.program;
1994251999-09-06Fredrik Hübinette (Hubbe)  break; case T_FUNCTION:
8634d72007-12-24Henrik Grubbström (Grubba)  if((*cast_arg(ptr, struct program **)=program_from_svalue(s)))
1994251999-09-06Fredrik Hübinette (Hubbe)  break; default:
e4cdbe2004-02-29Martin Stjernholm  if (*fmt == 'P' && UNSAFE_IS_ZERO(s))
b9ed5c2007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct program **) = NULL;
e4cdbe2004-02-29Martin Stjernholm  goto type_err;
1994251999-09-06Fredrik Hübinette (Hubbe)  }
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  break;
1994251999-09-06Fredrik Hübinette (Hubbe) 
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  case '*':
8634d72007-12-24Henrik Grubbström (Grubba)  *cast_arg(ptr, struct svalue **)=s;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  break;
13670c2015-05-25Martin Nilsson 
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  default:
e4cdbe2004-02-29Martin Stjernholm  Pike_fatal("Unknown format character %d.\n", *fmt);
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  } ret++; s++; fmt++; }
e4cdbe2004-02-29Martin Stjernholm  if (ret == num_args) *info = ARGS_OK; else *info = ARGS_LONG; return ret; type_err: *info = *fmt;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  return ret; }
e4cdbe2004-02-29Martin Stjernholm /* Compat wrapper, just in case. */ int va_get_args(struct svalue *s, INT32 num_args, const char *fmt, va_list ap) { int info; return va_get_args_2 (s, num_args, fmt, ap, &info); }
b50ff22005-12-04Martin Nilsson #ifdef NOT_USED
e4cdbe2004-02-29Martin Stjernholm /* get_args does NOT generate errors, it simply returns how * many arguments were actually matched. * usage: get_args(sp-args, args, "%i",&an_int) */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT int get_args(struct svalue *s,
b7afeb2002-09-12Henrik Grubbström (Grubba)  INT32 num_args,
0929a02002-09-12Marcus Comstedt  const char *fmt, ...)
dfa0b61997-01-21Fredrik Hübinette (Hubbe) { va_list ptr;
e4cdbe2004-02-29Martin Stjernholm  int ret, info;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  va_start(ptr, fmt);
e4cdbe2004-02-29Martin Stjernholm  ret=va_get_args_2(s, num_args, fmt, ptr, &info);
b7afeb2002-09-12Henrik Grubbström (Grubba)  va_end(ptr);
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  return ret;
dfa0b61997-01-21Fredrik Hübinette (Hubbe) }
b50ff22005-12-04Martin Nilsson #endif
dfa0b61997-01-21Fredrik Hübinette (Hubbe) 
0929a02002-09-12Marcus Comstedt PMOD_EXPORT void get_all_args(const char *fname, INT32 args, const char *format, ... )
dfa0b61997-01-21Fredrik Hübinette (Hubbe) { va_list ptr;
e4cdbe2004-02-29Martin Stjernholm  int ret, info;
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  va_start(ptr, format);
e4cdbe2004-02-29Martin Stjernholm  ret=va_get_args_2(sp-args, args, format, ptr, &info);
dfa0b61997-01-21Fredrik Hübinette (Hubbe)  va_end(ptr);
e4cdbe2004-02-29Martin Stjernholm  switch (info) { case ARGS_OK: case ARGS_OPT: case ARGS_LONG: break;
7fd6b92008-03-31Martin Stjernholm  case ARGS_NUL_IN_STRING: bad_arg_error( fname, sp-args, args, ret+1,
ba888d2014-08-23Martin Nilsson  "string(1..255)",
7fd6b92008-03-31Martin Stjernholm  sp+ret-args,
3c5c4a2014-11-11Stephen R. van den Berg  "Bad argument %d to %s(). NUL in string.\n",
b42e942015-09-28Martin Nilsson  ret+1, fname); UNREACHABLE();
7fd6b92008-03-31Martin Stjernholm 
781d7c2008-04-14Henrik Grubbström (Grubba)  case ARGS_SUBTYPED_OBJECT: bad_arg_error(fname, sp-args, args, ret+1, "object", sp+ret-args, "Subtyped objects are not supported.\n");
b42e942015-09-28Martin Nilsson  UNREACHABLE();
781d7c2008-04-14Henrik Grubbström (Grubba) 
e4cdbe2004-02-29Martin Stjernholm  case ARGS_SHORT: default: { char *expected_type; /* NB: For ARGS_SHORT we know there's no period in format that * might offset the format specs. */ switch(info == ARGS_SHORT ? format[ret*2+1] : info) { case 'd': case 'i': case 'l': expected_type = "int"; break; case 'D': case 'I': expected_type = "int|float"; break; case '+': expected_type = "int(0..)"; break;
ba888d2014-08-23Martin Nilsson  case 'c': case 's': expected_type = "string(1..255)"; break; case 'n': case 'S': expected_type = "string(8bit)"; break; case 'C': expected_type = "string(1..255) or zero"; break; case 'N': expected_type = "string(8bit) or zero"; break;
e4cdbe2004-02-29Martin Stjernholm  case 't': case 'W': expected_type = "string"; break; case 'T': expected_type = "string or zero"; break; case 'a': expected_type = "array"; break; case 'A': expected_type = "array or zero"; break; case 'f': expected_type = "float"; break; case 'F': expected_type = "float|int"; break; case 'm': expected_type = "mapping"; break; case 'G': expected_type = "mapping or zero"; break; case 'M': case 'u': expected_type = "multiset"; break; case 'U': expected_type = "multiset or zero"; break; case 'o': expected_type = "object"; break; case 'O': expected_type = "object or zero"; break; case 'p': expected_type = "program"; break; case 'P': expected_type = "program or zero"; break; case '*': expected_type = "mixed"; break; default: #ifdef PIKE_DEBUG Pike_fatal ("get_all_args not in sync with low_va_get_args.\n"); #else expected_type = NULL; /* To avoid warnings. */ #endif } if (info != ARGS_SHORT) { bad_arg_error( fname, sp-args, args, ret+1, expected_type, sp+ret-args, "Bad argument %d to %s(). Expected %s.\n", ret+1, fname, expected_type); } else { const char *req_args_end = strchr (format, '.'); if (!req_args_end) req_args_end = strchr (format, 0); bad_arg_error( fname, sp-args, args, ret+1, expected_type, 0, "Too few arguments to %s(). Expected %"PRINTPTRDIFFT"d arguments, got %d.\n" "The type of the next argument is expected to be %s.\n", fname, (req_args_end - format) / 2, args, expected_type); }
b42e942015-09-28Martin Nilsson  UNREACHABLE();
424e991998-09-25Henrik Grubbström (Grubba)  }
f58cac1997-03-11Henrik Grubbström (Grubba)  }
dfa0b61997-01-21Fredrik Hübinette (Hubbe) }
d7143b2000-12-13Fredrik Hübinette (Hubbe)  /* NOTA BENE: * The code below assumes that dynamic modules are not * unloaded from memory... */
13670c2015-05-25Martin Nilsson 
d7143b2000-12-13Fredrik Hübinette (Hubbe) static struct mapping *exported_symbols;
0929a02002-09-12Marcus Comstedt PMOD_EXPORT void pike_module_export_symbol(const char *name,
d7143b2000-12-13Fredrik Hübinette (Hubbe)  int len, void *ptr) { struct pike_string *str=make_shared_binary_string(name,len); struct svalue s; if(!exported_symbols) exported_symbols=allocate_mapping(10);
017b572011-10-28Henrik Grubbström (Grubba)  SET_SVAL(s, T_INT, NUMBER_NUMBER, ptr, ptr);
d7143b2000-12-13Fredrik Hübinette (Hubbe)  mapping_string_insert(exported_symbols, str, &s);
d6df0b2002-05-14Martin Stjernholm  free_string(str);
d7143b2000-12-13Fredrik Hübinette (Hubbe) }
0929a02002-09-12Marcus Comstedt PMOD_EXPORT void *pike_module_import_symbol(const char *name,
d7143b2000-12-13Fredrik Hübinette (Hubbe)  int len,
0929a02002-09-12Marcus Comstedt  const char *module,
d7143b2000-12-13Fredrik Hübinette (Hubbe)  int module_len) { struct svalue *s; struct pike_string *str=make_shared_binary_string(name,len); if(exported_symbols) { s=low_mapping_string_lookup(exported_symbols, str);
ce77762002-08-16Martin Stjernholm  if(s)
d7143b2000-12-13Fredrik Hübinette (Hubbe)  {
ce77762002-08-16Martin Stjernholm #ifdef PIKE_DEBUG
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s) != T_INT || SUBTYPEOF(*s) != NUMBER_NUMBER)
ce77762002-08-16Martin Stjernholm  Pike_fatal("Unexpected value in exported_symbols.\n"); #endif
d7143b2000-12-13Fredrik Hübinette (Hubbe)  free_string(str);
ce77762002-08-16Martin Stjernholm  return s->u.ptr;
d7143b2000-12-13Fredrik Hübinette (Hubbe)  } } /* Load the module */ push_string(make_shared_binary_string(module,module_len)); SAFE_APPLY_MASTER("resolv",1); pop_stack(); if(exported_symbols) { s=low_mapping_string_lookup(exported_symbols, str);
ce77762002-08-16Martin Stjernholm  if(s)
d7143b2000-12-13Fredrik Hübinette (Hubbe)  {
ce77762002-08-16Martin Stjernholm #ifdef PIKE_DEBUG
017b572011-10-28Henrik Grubbström (Grubba)  if (TYPEOF(*s) != T_INT || SUBTYPEOF(*s) != NUMBER_NUMBER)
ce77762002-08-16Martin Stjernholm  Pike_fatal("Unexpected value in exported_symbols.\n"); #endif
d7143b2000-12-13Fredrik Hübinette (Hubbe)  free_string(str);
ce77762002-08-16Martin Stjernholm  return s->u.ptr;
d7143b2000-12-13Fredrik Hübinette (Hubbe)  } } free_string(str); return 0; }
feef142002-05-14Martin Stjernholm  #ifdef DO_PIKE_CLEANUP void cleanup_module_support (void) { if (exported_symbols) { free_mapping (exported_symbols); exported_symbols = NULL; } } #endif