Exemplo n.º 1
0
/**
 * [File] read
 *
 * Reads contents of a file. Send this message to a file to read the entire contents in
 * one go. For big files you might want to prefer a streaming approach to avoid
 * memory exhaustion (see readBytes etc).
 *
 * Usage:
 *
 * data := File new: '/path/to/mydata.csv', read.
 *
 * In the example above we read the contents of the entire CSV file callled mydata.csv
 * in the variable called data.
 */
ctr_object* ctr_file_read(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string_from_cstring( "path" ), 0);
	ctr_object* str;
	ctr_size vlen, fileLen;
	char* pathString;
	char *buffer;
	FILE* f;
	if (path == NULL) return CtrStdNil;
	vlen = path->value.svalue->vlen;
	pathString = ctr_heap_allocate( sizeof(char) * ( vlen + 1 ) );
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	f = fopen(pathString, "rb");
	ctr_heap_free( pathString );
	if (!f) {
		CtrStdFlow = ctr_build_string_from_cstring( "Unable to open file." );
		CtrStdFlow->info.sticky = 1;
		return CtrStdNil;
	}
	fseek(f, 0, SEEK_END);
	fileLen=ftell(f);
	fseek(f, 0, SEEK_SET);
	buffer=(char *)ctr_heap_allocate(fileLen+1);
	if (!buffer){
		printf("Out of memory\n");
		fclose(f);exit(1);	
	}
	fread(buffer, fileLen, 1, f);
	fclose(f);
	str = ctr_build_string(buffer, fileLen);
	ctr_heap_free( buffer );
	return str;
}
Exemplo n.º 2
0
ctr_object* ctr_json_create_object(json_t* root, ctr_object* gt) {
    switch(json_typeof(root)) {
        case JSON_OBJECT: {
            ctr_object* sub = ctr_internal_create_object(CTR_OBJECT_TYPE_OTOBJECT);
            ctr_set_link_all(sub, gt);
            // size_t size;
            const char *key;
            json_t *value;
            ctr_argument* argl = ctr_heap_allocate(sizeof(*argl));
            argl->next = ctr_heap_allocate(sizeof(*argl));
            // size = json_object_size(root);
            json_object_foreach(root, key, value) {
              char* k = (char*)key;
              ctr_object* ko = ctr_build_string_from_cstring(k);
              ctr_object* vo = ctr_json_create_object(value, gt);
              argl->object = vo;
              argl->next->object = ko;
              sub = ctr_map_put(sub, argl);
            }
            ctr_heap_free(argl->next);
            ctr_heap_free(argl);
            return sub;
          }
        case JSON_ARRAY: {
          ctr_object* arr = ctr_array_new(CtrStdArray, NULL);
          ctr_argument* arg = ctr_heap_allocate(sizeof(ctr_argument));
          size_t i;
          size_t size = json_array_size(root);
          for (i = 0; i < size; i++) {
            arg->object = ctr_json_create_object(json_array_get(root, i), gt);
            ctr_array_push(arr, arg);
          }
          ctr_heap_free(arg);
          return arr;
        }
        case JSON_STRING: {
          ctr_object* str = ctr_build_string((char*)json_string_value(root), json_string_length(root));
          return str;
        }
        case JSON_INTEGER: {
          return ctr_build_number_from_float(json_integer_value(root));
        }
        case JSON_REAL: {
          return ctr_build_number_from_float(json_real_value(root));
        }
        case JSON_FALSE: {
          return ctr_build_bool(0);
        }
        case JSON_TRUE: {
          return ctr_build_bool(1);
        }
        case JSON_NULL: {
          return ctr_build_nil();
        }
        default: {
          CtrStdFlow = ctr_build_string_from_cstring("Unrecognized JSON type");
          return CtrStdNil;
        }
    }
Exemplo n.º 3
0
ctr_object* ctr_fiber_spawn(ctr_object* myself, ctr_argument* argumentList) {
  ctr_object* fiberObj = ctr_fiber_create(myself, NULL);
  ctr_object* blk = argumentList->object;
  if(blk == NULL || blk->info.type != CTR_OBJECT_TYPE_OTBLOCK) {CtrStdFlow = ctr_build_string_from_cstring("Fiber's spawning requires a block."); return myself;}
  int fiber = spawnFiber(argumentList->object);
  ctr_internal_object_add_property(fiberObj, ctr_build_string_from_cstring("fiberId"), ctr_build_number_from_float(fiber), CTR_CATEGORY_PRIVATE_PROPERTY);
  return fiberObj;
}
Exemplo n.º 4
0
/**
 * C-constructor function, as declared above.
 * 
 * This function gets called when the plugin is loaded into memory.
 * Here you have a chance to add the new object(s) to the World.
 * 
 * In our case, we are going to add the Percolator object to the
 * world.
 */
void begin(){
	/* Create the Coffee Percolator Object - Use new, because its a prototype, not a class !*/
	ctr_object* percolatorObject = ctr_percolator_new(CtrStdObject, NULL);
	
	/* Set the prototype */
	percolatorObject->link = CtrStdObject;

	/* Add the method 'new' so people can create their percolators */
	ctr_internal_create_func(percolatorObject, ctr_build_string_from_cstring( "new" ), &ctr_percolator_new );
	ctr_internal_create_func(percolatorObject, ctr_build_string_from_cstring( "brew" ), &ctr_percolator_brew );
	ctr_internal_create_func(percolatorObject, ctr_build_string_from_cstring( "coffee:water:" ), &ctr_percolator_add_coffee_water );

	/* Make the Percolator accessible to the world */
	ctr_internal_object_add_property(CtrStdWorld, ctr_build_string_from_cstring( "Percolator" ), percolatorObject, CTR_CATEGORY_PUBLIC_PROPERTY);
}
Exemplo n.º 5
0
/**
 * @internal
 * 
 * Returns an array from the request, either for GET, POST or COOKIE.
 */
ctr_object* ctr_request_array(ctr_object* myself, ctr_argument* argumentList, CGI_varlist* varlist) {
	ctr_object* cgiVarObject;
	ctr_object* list;
	char* cgiVar;
	const CGI_value* value;
	char* val;
	ctr_argument* arg;
	int i = 0;
	list = ctr_array_new(CtrStdArray, NULL);	
	cgiVarObject = ctr_internal_cast2string(argumentList->object);
	cgiVar = ctr_heap_allocate_cstring( cgiVarObject );
	value = CGI_lookup_all(varlist, (const char*)cgiVar);
	ctr_heap_free( cgiVar );
	if (value == NULL) {
		return list;
	}
	for (i = 0; value[i] != 0; i++) {
		arg = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) );
		val = (char*) value[i];
		arg->object = ctr_build_string_from_cstring(val);
		ctr_array_push(list, arg);
		ctr_heap_free( arg );
	}
	return list;
}
Exemplo n.º 6
0
/**
 * @internal
 * 
 * Reads a server option set by user.
 */
