Example #1
0
/* used here and in subset.c and subassign.c */
R_xlen_t attribute_hidden
get1index(SEXP s, SEXP names, R_xlen_t len, int pok, int pos, SEXP call)
{
/* Get a single index for the [[ and [[<- operators.
   Checks that only one index is being selected.
   Returns -1 for no match.

   s is the subscript
   len is the length of the object or dimension, with names its (dim)names.
   pos is len-1 or -1 for [[, -1 for [[<-
     -1 means use the only element of length-1 s.
   pok : is "partial ok" ?
	 if pok is -1, warn if partial matching occurs, but allow.
*/
    int  warn_pok = 0;
    const char *ss, *cur_name;
    R_xlen_t indx;
    const void *vmax;

    if (pok == -1) {
	pok = 1;
	warn_pok = 1;
    }

    if (pos < 0 && length(s) != 1) {
	if (length(s) > 1) {
	    ECALL(call, _("attempt to select more than one element"));
	} else {
	    ECALL(call, _("attempt to select less than one element"));
	}
    } else
	if(pos >= length(s)) {
	    ECALL(call, _("internal error in use of recursive indexing"));
	}
    if(pos < 0) pos = 0;
    indx = -1;
    switch (TYPEOF(s)) {
    case LGLSXP:
    case INTSXP:
    {
	int i = INTEGER(s)[pos];
	if (i != NA_INTEGER)
	    indx = integerOneIndex(i, len, call);
	break;
    }
    case REALSXP:
    {
	double dblind = REAL(s)[pos];
	if(!ISNAN(dblind)) {
	    /* see comment above integerOneIndex */
	    if (dblind > 0) indx = (R_xlen_t)(dblind - 1);
	    else if (dblind == 0 || len < 2) {
		ECALL(call, _("attempt to select less than one element"));
	    } else if (len == 2 && dblind > -3)
		indx = (R_xlen_t)(2 + dblind);
	    else {
		ECALL(call, _("attempt to select more than one element"));
	    }
	}
	break;
    }
    case STRSXP:
	/* NA matches nothing */
	if(STRING_ELT(s, pos) == NA_STRING) break;
	/* "" matches nothing: see names.Rd */
	if(!CHAR(STRING_ELT(s, pos))[0]) break;

	/* Try for exact match */
	vmax = vmaxget();
	ss = translateChar(STRING_ELT(s, pos));
	for (R_xlen_t i = 0; i < xlength(names); i++)
	    if (STRING_ELT(names, i) != NA_STRING) {
		if (streql(translateChar(STRING_ELT(names, i)), ss)) {
		    indx = i;
		    break;
		}
	    }
	/* Try for partial match */
	if (pok && indx < 0) {
	    size_t len = strlen(ss);
	    for(R_xlen_t i = 0; i < xlength(names); i++) {
		if (STRING_ELT(names, i) != NA_STRING) {
		    cur_name = translateChar(STRING_ELT(names, i));
		    if(!strncmp(cur_name, ss, len)) {
			if(indx == -1) {/* first one */
			    indx = i;
			    if (warn_pok) {
				if (call == R_NilValue)
				    warning(_("partial match of '%s' to '%s'"),
					    ss, cur_name);
				else
				    warningcall(call,
						_("partial match of '%s' to '%s'"),
						ss, cur_name);
			    }
			}
			else {
			    indx = -2;/* more than one partial match */
			    if (warn_pok) /* already given context */
				warningcall(R_NilValue,
					    _("further partial match of '%s' to '%s'"),
					    ss, cur_name);
			    break;
			}
		    }
		}
	    }
	}
	vmaxset(vmax);
	break;
    case SYMSXP:
	vmax = vmaxget();
	for (R_xlen_t i = 0; i < xlength(names); i++)
	    if (STRING_ELT(names, i) != NA_STRING &&
		streql(translateChar(STRING_ELT(names, i)),
		       CHAR(PRINTNAME(s)))) {
		indx = i;
		vmaxset(vmax);
		break;
	    }
    default:
	if (call == R_NilValue)
	    error(_("invalid subscript type '%s'"), type2char(TYPEOF(s)));
	else
	    errorcall(call, _("invalid subscript type '%s'"),
		      type2char(TYPEOF(s)));
    }
    return indx;
}
Example #2
0
/* Utility used (only in) do_subassign2_dflt(), i.e. "[[<-" in ./subassign.c : */
R_xlen_t attribute_hidden
OneIndex(SEXP x, SEXP s, R_xlen_t len, int partial, SEXP *newname,
	 int pos, SEXP call)
{
    SEXP names;
    R_xlen_t i, indx, nx;
    const void *vmax;

    if (pos < 0 && length(s) > 1) {
	ECALL(call, _("attempt to select more than one element"));
    }
    if (pos < 0 && length(s) < 1) {
	ECALL(call, _("attempt to select less than one element"));
    }

    if(pos < 0) pos = 0;

    indx = -1;
    *newname = R_NilValue;
    switch(TYPEOF(s)) {
    case LGLSXP:
    case INTSXP:
	indx = integerOneIndex(INTEGER(s)[pos], len, call);
	break;
    case REALSXP:
	indx = integerOneIndex((int)REAL(s)[pos], len, call);
	break;
    case STRSXP:
	vmax = vmaxget();
	nx = xlength(x);
	names = PROTECT(getAttrib(x, R_NamesSymbol));
	if (names != R_NilValue) {
	    /* Try for exact match */
	    for (i = 0; i < nx; i++) {
		const char *tmp = translateChar(STRING_ELT(names, i));
		if (!tmp[0]) continue;
		if (streql(tmp, translateChar(STRING_ELT(s, pos)))) {
		    indx = i;
		    break;
		}
	    }
	    /* Try for partial match */
	    if (partial && indx < 0) {
		size_t l = strlen(translateChar(STRING_ELT(s, pos)));
		for(i = 0; i < nx; i++) {
		    const char *tmp = translateChar(STRING_ELT(names, i));
		    if (!tmp[0]) continue;
		    if(!strncmp(tmp, translateChar(STRING_ELT(s, pos)), l)) {
			if(indx == -1 )
			    indx = i;
			else
			    indx = -2;
		    }
		}
	    }
	}
	UNPROTECT(1); /* names */
	if (indx == -1)
	    indx = nx;
	*newname = STRING_ELT(s, pos);
	vmaxset(vmax);
	break;
    case SYMSXP:
	vmax = vmaxget();
	nx = xlength(x);
	names = getAttrib(x, R_NamesSymbol);
	if (names != R_NilValue) {
	    PROTECT(names);
	    for (i = 0; i < nx; i++)
		if (streql(translateChar(STRING_ELT(names, i)),
			   translateChar(PRINTNAME(s)))) {
		    indx = i;
		    break;
		}
	    UNPROTECT(1); /* names */
	}
	if (indx == -1)
	    indx = nx;
	*newname = STRING_ELT(s, pos);
	vmaxset(vmax);
	break;
    default:
	if (call == R_NilValue)
	    error(_("invalid subscript type '%s'"), type2char(TYPEOF(s)));
	else
	    errorcall(call, _("invalid subscript type '%s'"),
		      type2char(TYPEOF(s)));
    }
    return indx;
}
Example #3
0
/* iconv(x, from, to, sub, mark) */
SEXP attribute_hidden do_iconv(SEXP call, SEXP op, SEXP args, SEXP env)
{
    SEXP ans, x = CAR(args), si;
    void * obj;
    const char *inbuf;
    char *outbuf;
    const char *sub;
    size_t inb, outb, res;
    R_StringBuffer cbuff = {NULL, 0, MAXELTSIZE};
    Rboolean isRawlist = FALSE;

    checkArity(op, args);
    if(isNull(x)) {  /* list locales */
#ifdef HAVE_ICONVLIST
	cnt = 0;
	iconvlist(count_one, NULL);
	PROTECT(ans = allocVector(STRSXP, cnt));
	cnt = 0;
	iconvlist(write_one, (void *)ans);
#else
	PROTECT(ans = R_NilValue);
#endif
    } else {
	int mark, toRaw;
	const char *from, *to;
	Rboolean isLatin1 = FALSE, isUTF8 = FALSE;

	args = CDR(args);
	if(!isString(CAR(args)) || length(CAR(args)) != 1)
	    error(_("invalid '%s' argument"), "from");
	from = CHAR(STRING_ELT(CAR(args), 0)); /* ASCII */
	args = CDR(args);
	if(!isString(CAR(args)) || length(CAR(args)) != 1)
	    error(_("invalid '%s' argument"), "to");
	to = CHAR(STRING_ELT(CAR(args), 0));
	args = CDR(args);
	if(!isString(CAR(args)) || length(CAR(args)) != 1)
	    error(_("invalid '%s' argument"), "sub");
	if(STRING_ELT(CAR(args), 0) == NA_STRING) sub = NULL;
	else sub = translateChar(STRING_ELT(CAR(args), 0));
	args = CDR(args);
	mark = asLogical(CAR(args));
	if(mark == NA_LOGICAL)
	    error(_("invalid '%s' argument"), "mark");	
	args = CDR(args);
	toRaw = asLogical(CAR(args));
	if(toRaw == NA_LOGICAL)
	    error(_("invalid '%s' argument"), "toRaw");	
	/* some iconv's allow "UTF8", but libiconv does not */
	if(streql(from, "UTF8") || streql(from, "utf8") ) from = "UTF-8";
	if(streql(to, "UTF8") || streql(to, "utf8") ) to = "UTF-8";
	/* Should we do something about marked CHARSXPs in 'from = ""'? */
	if(streql(to, "UTF-8")) isUTF8 = TRUE;
	if(streql(to, "latin1") || streql(to, "ISO_8859-1")
	    || streql(to, "CP1252")) isLatin1 = TRUE;
	if(streql(to, "") && known_to_be_latin1) isLatin1 = TRUE;
	if(streql(to, "") && known_to_be_utf8) isUTF8 = TRUE;
	obj = Riconv_open(to, from);
	if(obj == (iconv_t)(-1))
#ifdef Win32
	    error(_("unsupported conversion from '%s' to '%s' in codepage %d"), 
		  from, to, localeCP);
#else
	    error(_("unsupported conversion from '%s' to '%s'"), from, to);
#endif
	isRawlist = (TYPEOF(x) == VECSXP);
	if(isRawlist) {
	    if(toRaw)
		PROTECT(ans = duplicate(x));
	    else {
		PROTECT(ans = allocVector(STRSXP, LENGTH(x)));
		DUPLICATE_ATTRIB(ans, x);
	    }
	} else {   
	    if(TYPEOF(x) != STRSXP)
		error(_("'x' must be a character vector"));
	    if(toRaw) {
		PROTECT(ans = allocVector(VECSXP, LENGTH(x)));
		DUPLICATE_ATTRIB(ans, x);
	    } else 
		PROTECT(ans = duplicate(x));
	}
	R_AllocStringBuffer(0, &cbuff);  /* 0 -> default */
	for(R_xlen_t i = 0; i < XLENGTH(x); i++) {
	    if (isRawlist) {
		si = VECTOR_ELT(x, i);
		if (TYPEOF(si) == NILSXP) {
		    if (!toRaw) SET_STRING_ELT(ans, i, NA_STRING);
		    continue;
		} else if (TYPEOF(si) != RAWSXP)
		    error(_("'x' must be a list of NULL or raw vectors"));
	    } else {
		si = STRING_ELT(x, i);
		if (si == NA_STRING) {
		    if(!toRaw) SET_STRING_ELT(ans, i, NA_STRING);
		    continue;
		}
	    }
	top_of_loop:
	    inbuf = isRawlist ? (const char *) RAW(si) : CHAR(si); 
	    inb = LENGTH(si);
	    outbuf = cbuff.data; outb = cbuff.bufsize - 1;
	    /* First initialize output */
	    Riconv (obj, NULL, NULL, &outbuf, &outb);
	next_char:
	    /* Then convert input  */
	    res = Riconv(obj, &inbuf , &inb, &outbuf, &outb);
	    *outbuf = '\0';
	    /* other possible error conditions are incomplete
	       and invalid multibyte chars */
	    if(res == -1 && errno == E2BIG) {
		R_AllocStringBuffer(2*cbuff.bufsize, &cbuff);
		goto top_of_loop;
	    } else if(res == -1 && sub && 
		      (errno == EILSEQ || errno == EINVAL)) {
		/* it seems this gets thrown for non-convertible input too */
		if(strcmp(sub, "byte") == 0) {
		    if(outb < 5) {
			R_AllocStringBuffer(2*cbuff.bufsize, &cbuff);
			goto top_of_loop;
		    }
		    snprintf(outbuf, 5, "<%02x>", (unsigned char)*inbuf);
		    outbuf += 4; outb -= 4;
		} else {
		    size_t j;
		    if(outb < strlen(sub)) {
			R_AllocStringBuffer(2*cbuff.bufsize, &cbuff);
			goto top_of_loop;
		    }
		    memcpy(outbuf, sub, j = strlen(sub));
		    outbuf += j;
		    outb -= j;
		}
		inbuf++; inb--;
		goto next_char;
	    }

	    if(toRaw) {
		if(res != -1 && inb == 0) {
		    size_t nout = cbuff.bufsize - 1 - outb;
		    SEXP el = allocVector(RAWSXP, nout);
		    memcpy(RAW(el), cbuff.data, nout);
		    SET_VECTOR_ELT(ans, i, el);
		} /* otherwise is already NULL */
	    } else {
		if(res != -1 && inb == 0) {
		    cetype_t ienc = CE_NATIVE;
		    
		    size_t nout = cbuff.bufsize - 1 - outb;
		    if(mark) {
			if(isLatin1) ienc = CE_LATIN1;
			else if(isUTF8) ienc = CE_UTF8;
		    }
		    SET_STRING_ELT(ans, i, 
				   mkCharLenCE(cbuff.data, (int) nout, ienc));
		} else SET_STRING_ELT(ans, i, NA_STRING);
	    }
	}
	Riconv_close(obj);
	R_FreeStringBuffer(&cbuff);
    }
    UNPROTECT(1);
    return ans;
}
Example #4
0
/* "do_parse" - the user interface input/output to files.

 The internal R_Parse.. functions are defined in ./gram.y (-> gram.c)

 .Internal( parse(file, n, text, prompt, srcfile, encoding) )
 If there is text then that is read and the other arguments are ignored.
*/
SEXP attribute_hidden do_parse(SEXP call, SEXP op, SEXP args, SEXP env)
{
    SEXP text, prompt, s, source;
    Rconnection con;
    Rboolean wasopen, old_latin1 = known_to_be_latin1,
	old_utf8 = known_to_be_utf8, allKnown = TRUE;
    int ifile, num, i;
    const char *encoding;
    ParseStatus status;

    checkArity(op, args);
    R_ParseError = 0;
    R_ParseErrorMsg[0] = '\0';

    ifile = asInteger(CAR(args));                       args = CDR(args);

    con = getConnection(ifile);
    wasopen = con->isopen;
    num = asInteger(CAR(args));				args = CDR(args);
    if (num == 0)
	return(allocVector(EXPRSXP, 0));

    PROTECT(text = coerceVector(CAR(args), STRSXP));
    if(length(CAR(args)) && !length(text))
	errorcall(call, _("coercion of 'text' to character was unsuccessful"));
    args = CDR(args);
    prompt = CAR(args);					args = CDR(args);
    source = CAR(args);					args = CDR(args);
    if(!isString(CAR(args)) || LENGTH(CAR(args)) != 1)
	error(_("invalid '%s' value"), "encoding");
    encoding = CHAR(STRING_ELT(CAR(args), 0)); /* ASCII */
    known_to_be_latin1 = known_to_be_utf8 = FALSE;
    /* allow 'encoding' to override declaration on 'text'. */
    if(streql(encoding, "latin1")) {
	known_to_be_latin1 = TRUE;
	allKnown = FALSE;
    } else if(streql(encoding, "UTF-8"))  {
	known_to_be_utf8 = TRUE;
	allKnown = FALSE;
    } else if(!streql(encoding, "unknown") && !streql(encoding, "native.enc")) 
    	warning(_("argument '%s = \"%s\"' will be ignored"), "encoding", encoding);

    if (prompt == R_NilValue)
	PROTECT(prompt);
    else
	PROTECT(prompt = coerceVector(prompt, STRSXP));

    if (length(text) > 0) {
	/* If 'text' has known encoding then we can be sure it will be
	   correctly re-encoded to the current encoding by
	   translateChar in the parser and so could mark the result in
	   a Latin-1 or UTF-8 locale.

	   A small complication is that different elements could have
	   different encodings, but all that matters is that all
	   non-ASCII elements have known encoding.
	*/
	for(i = 0; i < length(text); i++)
	    if(!ENC_KNOWN(STRING_ELT(text, i)) &&
	       !IS_ASCII(STRING_ELT(text, i))) {
		allKnown = FALSE;
		break;
	    }
	if(allKnown) {
	    known_to_be_latin1 = old_latin1;
	    known_to_be_utf8 = old_utf8;
	}
	if (num == NA_INTEGER) num = -1;
	s = R_ParseVector(text, num, &status, source);
	if (status != PARSE_OK) parseError(call, R_ParseError);
    }
    else if (ifile >= 3) {/* file != "" */
	if (num == NA_INTEGER) num = -1;
	try {
	    if(!wasopen && !con->open(con))
		error(_("cannot open the connection"));
	    if(!con->canread) error(_("cannot read from this connection"));
	    s = R_ParseConn(con, num, &status, source);
	    if(!wasopen) con->close(con);
	} catch (...) {
	    if (!wasopen && con->isopen)
		con->close(con);
	    throw;
	}
	if (status != PARSE_OK) parseError(call, R_ParseError);
    }
    else {
	if (num == NA_INTEGER) num = 1;
	s = R_ParseBuffer(&R_ConsoleIob, num, &status, prompt, source);
	if (status != PARSE_OK) parseError(call, R_ParseError);
    }
    UNPROTECT(2);
    known_to_be_latin1 = old_latin1;
    known_to_be_utf8 = old_utf8;
    return s;
}
Example #5
0
void test(string args)
{
    args = splitArg(args, 1);
    if(streql(args, "") || streql(args, "-H"))
    {
        print("\nThis file is in charge of testing the data types embedded in Q-OS.",black);
        print("\nAccepted Arguments:\n-list\tTests the list.c file\n-set \ttests the set.c file", black);
        print("\n-strb\ttests the strbuilder.c file\n-y   \tshould return the current year...",black);
    }
    else if(streql(args, "-LIST"))//For testing lists
    {
        newline();
        list_t test_list = list_init();
        test_list.autoShrink = true;

        for(uint8 i = 0; i < 4; i++)
        {
            list_add(&test_list, "1");
            list_add(&test_list, "2");
            list_add(&test_list, "3");
            list_add(&test_list, "4");
            list_add(&test_list, "5");
            list_add(&test_list, "6");
            list_add(&test_list, "7");
            list_add(&test_list, "8");
            list_add(&test_list, "9");
            list_add(&test_list, "10");
            list_add(&test_list, "11");
            list_add(&test_list, "12");
            list_add(&test_list, "13");
            list_add(&test_list, "14");
            list_add(&test_list, "15");
            list_add(&test_list, "16");
        }
        list_add(&test_list, "Pointless");

        println("Done sizing up", white);
        printint(test_list.capt, white);

        element_t t;
        for(uint8 i = 0; i < 64; i++)
        {
            t = list_shift(&test_list);
        }
        println("\nLast item deleted should be \"16\"", white);
        println(t.udata.strdata, white);
        println("\nDeleting all but element \"Pointless\"", white);
        for(uint8 i = 0; i < test_list.size; i++)
        {
            println(list_get(test_list, i), white);
        }
        println("Done resizing up", white);
        printint(test_list.capt, white);
        list_destroy(&test_list);
    }
    else if(streql(args,"-SET"))
    {
        set_t test_set = set_init();
        for(uint8 i = 0; i < 4; i++)
        {
            set_add(&test_set, "0");
            set_add(&test_set, "1");
            set_add(&test_set, "2");
            set_add(&test_set, "3");
            set_add(&test_set, "4");
            set_add(&test_set, "5");
            set_add(&test_set, "6");
            set_add(&test_set, "7");
            set_add(&test_set, "8");
            set_add(&test_set, "9");
            set_add(&test_set, "10");
            set_add(&test_set, "11");
            set_add(&test_set, "12");
            set_add(&test_set, "13");
            set_add(&test_set, "14");
            set_add(&test_set, "15");
            set_add(&test_set, "16");
            print("\nIteration: ", white);
            printint(i, white);
        }
        println("\n\nInsertion::Output should be 17", white);
        printint(test_set.size, white);

        set_t tmp = set_init();
        set_add(&tmp, "Union item");
        set_union(&test_set, &tmp);
        println("\n\nUnion::Output should be 18", white);
        printint(test_set.size, white);

        set_intersect(&test_set, &tmp);
        println("\n\nIntersect::Output should be 1", white);
        printint(test_set.size, white);

        println("\n\nPreparing for diff test", white);
        set_add(&test_set, "1");
        set_add(&test_set, "2");
        set_add(&test_set, "3");
        set_add(&tmp, "2");
        set_add(&tmp, "3");
        set_add(&tmp, "4");
        set_diff(&test_set, &tmp);
        println("Diff::Output should be 2", white);
        printint(test_set.size, white);

        set_destroy(&tmp);
        set_destroy(&test_set);
    }
    else if(streql(args, "-STRB"))
    {
        static const string bak = "Hello, world ";
        static const uint32 bln = 13;
        strbuilder_t test_strb = strbuilder_init();

        strbuilder_append(&test_strb, bak);
        strbuilder_append(&test_strb, "Hello, 2nd world");
        println("\nTesting backup text. Output should 1", red);
        printint(streql(bak, test_strb.prevTxt), green);
        println("\nOutput should be \"Hello, world Hello, 2nd world\"", red);
        println(strbuilder_tostr(test_strb), green);
        println("\nRemoving greeters from first world", red);
        strbuilder_delete(&test_strb, 0, bln);
        println("\nOutput should be \"Hello, 2nd world\"", red);
        println(strbuilder_tostr(test_strb), green);
        strbuilder_flip(&test_strb);
        println("\nOutput should be \"dlrow dn2 ,olleH\"", red);
        println(strbuilder_tostr(test_strb), green);
        list_t tmp = strbuilder_split(test_strb, " ");
        println("\nOutput should be last str split by spaces", red);
        for(uint8 i = 0; i < tmp.size; i++)
        {
            println(list_get(tmp, i), white);
        }
        list_destroy(&tmp);
        strbuilder_destroy(&test_strb);
    }
    else if(streql(args,"-Y"))
    {
       //getTime() test
       printint(getTime("year"),white);
    }
}
Example #6
0
void
parse_control_point (char          **ss,
                     control_point  *cp)
{
  char *argv[MAXARGS];
  int argc, i, j;
  int set_cm = 0, set_image_size = 0, set_nbatches = 0, set_white_level = 0, set_cmap_inter = 0;
  int set_spatial_oversample = 0;
  double *slot = NULL, xf, cm, t, nbatches, white_level, spatial_oversample, cmap_inter;
  double image_size[2];

  for (i = 0; i < NXFORMS; i++)
    {
      cp->xform[i].density = 0.0;
      cp->xform[i].color = (i == 0);
      cp->xform[i].var[0] = 1.0;
      for (j = 1; j < NVARS; j++)
        cp->xform[i].var[j] = 0.0;
      cp->xform[i].c[0][0] = 1.0;
      cp->xform[i].c[0][1] = 0.0;
      cp->xform[i].c[1][0] = 0.0;
      cp->xform[i].c[1][1] = 1.0;
      cp->xform[i].c[2][0] = 0.0;
      cp->xform[i].c[2][1] = 0.0;
    }
  for (j = 0; j < 2; j++)
    {
      cp->pulse[j][0] = 0.0;
      cp->pulse[j][1] = 60.0;
      cp->wiggle[j][0] = 0.0;
      cp->wiggle[j][1] = 60.0;
    }

  tokenize (ss, argv, &argc);
  for (i = 0; i < argc; i++)
    {
      if (streql("xform", argv[i]))
        slot = &xf;
      else if (streql("time", argv[i]))
        slot = &cp->time;
      else if (streql("brightness", argv[i]))
        slot = &cp->brightness;
      else if (streql("contrast", argv[i]))
        slot = &cp->contrast;
      else if (streql("gamma", argv[i]))
        slot = &cp->gamma;
      else if (streql("zoom", argv[i]))
        slot = &cp->zoom;
      else if (streql("image_size", argv[i]))
        {
          slot = image_size;
          set_image_size = 1;
        }
      else if (streql("center", argv[i]))
        slot = cp->center;
      else if (streql("pulse", argv[i]))
        slot = (double *) cp->pulse;
      else if (streql("wiggle", argv[i]))
        slot = (double *) cp->wiggle;
      else if (streql("pixels_per_unit", argv[i]))
        slot = &cp->pixels_per_unit;
      else if (streql("spatial_filter_radius", argv[i]))
        slot = &cp->spatial_filter_radius;
      else if (streql("sample_density", argv[i]))
        slot = &cp->sample_density;
      else if (streql("nbatches", argv[i]))
        {
          slot = &nbatches;
          set_nbatches = 1;
        }
      else if (streql("white_level", argv[i]))
        {
          slot = &white_level;
          set_white_level = 1;
        }
      else if (streql("spatial_oversample", argv[i]))
        {
          slot = &spatial_oversample;
          set_spatial_oversample = 1;
        }
      else if (streql("cmap", argv[i]))
        {
          slot = &cm;
          set_cm = 1;
        }
      else if (streql("density", argv[i]))
        slot = &cp->xform[(int)xf].density;
      else if (streql("color", argv[i]))
        slot = &cp->xform[(int)xf].color;
      else if (streql("coefs", argv[i]))
        {
          slot = cp->xform[(int)xf].c[0];
          cp->xform[(int)xf].density = 1.0;
        }
      else if (streql("var", argv[i]))
        slot = cp->xform[(int)xf].var;
      else if (streql("cmap_inter", argv[i]))
        {
          slot = &cmap_inter;
          set_cmap_inter = 1;
        }
      else
        *slot++ = g_strtod(argv[i], NULL);
    }
  if (set_cm)
    {
      cp->cmap_index = (int) cm;
      get_cmap(cp->cmap_index, cp->cmap, 256);
    }
  if (set_image_size)
    {
      cp->width  = (int) image_size[0];
      cp->height = (int) image_size[1];
    }
  if (set_cmap_inter)
    cp->cmap_inter  = (int) cmap_inter;
  if (set_nbatches)
    cp->nbatches = (int) nbatches;
  if (set_spatial_oversample)
    cp->spatial_oversample = (int) spatial_oversample;
  if (set_white_level)
    cp->white_level = (int) white_level;
  for (i = 0; i < NXFORMS; i++)
    {
      t = 0.0;
      for (j = 0; j < NVARS; j++)
        t += cp->xform[i].var[j];
      t = 1.0 / t;
      for (j = 0; j < NVARS; j++)
        cp->xform[i].var[j] *= t;
    }
  qsort ((char *) cp->xform, NXFORMS, sizeof(xform), compare_xforms);
}
Example #7
0
int o2_clock_set(o2_time_callback callback, void *data)
{
    if (!o2_ensemble_name) {
        O2_DBk(printf("%s o2_clock_set cannot be called before o2_initialize.\n",
                      o2_debug_prefix));
        return O2_FAIL;
    }
    int was_synchronized = o2_clock_is_synchronized;
    // adjust local_start_time to ensure continuity of time:
    //   new_local_time - new_time_offset == old_local_time - old_time_offset
    //   new_time_offset = new_local_time - (old_local_time - old_time_offset)
    o2_time old_local_time = o2_local_time(); // (includes -old_time_offset)
    time_callback = callback;
    time_callback_data = data;
    time_offset = 0.0; // get the time without any offset
    o2_time new_local_time = o2_local_time();
    time_offset = new_local_time - old_local_time;

    if (!is_master) {
        o2_clock_synchronized(new_local_time, new_local_time);
        o2_service_new("_cs");
        o2_method_new("/_cs/get", "is", &cs_ping_handler, NULL, FALSE, FALSE);
        O2_DBg(printf("%s ** master clock established, time is now %g\n",
                     o2_debug_prefix, o2_local_time()));
        is_master = TRUE;
        announce_synchronized(new_local_time);
        if (!was_synchronized) {
            // every service including local ones and those provided by a
            // synchronized processes are now synchronized
            dyn_array_ptr table = &o2_context->path_tree.children;
            enumerate enumerator;
            o2_enumerate_begin(&enumerator, table);
            services_entry_ptr services_ptr;
            o2_in_find_and_call_handlers++;
            while ((services_ptr =
                    (services_entry_ptr) o2_enumerate_next(&enumerator))) {
                if ((services_ptr->tag == SERVICES) &&
                    (services_ptr->services.length > 0)) {
                    o2_info_ptr service = GET_SERVICE(services_ptr->services, 0);
                    // _cs was just created above and was reported as O2_LOCAL,
                    // so don't do it again.
                    if ((service->tag == PATTERN_NODE ||
                         service->tag == PATTERN_HANDLER) &&
                        !streql(services_ptr->key, "_cs")) {
                        o2_send_cmd("!_o2/si", 0.0, "sis", 
                                    services_ptr->key, O2_LOCAL,
                                    o2_context->process->proc.name);
                    } else if (service->tag == OSC_REMOTE_SERVICE) {
                        o2_send_cmd("!_o2/si", 0.0, "sis", 
                                    services_ptr->key, O2_TO_OSC,
                                    o2_context->process->proc.name);
                    } else if (service->tag == TCP_SOCKET &&
                               ((process_info_ptr) service)->proc.status == 
                               PROCESS_OK) {
                        o2_send_cmd("!_o2/si", 0.0, "sis", 
                                    services_ptr->key, O2_REMOTE,
                                    o2_context->process->proc.name);
                    }
                }
            }
        }
        o2_in_find_and_call_handlers--;
    }
    return O2_SUCCESS;
}
Example #8
0
#include "assert.h"
#include "stdlib.h"
#include "stdio.h"
#include "allegro.h"
#include "string.h"
#include "ctype.h"
//#include "memory.h"
#include "trace.h"
#include "strparse.h"
#ifndef EXPERIMENTAL_NOTE_TRACK
#include "allegrord.h"
#endif /* EXPERIMENTAL_NOTE_TRACK */
#define streql(s1, s2) (strcmp(s1, s2) == 0)
#define field_max 80


