/* Return an interpolated numeric value from a list based on a fractional "distance" through the list. */ MincFloat _minc_interp(const MincValue args[], const int nargs) { MincFloat outValue = -1; if (nargs != 2) minc_warn("interp: must have two arguments (list, fraction)"); else { assert(args[1].dataType() == MincFloatType); // must pass a float as fractional value if (args[0].dataType() != MincListType) { minc_warn("interp: first argument must be a list"); return -1.0; } MincValue *data = ((MincList*)args[0])->data; int len = ((MincList*)args[0])->len; // Deal with degenerate cases if (len == 0) return 0.0; else if (len == 1) return (MincFloat)data[0]; float fraction = (MincFloat)args[1]; fraction = (fraction < 0.0) ? 0.0 : (fraction > 1.0) ? 1.0 : fraction; int lowIndex = (int)((len - 1) * fraction); int highIndex = min(len - 1, lowIndex + 1); if (data[lowIndex].dataType() != MincFloatType || data[highIndex].dataType() != MincFloatType) { minc_warn("interp: list elements to interpolate must both be floats"); return -1; } outValue = (MincFloat)data[lowIndex] + fraction * ((MincFloat)data[highIndex] - (MincFloat)data[lowIndex]); } return outValue; }
/* Print the length of the argument. This is useful for getting the number of items in a list or the number of characters in a string. */ MincFloat _minc_len(const MincValue args[], const int nargs) { unsigned long len = 0; if (nargs != 1) minc_warn("len: must have one argument"); else { switch (args[0].dataType() ) { case MincFloatType: len = 1; break; case MincStringType: len = strlen((MincString)args[0]); break; case MincHandleType: /* NB: To get length of a table, call tablelen(handle) */ len = 1; break; case MincListType: len = ((MincList *)args[0])->len; break; default: minc_warn("len: invalid argument"); break; } } return (MincFloat) len; }
/* Given an item (float, string or handle), return the index of the item within the given list, or -1 if the item is not in the list. Example: list = {1, 2, "three", 4} id = index(list, 2) <id> equals 1 after this call. */ MincFloat _minc_index(const MincValue args[], const int nargs) { int i, len, index = -1; MincDataType argtype; MincValue *data; if (nargs != 2) { minc_warn("index: must have two arguments (list, item_to_find)"); return -1.0; } if (args[0].dataType() != MincListType) { minc_warn("index: first argument must be a list"); return -1.0; } argtype = args[1].dataType() ; assert(argtype == MincFloatType || argtype == MincStringType || argtype == MincHandleType || argtype == MincListType); len = ((MincList *)args[0])->len; data = ((MincList *)args[0])->data; for (i = 0; i < len; i++) { if (data[i].dataType() == argtype) { if (argtype == MincFloatType) { if ((MincFloat)data[i] == (MincFloat)args[1]) { index = i; break; } } else if (argtype == MincStringType) { if (strcmp((MincString)data[i], (MincString)args[1]) == 0) { index = i; break; } } //FIXME: should this recurse and match entire list contents?? else if (argtype == MincListType) { if ((MincList*)data[i] == (MincList*)args[1]) { index = i; break; } } else if (argtype == MincHandleType) { if ((MincHandle)data[i] == (MincHandle)args[1]) { index = i; break; } } } } return (MincFloat) index; }
/* Return the passed in (double) argument as a string type. */ MincString _minc_tostring(const MincValue args[], const int nargs) { if (nargs != 1) { minc_warn("tostring: must have one argument"); return NULL; } if (args[0].dataType() != MincFloatType) { minc_warn("tostring: argument must be float type"); return NULL; } const char *convertedString = DOUBLE_TO_STRING((MincString)args[0]); return strdup(convertedString); }
/* Print the object type of the argument: float, string, handle, list. */ MincString _minc_type(const MincValue args[], const int nargs) { if (nargs != 1) { minc_warn("type: must have one argument"); return NULL; } return _make_type_string(args[0].dataType() ); }
/* Free storage for reuse. Very closely connected to symalloc. TBD: only allow a maximum freelist length */ static void free_node(struct symbol *p) { if (p == NULL) { minc_warn("free_node was called with NULL ptr "); return; } if (freelist == NULL) freelist = p; else { p->next = freelist; freelist = p; } }
MincFloat _minc_printf(const MincValue args[], const int nargs) { int n; const char *p; if (get_print_option() < MMP_PRINTS) return 0.0; if (args[0].dataType() != MincStringType) { minc_warn("printf: first argument must be format string"); goto err; } n = 1; p = (MincString) args[0]; while (*p) { switch (*p) { case '%': p++; if (n >= nargs) { minc_warn("printf: not enough arguments for format string"); goto err; } switch (*p) { case 'd': /* print float object as integer */ if (args[n].dataType() != MincFloatType) { minc_warn("printf: wrong argument type for format"); goto err; } RTPrintfCat("%d", (int) (MincFloat)args[n]); break; case 'f': /* print float object */ if (args[n].dataType() != MincFloatType) { minc_warn("printf: wrong argument type for format"); goto err; } RTPrintfCat("%.12g", (MincFloat)args[n]); break; case 'l': /* print list object */ if (args[n].dataType() != MincListType) { minc_warn("printf: wrong argument type for format"); goto err; } RTPrintfCat("["); _do_print(((MincList *)args[n])->data, ((MincList *)args[n])->len); RTPrintfCat("]"); break; case 's': /* print string object */ if (args[n].dataType() != MincStringType) { minc_warn("printf: wrong argument type for format"); goto err; } RTPrintfCat("%s", (MincString)args[n]); break; case 't': /* print type of object */ { char *tstr = (char *) _make_type_string(args[n].dataType() ); RTPrintfCat("%s", tstr); free(tstr); } break; case 'z': /* print as appropriate for type */ _do_print(&args[n], 1); break; case '\0': minc_warn("printf: premature end of format string"); goto err; break; default: minc_warn("printf: invalid format specifier"); goto err; break; } n++; p++; break; case '\\': p++; switch (*p) { case 'n': RTPrintfCat("\n"); break; case 't': RTPrintfCat("\t"); break; //FIXME: currently, minc.l can't handle escaped quotes in strings case '\'': RTPrintfCat("'"); break; case '"': RTPrintfCat("\""); break; case '\0': minc_warn("printf: premature end of format string"); goto err; break; default: minc_warn("printf: invalid escape character"); goto err; break; } p++; break; default: RTPrintfCat("%c", *p); p++; break; } } return 0.0; err: RTPrintf("\n"); // fflush(stdout); return -1.0; }