ctr_object* ctr_request_internal_option(ctr_object* myself, char* optName) {
	ctr_object* key;
	ctr_object* val;
	key = ctr_build_string_from_cstring(optName);
	val = ctr_internal_object_find_property(myself, key, CTR_CATEGORY_PRIVATE_PROPERTY);
	return val;
}
Exemplo n.º 7
0
/**
 * [Map] each: [Block]
 *
 * Iterates over the map, passing key-value pairs to the specified block.
 * Note that within an each/map block, '⛏' and '⚿' refer to the collection.
 *
 * In other languages:
 * Dutch: [Lijst] elk: [Codeblok] | Past het blok code toe op elk paar uit de lijst.
 */
ctr_object* ctr_map_each(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* block = argumentList->object;
	ctr_mapitem* m;
	if (block->info.type != CTR_OBJECT_TYPE_OTBLOCK) {
		CtrStdFlow = ctr_build_string_from_cstring( CTR_ERR_EXP_BLK );
		CtrStdFlow->info.sticky = 1;
	}
	block->info.sticky = 1;
	m = myself->properties->head;
	while(m && !CtrStdFlow) {
		ctr_argument* arguments = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) );
		ctr_argument* argument2 = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) );
		ctr_argument* argument3 = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) );
		arguments->object = m->key;
		argument2->object = m->value;
		argument3->object = myself;
		arguments->next = argument2;
		argument2->next = argument3;
		ctr_block_run(block, arguments, myself);
		if (CtrStdFlow == CtrStdContinue) CtrStdFlow = NULL;
		m = m->next;
		ctr_heap_free( arguments );
		ctr_heap_free( argument2 );
		ctr_heap_free( argument3 );
	}
	if (CtrStdFlow == CtrStdBreak) CtrStdFlow = NULL;
	block->info.mark = 0;
	block->info.sticky = 0;
	return myself;
}
Exemplo n.º 8
0
/**
 * [List] map: [Block].
 *
 * Iterates over the array. Passing each element as a key-value pair to the
 * specified block.
 * The map message will pass the following arguments to the block, the key,
 * the value and a reference to the array itself. The last argument might seem
 * redundant but allows for a more functional programming style. Instead of map,
 * you can also use each:.
 *
 * Usage:
 *
 * files map: showName.
 * files map: {
 *   :key :filename :files
 *   ✎ write: filename.
 * }.
 *
 * files each: {
 *   :key :filename :files
 *   ✎ write: filename.
 * }.
 *
 * In other languages:
 * Dutch: [Reeks] lijst: [Codeblok] | Maakt van een reeks
 */