//Note that this is an #ifdef, not an #ifndef
#ifdef EXPERIMENTAL_NOTE_TRACK

class Alg_reader {
public:
    FILE *file;
    int line_no;
    String_parse line_parser;
    bool line_parser_flag;
    char field[field_max];
    bool error_flag;
    Alg_seq_ptr seq;
    double tsnum;
    double tsden;

    Alg_reader(FILE *a_file, Alg_seq_ptr new_seq);
    void readline();
    Alg_parameters_ptr process_attributes(Alg_parameters_ptr attributes, double time);
    bool parse();
    long parse_chan(char *field);
    long parse_int(char *field);
    int find_real_in(char *field, int n);
    double parse_real(char *field);
    void parse_error(char *field, long offset, char *message);
    double parse_dur(char *field, double base);
    double parse_after_dur(double dur, char *field, int n, double base);
    double parse_loud(char *field);
    long parse_key(char *field);
    double parse_pitch(char *field);
    long parse_after_key(int key, char *field, int n);
    long find_int_in(char *field, int n);
    bool parse_attribute(char *field, Alg_parameter_ptr parm);
    bool parse_val(Alg_parameter_ptr param, char *s, int i);
    bool check_type(char type_char, Alg_parameter_ptr param);
};

#endif /* EXPERIMENTAL_NOTE_TRACK */

