Beispiel #1
0
int Range::_parseSpec(RangeList *seq) {
    // Parse the top level TERM [; TERM] syntax

    // Have we seen a real preceding separator? 1=yes, -1=no, 0=maybe
    int seensep = 1, rc;

    DBGFPRINTF((stderr, "_parseSpec: at '%s'\n", pos));

    do {
	// Read first term
	if ( (rc = _parseTerm(seq)) <= 0) {
	    DBGFPRINTF((stderr, "_parseSpec:%s @ '%s'\n", errmsg, pos));
	    return rc;
	}
	seq = FindLastRangeList(seq);
	// If next chr is valid seq separator, try again
	char c = *pos;
	seensep = -1;
	if (c != '\0' && strchr(space, c)) {
	    pos += strspn(pos, space);
	    c = *pos;
	}
	if (c != '\0' && strchr(semis, c)) {
	    seensep = 1;
	    ++pos;
	    c = *pos;
	}
    } while (seensep != -1);
    DBGFPRINTF((stderr, "_parseSpec:OK @ '%s'\n", pos));
    return 1;
}
Beispiel #2
0
int Range::_parseTerm(RangeList *seq) {
    // Parse the full SEQUENCE [/SEQUENCE] syntax
    RangeList positive = NULL, negative = NULL;
    int rc;

    DBGFPRINTF((stderr, "_parseTerm: at '%s'\n", pos));

    // Skip leading WS
    pos += strspn(pos, space);
    
    // Read first sequence
    if ( (rc = _parseSequence(&positive)) <= 0) {
	DBGFPRINTF((stderr, "_parseTerm:%s @ '%s'\n", errmsg, pos));
	return rc;
    }
    // Maybe a slash now?
    pos += strspn(pos, space);
    char c = *pos;
    if (c != '\0' && strchr(slashes, c)) {
	++pos;
	// Read negative range
	if ( (rc = _parseSequence(&negative)) <= 0) {
	    DBGFPRINTF((stderr, "_parseTerm:%s @ '%s'\n", errmsg, pos));
	    return rc;
	}
    }
    // Combine positive and negative sequences
    SubtractSeqs(&positive, negative);
    *seq = positive;
    FreeRangeList(negative);
    DBGFPRINTF((stderr, "_parseTerm:OK @ '%s'\n", pos));
    return 1;
}
Beispiel #3
0
int Range::_parseNumber(int *pval) {
    // Grab the next number from the string
    // ignore leading WS
    int fromEnd = 0;
    int scale = 1;
    int val = 0;
    int len = 0;

    DBGFPRINTF((stderr, "_parseNumber: at '%s'\n", pos));

    pos += strspn(pos, space);
    char c = *pos;
    if (c == '^') {
	fromEnd = 1;
	++pos;
	c = *pos;
    }
    if (c == '-') {
	scale = -1;
	++pos;
	c = *pos;
    }
    if (c == '\0') {
	errmsg = "expecting number, hit EOS";
	DBGFPRINTF((stderr, "_parseNumber:%s @ '%s'\n", errmsg, pos));
	return 0;
    }
    while (c >= '0' && c <= '9') {
	val = 10*val + (c - '0');
	++len;
	++pos;
	c = *pos;
    }
    if (len == 0) {
	errmsg = "number not found";
	DBGFPRINTF((stderr, "_parseNumber:%s @ '%s'\n", errmsg, pos));
	return 0;
    }
    val = scale * val;
    if (fromEnd) {
	if (max_val == RNG_VAL_BAD) {
	    errmsg = "max_val not specified for ^ syntax";
	    DBGFPRINTF((stderr, "_parseNumber:%s @ '%s'\n", errmsg, pos));
	    return -1;
	}
	val = max_val - 1 - val;
    }
    DBGFPRINTF((stderr, "got number %d\n", val));
    *pval = val;
    return 1;
}
Beispiel #4
0
int Range::_parseSequence(RangeList *seq) {
    // Read a sequence of matlab-ranges, return as a linked list of new
    // RangeNodes
    int start, end, step, rc;

    DBGFPRINTF((stderr, "_parseSeq: at '%s'\n", pos));

    // Have we seen a real preceding separator? 1=yes, -1=no, 0=maybe
    int seensep = 0;

    // Skip leading WS
    pos += strspn(pos, space);
    
    do {
	if ( (rc=_parseRange(&start, &step, &end)) < 0) {
	    return rc;
	} else if (rc == 1) {
	    // Found one, add it to the list
	    *seq = new RangeNode(*seq, start, end, step);
	    seq = &((*seq)->next);
	    // OK for another sequence to follow without extra sep
	    seensep = 0;
	} else if (seensep == 1) {
	    errmsg = "sequence separator not followed by sequence";
	    DBGFPRINTF((stderr, "_parseSeq:%s @ '%s'\n", errmsg, pos));
	    return -1;
	} else {
	    // No range seen, so don't expect another
	    seensep = -1;
	}
	// If next chr is valid seq separator, try again
	char c = *pos;
	if (c != '\0' && strchr(space, c)) {
	    seensep = 0;
	    pos += strspn(pos, space);
	    c = *pos;
	}
	if (c != '\0' && strchr(commas, c)) {
	    seensep = 1;
	    ++pos;
	    c = *pos;
	}
	DBGFPRINTF((stderr, "seqLoop: seensep=%d @ '%s'\n", seensep, pos));
    } while (seensep != -1);

    return 1;
}
Beispiel #5
0
int Range::_parseRange(int *pstart, int *pstep, int *pend) {
    // Accept either a special-case token or a Matlab range
    // Special-case tokens
    int rc;
    int start, step, end;

    DBGFPRINTF((stderr, "_parseRange: at '%s'\n", pos));

    // Skip leading WS
    pos += strspn(pos, space);
    
    int slen = strspn(pos, alpha);
    if (slen == 3 && strncmp(pos, "all", slen) == 0) {
	if (min_val == RNG_VAL_BAD) {
	    errmsg = "min_val not specified for sequence \"all\"";
	    DBGFPRINTF((stderr, "_parseRange:%s @ '%s'\n", errmsg, pos));
	    return -1;
	}
	start = min_val;
	if (max_val == RNG_VAL_BAD) {
	    errmsg = "max_val not specified for sequence \"all\"";
	    DBGFPRINTF((stderr, "_parseRange:%s @ '%s'\n", errmsg, pos));
	    return -1;
	}
	end = max_val - 1;
	step = 1;
	pos += slen;
    } else if ( (slen == 3 && strncmp(pos, "nil", slen) == 0) \
		|| (slen == 4 && strncmp(pos, "none", slen) == 0)) {
	// Construct the sequence empty but consume the token
	start = 0; step = 1; end = -1;
	pos += slen;
    } else {
	// None of the ascii tokens - let it be Matlab ranges
	if ( (rc=_parseMatlabRange(&start, &step, &end)) <= 0) {
	    return rc;
	}
    }
    *pstart = start;
    *pstep = step;
    *pend = end;
    return 1;
}
Beispiel #6
0
int cleExtractArgs(CLE_ENTRY *entries, int* pargc, char *argv[], 
		   int noExtraArgs)
{  /* parse a set of command line arguments according to a structure.
      If noExtraArgs is not set, allow for a variable number of arguments 
      that we don't parse; return modified argc and argv pointing to the 
      residue. Return value is number of actual error objected to. */
    int i, j, errs = 0, anerr, rc, argUsed, tokDone, flaglen, toklen, minlen;
    int blankIndex = 0;     /* use each blank index just once */
    int blankCount;
    char *next, *arg, *tok;
    char tokbuf[CLE_STRLEN];
    char flag[CLE_STRLEN];
    CLE_ENTRY *ent;
    int outargc = 1;
    int argc = *pargc;
    char *pat;
    const char *state;
    int tokcontinued = 0;	/* flag that reparsing remainder */
    const char *programName = argv[0];

    /* first, set all defaults - we can overwrite them later */
    /* cleSetDefaults(entries); */  /* no, let program do this if it wants */
    i = 0;
    while(i + 1 - tokcontinued<argc)  {
	if (!tokcontinued) 
	    tok = argv[++i];	/* grab the next arg; preincrement
				   ensures we skip argv[0] */
	next = (i+1<argc)?argv[i+1]:NULL;
	ent = entries; 
	blankCount = 0;	argUsed = 0; tokDone = 0; anerr = 0; tokcontinued = 0;
	DBGFPRINTF((stderr, "cle(%d): testing '%s' (then '%s')\n", \
		    i, tok, next?next:"(NULL)"));
	while(!tokDone && ent->type != CLE_T_END)  {
	    state = NULL;
	    while(!tokDone && ent->type != CLE_T_USAGE && \
		  (minlen = cleNextPattern(ent->flag, flag, &state)) > -1) {
		toklen = strlen(tok);
		flaglen = strlen(flag);
		DBGFPRINTF((stderr, "cle: trying '%s' ('%s', %d)\n", \
			    tok,flag,minlen));
		if(flaglen == 0)
		    ++blankCount;    /* keep track of which blank field */
		if( /* Allow empty flags (untagged args) to match any (new) 
		       string, but not if they start with '-' unless they 
		       are exactly "-" */
		    ( flaglen == 0 \
		      && blankCount > blankIndex \
		      && ( tok[0] != '-' || tok[1] == '\0' ) ) \
		    /* Match all the tok, at least up to minlen of the flag */
		    || ((toklen >= minlen) \
			&& (strncmp(tok, flag, toklen) == 0)) \
		    /* special case: 2-chr flags only need match first bit */
		    || ( flaglen == 2 \
			 && flag[0] == '-' \
			 && ( tok[0] == '-' && tok[1] == flag[1]) ) ) {

		    /*** We matched a flag pattern ***/
		    tokDone = 1;

		    if(flaglen == 0) {		    
			++blankIndex;   /* mark this blank field as used */
			arg = tok;	/* for blank flds, tok is arg */
		    } else if(flag[0]=='-' && flaglen==2 
			      && strlen(tok)>flaglen) {
			/* simple "-X" flag was matched as prefix:
			   separate out the remainder as an arg, 
			   or the next tok. */
			arg = tok+flaglen;
		    } else {
			arg = next;
		    }
		    switch(ent->type)  {
		    case CLE_T_INT:
		    { int x; anerr = (arg==NULL) || (sscanf(arg, "%d", &x) != 1); 
		      if (!anerr) *(int *)(ent->where) = x; }   
		    argUsed = 1; break;
		    case CLE_T_LONG:
		    { long l; anerr = (arg==NULL) || (sscanf(arg, "%ld", &l) != 1); 
		      if(!anerr) *(int *)(ent->where) = l; }
		    argUsed = 1; break;
		    case CLE_T_FLOAT:
		    { float f; anerr = (arg==NULL) || (sscanf(arg, "%f", &f) != 1); 
		      if(!anerr) *(float *)(ent->where) = f; }
		    argUsed = 1; break;
		    case CLE_T_TIME:
		    { float f; anerr = (arg==NULL) || (cleScanTime(arg, &f) != 1); 
		      if(!anerr) *(float *)(ent->where) = f; }
		    argUsed = 1; break;
		    case CLE_T_STRING:
			if(arg==NULL) { anerr=1; } else {
			/* free any default value */
			if (*(char **)ent->where)  free(*(char **)ent->where);
			*(char **)(ent->where) = strdup(arg); argUsed = 1; }
			break;
		    case CLE_T_BOOL:
			++(*(int *)(ent->where)); break;
		    case CLE_T_INVBOOL:
			--(*(int *)(ent->where)); break;
		    case CLE_T_TOKEN:
			rc = cleTokenSetFn(arg,ent->where, tok, ent->specData);
			if(rc == 1) argUsed = 1; else if(rc != 0) anerr = 1;
			break;
		    case CLE_T_SPECIAL:
			rc = (*(ent->specialfn))(arg, ent->where, tok,
						 ent->specData);
			if(rc == 1) argUsed = 1; else if(rc != 0) anerr = 1;
			break;
		    default:
			fprintf(stderr, "cleExtractArgs: unknown CLE_TYPE %d\n", ent->type);
			abort;
		    }
		    if(anerr)  {
			fprintf(stderr, 
			  "%s: error reading '%s'(%s) as %s(%s)\n",
			  programName, tok, (arg==NULL)?"NULL":arg, ent->flag, ent->usage);
			++errs;
		    }
		    DBGFPRINTF((stderr, \
				"cle(%d): matched %s %s as %s %s (%s %s)\n", \
				i, tok, next?next:"(NULL)", flag, \
				argUsed?arg:"", ent->flag, ent->usage));
		}
	    }
	    ++ent;
	}
	if(!tokDone)  {	/* this token was not recognized at all */
	    float dummy;
	    if(noExtraArgs \
	       || (tok[0] == '-' && strlen(tok) > 1 \
		   && sscanf(tok, "%f", &dummy) == 0) ) {
		/* report an error if we don't expect any unrecognized 
		   args - or even if we do, but the tok is of "-foo" form, 
		   *unless* it's a valid number (e.g. -123) */
		fprintf(stderr, "%s: '%s' not recognized\n", programName, tok);
		++errs;
	    } else {
		/* just copy the missed tok to output */
		argv[outargc] = tok;
		++outargc;
	    }
	} else if(!argUsed) {
	    /* we recognized a token but it didn't use the arg - 
	       any arg is thus a candidate for the next token */
	    if(arg != next) {
		/* arg was not just the next token - so set it as a cont'n */
		/* fakely prepend the '-' (or ...) */
		tokbuf[0] = flag[0];
		strcpy(tokbuf+1, arg);
		/* flag looptop not read next arg */
		tokcontinued = 1;
		tok = tokbuf;
	    }
	} else {
	    /* tok used the arg.  If it was the next tok, skip it */
	    if(arg == next) {
		++i;
	    }
	}
    }
    *pargc = outargc;

/*  if(errs)
	cleUsage(entries, argv[0]);
 */
    return errs;
}
Beispiel #7
0
int Range::_parseMatlabRange(int *pstart, int *pstep, int *pend) {
    // Parse a matlab-style [start][:step][:[end]] string, 
    // which includes 1  1:5  1:2:10  :4  and :
    // Missing numbers take defaults from min_val and max_val
    int start = 0 , end = 0, step = 0, rc;

    DBGFPRINTF((stderr, "_parseRange: at '%s'\n", pos));

    // Either the first character is a colon, or it's a number
    // .. but skip leading WS
    pos += strspn(pos, space);
    char c = *pos;
    if (c == '\0') {
	errmsg = "expecting Matlab range, hit EOS";
	DBGFPRINTF((stderr, "_parseRange:%s @ '%s'\n", errmsg, pos));
	return 0;
    }
    // Try to get first number, OK to fail
    if ( (rc=_parseNumber(&start)) < 0) {
	// fatal error in number
	return rc;
    } else if (rc == 0) {
	// Next chr *must* be colon
	c = *pos;
	if (c == '\0' || strchr(colons, c) == NULL) {
	    errmsg = "Matlab range does not start with colon or number";
	    DBGFPRINTF((stderr, "_parseRange:%s @ '%s'\n", errmsg, pos));
	    return 0;
	}
	// It was a colon, but don't move over it, so we see it again blw
	//++pos;
	// default the first val
	if (min_val == RNG_VAL_BAD) {
	    errmsg = "min_val not specified for default range";
	    DBGFPRINTF((stderr, "_parseRange:%s @ '%s'\n", errmsg, pos));
	    return -1;
	}
	start = min_val;
    }
    // Parse up to two subseqent ":number" terms
    int i;
    int read_end = 0;
    end = start;
    for (i = 0; i < 2; ++i) {
	// Skip ws
	pos += strspn(pos, space);
	// Do we have a colon?
	c = *pos;
	if (c != '\0' && strchr(colons, c)) {
	    // We have a colon.  If this is the second pass, push the 
	    // first pass to the step
	    if (i > 0) {
		if (read_end == 0) {
		    // I think this means "::" found - just ignore
		    fprintf(stderr, "defaulted step (:: found?)\n");
		} else {
		    step = end;
		}
	    }
	    // Step over colon
	    ++pos;
	    // Either grab a number, or it defaults
	    if ( (rc=_parseNumber(&end)) < 0) {
		return rc;
	    } else if (rc == 0) {
		// Didn't find a number, so take default end
		if (max_val == RNG_VAL_BAD) {
		    errmsg = "max_val not specified for default range";
		    DBGFPRINTF((stderr, "_parseRange:%s @ '%s'\n", errmsg, pos));
		    return -1;
		}
		end = max_val - 1;
	    } else {
		read_end = 1;
	    }
	}
    }
    // Maybe choose appropriate default step
    if (step == 0) {
	if (end < start)	step = -1;
	else			step = 1;
    }
    // Should now have it all
    *pstart = start;
    *pend = end;
    *pstep = step;
    DBGFPRINTF((stderr, "got mat range %d:%d:%d @ '%s'\n", start, step, end, pos));
    return 1;
}