ctr_object* ctr_array_map(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* block = argumentList->object;
	int i = 0;
	if (block->info.type != CTR_OBJECT_TYPE_OTBLOCK) {
		CtrStdFlow = ctr_build_string_from_cstring( CTR_ERR_EXP_BLK );
		CtrStdFlow->info.sticky = 1;
	}
	for(i = myself->value.avalue->tail; i < myself->value.avalue->head; i++) {
		ctr_argument* arguments = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) );
		ctr_argument* argument2 = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) );
		ctr_argument* argument3 = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) );
		arguments->object = ctr_build_number_from_float((double) i);
		argument2->object = *(myself->value.avalue->elements + i);
		argument3->object = myself;
		arguments->next = argument2;
		argument2->next = argument3;
		/* keep receiver in block object otherwise, GC will destroy it */
		ctr_gc_internal_pin(block);
		ctr_gc_internal_pin(myself);
		ctr_gc_internal_pin(argument2->object);
		ctr_block_run(block, arguments, myself);
		ctr_heap_free( arguments );
		ctr_heap_free( argument2 );
		ctr_heap_free( argument3 );
		if (CtrStdFlow == CtrStdContinue) CtrStdFlow = NULL;
		if (CtrStdFlow) break;
	}
	if (CtrStdFlow == CtrStdBreak) CtrStdFlow = NULL; /* consume break */
	return myself;
}
Exemplo n.º 9
0
/**
 * OnMessageDoAction
 *
 * Makes the object respond to a new kind of message.
 *
 * Usage:
 * object on: 'greet' do {\ ... }.
 */
ctr_object* ctr_object_on_do(ctr_object* myself, ctr_argument* argumentList) {
	ctr_argument* nextArgument;
	ctr_object* methodBlock;
	ctr_object* methodName = argumentList->object;
	if (methodName->info.type != CTR_OBJECT_TYPE_OTSTRING) {
		CtrStdError = ctr_build_string_from_cstring("Expected on: argument to be of type string.");
		return myself;
	}
	nextArgument = argumentList->next;
	methodBlock = nextArgument->object;
	if (methodBlock->info.type != CTR_OBJECT_TYPE_OTBLOCK) {
		CtrStdError = ctr_build_string_from_cstring("Expected argument do: to be of type block.");
		return myself;
	}
	ctr_internal_object_add_property(myself, methodName, methodBlock, 1);
	return myself;
}
Exemplo n.º 10
0
/**
 * [List] position: [Number]
 *
 * Returns the element in the list at the specified position.
 * Note that the first position of the list is index 0.
 * If you attempt to retrieve an element of the list
 * using a an index that is something other than a number
 * a catchable error will be triggered. An error will
 * also be triggered if your position is out of bounds
 * (i.e. outside the list). Instead of the message
 * 'position:' you can also send the message '?'.
 *
 * Usage:
 *
 * ☞ fruits  := List ← 'apples' ; 'oranges' ; 'bananas'.
 * ☞ oranges := fruits position: 1.
 * ☞ oranges := fruits ? 1.
 *
 * In other languages:
 * Dutch: [Reeks] positie: [Getal] | Geeft het object op de aangegeven plek in de reeks.
 */
ctr_object* ctr_array_get(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* getIndex = argumentList->object;
	int i;
	if (getIndex->info.type != CTR_OBJECT_TYPE_OTNUMBER) {
		CtrStdFlow = ctr_build_string_from_cstring( CTR_ERR_EXP_NUM );
		CtrStdFlow->info.sticky = 1;
		return CtrStdNil;
	}
	i = (int) getIndex->value.nvalue;
	if (myself->value.avalue->head <= (i + myself->value.avalue->tail) || i < 0) {
		CtrStdFlow = ctr_build_string_from_cstring( CTR_ERR_BOUNDS );
		CtrStdFlow->info.sticky = 1;
		return CtrStdNil;
	}
	ctr_object* q =  *(myself->value.avalue->elements + myself->value.avalue->tail + i);
	return q;
}
Exemplo n.º 11
0
/**
 * @internal
 *
 * Adds the Request object to the World.
 */