void subseq(char *result, char *source, int from, int to)
{
    memcpy(result, source + from, to - from);
    result[to - from] = 0;
}

#ifndef EXPERIMENTAL_NOTE_TRACK
double Allegro_reader::parse_pitch(char *field)
#else /* EXPERIMENTAL_NOTE_TRACK */
double Alg_reader::parse_pitch(char *field)
#endif /* EXPERIMENTAL_NOTE_TRACK */
{
    if (isdigit(field[1])) {
        char real_string[80];
        int last = find_real_in(field, 1);
        subseq(real_string, field, 1, last);
        return atof(real_string);
    } else {
        return (double) parse_key(field);
    }
}


#ifndef EXPERIMENTAL_NOTE_TRACK
Allegro_reader::Allegro_reader(FILE *a_file)
{
    file = a_file; // save the file
    line_parser_flag = false;
    line_no = 0;
    seq = Seq();
    tsnum = 4; // default time signature
    tsden = 4;
}
#else /* EXPERIMENTAL_NOTE_TRACK */
// it is the responsibility of the caller to delete
// the seq
Alg_reader::Alg_reader(FILE *a_file, Alg_seq_ptr new_seq)
{
    file = a_file; // save the file
    line_parser_flag = false;
    line_no = 0;
    tsnum = 4; // default time signature
    tsden = 4;
    seq = new_seq;
}
#endif /* EXPERIMENTAL_NOTE_TRACK */


//Note that this is an #ifdef, not an #ifndef
#ifdef EXPERIMENTAL_NOTE_TRACK
Alg_seq_ptr alg_read(FILE *file, Alg_seq_ptr new_seq)
    // read a sequence from allegro file
{
    if (!new_seq) new_seq = new Alg_seq();
    Alg_reader alg_reader(file, new_seq);
    alg_reader.parse();
    return alg_reader.seq;
}
#endif /* EXPERIMENTAL_NOTE_TRACK */


#ifndef EXPERIMENTAL_NOTE_TRACK
void Allegro_reader::readline()
#else /* EXPERIMENTAL_NOTE_TRACK */
void Alg_reader::readline()
#endif /* EXPERIMENTAL_NOTE_TRACK */
{
    char line[256];
    char *line_flag = fgets(line, 256, file);
    line_parser_flag = false;
    if (line_flag) {
        line_parser.init(line);
        line_parser_flag = true;
        error_flag = false;
    }
}


#ifndef EXPERIMENTAL_NOTE_TRACK
void Allegro_reader::process_attributes(Parameters_ptr attributes, double time)
{
    // print "process_attributes:", attributes
    bool ts_flag;
    if (attributes) {
        Parameters_ptr a;
        if (a = Parameters::remove_key(&attributes, "tempor")) {
            double tempo = a->parm.r;
            seq.insert_tempo(tempo, seq.map.time_to_beat(time));
        }
        if (a = Parameters::remove_key(&attributes, "beatr")) {
            double beat = a->parm.r;
            seq.insert_beat(time, beat);
        }
        if (a = Parameters::remove_key(&attributes, "tsnumr")) {
            tsnum = a->parm.r;
            ts_flag = true;
        }
        if (a = Parameters::remove_key(&attributes, "tsdenr")) {
            tsden = a->parm.r;
            ts_flag = true;
        }
        if (ts_flag) {
            seq.set_time_sig(seq.map.time_to_beat(time), tsnum, tsden);
        }
    }
}
#else /* EXPERIMENTAL_NOTE_TRACK */
Alg_parameters_ptr Alg_reader::process_attributes(
        Alg_parameters_ptr attributes, double time)
{
    // print "process_attributes:", attributes
    bool ts_flag = false;
    if (attributes) {
        Alg_parameters_ptr a;
        bool in_seconds = seq->get_units_are_seconds();
        if (a = Alg_parameters::remove_key(&attributes, "tempor")) {
            double tempo = a->parm.r;
            seq->insert_tempo(tempo, seq->get_time_map()->time_to_beat(time));
        }
        if (a = Alg_parameters::remove_key(&attributes, "beatr")) {
            double beat = a->parm.r;
            seq->insert_beat(time, beat);
        }
        if (a = Alg_parameters::remove_key(&attributes, "timesig_numr")) {
            tsnum = a->parm.r;
            ts_flag = true;
        }
        if (a = Alg_parameters::remove_key(&attributes, "timesig_denr")) {
            tsden = a->parm.r;
            ts_flag = true;
        }
        if (ts_flag) {
            seq->set_time_sig(seq->get_time_map()->time_to_beat(time),
            tsnum, tsden);
        }
        if (in_seconds) seq->convert_to_seconds();
    }
    return attributes; // in case it was modified
}
#endif /* EXPERIMENTAL_NOTE_TRACK */

