| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | /*  $Id$
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Part of SWI-Prolog | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Author:        Jan Wielemaker | 
					
						
							|  |  |  |     E-mail:        J.Wielemaker@uva.nl | 
					
						
							|  |  |  |     WWW:           http://www.swi-prolog.org
 | 
					
						
							|  |  |  |     Copyright (C): 1985-2008, University of Amsterdam | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |     modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |     License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |     version 2.1 of the License, or (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |     but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |     Lesser General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |     License along with this library; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "pl-incl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | 
					
						
							|  |  |  | Variable argument list: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	atom_t	name | 
					
						
							|  |  |  | 	int	type	OPT_ATOM, OPT_STRING, OPT_BOOL, OPT_INT, OPT_LONG | 
					
						
							|  |  |  | 	pointer	value | 
					
						
							|  |  |  | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MAXOPTIONS 32
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef union | 
					
						
							| 
									
										
										
										
											2015-03-24 09:38:02 +00:00
										 |  |  | { int *b;				/* boolean value */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   long *l;				/* long value */ | 
					
						
							|  |  |  |   int  *i;				/* integer value */ | 
					
						
							|  |  |  |   uintptr_t *sz;			/* size_t value */ | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  |   double *f;				/* double value */ | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  |   char **s;				/* string value */ | 
					
						
							|  |  |  |   word *a;				/* atom value */ | 
					
						
							|  |  |  |   term_t *t;				/* term-reference */ | 
					
						
							|  |  |  |   void *ptr;				/* anonymous pointer */ | 
					
						
							|  |  |  | } optvalue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool | 
					
						
							|  |  |  | scan_options(term_t options, int flags, atom_t optype, | 
					
						
							|  |  |  | 	     const opt_spec *specs, ...) | 
					
						
							|  |  |  | { GET_LD | 
					
						
							|  |  |  |   va_list args; | 
					
						
							|  |  |  |   const opt_spec *s; | 
					
						
							|  |  |  |   optvalue values[MAXOPTIONS]; | 
					
						
							|  |  |  |   term_t list = PL_copy_term_ref(options); | 
					
						
							|  |  |  |   term_t head = PL_new_term_ref(); | 
					
						
							|  |  |  |   term_t tmp  = PL_new_term_ref(); | 
					
						
							|  |  |  |   term_t val  = PL_new_term_ref(); | 
					
						
							|  |  |  |   int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( truePrologFlag(PLFLAG_ISO) ) | 
					
						
							|  |  |  |     flags |= OPT_ALL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   va_start(args, specs); | 
					
						
							|  |  |  |   for( n=0, s = specs; s->name; s++, n++ ) | 
					
						
							|  |  |  |     values[n].ptr = va_arg(args, void *); | 
					
						
							|  |  |  |   va_end(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while ( PL_get_list(list, head, list) ) | 
					
						
							|  |  |  |   { atom_t name; | 
					
						
							|  |  |  |     int arity; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( PL_get_name_arity(head, &name, &arity) ) | 
					
						
							|  |  |  |     { if ( name == ATOM_equals && arity == 2 ) | 
					
						
							|  |  |  |       { _PL_get_arg(1, head, tmp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ( !PL_get_atom(tmp, &name) ) | 
					
						
							|  |  |  | 	  goto itemerror; | 
					
						
							|  |  |  | 	_PL_get_arg(2, head, val); | 
					
						
							|  |  |  |       } else if ( arity == 1 ) | 
					
						
							|  |  |  |       { _PL_get_arg(1, head, val); | 
					
						
							|  |  |  |       } else if ( arity == 0 ) | 
					
						
							|  |  |  | 	PL_put_atom(val, ATOM_true); | 
					
						
							|  |  |  |     } else if ( PL_is_variable(head) ) | 
					
						
							|  |  |  |     { return PL_error(NULL, 0, NULL, ERR_INSTANTIATION); | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |     { itemerror: | 
					
						
							|  |  |  |       return PL_error(NULL, 0, NULL, ERR_DOMAIN, optype, head); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for( n=0, s = specs; s->name; n++, s++ ) | 
					
						
							|  |  |  |     { if ( s->name == name ) | 
					
						
							|  |  |  |       { switch((s->type & OPT_TYPE_MASK)) | 
					
						
							|  |  |  | 	{ case OPT_BOOL: | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	  { int bval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    if ( !PL_get_bool_ex(val, &bval) ) | 
					
						
							|  |  |  | 	      return FALSE; | 
					
						
							|  |  |  | 	    *values[n].b = bval; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  case OPT_INT: | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	  { if ( !PL_get_integer_ex(val, values[n].i) ) | 
					
						
							|  |  |  | 	      return FALSE; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  case OPT_LONG: | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	  { if ( (s->type & OPT_INF) && PL_is_inf(val) ) | 
					
						
							|  |  |  | 	      *values[n].l = LONG_MAX; | 
					
						
							|  |  |  | 	    else if ( !PL_get_long_ex(val, values[n].l) ) | 
					
						
							|  |  |  | 	      return FALSE; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  case OPT_NATLONG: | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	  { if ( !PL_get_long_ex(val, values[n].l) ) | 
					
						
							|  |  |  | 	      return FALSE; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	    if ( *(values[n].l) <= 0 ) | 
					
						
							|  |  |  | 	      return PL_error(NULL, 0, NULL, ERR_DOMAIN, | 
					
						
							|  |  |  | 			      ATOM_not_less_than_one, val); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  case OPT_SIZE: | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	  { if ( (s->type & OPT_INF) && PL_is_inf(val) ) | 
					
						
							|  |  |  | 	      *values[n].sz = (size_t)-1; | 
					
						
							|  |  |  | 	    else if ( !PL_get_size_ex(val, values[n].sz) ) | 
					
						
							|  |  |  | 	      return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  case OPT_DOUBLE: | 
					
						
							|  |  |  | 	  { if ( !PL_get_float_ex(val, values[n].f) ) | 
					
						
							|  |  |  | 	      return FALSE; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  case OPT_STRING: | 
					
						
							|  |  |  | 	  { char *str; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	    if ( !PL_get_chars(val, &str, CVT_ALL|CVT_EXCEPTION) ) /* copy? */ | 
					
						
							|  |  |  | 	      return FALSE; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	    *values[n].s = str; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  case OPT_ATOM: | 
					
						
							|  |  |  | 	  { atom_t a; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | 	    if ( !PL_get_atom_ex(val, &a) ) | 
					
						
							|  |  |  | 	      return FALSE; | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	    *values[n].a = a; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							| 
									
										
										
										
											2013-11-15 01:10:25 +00:00
										 |  |  | #ifdef O_LOCALE
 | 
					
						
							|  |  |  | 	  case OPT_LOCALE: | 
					
						
							|  |  |  | 	  { PL_locale *l; | 
					
						
							|  |  |  | 	    PL_locale **lp = values[n].ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    if ( !getLocaleEx(val, &l) ) | 
					
						
							|  |  |  | 	      return FALSE; | 
					
						
							|  |  |  | 	    *lp = l; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-02-10 00:01:19 +00:00
										 |  |  | 	  case OPT_TERM: | 
					
						
							|  |  |  | 	  { *values[n].t = val; | 
					
						
							|  |  |  | 	    val = PL_new_term_ref();	/* can't reuse anymore */ | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	  default: | 
					
						
							|  |  |  | 	    assert(0); | 
					
						
							|  |  |  | 	    fail; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ( !s->name && (flags & OPT_ALL) ) | 
					
						
							|  |  |  |       goto itemerror; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ( !PL_get_nil(list) ) | 
					
						
							|  |  |  |     return PL_error(NULL, 0, NULL, ERR_TYPE, ATOM_list, list); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   succeed; | 
					
						
							|  |  |  | } |