void begin(){
	ctr_object* requestObject = ctr_internal_create_object(CTR_OBJECT_TYPE_OTOBJECT);
	requestObject->link = CtrStdObject;
	ctr_internal_create_func(requestObject, ctr_build_string_from_cstring( "get:" ), &ctr_request_get_string );
	ctr_internal_create_func(requestObject, ctr_build_string_from_cstring( "getArray:" ), &ctr_request_get_array );
	ctr_internal_create_func(requestObject, ctr_build_string_from_cstring( "cookie:" ), &ctr_request_cookie_string );
	ctr_internal_create_func(requestObject, ctr_build_string_from_cstring( "cookieArray:" ), &ctr_request_cookie_array );
	ctr_internal_create_func(requestObject, ctr_build_string_from_cstring( "post:" ), &ctr_request_post_string );
	ctr_internal_create_func(requestObject, ctr_build_string_from_cstring( "file:" ), &ctr_request_file );
	ctr_internal_create_func(requestObject, ctr_build_string_from_cstring( "postArray:" ), &ctr_request_post_array );
	ctr_internal_create_func(requestObject, ctr_build_string_from_cstring( "serverOption:is:" ), &ctr_request_server_option );
	ctr_internal_create_func(requestObject, ctr_build_string_from_cstring( "host:listen:pid:callback:" ), &ctr_request_serve );
	ctr_internal_object_add_property(CtrStdWorld, ctr_build_string_from_cstring( "Request" ), requestObject, 0);
	varlistGet = CGI_get_query(NULL);
	varlistPost = CGI_get_post(NULL,0);
	varlistCookie = CGI_get_cookie(NULL);
}
Exemplo n.º 12
0
/**
 * CTRWalkerAssignment
 *
 * Processes an assignment operation.
 */
ctr_object *
ctr_cwlk_assignment (ctr_tnode * node)
{
  char wasReturn = 0;
  ctr_tlistitem *assignmentItems = node->nodes;
  ctr_tnode *assignee = assignmentItems->node;
  ctr_tlistitem *valueListItem = assignmentItems->next;
  ctr_tnode *value = valueListItem->node;
  ctr_object *x;
  ctr_object *result;
  char ret;
  if (CtrStdFlow == NULL)
    {
      ctr_callstack[ctr_callstack_index++] = assignee;
    }
  x = ctr_cwlk_expr (value, &wasReturn);
  if (!x)
    {
      CtrStdFlow = ctr_build_string_from_cstring ("NULL expression");
      return NULL;
    }
  if (assignee->type == CTR_AST_NODE_REFERENCE)
    {
      if (assignee->modifier == 1)
	{
	  result = ctr_assign_value_to_my (ctr_build_string (assignee->value, assignee->vlen), x);
	}
      else if (assignee->modifier == 2)
	{
	  result = ctr_assign_value_to_local (ctr_build_string (assignee->value, assignee->vlen), x);
	}
      else if (assignee->modifier == 3)
	{
	  result = ctr_assign_value (ctr_build_string (assignee->value, assignee->vlen), x);	//Handle lexical scoping
	}
      else
	{
	  result = ctr_assign_value (ctr_build_string (assignee->value, assignee->vlen), x);
	}
    }
  else
    {
      int old_replace = ctr_cwlk_replace_refs;
      ctr_cwlk_replace_refs = 1;
      ctr_cwlk_last_msg_level = ctr_cwlk_msg_level;
      ctr_object *y = ctr_cwlk_expr (assignee, &ret);
      ctr_cwlk_replace_refs = old_replace;	//set back in case we didn't reset
      result = ctr_send_message_variadic (x, "unpack:", 7, 1, y);
      ctr_object *old_result = NULL;
      while (old_result != result && result->info.type == CTR_OBJECT_TYPE_OTBLOCK)
	result = ctr_block_run_here (result, NULL, (old_result = result));
    }
  if (CtrStdFlow == NULL)
    {
      ctr_callstack_index--;
    }
  return result;
}
Exemplo n.º 13
0
/**
 * [Percolator] coffee: [Number] water: [Number]
 * 
 * Adds coffee and water to the perculator.
 * 
 * myPercolator := Percolator new.
 * cupOfCoffee  := myPercolator coffee: 1 water: 2, brew.
 * 
 */