#ifndef EXPERIMENTAL_NOTE_TRACK
bool Allegro_reader::parse()
{
    int voice = 0;
    int key = 60;
    double loud = 100.0;
    double pitch = 60.0;
    double dur = 1.0;
    double time = 0.0;
    readline();
    bool valid = false; // ignore blank lines
    while (line_parser_flag) {
        bool time_flag = false;
        bool next_flag = false;
        double next;
        bool voice_flag = false;
        bool loud_flag = false;
        bool dur_flag = false;
        bool new_pitch_flag = false; // "P" syntax
        double new_pitch = 0.0;
        bool new_key_flag = false;   // "K" syntax
        int new_key = 0;
        bool new_note_flag = false;  // "A"-"G" syntax
        int new_note = 0;
        Parameters_ptr attributes = NULL;
        line_parser.get_nonspace_quoted(field);
        char pk = line_parser.peek();
        if (pk && !isspace(pk)) {
            line_parser.get_nonspace_quoted(field + strlen(field));
        }
        while (field[0]) {
            // print "field", "|";field;"|", "|";line_parser.string;"|", line_parser.pos
            char first = toupper(field[0]);
            if (strchr("ABCDEFGKLPUSIQHW-", first)) {
                valid = true; // it's a note or event
            }
            if (first == 'V') {
                if (voice_flag) {
                    parse_error(field, 0, "Voice specified twice");
                } else {
                    voice = parse_int(field);
                }
                voice_flag = true;
            } else if (first == 'T') {
                if (time_flag) {
                    parse_error(field, 0, "Time specified twice");
                } else {
                    time = parse_dur(field, 0.0);
                }
                time_flag = true;
            } else if (first == 'N') {
                if (next_flag) {
                    parse_error(field, 0, "Next specified twice");
                } else {
                    next = parse_dur(field, time);
                }
                next_flag = true;
            } else if (first == 'K') {
                if (new_key_flag) {
                    parse_error(field, 0, "Key specified twice");
                } else {
                    new_key = parse_key(field);
                    new_key_flag = true;
                }
            } else if (first == 'L') {
                if (loud_flag) {
                    parse_error(field, 0, "Loudness specified twice");
                } else {
                    loud = parse_loud(field);
                }
                loud_flag = true;
            } else if (first == 'P') {
                if (new_note_flag || new_pitch_flag) {
                    parse_error(field, 0, "Pitch specified twice");
                } else {
                    new_pitch = parse_pitch(field);
                    new_pitch_flag = true;
                }
            } else if (first == 'U') {
                if (dur_flag) {
                    parse_error(field, 0, "Dur specified twice");
                } else {
                    dur = parse_dur(field, time);
                    dur_flag = true;
                }
            } else if (strchr("SIQHW", first)) {
                if (dur_flag) {
                    parse_error(field, 0, "Dur specified twice");
                } else {
                    // prepend 'U' to field, copy EOS too
                    memmove(field + 1, field, strlen(field) + 1);
                    field[0] = 'U';
                    dur = parse_dur(field, time);
                    dur_flag = true;
                }
            } else if (strchr("ABCDEFG", first)) {
                if (new_note_flag || new_pitch_flag) {
                    parse_error(field, 0, "Pitch specified twice");
                } else {
                    // prepend 'K' to field, copy EOS too
                    memmove(field + 1, field, strlen(field) + 1);
                    field[0] = 'K';
                    new_note = parse_key(field);
                    new_note_flag = true;
                }
            } else if (first == '-') {
                Parameter parm;
                if (parse_attribute(field, &parm)) { // enter attribute-value pair
                    attributes = new Parameters(attributes);
                    attributes->parm = parm;
                    parm.s = NULL; // protect string from deletion by destructor
                }
            } else {
                parse_error(field, 0, "Unknown field");
            }

            if (error_flag) {
                field[0] = 0; // exit the loop
            } else {
                line_parser.get_nonspace_quoted(field);
                pk = line_parser.peek();
                if (pk && !isspace(pk)) {
                    line_parser.get_nonspace_quoted(field + strlen(field));
                }
            }
        }
        // a case analysis:
        // Key < 128 counts as both key and pitch
        // A-G implies pitch AND key unless key given too
        //   K60 P60 -- both are specified, use 'em
        //   K60 P60 C4 -- overconstrained, an error
        //   K60 C4 -- overconstrained
        //   K60 -- OK, pitch is 60
        //   C4 P60 -- over constrained
        //   P60 -- OK, key is from before, pitch is 60
        //   C4 -- OK, key is 60, pitch is 60
        //   <nothing> -- OK, key and pitch from before
        //   K200 with P60 ok, pitch is 60
        //   K200 with neither P60 nor C4 uses 
        //       pitch from before
        // figure out what the key/instance is:
        if (new_key_flag) { // it was directly specified
            key = new_key;
            if (key < 128 && new_note_flag) {
                parse_error("", 0, "Pitch specified twice");
            }
        } else if (new_note_flag) { // "A"-"G" used
            key = new_note;
        }
        if (new_pitch_flag) {
            pitch = new_pitch;
        } else if (key < 128) {
            pitch = key;
        }
        // now we've acquired new parameters
        // if (it is a note, then enter the note
        if (valid) {
            // change tempo or beat
            process_attributes(attributes, time);
            // if there's a duration or pitch, make a note:
            if (new_pitch_flag || dur_flag || new_note_flag) {
                new_key_flag = false;
                new_pitch_flag = false;
                Allegro_note_ptr note_ptr = new Allegro_note;
                note_ptr->chan = voice;
                note_ptr->time = time;
                note_ptr->dur = dur;
                note_ptr->key = key;
                note_ptr->pitch = pitch;
                note_ptr->loud = loud;
                note_ptr->parameters = attributes;
                seq.add_event(note_ptr); // sort later
            } else {
                int update_key = -1;
                // key or pitch must appear explicitly; otherwise
                //    update applies to channel
                if (new_key_flag || new_pitch_flag) {
                    update_key = key;
                }
                if (loud_flag) {
                    Allegro_update_ptr new_upd = new Allegro_update;
                    new_upd->chan = voice;
                    new_upd->time = time;
                    new_upd->key = update_key;
                    new_upd->parameter.set_attr(symbol_table.insert_string("loudr"));
                    new_upd->parameter.r = pitch;
                    seq.add_event(new_upd);
                }
                if (attributes) {
                    while (attributes) {
                        Allegro_update_ptr new_upd = new Allegro_update;
                        new_upd->chan = voice;
                        new_upd->time = time;
                        new_upd->key = update_key;
                        new_upd->parameter = attributes->parm;
                        seq.add_event(new_upd);
                        Parameters_ptr p = attributes;
                        attributes = attributes->next;
                        delete p;
                    }
                }
            }
            if (next_flag) {
                time = time + next;
            } else if (dur_flag) {
                time = time + dur;
            }
        }
        readline();
    }
    //print "Finished reading score"
    if (!error_flag) {
        seq.convert_to_seconds(); // make sure format is correct
        // seq.notes.sort('event_greater_than');
    }
    // print "parse returns error_flag", error_flag
    return error_flag;
}
#else /* EXPERIMENTAL_NOTE_TRACK */
bool Alg_reader::parse()
{
    int voice = 0;
    int key = 60;
    double loud = 100.0;
    double pitch = 60.0;
    double dur = 1.0;
    double time = 0.0;
    int track_num = 0;
    seq->convert_to_seconds();
    //seq->set_real_dur(0.0); // just in case it's not initialized already
    readline();
    bool valid = false; // ignore blank lines
    while (line_parser_flag) {
        bool time_flag = false;
        bool next_flag = false;
        double next;
        bool voice_flag = false;
        bool loud_flag = false;
        bool dur_flag = false;
        bool new_pitch_flag = false; // "P" syntax
        double new_pitch = 0.0;
        bool new_key_flag = false;   // "K" syntax
        int new_key = 0;
        bool new_note_flag = false;  // "A"-"G" syntax
        int new_note = 0;
        Alg_parameters_ptr attributes = NULL;
        if (line_parser.peek() == '#') {
            // look for #track
            line_parser.get_nonspace_quoted(field);
            if (streql(field, "#track")) {
                line_parser.get_nonspace_quoted(field); // number
                track_num = parse_int(field - 1);
                seq->add_track(track_num);
            }
            // maybe we have a comment
        } else {
            // we must have a track to insert into
            if (seq->tracks() == 0) seq->add_track(0);
            line_parser.get_nonspace_quoted(field);
            char pk = line_parser.peek();
            // attributes are parsed as two adjacent nonspace_quoted tokens
            // so we have to conditionally call get_nonspace_quoted() again
            if (pk && !isspace(pk)) {
                line_parser.get_nonspace_quoted(field + strlen(field));
            }
            while (field[0]) {
                char first = toupper(field[0]);
                if (strchr("ABCDEFGKLPUSIQHW-", first)) {
                    valid = true; // it's a note or event
                }
                if (first == 'V') {
                    if (voice_flag) {
                        parse_error(field, 0, "Voice specified twice");
                    } else {
                        voice = parse_chan(field);
                    }
                    voice_flag = true;
                } else if (first == 'T') {
                    if (time_flag) {
                        parse_error(field, 0, "Time specified twice");
                    } else {
                        time = parse_dur(field, 0.0);
                    }
                    time_flag = true;
                } else if (first == 'N') {
                    if (next_flag) {
                        parse_error(field, 0, "Next specified twice");
                    } else {
                        next = parse_dur(field, time);
                    }
                    next_flag = true;
                } else if (first == 'K') {
                    if (new_key_flag) {
                        parse_error(field, 0, "Key specified twice");
                    } else {
                        new_key = parse_key(field);
                        new_key_flag = true;
                    }
                } else if (first == 'L') {
                    if (loud_flag) {
                        parse_error(field, 0, "Loudness specified twice");
                    } else {
                        loud = parse_loud(field);
                    }
                    loud_flag = true;
                } else if (first == 'P') {
                    if (new_note_flag || new_pitch_flag) {
                        parse_error(field, 0, "Pitch specified twice");
                    } else {
                        new_pitch = parse_pitch(field);
                        new_pitch_flag = true;
                    }
                } else if (first == 'U') {
                    if (dur_flag) {
                        parse_error(field, 0, "Dur specified twice");
                    } else {
                        dur = parse_dur(field, time);
                        dur_flag = true;
                    }
                } else if (strchr("SIQHW", first)) {
                    if (dur_flag) {
                        parse_error(field, 0, "Dur specified twice");
                    } else {
                        // prepend 'U' to field, copy EOS too
                        memmove(field + 1, field, strlen(field) + 1);
                        field[0] = 'U';
                        dur = parse_dur(field, time);
                        dur_flag = true;
                    }
                } else if (strchr("ABCDEFG", first)) {
                    if (new_note_flag || new_pitch_flag) {
                        parse_error(field, 0, "Pitch specified twice");
                    } else {
                        // prepend 'K' to field, copy EOS too
                        memmove(field + 1, field, strlen(field) + 1);
                        field[0] = 'K';
                        new_note = parse_key(field);
                        new_note_flag = true;
                    }
                } else if (first == '-') {
                    Alg_parameter parm;
                    if (parse_attribute(field, &parm)) { // enter attribute-value pair
                        attributes = new Alg_parameters(attributes);
                        attributes->parm = parm;
                        parm.s = NULL; // protect string from deletion by destructor
                    }
                } else {
                    parse_error(field, 0, "Unknown field");
                }

                if (error_flag) {
                    field[0] = 0; // exit the loop
                } else {
                    line_parser.get_nonspace_quoted(field);
                    pk = line_parser.peek();
                    // attributes are parsed as two adjacent nonspace_quoted 
                    // tokens so we have to conditionally call 
                    // get_nonspace_quoted() again
                    if (pk && !isspace(pk)) {
                        line_parser.get_nonspace_quoted(field + strlen(field));
                    }
                }
            }
            // a case analysis:
            // Key < 128 counts as both key and pitch
            // A-G implies pitch AND key unless key given too
            //   K60 P60 -- both are specified, use 'em
            //   K60 P60 C4 -- overconstrained, an error
            //   K60 C4 -- overconstrained
            //   K60 -- OK, pitch is 60
            //   C4 P60 -- over constrained
            //   P60 -- OK, key is from before, pitch is 60
            //   C4 -- OK, key is 60, pitch is 60
            //   <nothing> -- OK, key and pitch from before
            //   K200 with P60 ok, pitch is 60
            //   K200 with neither P60 nor C4 uses 
            //       pitch from before
            // figure out what the key/instance is:
            if (new_key_flag) { // it was directly specified
                key = new_key;
                if (key < 128 && new_note_flag) {
                    parse_error("", 0, "Pitch specified twice");
                }
            } else if (new_note_flag) { // "A"-"G" used
                key = new_note;
            }
            if (new_pitch_flag) {
                pitch = new_pitch;
            } else if (key < 128) {
                pitch = key;
            }
            // now we've acquired new parameters
            // if (it is a note, then enter the note
            if (valid) {
                // change tempo or beat
                attributes = process_attributes(attributes, time);
                // if there's a duration or pitch, make a note:
                if (new_pitch_flag || dur_flag || new_note_flag) {
                    new_key_flag = false;
                    new_pitch_flag = false;
                    Alg_note_ptr note_ptr = new Alg_note;
                    note_ptr->chan = voice;
                    note_ptr->time = time;
                    note_ptr->dur = dur;
                    note_ptr->set_identifier(key);
                    note_ptr->pitch = pitch;
                    note_ptr->loud = loud;
                    note_ptr->parameters = attributes;
                    seq->add_event(note_ptr, track_num); // sort later
                    if (seq->get_real_dur() < (time + dur)) seq->set_real_dur(time + dur);
                } else {
                    int update_key = -1;
                    // key or pitch must appear explicitly; otherwise
                    //    update applies to channel
                    if (new_key_flag || new_pitch_flag) {
                        update_key = key;
                    }
                    if (loud_flag) {
                        Alg_update_ptr new_upd = new Alg_update;
                        new_upd->chan = voice;
                        new_upd->time = time;
                        new_upd->set_identifier(update_key);
                        new_upd->parameter.set_attr(symbol_table.insert_string("loudr"));
                        new_upd->parameter.r = pitch;
                        seq->add_event(new_upd, track_num);
                        if (seq->get_real_dur() < time) seq->set_real_dur(time);
                    }
                    if (attributes) {
                        while (attributes) {
                            Alg_update_ptr new_upd = new Alg_update;
                            new_upd->chan = voice;
                            new_upd->time = time;
                            new_upd->set_identifier(update_key);
                            new_upd->parameter = attributes->parm;
                            seq->add_event(new_upd, track_num);
                            Alg_parameters_ptr p = attributes;
                            attributes = attributes->next;
                            p->parm.s = NULL; // so we don't delete the string
                            delete p;
                        }
                    }
                }
                if (next_flag) {
                    time = time + next;
                } else if (dur_flag) {
                    time = time + dur;
                }
            }
        }
        readline();
    }
    //print "Finished reading score"
    if (!error_flag) {
        seq->convert_to_seconds(); // make sure format is correct
        // seq->notes.sort('event_greater_than');
    }
    // real_dur is valid, translate to beat_dur
    seq->set_beat_dur((seq->get_time_map())->time_to_beat(seq->get_real_dur()));
    // print "parse returns error_flag", error_flag
    return error_flag;
}
Example #9
0
SEXP Random2(SEXP args)
{
    if (!isVectorList(CAR(args))) error("incorrect usage");
    SEXP x, a, b;
    R_xlen_t i, n, na, nb;
    ran2 fn = NULL; /* -Wall */
    const char *dn = CHAR(STRING_ELT(getListElement(CAR(args), "name"), 0));
    SEXPTYPE type = REALSXP;

    if (streql(dn, "rbeta")) fn = &rbeta;
    else if (streql(dn, "rbinom")) {
	type = INTSXP;
	fn = &rbinom;
    } else if (streql(dn, "rcauchy")) fn = &rcauchy;
    else if (streql(dn, "rf")) fn = &rf;
    else if (streql(dn, "rgamma")) fn = &rgamma;
    else if (streql(dn, "rlnorm")) fn = &rlnorm;
    else if (streql(dn, "rlogis")) fn = &rlogis;
    else if (streql(dn, "rnbinom")) {
	type = INTSXP;
	fn = &rnbinom;
    } else if (streql(dn, "rnorm")) fn = &rnorm;
    else if (streql(dn, "runif")) fn = &runif;
    else if (streql(dn, "rweibull")) fn = &rweibull;
    else if (streql(dn, "rwilcox")) {
	type = INTSXP;
	fn = &rwilcox;
    } else if (streql(dn, "rnchisq")) fn = &rnchisq;
    else if (streql(dn, "rnbinom_mu")) {
	fn = &rnbinom_mu;
    } else error(_("invalid arguments"));

    args = CDR(args);
    if (!isVector(CAR(args)) ||
	!isNumeric(CADR(args)) ||
	!isNumeric(CADDR(args)))
	error(_("invalid arguments"));
    if (XLENGTH(CAR(args)) == 1) {
#ifdef LONG_VECTOR_SUPPORT
	double dn = asReal(CAR(args));
	if (ISNAN(dn) || dn < 0 || dn > R_XLEN_T_MAX)
	    error(_("invalid arguments"));
	n = (R_xlen_t) dn;
#else
	n = asInteger(CAR(args));
	if (n == NA_INTEGER || n < 0)
	    error(_("invalid arguments"));
#endif
    }
    else n = XLENGTH(CAR(args));
    PROTECT(x = allocVector(type, n));
    if (n == 0) {
	UNPROTECT(1);
	return(x);
    }
    na = XLENGTH(CADR(args));
    nb = XLENGTH(CADDR(args));
    if (na < 1 || nb < 1) {
	if (type == INTSXP)
	    for (i = 0; i < n; i++) INTEGER(x)[i] = NA_INTEGER;
	else
	    for (i = 0; i < n; i++) REAL(x)[i] = NA_REAL;
	for (i = 0; i < n; i++) REAL(x)[i] = NA_REAL;
	warning(_("NAs produced"));
    }
    else {
	Rboolean naflag = FALSE;
	PROTECT(a = coerceVector(CADR(args), REALSXP));
	PROTECT(b = coerceVector(CADDR(args), REALSXP));
	GetRNGstate();
	double *ra = REAL(a), *rb = REAL(b);
	if (type == INTSXP) {
	    int *ix = INTEGER(x); double rx;
	    errno = 0;
	    for (R_xlen_t i = 0; i < n; i++) {
//		if ((i+1) % NINTERRUPT) R_CheckUserInterrupt();
		rx = fn(ra[i % na], rb[i % nb]);
		if (ISNAN(rx) || rx > INT_MAX || rx <= INT_MIN) {
		    naflag = TRUE;
		    ix[i] = NA_INTEGER;
		} else ix[i] = (int) rx;
	    }
	} else {
	    double *rx = REAL(x);
	    errno = 0;
	    for (R_xlen_t i = 0; i < n; i++) {
//		if ((i+1) % NINTERRUPT) R_CheckUserInterrupt();
		rx[i] = fn(ra[i % na], rb[i % nb]);
		if (ISNAN(rx[i])) naflag = TRUE;
	    }
	}
	if (naflag) warning(_("NAs produced"));
	PutRNGstate();
	UNPROTECT(2);
    }
    UNPROTECT(1);
    return x;
}
Example #10
0
SEXP Random1(SEXP args)
{
    if (!isVectorList(CAR(args))) error("incorrect usage");
    SEXP x, a;
    R_xlen_t i, n, na;
    ran1 fn = NULL; /* -Wall */
    const char *dn = CHAR(STRING_ELT(getListElement(CAR(args), "name"), 0));
    SEXPTYPE type = REALSXP;

    if (streql(dn, "rchisq")) fn = &rchisq;
    else if (streql(dn, "rexp")) fn = &rexp;
    else if (streql(dn, "rgeom")) {
	type = INTSXP;
	fn = &rgeom;
    } else if (streql(dn, "rpois")) {
	type = INTSXP;
	fn = &rpois;
    }
    else if (streql(dn, "rt")) fn = &rt;
    else if (streql(dn, "rsignrank")) {
	type = INTSXP;
	fn = &rsignrank;
    }
    else error(_("invalid arguments"));

    args = CDR(args);
    if (!isVector(CAR(args)) || !isNumeric(CADR(args)))
	error(_("invalid arguments"));
    if (XLENGTH(CAR(args)) == 1) {
#ifdef LONG_VECTOR_SUPPORT
	double dn = asReal(CAR(args));
	if (ISNAN(dn) || dn < 0 || dn > R_XLEN_T_MAX)
	    error(_("invalid arguments"));
	n = (R_xlen_t) dn;
#else
	n = asInteger(CAR(args));
	if (n == NA_INTEGER || n < 0)
	    error(_("invalid arguments"));
#endif
    }
    else n = XLENGTH(CAR(args));
    PROTECT(x = allocVector(type, n));
    if (n == 0) {
	UNPROTECT(1);
	return(x);
    }
    na = XLENGTH(CADR(args));
    if (na < 1) {
	if (type == INTSXP)
	    for (i = 0; i < n; i++) INTEGER(x)[i] = NA_INTEGER;
	else
	    for (i = 0; i < n; i++) REAL(x)[i] = NA_REAL;
	warning(_("NAs produced"));
    } else {
	Rboolean naflag = FALSE;
	PROTECT(a = coerceVector(CADR(args), REALSXP));
	GetRNGstate();
	double *ra = REAL(a);
	errno = 0;
	if (type == INTSXP) {
	    double rx;
	    int *ix = INTEGER(x);
	    for (R_xlen_t i = 0; i < n; i++) {
//		if ((i+1) % NINTERRUPT) R_CheckUserInterrupt();
		rx = fn(ra[i % na]);
		if (ISNAN(rx) || rx > INT_MAX || rx <= INT_MIN ) {
		    naflag = TRUE;
		    ix[i] = NA_INTEGER;
		}
		else ix[i] = (int) rx;
	    }
	} else {
	    double *rx = REAL(x);
	    for (R_xlen_t i = 0; i < n; i++) {
//		if ((i+1) % NINTERRUPT) R_CheckUserInterrupt();
		rx[i] = fn(ra[i % na]);
		if (ISNAN(rx[i])) naflag = TRUE;
	    }
	}
	if (naflag) warning(_("NAs produced"));
	PutRNGstate();
	UNPROTECT(1);
    }
    UNPROTECT(1);
    return x;
}
Example #11
0
// supercomparateur joker (tm)
// compare a et b (b=avec joker dedans), case insensitive [voir CI]
// renvoi l'adresse de la première lettre de la chaine
// (càd *[..]toto.. renvoi adresse de toto dans la chaine)
// accepte les délires du genre www.*.*/ * / * truc*.*
// cet algo est 'un peu' récursif mais ne consomme pas trop de tm
// * = toute lettre
// --?-- : spécifique à HTTrack et aux ?
HTS_INLINE char *strjoker(char *chaine, char *joker, LLint * size,
                          int *size_flag) {
  //int err=0;
  if (strnotempty(joker) == 0) {        // fin de chaine joker
    if (strnotempty(chaine) == 0)       // fin aussi pour la chaine: ok
      return chaine;
    else if (chaine[0] == '?')
      return chaine;            // --?-- pour les index.html?Choix=2
    else
      return NULL;              // non trouvé
  }
  // on va progresser en suivant les 'mots' contenus dans le joker
  // un mot peut être un * ou bien toute autre séquence de lettres

  if (strcmp(joker, "*") == 0) {        // ok, rien après
    return chaine;
  }
  // 1er cas: jokers * ou jokers multiples *[..]
  if (joker[0] == '*') {        // comparer joker+reste (*toto/..)
    int jmp;                    // nombre de caractères pour le prochain mot dans joker
    int cut = 0;                // interdire tout caractère superflu
    char pass[256];
    char LEFT = '[', RIGHT = ']';
    int unique = 0;

    switch (joker[1]) {
    case '[':
      LEFT = '[';
      RIGHT = ']';
      unique = 0;
      break;
    case '(':
      LEFT = '(';
      RIGHT = ')';
      unique = 1;
      break;
    }

    if ((joker[1] == LEFT) && (joker[2] != LEFT)) {     // multijoker (tm)
      int i;

      for(i = 0; i < 256; i++)
        pass[i] = 0;

      // noms réservés
      if ((strfield(joker + 2, "file")) || (strfield(joker + 2, "name"))) {
        for(i = 0; i < 256; i++)
          pass[i] = 1;
        pass[(int) '?'] = 0;
        //pass[(int) ';'] = 0;
        pass[(int) '/'] = 0;
        i = 2;
        {
          int len = (int) strlen(joker);

          while((joker[i] != RIGHT) && (joker[i]) && (i < len))
            i++;
        }
      } else if (strfield(joker + 2, "path")) {
        for(i = 0; i < 256; i++)
          pass[i] = 1;
        pass[(int) '?'] = 0;
        //pass[(int) ';'] = 0;
        i = 2;
        {
          int len = (int) strlen(joker);

          while((joker[i] != RIGHT) && (joker[i]) && (i < len))
            i++;
        }
      } else if (strfield(joker + 2, "param")) {
        if (chaine[0] == '?') { // il y a un paramètre juste là
          for(i = 0; i < 256; i++)
            pass[i] = 1;
        }                       // sinon synonyme de 'rien'
        i = 2;
        {
          int len = (int) strlen(joker);

          while((joker[i] != RIGHT) && (joker[i]) && (i < len))
            i++;
        }
      } else {
        // décode les directives comme *[A-Z,âêîôû,0-9]
        i = 2;
        if (joker[i] == RIGHT) {        // *[] signifie "plus rien après"
          cut = 1;              // caractère supplémentaire interdit
        } else {
          int len = (int) strlen(joker);

          while((joker[i] != RIGHT) && (joker[i]) && (i < len)) {
            if ((joker[i] == '<') || (joker[i] == '>')) {       // *[<10]
              int lsize = 0;
              int lverdict;

              i++;
              if (sscanf(joker + i, "%d", &lsize) == 1) {
                if (size) {
                  if (*size >= 0) {
                    if (size_flag)
                      *size_flag = 1;   /* a joué */
                    if (joker[i - 1] == '<')
                      lverdict = (*size < lsize);
                    else
                      lverdict = (*size > lsize);
                    if (!lverdict) {
                      return NULL;      // ne correspond pas
                    } else {
                      *size = lsize;
                      return chaine;    // ok
                    }
                  } else
                    return NULL;        // ne correspond pas
                } else
                  return NULL;  // ne correspond pas (test impossible)
                // jump
                while(isdigit((unsigned char) joker[i]))
                  i++;
              }
            } else if (joker[i + 1] == '-') {   // 2 car, ex: *[A-Z]
              if ((int) (unsigned char) joker[i + 2] >
                  (int) (unsigned char) joker[i]) {
                int j;

                for(j = (int) (unsigned char) joker[i];
                    j <= (int) (unsigned char) joker[i + 2]; j++)
                  pass[j] = 1;

              }
              // else err=1;
              i += 3;
            } else {            // 1 car, ex: *[ ]
              if (joker[i + 2] == '\\' && joker[i + 3] != 0) {  // escaped char, such as *[\[] or *[\]]
                i++;
              }
              pass[(int) (unsigned char) joker[i]] = 1;
              i++;
            }
            if ((joker[i] == ',') || (joker[i] == ';'))
              i++;
          }
        }
      }
      // à sauter dans joker
      jmp = i;
      if (joker[i])
        jmp++;

      //
    } else {                    // tout autoriser
      //
      int i;

      for(i = 0; i < 256; i++)
        pass[i] = 1;            // tout autoriser
      jmp = 1;
      ////if (joker[2]==LEFT) jmp=3;        // permet de recher *<crochet ouvrant>
    }

    {
      int i, max;
      char *adr;

      // la chaine doit se terminer exactement
      if (cut) {
        if (strnotempty(chaine))
          return NULL;          // perdu
        else
          return chaine;        // ok
      }
      // comparaison en boucle, c'est ca qui consomme huhu..
      // le tableau pass[256] indique les caractères ASCII autorisés

      // tester sans le joker (pas ()+ mais ()*)
      if (!unique) {
        if ((adr = strjoker(chaine, joker + jmp, size, size_flag))) {
          return adr;
        }
      }
      // tester
      i = 0;
      if (!unique)
        max = (int) strlen(chaine);
      else                      /* *(a) only match a (not aaaaa) */
        max = 1;
      while(i < (int) max) {
        if (pass[(int) (unsigned char) chaine[i]]) {    // caractère autorisé
          if ((adr = strjoker(chaine + i + 1, joker + jmp, size, size_flag))) {
            return adr;
          }
          i++;
        } else
          i = max + 2;          // sortir
      }

      // tester chaîne vide
      if (i != max + 2)         // avant c'est ok
        if ((adr = strjoker(chaine + max, joker + jmp, size, size_flag)))
          return adr;

      return NULL;              // perdu
    }

  } else {                      // comparer mot+reste (toto*..)
    if (strnotempty(chaine)) {
      int jmp = 0, ok = 1;

      // comparer début de joker et début de chaine
      while((joker[jmp] != '*') && (joker[jmp]) && (ok)) {
        // CI : remplacer streql par une comparaison !=
        if (!streql(chaine[jmp], joker[jmp])) {
          ok = 0;               // quitter
        }
        jmp++;
      }

      // comparaison ok?
      if (ok) {
        // continuer la comparaison.
        if (strjoker(chaine + jmp, joker + jmp, size, size_flag))
          return chaine;        // retourner 1e lettre
      }

    }                           // strlen(a)
    return NULL;
  }                             // * ou mot

  return NULL;
}
Example #12
0
// créer dans s, à partir du chemin courant curr_fil, le lien vers link (absolu)
// un ident_url_relatif a déja été fait avant, pour que link ne soit pas un chemin relatif
int lienrelatif(char *s, const char *link, const char *curr_fil) {
  char BIGSTK _curr[HTS_URLMAXSIZE * 2];
  char BIGSTK newcurr_fil[HTS_URLMAXSIZE * 2], newlink[HTS_URLMAXSIZE * 2];
  char *curr;

  //int n=0;
  char *a;
  int slash = 0;

  //
  newcurr_fil[0] = '\0';
  newlink[0] = '\0';
  //

  // patch: éliminer les ? (paramètres) sinon bug
  {
    const char *a;

    if ((a = strchr(curr_fil, '?'))) {
      strncatbuff(newcurr_fil, curr_fil, (int) (a - curr_fil));
      curr_fil = newcurr_fil;
    }
    if ((a = strchr(link, '?'))) {
      strncatbuff(newlink, link, (int) (a - link));
      link = newlink;
    }
  }

  // recopier uniquement le chemin courant
  curr = _curr;
  strcpybuff(curr, curr_fil);
  if ((a = strchr(curr, '?')) == NULL)  // couper au ? (params)
    a = curr + strlen(curr) - 1;        // pas de params: aller à la fin
  while((*a != '/') && (a > curr))
    a--;                        // chercher dernier / du chemin courant
  if (*a == '/')
    *(a + 1) = '\0';            // couper dernier /

  // "effacer" s
  s[0] = '\0';

  // sauter ce qui est commun aux 2 chemins
  {
    const char *l;

    if (*link == '/')
      link++;                   // sauter slash
    if (*curr == '/')
      curr++;
    l = link;
    //c=curr;
    // couper ce qui est commun
    while((streql(*link, *curr)) && (*link != 0)) {
      link++;
      curr++;
    }
    // mais on veut un répertoirer entier!
    // si on a /toto/.. et /toto2/.. on ne veut pas sauter /toto !
    while(((*link != '/') || (*curr != '/')) && (link > l)) {
      link--;
      curr--;
    }
    //if (*link=='/') link++;
    //if (*curr=='/') curr++;
  }

  // calculer la profondeur du répertoire courant et remonter
  // LES ../ ONT ETE SIMPLIFIES
  a = curr;
  if (*a == '/')
    a++;
  while(*a)
    if (*(a++) == '/')
      strcatbuff(s, "../");
  //if (strlen(s)==0) strcatbuff(s,"/");

  if (slash)
    strcatbuff(s, "/");         // garder absolu!!

  // on est dans le répertoire de départ, copier
  strcatbuff(s, link + ((*link == '/') ? 1 : 0));

  /* Security check */
  if (strlen(s) >= HTS_URLMAXSIZE)
    return -1;

  // on a maintenant une chaine de la forme ../../test/truc.html  
  return 0;
}
Example #13
0
SEXP attribute_hidden do_filepath(SEXP call, SEXP op, SEXP args, SEXP env)
{
    SEXP ans, sep, x;
    int i, j, k, ln, maxlen, nx, nzero, pwidth, sepw;
    const char *s, *csep, *cbuf;
    char *buf;

    checkArity(op, args);

    /* Check the arguments */

    x = CAR(args);
    if (!isVectorList(x))
	error(_("invalid first argument"));
    nx = length(x);
    if(nx == 0) return allocVector(STRSXP, 0);


    sep = CADR(args);
    if (!isString(sep) || LENGTH(sep) <= 0 || STRING_ELT(sep, 0) == NA_STRING)
	error(_("invalid separator"));
    sep = STRING_ELT(sep, 0);
    csep = CHAR(sep);
    sepw = (int) strlen(csep); /* hopefully 1 */

    /* Any zero-length argument gives zero-length result */
    maxlen = 0; nzero = 0;
    for (j = 0; j < nx; j++) {
	if (!isString(VECTOR_ELT(x, j))) {
	    /* formerly in R code: moved to C for speed */
	    SEXP call, xj = VECTOR_ELT(x, j);
	    if(OBJECT(xj)) { /* method dispatch */
		PROTECT(call = lang2(install("as.character"), xj));
		SET_VECTOR_ELT(x, j, eval(call, env));
		UNPROTECT(1);
	    } else if (isSymbol(xj))
		SET_VECTOR_ELT(x, j, ScalarString(PRINTNAME(xj)));
	    else
		SET_VECTOR_ELT(x, j, coerceVector(xj, STRSXP));

	    if (!isString(VECTOR_ELT(x, j)))
		error(_("non-string argument to Internal paste"));
	}
	ln = length(VECTOR_ELT(x, j));
	if(ln > maxlen) maxlen = ln;
	if(ln == 0) {nzero++; break;}
    }
    if(nzero || maxlen == 0) return allocVector(STRSXP, 0);

    PROTECT(ans = allocVector(STRSXP, maxlen));

    for (i = 0; i < maxlen; i++) {
	pwidth = 0;
	for (j = 0; j < nx; j++) {
	    k = length(VECTOR_ELT(x, j));
	    pwidth += (int) strlen(translateChar(STRING_ELT(VECTOR_ELT(x, j), i % k)));
	}
	pwidth += (nx - 1) * sepw;
	cbuf = buf = R_AllocStringBuffer(pwidth, &cbuff);
	for (j = 0; j < nx; j++) {
	    k = length(VECTOR_ELT(x, j));
	    if (k > 0) {
		s = translateChar(STRING_ELT(VECTOR_ELT(x, j), i % k));
		strcpy(buf, s);
		buf += strlen(s);
	    }
	    if (j != nx - 1 && sepw != 0) {
		strcpy(buf, csep);
		buf += sepw;
	    }
	}
#ifdef Win32
	// Trailing seps are invalid for file paths except for / and d:/
	if(streql(csep, "/") || streql(csep, "\\")) {
	    if(buf > cbuf) {
		buf--;
		if(*buf == csep[0] && buf > cbuf &&
		   (buf != cbuf+2 || cbuf[1] != ':')) *buf = '\0';
	    }
	}
#endif
	SET_STRING_ELT(ans, i, mkChar(cbuf));
    }
    R_FreeStringBufferL(&cbuff);
    UNPROTECT(1);
    return ans;
}
Example #14
0
File: migcom.c Project: Prajna/mach
static void
parseArgs(int argc, char **argv)
{
    while (--argc > 0)
	if ((++argv)[0][0] == '-') 
	{
	    switch (argv[0][1]) 
	    {
	      case 'q':
		BeQuiet = TRUE;
		break;
	      case 'Q':
		BeQuiet = FALSE;
		break;
	      case 'v':
		BeVerbose = TRUE;
		break;
	      case 'V':
		BeVerbose = FALSE;
		break;
	      case 'r':
		UseMsgRPC = TRUE;
		break;
	      case 'R':
		UseMsgRPC = FALSE;
		break;
	      case 's':
		if (streql(argv[0], "-server"))
		{
		    --argc; ++argv;
		    if (argc == 0)
			fatal("missing name for -server option");
		    ServerFileName = strmake(argv[0]);
		}
		else if (streql(argv[0], "-sheader"))
		{
		    --argc; ++argv;
		    if (argc == 0)
		      fatal ("missing name for -sheader option");
		    ServerHeaderFileName = strmake(argv[0]);
		}
		else
		    GenSymTab = TRUE;
		break;
	      case 'S':
	        GenSymTab = FALSE;
		break;
	      case 'i':
		if (streql(argv[0], "-iheader"))
		{
		    --argc; ++argv;
		    if (argc == 0)
			fatal("missing name for -iheader option");
		    InternalHeaderFileName = strmake(argv[0]);
		}
		else
		{
		    --argc; ++argv;
		    if (argc == 0)
			fatal("missing prefix for -i option");
		    UserFilePrefix = strmake(argv[0]);
		}
		break;
	      case 'u':
		if (streql(argv[0], "-user"))
		{
		    --argc; ++argv;
		    if (argc == 0)
			fatal("missing name for -user option");
		    UserFileName = strmake(argv[0]);
		}
		else
		    fatal("unknown flag: '%s'", argv[0]);
		break;
	      case 'h':
		if (streql(argv[0], "-header"))
		{
		    --argc; ++argv;
		    if (argc == 0)
			fatal("missing name for -header option");
		    UserHeaderFileName = strmake(argv[0]);
		}
		else
		    fatal("unknown flag: '%s'", argv[0]);
		break;
	      default:
		fatal("unknown flag: '%s'", argv[0]);
		/*NOTREACHED*/
	    }
	}
	else
	    fatal("bad argument: '%s'", *argv);
}
Example #15
0
/* do the two objects compute as identical?
   Also used in unique.c */
