Esempio n. 1
0
int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char *format, va_list ap)
{
	char	fch, ich;
	 int	ret = 0, nch = 0;
	
	while( (fch = *format++) )
	{
		union {
			void	*_void;
			char	*_char;
			short	*_short;
			 int	*_int;
			long	*_long;
			long long	*_longlong;
		}	ptr;
		long long	ival;
		//long double	rval;
		 int	maxlen = 0;
		// int	offset = -1;
		enum e_vcscanf_sizes	size = _VCSCANF_UNDEF;
		enum e_vcscanf_types	valtype;
		 int	fail = 0;
		 int	nnewch;

		const char	*set_start;
		 int	set_len;		

		// Whitespace matches any ammount of whitespace (including none)
		if( isspace(fch) )
		{
			while( (ich = __getc(h)) && isspace(ich) )
				nch ++;
			if(ich)	__rewind(h);
			continue ;
		}
		
		// Any non-whitespace and non-% characters must match exactly
		if( fch != '%' )
		{
			if( __getc(h) != fch )
				break;
			nch ++;
			continue ;
		}
		
		// Format specifier
		fch = *format++;
		if(!fch)	break;

		// Catch '%%' early
		if( fch == '%' ) {
			if( __getc(h) != '%' )
				break;
			nch ++;
			continue ;
		}		

		// %n$ - Direct offset selection, shouldn't be mixed with just %
		#if 0
		for( ; isdigit(fch); fch = *format++ )
			maxlen = maxlen * 10 + (fch - '0');
		if( fch == '$' ) {
			offset = maxlen;
			maxlen = 0;
		}
		#endif
		
		// Supress assignemnt?
		if( fch == '*' )
		{
			fch = *format++;
			ptr._void = NULL;
			ret --;
		}
		else
			ptr._void = va_arg(ap, void*);
		
		// Max field length
		while( isdigit(fch) )
		{
			maxlen = maxlen * 10 + fch - '0';
			fch = *format++;
		}
		
		// Length modifier
		switch( fch )
		{
		case 'h':
			// 'short'
			size = _VCSCANF_SHORT;
			fch = *format++;
			if( fch == 'h' ) {
				// 'char'
				size = _VCSCANF_CHAR;
				fch = *format++;
			}
			break;
		case 'l':
			// 'long'
			size = _VCSCANF_LONG;
			fch = *format++;
			if( fch == 'l' ) {
				// 'long long'
				size = _VCSCANF_LONGLONG;
				fch = *format++;
			}
			break;
		case 'j':
			// '(u)intmax_t'
			size = _VCSCANF_INTMAX;
			fch = *format++;
			break;
		case 'z':
			// 'size_t'
			size = _VCSCANF_SIZET;
			fch = *format++;
			break;
		case 't':
			// 'ptrdiff_t'
			size = _VCSCANF_PTRDIFF;
			fch = *format++;
			break;
		case 'L':
			// 'long double' (a, A, e, E, f, F, g, G)
			size = _VCSCANF_LONGDOUBLE;
			fch = *format++;
			break;
		}
		
		// Format specifiers
		switch( fch )
		{
		// Decimal integer
		case 'd':
			nnewch = _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
			if(nnewch==0)	fail=1;
			nch += nnewch;
			valtype = _VCSCANF_INT;
			break;
		// variable-base integer
		case 'i':
			nnewch = _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
			if(nnewch==0)	fail=1;
			nch += nnewch;
			valtype = _VCSCANF_INT;
			break;
		// Octal integer
		case 'o':
			nnewch = _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
			if(nnewch==0)	fail=1;
			nch += nnewch;
			valtype = _VCSCANF_INT;
			break;
		// Hexadecimal integer
		case 'x': case 'X':
			nnewch = _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
			if(nnewch==0)	fail=1;
			nch += nnewch;
			valtype = _VCSCANF_INT;
			break;
		// strtod format float
		case 'a': case 'A':
		case 'e': case 'E':
		case 'f': case 'F':
		case 'g': case 'G':
			valtype = _VCSCANF_REAL;
			break;
 		// `maxlen` or 1 characters
		case 'c':
			if( maxlen == 0 )
				maxlen = 1;
			while( maxlen -- && (ich = __getc(h)) )
			{
				if(ptr._char)	*ptr._char++ = ich;
				nch ++;
			}
			valtype = _VCSCANF_NOTYPE;
			break;
		// sequence of non-whitespace characters
		case 's':
			if( maxlen == 0 )
				maxlen = -1;

			ich = 0;
			while( maxlen -- && (ich = __getc(h)) && !isspace(ich) )
			{
				if(ptr._char)	*ptr._char++ = ich;
				nch ++;
			}
			if( maxlen >= 0 && ich )
				__rewind(h);
			if(ptr._char)	*ptr._char++ = 0;
			valtype = _VCSCANF_NOTYPE;
			break;
		// match a set of characters
		case '[': {
			int invert = 0;
			if( *format++ == '^' ) {
				// Invert
				invert = 1;
			}
			set_start = format;
			set_len = 0;
			// if the first character is ']' it's part of the set
			do {
				// permissable character
				set_len ++;
				fch = *format++;
			} while( fch && fch != ']' );

			if( maxlen == 0 )
				maxlen = -1;
			ich = 0;
			while( maxlen -- && (ich = __getc(h)) && invert == !memchr(set_start, set_len, ich) )
			{
				if(ptr._char)	*ptr._char++ = ich;
				nch ++;
			}
			if( maxlen >= 0 && ich )
				__rewind(h);
			if(ptr._char)	*ptr._char++ = 0;
			valtype = _VCSCANF_NOTYPE;
			break;
			}
		case 'p': // read back printf("%p")
			valtype = _VCSCANF_NOTYPE;
			break;
		case 'n': // number of read characters to this point
			if(ptr._int) {
				*ptr._int = nch;
				ret --;	// negates the ret ++ at the end
			}
			valtype = _VCSCANF_NOTYPE;
			break;
		default:
			// Implimentation defined
			valtype = _VCSCANF_NOTYPE;
			break;
		}

		if(fail)
			break;		

		switch(valtype)
		{
		case _VCSCANF_NOTYPE:
			// Used when assignment is done above
			break;
		case _VCSCANF_INT:
			switch(size)
			{
			case _VCSCANF_UNDEF:	*ptr._int = ival;	break;
			case _VCSCANF_CHAR:	*ptr._char = ival;	break;
			case _VCSCANF_SHORT:	*ptr._short = ival;	break;
			case _VCSCANF_LONG:	*ptr._long = ival;	break;
			case _VCSCANF_LONGLONG:	*ptr._longlong = ival;	break;
			default:	// ???
				break;
			}
			break;
		case _VCSCANF_REAL:
			break;
		}
		
		ret ++;
	}
	
	return ret;
}
Esempio n. 2
0
// === CODE ===
int _vcscanf_int(int (*__getc)(void *), void (*__rewind)(void*), void *h, int base, int maxlen, long long *outval)
{
	char	ich;
	 int	sgn = 1;
	long long int	ret = 0;
	 int	n_read = 0;

	// Initialise output to something sane
	*outval = 0;

	// First character
	// - maxlen == 0 means no limit
	ich = __getc(h);
	n_read ++;
	
	// Sign?
	if( ich == '-' || ich == '+' ) {
		sgn = (ich == '-' ? -1 : 1);
		if( n_read == maxlen )
			return n_read;
		ich = __getc(h);
		n_read ++;
	}
	
	// Determine base
	if( base == 0 ) {
		if( ich != '0' ) {
			base = 10;
		}
		else {
			if( n_read == maxlen )
				return n_read;
			ich = __getc(h);
			n_read ++;
			if( ich != 'x' ) {
				base = 8;
			}
			else {
				base = 16;
				if( n_read == maxlen )
					return n_read;
				ich = __getc(h);
				n_read ++;
			}
		}
	}
	
	if( ich == 0 ) {
		// Oops?
		return n_read;
	}
	
	while( ich )
	{
		 int	next = -1;
		
		// Get the digit value
		if( base <= 10 ) {
			if( '0' <= ich && ich <= '0'+base-1 )
				next = ich - '0';
		}
		else {
			if( '0' <= ich && ich <= '9' )
				next = ich - '0';
			if( 'A' <= ich && ich <= 'A'+base-10-1 )
				next = ich - 'A' + 10;
			if( 'a' <= ich && ich <= 'a'+base-10-1 )
				next = ich - 'a' + 10;
		}
		// if it's not a digit, rewind and break
		if( next < 0 ) {
			__rewind(h);
			n_read --;
			break;
		}
		
		// Add to the result
		ret *= base;
		ret += next;
		//_SysDebug("- %i/%i read, 0x%x val", n_read, maxlen, ret);

		// Check if we've reached the limit
		if( n_read == maxlen )
			break ;

		// Next character
		ich = __getc(h);
		n_read ++;
	}
	
	// Apply sign
	if( sgn == -1 )
		ret = -ret;

	*outval = ret;
	return n_read;
}
Esempio n. 3
0
static Boolean _lock( struct OBlockGroup* inst ,const char* BlockId ,const char* LocoId ) {
  iOBlockGroupData data = Data(inst);
  iOModel model  = AppOp.getModel();
  Boolean selectShortest = wCtrl.isselectshortestblock( wRocRail.getctrl( AppOp.getIni() ) );

  TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "loco %s request to lock blockgroup %s with block %s",
      LocoId, wLink.getid(data->props), BlockId);

  if( MapOp.get(data->lockmap, LocoId) != NULL ) {
    TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "loco %s already locked blockgroup %s", LocoId, wLink.getid(data->props));
    return True;
  }

  if( MapOp.size(data->lockmap) == 0 ) {
    iOStrTok tok = StrTokOp.inst( wLink.getdst(data->props), ',' );
    Boolean grouplocked = True;
    TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "loco %s pending to lock blockgroup %s", LocoId, wLink.getid(data->props));

    while( StrTokOp.hasMoreTokens(tok) && grouplocked ) {
      const char* id = StrTokOp.nextToken( tok );
      iIBlockBase gblock = ModelOp.getBlock( model, id );
      if( gblock != NULL ) {
        grouplocked = gblock->lockForGroup( gblock, LocoId );
      }
    };
    StrTokOp.base.del(tok);

    if( !grouplocked ) {
      TraceOp.trc( name, TRCLEVEL_USER1, __LINE__, 9999,
          "unable to lock blockgroup %s for loco %s", wLink.getid(data->props), LocoId);
      __rewind(inst, LocoId);
      data->firstBlock = NULL;
      data->firstLoco  = NULL;
    }
    else {
      /* check the conditions... */
      Boolean condOK = True;
      iONode cond = wLink.getlinkcond(data->props);
      while( cond != NULL && condOK ) {
        TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "checking blockgroup %s condition first=%s...",
            wLink.getid(data->props), wLinkCond.getfirst(cond) );
        if( StrOp.equals( wLinkCond.getfirst(cond), BlockId )) {
          Boolean freeBlock = False;
          int restlen = 0;
          iOStrTok tok = StrTokOp.inst(wLinkCond.getfree(cond), ',');
          while( StrTokOp.hasMoreTokens(tok) ) {
            const char* id = StrTokOp.nextToken( tok );
            iIBlockBase block = ModelOp.getBlock( model, id );
            if( block != NULL && block->isFree(block, LocoId) ) {
              iOLoc loc = ModelOp.getLoc( model, LocoId, NULL, False );
              block_suits  suits = block->isSuited( block, loc, &restlen, !selectShortest );
              if( suits != suits_not ) {
                freeBlock = True;
                break;
              }
            }
          };
          StrTokOp.base.del(tok);
          if( freeBlock ) {
            break;
          }
          else {
            TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999,
                "loco %s cannot lock blockgroup %s with block %s because there is no block free. [%s]",
                LocoId, wLink.getid(data->props), BlockId, wLinkCond.getfree(cond));
            condOK = False;
            grouplocked = False;
            data->firstBlock = NULL;
            data->firstLoco  = NULL;
            __rewind(inst, LocoId);
          }
        }
        cond = wLink.nextlinkcond(data->props, cond);
      }
      if( condOK ) {
        TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "loco %s locked blockgroup %s with block %s",
            LocoId, wLink.getid(data->props), BlockId);
        data->firstBlock = BlockId;
        data->firstLoco  = LocoId;
      }
    }

    if( grouplocked && !MapOp.haskey(data->lockmap, LocoId) ) {
      MapOp.put( data->lockmap, LocoId, (obj)LocoId);
    }

    return grouplocked;
  }
  else if( MapOp.size(data->lockmap) > 0 && data->allowfollowup && data->firstBlock != NULL ) {
    if( StrOp.equals( BlockId, data->firstBlock) && MapOp.get(data->lockmap, LocoId) == NULL && !data->followupend ) {
      MapOp.put( data->lockmap, LocoId, (obj)LocoId);
      TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999,
          "loco %s locked blockgroup %s for followup starting in block %s",
          LocoId, wLink.getid(data->props), BlockId);
      if( data->maxfollowup > 0 && data->maxfollowup >= MapOp.size( data->lockmap ) ) {
        data->followupend = True;
      }
      return True;
    }
    else if( MapOp.get(data->lockmap, LocoId) == NULL ) {
      TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999,
          "loco %s not allowed to followup in blockgroup %s starting in block %s (max=%d/%d)",
          LocoId, wLink.getid(data->props), BlockId, MapOp.size( data->lockmap ), data->maxfollowup );
    }

  }
  else {
    TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999,
        "loco %s cannot lock(%d) blockgroup %s for block %s, starting block is %s, followup is %s",
        LocoId, MapOp.size(data->lockmap), wLink.getid(data->props), BlockId,
        data->firstBlock!=NULL?data->firstBlock:"-", data->allowfollowup?"allowed":"not allowed");
  }

  return False;
}