ctr_object* ctr_percolator_add_coffee_water(ctr_object* myself, ctr_argument* argumentList) {
	
	ctr_internal_object_set_property(
		myself, 
		ctr_build_string_from_cstring( "coffee" ),
		ctr_internal_cast2number(argumentList->object),
		CTR_CATEGORY_PRIVATE_PROPERTY
	);
	
	ctr_internal_object_set_property(
		myself, 
		ctr_build_string_from_cstring( "water" ),
		ctr_internal_cast2number(argumentList->next->object),
		CTR_CATEGORY_PRIVATE_PROPERTY
	);
	
	return myself;	
}
Exemplo n.º 14
0
ctr_object* ctr_number_div(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* otherNum = ctr_internal_cast2number(argumentList->object);
	if (otherNum->value.nvalue == 0) {
		CtrStdError = ctr_build_string_from_cstring("Division by zero.");
		return myself;
	}
	myself->value.nvalue /= otherNum->value.nvalue;
	return myself;
}
Exemplo n.º 15
0
/**
 * [Array] sort: [Block]
 *
 * Sorts the contents of an array using a sort block.
 * Uses qsort.
 */
ctr_object* ctr_array_sort(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* sorter = argumentList->object;
	if (sorter->info.type != CTR_OBJECT_TYPE_OTBLOCK) {
		CtrStdError = ctr_build_string_from_cstring("Expected block.\0");
		return myself;
	}
	temp_sorter = sorter;
	qsort(myself->value.avalue->elements, myself->value.avalue->head, sizeof(ctr_object*), ctr_sort_cmp);
	return myself;
}
Exemplo n.º 16
0
ctr_object* ctr_number_modulo(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* otherNum = ctr_internal_cast2number(argumentList->object);
ctr_number a = myself->value.nvalue;
ctr_number b = otherNum->value.nvalue;
	if (b == 0) {
		CtrStdError = ctr_build_string_from_cstring("Division by zero.");
		return myself;
	}
	return ctr_build_number_from_float(fmod(a,b));
}
Exemplo n.º 17
0
/**
 * [File] delete
 *
 * Deletes the file.
 */
ctr_object* ctr_file_delete(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string_from_cstring( "path" ), 0);
	ctr_size vlen;
	char* pathString;
	int r;
	if (path == NULL) return myself;
	vlen = path->value.svalue->vlen;
	pathString = ctr_heap_allocate( sizeof( char ) * ( vlen + 1 ) );
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	r = remove(pathString);
	ctr_heap_free( pathString );
	if (r!=0) {
		CtrStdFlow = ctr_build_string_from_cstring( "Unable to delete file." );
		CtrStdFlow->info.sticky = 1;
		return CtrStdNil;
	}
	return myself;
}
Exemplo n.º 18
0
/**
 * File
 * 
 * Represents a File object.
 * Creates a new file object based on the specified path.
 * 
 * Usage:
 * 
 * File new: '/example/path/to/file.txt'.
 */
ctr_object* ctr_file_new(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* s = ctr_object_make(myself, argumentList);
	ctr_object* pathObject;
	s->info.type = CTR_OBJECT_TYPE_OTEX; /* indicates resource for GC */
	s->link = myself;
	s->value.rvalue = NULL;
	pathObject = ctr_build_string( argumentList->object->value.svalue->value, argumentList->object->value.svalue->vlen );
	ctr_internal_object_add_property( s, ctr_build_string_from_cstring( "path" ), pathObject, 0 );
	return s;
}
Exemplo n.º 19
0
/**
 * Percolator new
 * 
 * Creates a new instance of the percolator object.
 * 
 * Usage:
 * 
 * myPercolator := Percolator new.
 * cupOfCoffee  := myPercolator coffee: 1 water: 2, brew.
 * 
 */