Rboolean
R_compute_identical(SEXP x, SEXP y, int flags)
{
    SEXP ax, ay, atrx, atry;
    if(x == y) /* same pointer */
	return TRUE;
    if(TYPEOF(x) != TYPEOF(y))
	return FALSE;
    if(OBJECT(x) != OBJECT(y))
	return FALSE;

    /* Skip attribute checks for CHARSXP
       -- such attributes are used for the cache.  */
    if(TYPEOF(x) == CHARSXP)
    {
	/* This matches NAs */
	return Seql(x, y);
    }

    ax = ATTRIB(x); ay = ATTRIB(y);
    if (!ATTR_AS_SET) {
	if(!R_compute_identical(ax, ay, flags)) return FALSE;
    }
    /* Attributes are special: they should be tagged pairlists.  We
       don't test them if they are not, and we do not test the order
       if they are.

       This code is not very efficient, but then neither is using
       pairlists for attributes.  If long attribute lists become more
       common (and they are used for S4 slots) we should store them in
       a hash table.
    */
    else if(ax != R_NilValue || ay != R_NilValue) {
	if(ax == R_NilValue || ay == R_NilValue)
	    return FALSE;
	if(TYPEOF(ax) != LISTSXP || TYPEOF(ay) != LISTSXP) {
	    warning(_("ignoring non-pairlist attributes"));
	} else {
	    SEXP elx, ely;
	    if(length(ax) != length(ay)) return FALSE;
	    /* They are the same length and should have
	       unique non-empty non-NA tags */
	    for(elx = ax; elx != R_NilValue; elx = CDR(elx)) {
		const char *tx = CHAR(PRINTNAME(TAG(elx)));
		for(ely = ay; ely != R_NilValue; ely = CDR(ely))
		    if(streql(tx, CHAR(PRINTNAME(TAG(ely))))) {
			/* We need to treat row.names specially here */
			if(streql(tx, "row.names")) {
			    PROTECT(atrx = getAttrib(x, R_RowNamesSymbol));
			    PROTECT(atry = getAttrib(y, R_RowNamesSymbol));
			    if(!R_compute_identical(atrx, atry, flags)) {
				UNPROTECT(2);
				return FALSE;
			    } else
				UNPROTECT(2);
			} else
			    if(!R_compute_identical(CAR(elx), CAR(ely), flags))
				return FALSE;
			break;
		    }
		if(ely == R_NilValue) return FALSE;
	    }
	}
    }
    switch (TYPEOF(x)) {
    case NILSXP:
	return TRUE;
    case LGLSXP:
	if (length(x) != length(y)) return FALSE;
	/* Use memcmp (which is ISO C90) to speed up the comparison */
	return memcmp((void *)LOGICAL(x), (void *)LOGICAL(y),
		      length(x) * sizeof(int)) == 0 ? TRUE : FALSE;
    case INTSXP:
	if (length(x) != length(y)) return FALSE;
	/* Use memcmp (which is ISO C90) to speed up the comparison */
	return memcmp((void *)INTEGER(x), (void *)INTEGER(y),
		      length(x) * sizeof(int)) == 0 ? TRUE : FALSE;
    case REALSXP:
    {
	int n = length(x);
	if(n != length(y)) return FALSE;
	else {
	    double *xp = REAL(x), *yp = REAL(y);
	    int i, ne_strict = NUM_EQ | (SINGLE_NA << 1);
	    for(i = 0; i < n; i++)
		if(neWithNaN(xp[i], yp[i], ne_strict)) return FALSE;
	}
	return TRUE;
    }
    case CPLXSXP:
    {
	int n = length(x);
	if(n != length(y)) return FALSE;
	else {
	    Rcomplex *xp = COMPLEX(x), *yp = COMPLEX(y);
	    int i, ne_strict = NUM_EQ | (SINGLE_NA << 1);
	    for(i = 0; i < n; i++)
		if(neWithNaN(xp[i].r, yp[i].r, ne_strict) ||
		   neWithNaN(xp[i].i, yp[i].i, ne_strict))
		    return FALSE;
	}
	return TRUE;
    }
    case STRSXP:
    {
	int i, n = length(x);
	if(n != length(y)) return FALSE;
	for(i = 0; i < n; i++) {
	    /* This special-casing for NAs is not needed */
	    Rboolean na1 = (STRING_ELT(x, i) == NA_STRING),
		na2 = (STRING_ELT(y, i) == NA_STRING);
	    if(na1 ^ na2) return FALSE;
	    if(na1 && na2) continue;
	    if (! Seql(STRING_ELT(x, i), STRING_ELT(y, i))) return FALSE;
	}
	return TRUE;
    }
    case CHARSXP: /* Probably unreachable, but better safe than sorry... */
    {
	/* This matches NAs */
	return Seql(x, y);
    }
    case VECSXP:
    case EXPRSXP:
    {
	int i, n = length(x);
	if(n != length(y)) return FALSE;
	for(i = 0; i < n; i++)
	    if(!R_compute_identical(VECTOR_ELT(x, i),VECTOR_ELT(y, i), flags))
		return FALSE;
	return TRUE;
    }
    case LANGSXP:
    case LISTSXP:
    {
	while (x != R_NilValue) {
	    if(y == R_NilValue)
		return FALSE;
	    if(!R_compute_identical(CAR(x), CAR(y), flags))
		return FALSE;
	    if(!R_compute_identical(PRINTNAME(TAG(x)), PRINTNAME(TAG(y)), flags))
		return FALSE;
	    x = CDR(x);
	    y = CDR(y);
	}
	return(y == R_NilValue);
    }
    case CLOSXP:
	return(R_compute_identical(FORMALS(x), FORMALS(y), flags) &&
	       R_compute_identical(BODY_EXPR(x), BODY_EXPR(y), flags) &&
	       (CLOENV(x) == CLOENV(y) ? TRUE : FALSE) &&
	       (IGNORE_BYTECODE || R_compute_identical(BODY(x), BODY(y), flags))
	       );
    case SPECIALSXP:
    case BUILTINSXP:
	return(PRIMOFFSET(x) == PRIMOFFSET(y) ? TRUE : FALSE);
    case ENVSXP:
    case SYMSXP:
    case WEAKREFSXP:
    case BCODESXP: /**** is this the best approach? */
	return(x == y ? TRUE : FALSE);
    case EXTPTRSXP:
	return (EXTPTR_PTR(x) == EXTPTR_PTR(y) ? TRUE : FALSE);
    case RAWSXP:
	if (length(x) != length(y)) return FALSE;
	/* Use memcmp (which is ISO C90) to speed up the comparison */
	return memcmp((void *)RAW(x), (void *)RAW(y),
		      length(x) * sizeof(Rbyte)) == 0 ? TRUE : FALSE;

/*  case PROMSXP: args are evaluated, so will not be seen */
	/* test for equality of the substituted expression -- or should
	   we require both expression and environment to be identical? */
	/*#define PREXPR(x)	((x)->u.promsxp.expr)
	  #define PRENV(x)	((x)->u.promsxp.env)
	  return(R_compute_identical(subsititute(PREXPR(x), PRENV(x),
	                             flags),
	  subsititute(PREXPR(y), PRENV(y))));*/
    case S4SXP:
	/* attributes already tested, so all slots identical */
	return TRUE;
    default:
	/* these are all supposed to be types that represent constant
	   entities, so no further testing required ?? */
	printf("Unknown Type: %s (%x)\n", type2char(TYPEOF(x)), TYPEOF(x));
	return TRUE;
    }
}
Example #16
0
mrb_value
node_to_value_with_aliases(mrb_state *mrb,
  yaml_document_t *document, yaml_node_t *node, int use_scalar_aliases)
{
  /* YAML will return a NULL node if the input was empty */
  if (!node)
    return mrb_nil_value();

  switch (node->type)
  {
    case YAML_SCALAR_NODE:
    {
      const char *str = (char *) node->data.scalar.value;
      char *endptr;
      long long ll;
      double dd;

      /* if node is a YAML_PLAIN_SCALAR_STYLE */
      if (node->data.scalar.style == YAML_PLAIN_SCALAR_STYLE) {
        if (streql("~", str)) return mrb_nil_value();

        if (use_scalar_aliases) {
          /* Check if it is a null http://yaml.org/type/null.html */
          if (streql("nil", str) || streql("", str)
          #if MRUBY_YAML_NULL
            || streql("null", str) || streql("Null", str) || streql("NULL", str)
          #endif
            ) {
            return mrb_nil_value();
          /* Check if it is a Boolean http://yaml.org/type/bool.html */
          } else if (
            streql("true", str) || streql("True", str) || streql("TRUE", str)
          #if MRUBY_YAML_BOOLEAN_ON
            || streql("on", str) || streql("On", str) || streql("ON", str)
          #endif
          #if MRUBY_YAML_BOOLEAN_YES
            || streql("yes", str) || streql("Yes", str) || streql("YES", str)
          #endif
          #if MRUBY_YAML_BOOLEAN_SHORTHAND_YES
            || streql("y", str) || streql("Y", str)
          #endif
            ) {
            return mrb_true_value();
          } else if (
            streql("false", str) || streql("False", str) || streql("FALSE", str)
          #if MRUBY_YAML_BOOLEAN_OFF
            || streql("off", str) || streql("Off", str) || streql("OFF", str)
          #endif
          #if MRUBY_YAML_BOOLEAN_NO
            || streql("no", str) || streql("No", str)  || streql("NO", str)
          #endif
          #if MRUBY_YAML_BOOLEAN_SHORTHAND_NO
            || streql("n", str) || streql("N", str)
          #endif
            ) {
            return mrb_false_value();
          }
        }

        /* Check if it is a Fixnum */
        ll = strtoll(str, &endptr, 0);
        if (str != endptr && *endptr == '\0')
          return mrb_fixnum_value(ll);

        /* Check if it is a Float */
        dd = strtod(str, &endptr);
        if (str != endptr && *endptr == '\0')
          return mrb_float_value(mrb, dd);
      }

      /* Otherwise it is a String */
      return mrb_str_new(mrb, str, node->data.scalar.length);
    }

    case YAML_SEQUENCE_NODE:
    {
      /* Sequences are arrays in Ruby */
      mrb_value result = mrb_ary_new(mrb);
      yaml_node_item_t *item;

      int ai = mrb_gc_arena_save(mrb);

      for (item = node->data.sequence.items.start;
        item < node->data.sequence.items.top; item++)
      {
        yaml_node_t *child_node = yaml_document_get_node(document, *item);
        mrb_value child = node_to_value(mrb, document, child_node);

        mrb_ary_push(mrb, result, child);
        mrb_gc_arena_restore(mrb, ai);
      }

      return result;
    }

    case YAML_MAPPING_NODE:
    {
      /* Mappings are hashes in Ruby */
      mrb_value result = mrb_hash_new(mrb);
      yaml_node_t *key_node;
      yaml_node_t *value_node;
      yaml_node_pair_t *pair;
      mrb_value key, value;

      int ai = mrb_gc_arena_save(mrb);

      for (pair = node->data.mapping.pairs.start;
        pair < node->data.mapping.pairs.top; pair++)
      {
        key_node = yaml_document_get_node(document, pair->key);
        value_node = yaml_document_get_node(document, pair->value);

        key = node_to_value_key(mrb, document, key_node);
        value = node_to_value(mrb, document, value_node);

        mrb_hash_set(mrb, result, key, value);
        mrb_gc_arena_restore(mrb, ai);
      }

      return result;
    }

    default:
      return mrb_nil_value();
  }
}
Example #17
0
#include "assert.h"
#include "stdlib.h"
#include "stdio.h"
#include "allegro.h"
#include "string.h"
#include "ctype.h"
//#include "memory.h"
#include "trace.h"
#include "strparse.h"
#ifndef EXPERIMENTAL_NOTE_TRACK
#include "allegrord.h"
#endif /* EXPERIMENTAL_NOTE_TRACK */
#define streql(s1, s2) (strcmp(s1, s2) == 0)
#define field_max 80


//Note that this is an #ifdef, not an #ifndef
#ifdef EXPERIMENTAL_NOTE_TRACK

class Alg_reader {
public:
    FILE *file;
    int line_no;
    String_parse line_parser;
    bool line_parser_flag;
    char field[field_max];
    bool error_flag;
    Alg_seq_ptr seq;
    double tsnum;
    double tsden;

    Alg_reader(FILE *a_file, Alg_seq_ptr new_seq);
    void readline();
    Alg_parameters_ptr process_attributes(Alg_parameters_ptr attributes, double time);
    bool parse();
    long parse_chan(char *field);
    long parse_int(char *field);
    int find_real_in(char *field, int n);
    double parse_real(char *field);
    void parse_error(char *field, long offset, char *message);
    double parse_dur(char *field, double base);
    double parse_after_dur(double dur, char *field, int n, double base);
    double parse_loud(char *field);
    long parse_key(char *field);
    double parse_pitch(char *field);
    long parse_after_key(int key, char *field, int n);
    long find_int_in(char *field, int n);
    bool parse_attribute(char *field, Alg_parameter_ptr parm);
    bool parse_val(Alg_parameter_ptr param, char *s, int i);
    bool check_type(char type_char, Alg_parameter_ptr param);
};

#endif /* EXPERIMENTAL_NOTE_TRACK */

void subseq(char *result, char *source, int from, int to)
{
    memcpy(result, source + from, to - from);
    result[to - from] = 0;
}

#ifndef EXPERIMENTAL_NOTE_TRACK
double Allegro_reader::parse_pitch(char *field)
#else /* EXPERIMENTAL_NOTE_TRACK */
double Alg_reader::parse_pitch(char *field)
#endif /* EXPERIMENTAL_NOTE_TRACK */
{
    if (isdigit(field[1])) {
        char real_string[80];
        int last = find_real_in(field, 1);
        subseq(real_string, field, 1, last);
        return atof(real_string);
    } else {
        return (double) parse_key(field);
    }
}


#ifndef EXPERIMENTAL_NOTE_TRACK
Allegro_reader::Allegro_reader(FILE *a_file)
{
    file = a_file; // save the file
    line_parser_flag = false;
    line_no = 0;
    seq = Seq();
    tsnum = 4; // default time signature
    tsden = 4;
}
#else /* EXPERIMENTAL_NOTE_TRACK */
// it is the responsibility of the caller to delete
// the seq
Alg_reader::Alg_reader(FILE *a_file, Alg_seq_ptr new_seq)
{
    file = a_file; // save the file
    line_parser_flag = false;
    line_no = 0;
    tsnum = 4; // default time signature
    tsden = 4;
    seq = new_seq;
}
#endif /* EXPERIMENTAL_NOTE_TRACK */


//Note that this is an #ifdef, not an #ifndef
#ifdef EXPERIMENTAL_NOTE_TRACK
Alg_seq_ptr alg_read(FILE *file, Alg_seq_ptr new_seq)
    // read a sequence from allegro file
{
    if (!new_seq) new_seq = new Alg_seq();
    Alg_reader alg_reader(file, new_seq);
    alg_reader.parse();
    return alg_reader.seq;
}
#endif /* EXPERIMENTAL_NOTE_TRACK */


#ifndef EXPERIMENTAL_NOTE_TRACK
void Allegro_reader::readline()
#else /* EXPERIMENTAL_NOTE_TRACK */
void Alg_reader::readline()
#endif /* EXPERIMENTAL_NOTE_TRACK */
{
    char line[256];
    char *line_flag = fgets(line, 256, file);
    line_parser_flag = false;
    if (line_flag) {
        line_parser.init(line);
        line_parser_flag = true;
        error_flag = false;
    }
}


#ifndef EXPERIMENTAL_NOTE_TRACK
void Allegro_reader::process_attributes(Parameters_ptr attributes, double time)
{
    // print "process_attributes:", attributes
    bool ts_flag;
    if (attributes) {
        Parameters_ptr a;
        if (a = Parameters::remove_key(&attributes, "tempor")) {
            double tempo = a->parm.r;
            seq.insert_tempo(tempo, seq.map.time_to_beat(time));
        }
        if (a = Parameters::remove_key(&attributes, "beatr")) {
            double beat = a->parm.r;
            seq.insert_beat(time, beat);
        }
        if (a = Parameters::remove_key(&attributes, "tsnumr")) {
            tsnum = a->parm.r;
            ts_flag = true;
        }
        if (a = Parameters::remove_key(&attributes, "tsdenr")) {
            tsden = a->parm.r;
            ts_flag = true;
        }
        if (ts_flag) {
            seq.set_time_sig(seq.map.time_to_beat(time), tsnum, tsden);
        }
    }
}
#else /* EXPERIMENTAL_NOTE_TRACK */
Alg_parameters_ptr Alg_reader::process_attributes(
        Alg_parameters_ptr attributes, double time)
{
    // print "process_attributes:", attributes
    bool ts_flag = false;
    if (attributes) {
        Alg_parameters_ptr a;
        bool in_seconds = seq->get_units_are_seconds();
        if (a = Alg_parameters::remove_key(&attributes, "tempor")) {
            double tempo = a->parm.r;
            seq->insert_tempo(tempo, seq->get_time_map()->time_to_beat(time));
        }
        if (a = Alg_parameters::remove_key(&attributes, "beatr")) {
            double beat = a->parm.r;
            seq->insert_beat(time, beat);
        }
        if (a = Alg_parameters::remove_key(&attributes, "timesig_numr")) {
            tsnum = a->parm.r;
            ts_flag = true;
        }
        if (a = Alg_parameters::remove_key(&attributes, "timesig_denr")) {
            tsden = a->parm.r;
            ts_flag = true;
        }
        if (ts_flag) {
            seq->set_time_sig(seq->get_time_map()->time_to_beat(time),
            tsnum, tsden);
        }
        if (in_seconds) seq->convert_to_seconds();
    }
    return attributes; // in case it was modified
}
#endif /* EXPERIMENTAL_NOTE_TRACK */