ctr_object* ctr_percolator_new(ctr_object* myself, ctr_argument* argumentList) {
	
	ctr_object* percolatorInstance = ctr_internal_create_object(CTR_OBJECT_TYPE_OTOBJECT);
	percolatorInstance->link = myself;
	ctr_internal_object_set_property(
		percolatorInstance, 
		ctr_build_string_from_cstring( "coffee" ),
		ctr_build_number_from_float(0),
		CTR_CATEGORY_PRIVATE_PROPERTY
	);
	ctr_internal_object_set_property(
		percolatorInstance, 
		ctr_build_string_from_cstring( "water" ),
		ctr_build_number_from_float(0),
		CTR_CATEGORY_PRIVATE_PROPERTY
	);
	
	return percolatorInstance;	
}
Exemplo n.º 20
0
/**
 * [File] readBytes: [Number].
 *
 * Reads a number of bytes from the file.
 *
 * Usage:
 *
 * f := File new: '/path/to/file.txt'.
 * f open: 'r+'.
 * x := f readBytes: 10.
 * f close.
 *
 * The example above reads 10 bytes from the file represented by f
 * and puts them in buffer x.
 */
ctr_object* ctr_file_read_bytes(ctr_object* myself, ctr_argument* argumentList) {
	int bytes;
	char* buffer;
	ctr_object* result;
	if (myself->value.rvalue == NULL) return myself;
	if (myself->value.rvalue->type != 1) return myself;
	bytes = ctr_internal_cast2number(argumentList->object)->value.nvalue;
	if (bytes < 0) return ctr_build_string_from_cstring("");
	buffer = (char*) ctr_heap_allocate(bytes);
	if (buffer == NULL) {
		CtrStdFlow = ctr_build_string_from_cstring("Cannot allocate memory for file buffer.");
		CtrStdFlow->info.sticky = 1;
		return ctr_build_string_from_cstring("");
	}
	fread(buffer, sizeof(char), (int)bytes, (FILE*)myself->value.rvalue->ptr);
	result = ctr_build_string(buffer, bytes);
	ctr_heap_free( buffer );
	return result;
}
Exemplo n.º 21
0
/**
 * CTRMessageSend
 *
 * Sends a message to a receiver object.
 */
ctr_object* ctr_send_message(ctr_object* receiverObject, char* message, long vlen, ctr_argument* argumentList) {
	char toParent = 0;
	ctr_object* me;
	ctr_object* methodObject;
	ctr_object* searchObject;
	ctr_argument* argCounter;
	ctr_argument* mesgArgument;
	ctr_object* result;
	ctr_object* (*funct)(ctr_object* receiverObject, ctr_argument* argumentList);
	int argCount;
	if (CtrStdError != NULL) return NULL; /* Error mode, ignore subsequent messages until resolved. */
	methodObject = NULL;
	searchObject = receiverObject;
	if (vlen > 1 && message[0] == '`') {
		me = ctr_internal_object_find_property(ctr_contexts[ctr_context_id], ctr_build_string_from_cstring("me\0"), 0);
		if (searchObject == me) {
			toParent = 1;
			message = message + 1;
			vlen--;
		}
	}
	while(!methodObject) {
		methodObject = ctr_internal_object_find_property(searchObject, ctr_build_string(message, vlen), 1);
		if (methodObject && toParent) { toParent = 0; methodObject = NULL; }
		if (methodObject) break;
		if (!searchObject->link) break;
		searchObject = searchObject->link;
	}
	if (!methodObject) {
		argCounter = argumentList;
		argCount = 0;
		while(argCounter->next && argCount < 4) {
			argCounter = argCounter->next;
			argCount ++;
		}
		mesgArgument = CTR_CREATE_ARGUMENT();
		mesgArgument->object = ctr_build_string(message, vlen);
		mesgArgument->next = argumentList;
		if (argCount == 0 || argCount > 2) {
			return ctr_send_message(receiverObject, "respondTo:", 10,  mesgArgument);
		} else if (argCount == 1) {
			return ctr_send_message(receiverObject, "respondTo:with:", 15,  mesgArgument);
		} else if (argCount == 2) {
			return ctr_send_message(receiverObject, "respondTo:with:and:", 19,  mesgArgument);
		}
	}
	if (methodObject->info.type == CTR_OBJECT_TYPE_OTNATFUNC) {
		funct = methodObject->value.fvalue;
		result = funct(receiverObject, argumentList);
	}
	if (methodObject->info.type == CTR_OBJECT_TYPE_OTBLOCK) {
		result = ctr_block_run(methodObject, argumentList, receiverObject);
	}	
	return result;
}
Exemplo n.º 22
0
/**
 * [File] end.
 *
 * Moves the file pointer to the end of the file. Use this in combination with
 * negative seek operations.
 *
 * Usage:
 *
 * file open: 'r'.
 * file end.
 * x := file seek: -10, readBytes: 10.
 *
 * The example above will read the last 10 bytes of the file. This is
 * accomplished by first moving the file pointer to the end of the file,
 * then putting it back 10 bytes (negative number), and then reading 10
 * bytes.
 */
ctr_object* ctr_file_seek_end(ctr_object* myself, ctr_argument* argumentList) {
	int error;
	if (myself->value.rvalue == NULL) return myself;
	if (myself->value.rvalue->type != 1) return myself;
	error = fseek((FILE*)myself->value.rvalue->ptr, 0, SEEK_END);
	if (error) {
		CtrStdFlow = ctr_build_string_from_cstring("Seek end failed.");
		CtrStdFlow->info.sticky = 1;
	}
	return myself;
}
Exemplo n.º 23
0
/**
 * @internal
 * 
 * Returns a string from the request, either for GET, POST or COOKIE.
 */
ctr_object* ctr_request_string(ctr_object* myself, ctr_argument* argumentList, CGI_varlist* varlist) {
	ctr_object* cgiVarObject;
	char* cgiVar;
	char* value;
	cgiVarObject = ctr_internal_cast2string(argumentList->object);
	cgiVar = ctr_heap_allocate_cstring( cgiVarObject );
	value = (char*) CGI_lookup(varlist, (const char*)cgiVar);
	ctr_heap_free( cgiVar );
	if (value == NULL) return CtrStdNil;
	return ctr_build_string_from_cstring(value);
}
Exemplo n.º 24
0
/**
 * [List] sort: [Block]
 *
 * Sorts the contents of an list using a sort block.
 * Uses qsort.
 *
 * In other languages:
 * Dutch: [Reeks] sorteer: [Codeblok]
 * Sorteert de reeks door de elementen door het codeblok te halen.
 */
ctr_object* ctr_array_sort(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* sorter = argumentList->object;
	if (sorter->info.type != CTR_OBJECT_TYPE_OTBLOCK) {
		CtrStdFlow = ctr_build_string_from_cstring( CTR_ERR_EXP_BLK );
		CtrStdFlow->info.sticky = 1;
		return myself;
	}
	temp_sorter = sorter;
	temp_self = myself;
	qsort((myself->value.avalue->elements+myself->value.avalue->tail), myself->value.avalue->head-myself->value.avalue->tail, sizeof(ctr_object*), ctr_sort_cmp);
	return myself;
}
Exemplo n.º 25
0
void begin() {
  initFibers();

  CTR_FIBER_CONTROLLER = ctr_internal_create_object(CTR_OBJECT_TYPE_OTEX);
  ctr_internal_create_func(CTR_FIBER_CONTROLLER, ctr_build_string_from_cstring("toString"), &ctr_fiber_tostring);
  ctr_internal_create_func(CTR_FIBER_CONTROLLER, ctr_build_string_from_cstring("new:"), &ctr_fiber_spawn);
  ctr_internal_create_func(CTR_FIBER_CONTROLLER, ctr_build_string_from_cstring("yield:"), &ctr_fiber_yield); //with value
  ctr_internal_create_func(CTR_FIBER_CONTROLLER, ctr_build_string_from_cstring("yield"), &ctr_fiber_yield); //without value
  ctr_internal_create_func(CTR_FIBER_CONTROLLER, ctr_build_string_from_cstring("yielded"), &ctr_fiber_yielded);
  ctr_internal_create_func(CTR_FIBER_CONTROLLER, ctr_build_string_from_cstring("waitForAll"), &ctr_fiber_join_all);
  ctr_internal_object_add_property(CTR_FIBER_CONTROLLER, ctr_build_string_from_cstring("fiberId"), ctr_build_number_from_float(-1), CTR_CATEGORY_PRIVATE_PROPERTY);

  ctr_internal_object_add_property(CtrStdWorld, ctr_build_string_from_cstring("Fiber"), CTR_FIBER_CONTROLLER, 0);
}
Exemplo n.º 26
0
/**
 * [File] append: [String]
 *
 * Appends content to a file. The file object responds to this message like it
 * responds to the write-message, however in this case the contents of the string
 * will be appended to the existing content inside the file.
 */