#ifndef EXPERIMENTAL_NOTE_TRACK
bool Allegro_reader::parse()
{
    int voice = 0;
    int key = 60;
    double loud = 100.0;
    double pitch = 60.0;
    double dur = 1.0;
    double time = 0.0;
    readline();
    bool valid = false; // ignore blank lines
    while (line_parser_flag) {
        bool time_flag = false;
        bool next_flag = false;
        double next;
        bool voice_flag = false;
        bool loud_flag = false;
        bool dur_flag = false;
        bool new_pitch_flag = false; // "P" syntax
        double new_pitch = 0.0;
        bool new_key_flag = false;   // "K" syntax
        int new_key = 0;
        bool new_note_flag = false;  // "A"-"G" syntax
        int new_note = 0;
        Parameters_ptr attributes = NULL;
        line_parser.get_nonspace_quoted(field);
        char pk = line_parser.peek();
        if (pk && !isspace(pk)) {
            line_parser.get_nonspace_quoted(field + strlen(field));
        }
        while (field[0]) {
            // print "field", "|";field;"|", "|";line_parser.string;"|", line_parser.pos
            char first = toupper(field[0]);
            if (strchr("ABCDEFGKLPUSIQHW-", first)) {
                valid = true; // it's a note or event
            }
            if (first == 'V') {
                if (voice_flag) {
                    parse_error(field, 0, "Voice specified twice");
                } else {
                    voice = parse_int(field);
                }
                voice_flag = true;
            } else if (first == 'T') {
                if (time_flag) {
                    parse_error(field, 0, "Time specified twice");
                } else {
                    time = parse_dur(field, 0.0);
                }
                time_flag = true;
            } else if (first == 'N') {
                if (next_flag) {
                    parse_error(field, 0, "Next specified twice");
                } else {
                    next = parse_dur(field, time);
                }
                next_flag = true;
            } else if (first == 'K') {
                if (new_key_flag) {
                    parse_error(field, 0, "Key specified twice");
                } else {
                    new_key = parse_key(field);
                    new_key_flag = true;
                }
            } else if (first == 'L') {
                if (loud_flag) {
                    parse_error(field, 0, "Loudness specified twice");
                } else {
                    loud = parse_loud(field);
                }
                loud_flag = true;
            } else if (first == 'P') {
                if (new_note_flag || new_pitch_flag) {
                    parse_error(field, 0, "Pitch specified twice");
                } else {
                    new_pitch = parse_pitch(field);
                    new_pitch_flag = true;
                }
            } else if (first == 'U') {
                if (dur_flag) {
                    parse_error(field, 0, "Dur specified twice");
                } else {
                    dur = parse_dur(field, time);
                    dur_flag = true;
                }
            } else if (strchr("SIQHW", first)) {
                if (dur_flag) {
                    parse_error(field, 0, "Dur specified twice");
                } else {
                    // prepend 'U' to field, copy EOS too
                    memmove(field + 1, field, strlen(field) + 1);
                    field[0] = 'U';
                    dur = parse_dur(field, time);
                    dur_flag = true;
                }
            } else if (strchr("ABCDEFG", first)) {
                if (new_note_flag || new_pitch_flag) {
                    parse_error(field, 0, "Pitch specified twice");
                } else {
                    // prepend 'K' to field, copy EOS too
                    memmove(field + 1, field, strlen(field) + 1);
                    field[0] = 'K';
                    new_note = parse_key(field);
                    new_note_flag = true;
                }
            } else if (first == '-') {
                Parameter parm;
                if (parse_attribute(field, &parm)) { // enter attribute-value pair
                    attributes = new Parameters(attributes);
                    attributes->parm = parm;
                    parm.s = NULL; // protect string from deletion by destructor
                }
            } else {
                parse_error(field, 0, "Unknown field");
            }

            if (error_flag) {
                field[0] = 0; // exit the loop
            } else {
                line_parser.get_nonspace_quoted(field);
                pk = line_parser.peek();
                if (pk && !isspace(pk)) {
                    line_parser.get_nonspace_quoted(field + strlen(field));
                }
            }
        }
        // a case analysis:
        // Key < 128 counts as both key and pitch
        // A-G implies pitch AND key unless key given too
        //   K60 P60 -- both are specified, use 'em
        //   K60 P60 C4 -- overconstrained, an error
        //   K60 C4 -- overconstrained
        //   K60 -- OK, pitch is 60
        //   C4 P60 -- over constrained
        //   P60 -- OK, key is from before, pitch is 60
        //   C4 -- OK, key is 60, pitch is 60
        //   <nothing> -- OK, key and pitch from before
        //   K200 with P60 ok, pitch is 60
        //   K200 with neither P60 nor C4 uses 
        //       pitch from before
        // figure out what the key/instance is:
        if (new_key_flag) { // it was directly specified
            key = new_key;
            if (key < 128 && new_note_flag) {
                parse_error("", 0, "Pitch specified twice");
            }
        } else if (new_note_flag) { // "A"-"G" used
            key = new_note;
        }
        if (new_pitch_flag) {
            pitch = new_pitch;
        } else if (key < 128) {
            pitch = key;
        }
        // now we've acquired new parameters
        // if (it is a note, then enter the note
        if (valid) {
            // change tempo or beat
            process_attributes(attributes, time);
            // if there's a duration or pitch, make a note:
            if (new_pitch_flag || dur_flag || new_note_flag) {
                new_key_flag = false;
                new_pitch_flag = false;
                Allegro_note_ptr note_ptr = new Allegro_note;
                note_ptr->chan = voice;
                note_ptr->time = time;
                note_ptr->dur = dur;
                note_ptr->key = key;
                note_ptr->pitch = pitch;
                note_ptr->loud = loud;
                note_ptr->parameters = attributes;
                seq.add_event(note_ptr); // sort later
            } else {
                int update_key = -1;
                // key or pitch must appear explicitly; otherwise
                //    update applies to channel
                if (new_key_flag || new_pitch_flag) {
                    update_key = key;
                }
                if (loud_flag) {
                    Allegro_update_ptr new_upd = new Allegro_update;
                    new_upd->chan = voice;
                    new_upd->time = time;
                    new_upd->key = update_key;
                    new_upd->parameter.set_attr(symbol_table.insert_string("loudr"));
                    new_upd->parameter.r = pitch;
                    seq.add_event(new_upd);
                }
                if (attributes) {
                    while (attributes) {
                        Allegro_update_ptr new_upd = new Allegro_update;
                        new_upd->chan = voice;
                        new_upd->time = time;
                        new_upd->key = update_key;
                        new_upd->parameter = attributes->parm;
                        seq.add_event(new_upd);
                        Parameters_ptr p = attributes;
                        attributes = attributes->next;
                        delete p;
                    }
                }
            }
            if (next_flag) {
                time = time + next;
            } else if (dur_flag) {
                time = time + dur;
            }
        }
        readline();
    }
    //print "Finished reading score"
    if (!error_flag) {
        seq.convert_to_seconds(); // make sure format is correct
        // seq.notes.sort('event_greater_than');
    }
    // print "parse returns error_flag", error_flag
    return error_flag;
}
#else /* EXPERIMENTAL_NOTE_TRACK */
bool Alg_reader::parse()
{
    int voice = 0;
    int key = 60;
    double loud = 100.0;
    double pitch = 60.0;
    double dur = 1.0;
    double time = 0.0;
    int track_num = 0;
    seq->convert_to_seconds();
    //seq->set_real_dur(0.0); // just in case it's not initialized already
    readline();
    bool valid = false; // ignore blank lines
    while (line_parser_flag) {
        bool time_flag = false;
        bool next_flag = false;
        double next;
        bool voice_flag = false;
        bool loud_flag = false;
        bool dur_flag = false;
        bool new_pitch_flag = false; // "P" syntax
        double new_pitch = 0.0;
        bool new_key_flag = false;   // "K" syntax
        int new_key = 0;
        bool new_note_flag = false;  // "A"-"G" syntax
        int new_note = 0;
        Alg_parameters_ptr attributes = NULL;
        if (line_parser.peek() == '#') {
            // look for #track
            line_parser.get_nonspace_quoted(field);
            if (streql(field, "#track")) {
                line_parser.get_nonspace_quoted(field); // number
                track_num = parse_int(field - 1);
                seq->add_track(track_num);
            }
            // maybe we have a comment
        } else {
            // we must have a track to insert into
            if (seq->tracks() == 0) seq->add_track(0);
            line_parser.get_nonspace_quoted(field);
            char pk = line_parser.peek();
            // attributes are parsed as two adjacent nonspace_quoted tokens
            // so we have to conditionally call get_nonspace_quoted() again
            if (pk && !isspace(pk)) {
                line_parser.get_nonspace_quoted(field + strlen(field));
            }
            while (field[0]) {
                char first = toupper(field[0]);
                if (strchr("ABCDEFGKLPUSIQHW-", first)) {
                    valid = true; // it's a note or event
                }
                if (first == 'V') {
                    if (voice_flag) {
                        parse_error(field, 0, "Voice specified twice");
                    } else {
                        voice = parse_chan(field);
                    }
                    voice_flag = true;
                } else if (first == 'T') {
                    if (time_flag) {
                        parse_error(field, 0, "Time specified twice");
                    } else {
                        time = parse_dur(field, 0.0);
                    }
                    time_flag = true;
                } else if (first == 'N') {
                    if (next_flag) {
                        parse_error(field, 0, "Next specified twice");
                    } else {
                        next = parse_dur(field, time);
                    }
                    next_flag = true;
                } else if (first == 'K') {
                    if (new_key_flag) {
                        parse_error(field, 0, "Key specified twice");
                    } else {
                        new_key = parse_key(field);
                        new_key_flag = true;
                    }
                } else if (first == 'L') {
                    if (loud_flag) {
                        parse_error(field, 0, "Loudness specified twice");
                    } else {
                        loud = parse_loud(field);
                    }
                    loud_flag = true;
                } else if (first == 'P') {
                    if (new_note_flag || new_pitch_flag) {
                        parse_error(field, 0, "Pitch specified twice");
                    } else {
                        new_pitch = parse_pitch(field);
                        new_pitch_flag = true;
                    }
                } else if (first == 'U') {
                    if (dur_flag) {
                        parse_error(field, 0, "Dur specified twice");
                    } else {
                        dur = parse_dur(field, time);
                        dur_flag = true;
                    }
                } else if (strchr("SIQHW", first)) {
                    if (dur_flag) {
                        parse_error(field, 0, "Dur specified twice");
                    } else {
                        // prepend 'U' to field, copy EOS too
                        memmove(field + 1, field, strlen(field) + 1);
                        field[0] = 'U';
                        dur = parse_dur(field, time);
                        dur_flag = true;
                    }
                } else if (strchr("ABCDEFG", first)) {
                    if (new_note_flag || new_pitch_flag) {
                        parse_error(field, 0, "Pitch specified twice");
                    } else {
                        // prepend 'K' to field, copy EOS too
                        memmove(field + 1, field, strlen(field) + 1);
                        field[0] = 'K';
                        new_note = parse_key(field);
                        new_note_flag = true;
                    }
                } else if (first == '-') {
                    Alg_parameter parm;
                    if (parse_attribute(field, &parm)) { // enter attribute-value pair
                        attributes = new Alg_parameters(attributes);
                        attributes->parm = parm;
                        parm.s = NULL; // protect string from deletion by destructor
                    }
                } else {
                    parse_error(field, 0, "Unknown field");
                }

                if (error_flag) {
                    field[0] = 0; // exit the loop
                } else {
                    line_parser.get_nonspace_quoted(field);
                    pk = line_parser.peek();
                    // attributes are parsed as two adjacent nonspace_quoted 
                    // tokens so we have to conditionally call 
                    // get_nonspace_quoted() again
                    if (pk && !isspace(pk)) {
                        line_parser.get_nonspace_quoted(field + strlen(field));
                    }
                }
            }
            // a case analysis:
            // Key < 128 counts as both key and pitch
            // A-G implies pitch AND key unless key given too
            //   K60 P60 -- both are specified, use 'em
            //   K60 P60 C4 -- overconstrained, an error
            //   K60 C4 -- overconstrained
            //   K60 -- OK, pitch is 60
            //   C4 P60 -- over constrained
            //   P60 -- OK, key is from before, pitch is 60
            //   C4 -- OK, key is 60, pitch is 60
            //   <nothing> -- OK, key and pitch from before
            //   K200 with P60 ok, pitch is 60
            //   K200 with neither P60 nor C4 uses 
            //       pitch from before
            // figure out what the key/instance is:
            if (new_key_flag) { // it was directly specified
                key = new_key;
                if (key < 128 && new_note_flag) {
                    parse_error("", 0, "Pitch specified twice");
                }
            } else if (new_note_flag) { // "A"-"G" used
                key = new_note;
            }
            if (new_pitch_flag) {
                pitch = new_pitch;
            } else if (key < 128) {
                pitch = key;
            }
            // now we've acquired new parameters
            // if (it is a note, then enter the note
            if (valid) {
                // change tempo or beat
                attributes = process_attributes(attributes, time);
                // if there's a duration or pitch, make a note:
                if (new_pitch_flag || dur_flag || new_note_flag) {
                    new_key_flag = false;
                    new_pitch_flag = false;
                    Alg_note_ptr note_ptr = new Alg_note;
                    note_ptr->chan = voice;
                    note_ptr->time = time;
                    note_ptr->dur = dur;
                    note_ptr->set_identifier(key);
                    note_ptr->pitch = pitch;
                    note_ptr->loud = loud;
                    note_ptr->parameters = attributes;
                    seq->add_event(note_ptr, track_num); // sort later
                    if (seq->get_real_dur() < (time + dur)) seq->set_real_dur(time + dur);
                } else {
                    int update_key = -1;
                    // key or pitch must appear explicitly; otherwise
                    //    update applies to channel
                    if (new_key_flag || new_pitch_flag) {
                        update_key = key;
                    }
                    if (loud_flag) {
                        Alg_update_ptr new_upd = new Alg_update;
                        new_upd->chan = voice;
                        new_upd->time = time;
                        new_upd->set_identifier(update_key);
                        new_upd->parameter.set_attr(symbol_table.insert_string("loudr"));
                        new_upd->parameter.r = pitch;
                        seq->add_event(new_upd, track_num);
                        if (seq->get_real_dur() < time) seq->set_real_dur(time);
                    }
                    if (attributes) {
                        while (attributes) {
                            Alg_update_ptr new_upd = new Alg_update;
                            new_upd->chan = voice;
                            new_upd->time = time;
                            new_upd->set_identifier(update_key);
                            new_upd->parameter = attributes->parm;
                            seq->add_event(new_upd, track_num);
                            Alg_parameters_ptr p = attributes;
                            attributes = attributes->next;
                            p->parm.s = NULL; // so we don't delete the string
                            delete p;
                        }
                    }
                }
                if (next_flag) {
                    time = time + next;
                } else if (dur_flag) {
                    time = time + dur;
                }
            }
        }
        readline();
    }
    //print "Finished reading score"
    if (!error_flag) {
        seq->convert_to_seconds(); // make sure format is correct
        // seq->notes.sort('event_greater_than');
    }
    // real_dur is valid, translate to beat_dur
    seq->set_beat_dur((seq->get_time_map())->time_to_beat(seq->get_real_dur()));
    // print "parse returns error_flag", error_flag
    return error_flag;
}
#endif /* EXPERIMENTAL_NOTE_TRACK */


//Note that this is an #ifdef, not an #ifndef
#ifdef EXPERIMENTAL_NOTE_TRACK
long Alg_reader::parse_chan(char *field)
{
    char *int_string = field + 1;
    char *msg = "Integer or - expected";
    char *p = int_string;
    char c;
    // check that all chars in int_string are digits or '-':
    while (c = *p++) {
        if (!isdigit(c) && c != '-') {
            parse_error(field, p - field - 1, msg);
            return 0;
        }
    }
    p--; // p now points to end-of-string character
    if (p - int_string == 0) {
        // bad: string length is zero
        parse_error(field, 1, msg);
        return 0;
    }
    if (p - int_string == 1 && int_string[0] == '-') {
        // special case: entire string is "-", interpret as -1
        return -1;
    }
    return atoi(int_string);
}
#endif /* EXPERIMENTAL_NOTE_TRACK */