ctr_object* ctr_file_append(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* str = ctr_internal_cast2string(argumentList->object);
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string_from_cstring( "path" ), 0);
	ctr_size vlen;
	char* pathString;
	FILE* f;
	if (path == NULL) return myself;
	vlen = path->value.svalue->vlen;
	pathString = ctr_heap_allocate(vlen + 1);
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	f = fopen(pathString, "ab+");
	ctr_heap_free( pathString );
	if (!f) {
		CtrStdFlow = ctr_build_string_from_cstring("Unable to open file.\0");
		CtrStdFlow->info.sticky = 1;
		return CtrStdNil;
	}
	fwrite(str->value.svalue->value, sizeof(char), str->value.svalue->vlen, f);
	fclose(f);
	return myself;
}
Exemplo n.º 27
0
/**
 * [File] seek: [Number].
 *
 * Moves the file pointer to the specified position in the file
 * (relative to the current position).
 *
 * Usage:
 *
 * file open: 'r', seek: 10.
 *
 * The example above opens a file for reading and moves the
 * pointer to position 10 (meaning 10 bytes from the beginning of the file).
 * The seek value may be negative.
 */
ctr_object* ctr_file_seek(ctr_object* myself, ctr_argument* argumentList) {
	int offset;
	int error;
	if (myself->value.rvalue == NULL) return myself;
	if (myself->value.rvalue->type != 1) return myself;
	offset = (long int) ctr_internal_cast2number(argumentList->object)->value.nvalue;
	error = fseek((FILE*)myself->value.rvalue->ptr, offset, SEEK_CUR);
	if (error) {
		CtrStdFlow = ctr_build_string_from_cstring("Seek failed.");
		CtrStdFlow->info.sticky = 1;
	}
	return myself;
}
Exemplo n.º 28
0
/**
 * [Array] at: [Index]
 *
 * Returns the element in the array at the specified index.
 * Note that the fisrt index of the array is index 0.
 *
 * Usage:
 * 
 * fruits := Array <- 'apples' ; 'oranges' ; 'bananas'.
 * fruits at: 1. #returns 'oranges'
 */
ctr_object* ctr_array_get(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* getIndex = argumentList->object;
	int i;
	if (getIndex->info.type != CTR_OBJECT_TYPE_OTNUMBER) {
		printf("Index must be number.\n"); exit(1);
	}
	i = (int) getIndex->value.nvalue;
	if (myself->value.avalue->head <= i || i < 0) {
		CtrStdError = ctr_build_string_from_cstring("Index out of bounds.\0");
		return CtrStdNil;
	}
	return *(myself->value.avalue->elements + i);
}
Exemplo n.º 29
0
/**
 * @internal
 *
 * Adds the Curl object into the world
 **/
void begin(){
	ctr_object*  CtrStdHandle = ctr_internal_create_object(CTR_OBJECT_TYPE_OTOBJECT);
	ctr_internal_create_func(CtrStdHandle, ctr_build_string_from_cstring( "new" ), &ctr_curl_new );
	ctr_internal_create_func(CtrStdHandle, ctr_build_string_from_cstring( "nieuw" ), &ctr_curl_new );
	ctr_internal_create_func(CtrStdHandle, ctr_build_string_from_cstring( "type" ), &ctr_curl_type );
	ctr_internal_create_func(CtrStdHandle, ctr_build_string_from_cstring( "cleanup" ), &ctr_curl_cleanup );
	ctr_internal_create_func(CtrStdHandle, ctr_build_string_from_cstring( "perform" ), &ctr_curl_perform );
	ctr_internal_create_func(CtrStdHandle, ctr_build_string_from_cstring( "respondTo:and:"), &ctr_curl_respondto );
	ctr_internal_object_add_property(CtrStdWorld, ctr_build_string_from_cstring( "Curl" ), CtrStdHandle, CTR_CATEGORY_PUBLIC_PROPERTY);
	CtrStdHandle->link = CtrStdObject;
	CtrStdHandle->info.sticky = 1;
}
Exemplo n.º 30
0
/**
 * [Program] env: [String]
 *
 * Returns the value of an environment variable.
 *
 * Usage:
 *
 * x := Command env: 'MY_PATH_VAR'.
 */
ctr_object* ctr_command_get_env(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* envVarNameObj;
	char*       envVarNameStr;
	char*       envVal;
	envVarNameObj = ctr_internal_cast2string(argumentList->object);
	envVarNameStr = malloc((envVarNameObj->value.svalue->vlen+1)*sizeof(char));
	strncpy(envVarNameStr, envVarNameObj->value.svalue->value, envVarNameObj->value.svalue->vlen);
	*(envVarNameStr + (envVarNameObj->value.svalue->vlen)) = '\0';
	envVal = getenv(envVarNameStr);
	if (envVal == NULL) {
		return CtrStdNil;
	}
	return ctr_build_string_from_cstring(envVal);
}