#ifndef EXPERIMENTAL_NOTE_TRACK
long Allegro_reader::parse_int(char *field)
{
    char int_string[field_max];
    strcpy(int_string, field + 1);
    char *msg = "Integer expected";
    char *p = int_string;
    char c;
    while (c = *p++) {
        if (!isdigit(c)) {
            parse_error(field, 1, msg);
            return 0;
        }
    }
    if (strlen(int_string) < 1) {
        parse_error(field, 1, msg);
        return 0;
    }
    return atoi(int_string);
}
#else /* EXPERIMENTAL_NOTE_TRACK */
long Alg_reader::parse_int(char *field)
{
    char *int_string = field + 1;
    char *msg = "Integer expected";
    char *p = int_string;
    char c;
    // check that all chars in int_string are digits:
    while (c = *p++) {
        if (!isdigit(c)) {
            parse_error(field, p - field - 1, msg);
            return 0;
        }
    }
    p--; // p now points to end-of-string character
    if (p - int_string == 0) {
        // bad: string length is zero
        parse_error(field, 1, msg);
        return 0;
    }
    return atoi(int_string);
}
#endif /* EXPERIMENTAL_NOTE_TRACK */


#ifndef EXPERIMENTAL_NOTE_TRACK
int Allegro_reader::find_real_in(char *field, int n)
#else /* EXPERIMENTAL_NOTE_TRACK */
int Alg_reader::find_real_in(char *field, int n)
#endif /* EXPERIMENTAL_NOTE_TRACK */
{
    // scans from offset n to the end of a real constant
    bool decimal = false;
    int len = strlen(field);
    for (int i = n; i < len; i++) {
        char c = field[i];
        if (!isdigit(c)) {
            if (c == '.' && !decimal) {
                decimal = true;
            } else {
                return i;
            }
        }
    }
    return strlen(field);
}


#ifndef EXPERIMENTAL_NOTE_TRACK
double Allegro_reader::parse_real(char *field)
#else /* EXPERIMENTAL_NOTE_TRACK */
double Alg_reader::parse_real(char *field)
#endif /* EXPERIMENTAL_NOTE_TRACK */
{
    char real_string[80];
    char *msg = "Real expected";
    bool decimal = false;
    int last = find_real_in(field, 1);
    subseq(real_string, field, 1, last);
    if (last <= 1 || last < (int) strlen(field)) {
       parse_error(field, 1, msg);
       return 0;
    }
    return atof(real_string);
}


#ifndef EXPERIMENTAL_NOTE_TRACK
void Allegro_reader::parse_error(char *field, long offset, char *message)
#else /* EXPERIMENTAL_NOTE_TRACK */
void Alg_reader::parse_error(char *field, long offset, char *message)
#endif /* EXPERIMENTAL_NOTE_TRACK */
{
    int position = line_parser.pos - strlen(field) + offset;
    error_flag = true;
    puts(line_parser.string);
    for (int i = 0; i < position; i++) {
        putc(' ', stdout);
    }
    putc('^', stdout);
    printf("    %s\n", message);
}


double duration_lookup[] = { 0.25, 0.5, 1.0, 2.0, 4.0 };


#ifndef EXPERIMENTAL_NOTE_TRACK
double Allegro_reader::parse_dur(char *field, double base)
{
    char *msg = "Duration expected";
    char real_string[80];
    char *durs = "SIQHW";
    char *p;
    int last;
    double dur;
    if (strlen(field) < 2) {
        // fall through to error message
        return -1;
    } else if (isdigit(field[1])) {
        last = find_real_in(field, 1);
        subseq(real_string, field, 1, last);
        dur = atof(real_string);
        // convert dur from seconds to beats
        dur = seq.map.time_to_beat(base + dur) - seq.map.time_to_beat(base);
    } else if (p = strchr(durs, field[1])) {
        dur = duration_lookup[p - durs];
        last = 2;
    } else {
        parse_error(field, 1, msg);
        return 0;
    }
    dur = parse_after_dur(dur, field, last, base);
    dur = seq.map.beat_to_time(seq.map.time_to_beat(base) + dur) - base;
    return dur;
}
#else /* EXPERIMENTAL_NOTE_TRACK */
double Alg_reader::parse_dur(char *field, double base)
{
    char *msg = "Duration expected";
    char real_string[80];
    char *durs = "SIQHW";
    char *p;
    int last;
    double dur;
    if (strlen(field) < 2) {
        // fall through to error message
        return -1;
    } else if (isdigit(field[1])) {
        last = find_real_in(field, 1);
        subseq(real_string, field, 1, last);
        dur = atof(real_string);
        // convert dur from seconds to beats
        dur = seq->get_time_map()->time_to_beat(base + dur) - 
              seq->get_time_map()->time_to_beat(base);
    } else if (p = strchr(durs, field[1])) {
        dur = duration_lookup[p - durs];
        last = 2;
    } else {
        parse_error(field, 1, msg);
        return 0;
    }
    dur = parse_after_dur(dur, field, last, base);
    dur = seq->get_time_map()->beat_to_time(
              seq->get_time_map()->time_to_beat(base) + dur) - base;
    return dur;
}
#endif /* EXPERIMENTAL_NOTE_TRACK */


#ifndef EXPERIMENTAL_NOTE_TRACK
double Allegro_reader::parse_after_dur(double dur, char *field, int n, double base)
{
    char a_string[80];
    if ((int) strlen(field) == n) {
        return dur;
    }
    if (field[n] == 'T') {
        return parse_after_dur(dur * 2/3, field, n + 1, base);
    }
    if (field[n] == '.') {
        return parse_after_dur(dur * 1.5, field, n + 1, base);
    }
    if (isdigit(field[n])) {
        int last = find_real_in(field, n);
        subseq(a_string, field, n, last);
        double f = atof(a_string);
        return parse_after_dur(dur * f, field, last, base);
    }
    if (field[n] == '+') {
        subseq(a_string, field, n + 1, -1);
        return dur + parse_dur(a_string, 
                               seq.map.beat_to_time(
                                   seq.map.time_to_beat(base) + dur));
    }
    parse_error(field, n, "Unexpected character in duration");
    return dur;
}
#else /* EXPERIMENTAL_NOTE_TRACK */
double Alg_reader::parse_after_dur(double dur, char *field, int n, double base)
{
    char a_string[80];
    if ((int) strlen(field) == n) {
        return dur;
    }
    if (field[n] == 'T') {
        return parse_after_dur(dur * 2/3, field, n + 1, base);
    }
    if (field[n] == '.') {
        return parse_after_dur(dur * 1.5, field, n + 1, base);
    }
    if (isdigit(field[n])) {
        int last = find_real_in(field, n);
        subseq(a_string, field, n, last);
        double f = atof(a_string);
        return parse_after_dur(dur * f, field, last, base);
    }
    if (field[n] == '+') {
        subseq(a_string, field, n + 1, -1);
        return dur + parse_dur(
                a_string, seq->get_time_map()->beat_to_time(
                              seq->get_time_map()->time_to_beat(base) + dur));
    }
    parse_error(field, n, "Unexpected character in duration");
    return dur;
}
#endif /* EXPERIMENTAL_NOTE_TRACK */

#ifndef EXPERIMENTAL_NOTE_TRACK
static struct {
#else /* EXPERIMENTAL_NOTE_TRACK */
struct loud_lookup_struct {
#endif /* EXPERIMENTAL_NOTE_TRACK */
    char *str;
    int val;
} loud_lookup[] = { {"FFF", 127}, {"FF", 120}, {"F", 110}, {"MF", 100}, 
                    {"MP", 90}, {"P", 80}, {"PP", 70}, {"PPP", 60}, 
                    {NULL, 0} };


#ifndef EXPERIMENTAL_NOTE_TRACK
double Allegro_reader::parse_loud(char *field)
{
    char *msg = "Loudness expected";
    if (isdigit(field[1])) {
        return parse_int(field);
    } else {
        double loud = 0.0;
        char dyn[field_max];
        strcpy(dyn, field + 1);
        char *p = dyn;
        while (*p) {
            if (isupper(*p)) *p = toupper(*p);
        }
        for (int i = 0; loud_lookup[i].str; i++) {
            if (streql(loud_lookup[i].str, dyn)) {
                return (double) loud_lookup[i].val;
            }
        }
    }
    parse_error(field, 1, msg);
    return 100.0;
}
#else /* EXPERIMENTAL_NOTE_TRACK */
double Alg_reader::parse_loud(char *field)
{
    char *msg = "Loudness expected";
    if (isdigit(field[1])) {
        return parse_int(field);
    } else {
        double loud = 0.0;
        char dyn[field_max];
        strcpy(dyn, field + 1);
        char *p = dyn;
        while (*p) {
            if (islower(*p)) *p = toupper(*p);
        p++;
        }
        for (int i = 0; loud_lookup[i].str; i++) {
            if (streql(loud_lookup[i].str, dyn)) {
                return (double) loud_lookup[i].val;
            }
        }
    }
    parse_error(field, 1, msg);
    return 100.0;
}
#endif /* EXPERIMENTAL_NOTE_TRACK */


int key_lookup[] = {21, 23, 12, 14, 16, 17, 19};

#ifndef EXPERIMENTAL_NOTE_TRACK
long Allegro_reader::parse_key(char *field)
#else /* EXPERIMENTAL_NOTE_TRACK */
long Alg_reader::parse_key(char *field)
#endif /* EXPERIMENTAL_NOTE_TRACK */
{
    char *msg = "Pitch expected";
    char *pitches = "ABCDEFG";
    char *p;
    if (isdigit(field[1])) {
        return parse_int(field);
    } else if (p = strchr(pitches, field[1])) {
        long key = key_lookup[p - pitches];
        key = parse_after_key(key, field, 2);
        return key;
    }
    parse_error(field, 1, msg);
    return 0;
}


#ifndef EXPERIMENTAL_NOTE_TRACK
long Allegro_reader::parse_after_key(int key, char *field, int n)
#else /* EXPERIMENTAL_NOTE_TRACK */
long Alg_reader::parse_after_key(int key, char *field, int n)
#endif /* EXPERIMENTAL_NOTE_TRACK */
{
    char octave[20];
    if ((int) strlen(field) == n) {
        return key;
    }
    char c = toupper(field[n]);
    if (c == 'S') {
        return parse_after_key(key + 1, field, n + 1);
    }
    if (c == 'F') {
        return parse_after_key(key - 1, field, n + 1);
    }
    if (isdigit(c)) {
        int last = find_int_in(field, n);
        subseq(octave, field, n, last);
        int oct = atoi(octave);
        return parse_after_key(key + oct * 12, field, last);
    }
    parse_error(field, n, "Unexpected character in pitch");
    return key;
}


#ifndef EXPERIMENTAL_NOTE_TRACK
long Allegro_reader::find_int_in(char *field, int n)
#else /* EXPERIMENTAL_NOTE_TRACK */
long Alg_reader::find_int_in(char *field, int n)
#endif /* EXPERIMENTAL_NOTE_TRACK */
{
    while ((int) strlen(field) > n && isdigit(field[n])) {
        n = n + 1;
    }
    return n;
}


#ifndef EXPERIMENTAL_NOTE_TRACK
bool Allegro_reader::parse_attribute(char *field, Parameter_ptr param)
{
    int i = 1;
    while (i < (int) strlen(field)) {
        if (field[i] == ':') {
            char attr[80];
            subseq(attr, field, 1, i);
            char type_char = field[i - 1];
            if (strchr("iarsl", type_char)) {
                param->set_attr(symbol_table.insert_string(attr));
                parse_val(param, field, i + 1);
            }
            return !error_flag;
        }
        i = i + 1;
    }
    return false;
}
#else /* EXPERIMENTAL_NOTE_TRACK */
bool Alg_reader::parse_attribute(char *field, Alg_parameter_ptr param)
{
    int i = 1;
    while (i < (int) strlen(field)) {
        if (field[i] == ':') {
            char attr[80];
            subseq(attr, field, 1, i);
            char type_char = field[i - 1];
            if (strchr("iarsl", type_char)) {
                param->set_attr(symbol_table.insert_string(attr));
                parse_val(param, field, i + 1);
            } else {
                parse_error(field, 0, "attribute needs to end with typecode: i,a,r,s, or l");
            }
            return !error_flag;
        }
        i = i + 1;
    }
    return false;
}
#endif /* EXPERIMENTAL_NOTE_TRACK */


#ifndef EXPERIMENTAL_NOTE_TRACK
bool Allegro_reader::parse_val(Parameter_ptr param, char *s, int i)
{
    int len = (int) strlen(s);
    if (i >= len) {
        return false;
    }
    if (s[i] == '"') {
        if (!check_type('s', param)) {
            return false;
        }
        char *r = new char[len - i];
        subseq(r, s, i + 1, len - 1);
        param->s = r;
    } else if (s[i] == '\'') {
        if (!check_type('a', param)) {
            return false;
        }
        char r[80];
        subseq(r, s, i + 1, len - 1);
        param->a = symbol_table.insert_string(r);
    } else if (param->attr_type() == 'l') {
        if (streql(s + i, "true") || streql(s + i, "t")) {
            param->l = true;
        } else if (streql(s + i, "false") || streql(s + i, "nil")) {
            param->l = false;
        } else return false;
    } else if (isdigit(s[i])) {
        int pos = i + 1;
        bool period = false;
        while (pos < len) {
            if (isdigit(s[pos])) {
                ;
            } else if (!period && s[pos] == '.') {
                period = true;
            } else {
                parse_error(s, pos, "Unexpected char in number");
                return false;
            }
            pos = pos + 1;
        }
        char r[80];
        subseq(r, s, i, len);
        if (period) {
            if (!check_type('r', param)) {
                return false;
            }
            param->r = atof(r);
        } else {
            if (param->attr_type() == 'r') {
                param->r = atoi(r);
            } else if (!check_type('i', param)) {
                return false;
            } else {
                param->i = atoi(r);
            }
        }
    }
    return true;
}
#else /* EXPERIMENTAL_NOTE_TRACK */
bool Alg_reader::parse_val(Alg_parameter_ptr param, char *s, int i)
{
    int len = (int) strlen(s);
    if (i >= len) {
        return false;
    }
    if (s[i] == '"') {
        if (!check_type('s', param)) {
            return false;
        }
        char *r = new char[len - i];
        subseq(r, s, i + 1, len - 1);
        param->s = r;
    } else if (s[i] == '\'') {
        if (!check_type('a', param)) {
            return false;
        }
        char r[80];
        subseq(r, s, i + 1, len - 1);
        param->a = symbol_table.insert_string(r);
    } else if (param->attr_type() == 'l') {
        if (streql(s + i, "true") || streql(s + i, "t")) {
            param->l = true;
        } else if (streql(s + i, "false") || streql(s + i, "nil")) {
            param->l = false;
        } else return false;
    } else if (isdigit(s[i]) || s[i] == '-') {
        int pos = i + 1;
        bool period = false;
        int sign = 1;
        if (s[i] == '-') {
            sign = -1;
            pos = i + 2;
        }
        while (pos < len) {
            if (isdigit(s[pos])) {
                ;
            } else if (!period && s[pos] == '.') {
                period = true;
            } else {
                parse_error(s, pos, "Unexpected char in number");
                return false;
            }
            pos = pos + 1;
        }
        char r[80];
        subseq(r, s, i, len);
        if (period) {
            if (!check_type('r', param)) {
                return false;
            }
            param->r = atof(r);
        } else {
            if (param->attr_type() == 'r') {
                param->r = atoi(r);
            } else if (!check_type('i', param)) {
                return false;
            } else {
                param->i = sign * atoi(r);
            }
        }
    } else {
        parse_error(s, i, "invalid value");
        return false;
    }
    return true;
}