/** * StringLastIndexOf * * Returns the index (character number, not the byte!) of the * needle in the haystack. * * Usage: * 'find the needle' lastIndexOf: 'needle'. #9 */ ctr_object* ctr_string_last_index_of(ctr_object* myself, ctr_argument* argumentList) { ctr_object* sub = ctr_internal_cast2string(argumentList->object); long hlen = myself->value.svalue->vlen; long nlen = sub->value.svalue->vlen; ctr_size uchar_index; ctr_size byte_index; char* p = ctr_internal_memmem(myself->value.svalue->value, hlen, sub->value.svalue->value, nlen, 1); if (p == NULL) return ctr_build_number_from_float((float)-1); byte_index = (ctr_size) ( (uintptr_t) p - (uintptr_t) (myself->value.svalue->value) ); uchar_index = ctr_getutf8len(myself->value.svalue->value, byte_index); return ctr_build_number_from_float((float) uchar_index); }
/** * StringLength * * Returns the length of the string in symbols. * This message is UTF-8 unicode aware. A 4 byte character will be counted as ONE. */ ctr_object* ctr_string_length(ctr_object* myself, ctr_argument* argumentList) { ctr_size n = ctr_getutf8len(myself->value.svalue->value, (ctr_size) myself->value.svalue->vlen); return ctr_build_number_from_float((ctr_number) n); }
/** * CTRParserMessage * * Creates the AST nodes for sending a message. * * - precedence mode 0: no argument (allows processing of unary message, binary message and keyword message) * - precedence mode 1: as argument of keyword message (allows processing of unary message and binary message) * - precedence mode 2: as argument of binary message (only allows processing of unary message) */ ctr_tnode* ctr_cparse_message(int mode) { long msgpartlen; /* length of part of message string */ ctr_tnode* m; int t; char* s; char* msg; ctr_tlistitem* li; ctr_tlistitem* curlistitem; int lookAhead; int isBin; int first; ctr_size ulen; t = ctr_clex_tok(); msgpartlen = ctr_clex_tok_value_length(); if ((msgpartlen) > 255) { printf("Message too long\n"); exit(1); } m = CTR_PARSER_CREATE_NODE(); m->type = -1; s = ctr_clex_tok_value(); msg = ctr_malloc(255*sizeof(char), 0); memcpy(msg, s, msgpartlen); ulen = ctr_getutf8len(msg, msgpartlen); isBin = (ulen == 1); if (mode == 2 && isBin) { ctr_clex_putback(); return m; } if (isBin) { if (ctr_mode_debug) printf("Parsing binary message: '%s' (mode: %d)\n", msg, mode); m->type = CTR_AST_NODE_BINMESSAGE; m->value = msg; m->vlen = msgpartlen; li = CTR_PARSER_CREATE_LISTITEM(); if (ctr_mode_debug) printf("Binary argument start..\n"); li->node = ctr_cparse_expr(2); if (ctr_mode_debug) printf("Binary argument end..\n"); m->nodes = li; return m; } lookAhead = ctr_clex_tok(); ctr_clex_putback(); if (lookAhead == CTR_TOKEN_COLON) { if (mode > 0) { ctr_clex_putback(); if (ctr_mode_debug) printf("> End of argument, next token: %s .\n", msg); return m; } *(msg + msgpartlen) = ':'; msgpartlen += 1; if ((msgpartlen) > 255) { printf("Message too long\n"); exit(1); } if (ctr_mode_debug) printf("Message so far: %s\n", msg); m->type = CTR_AST_NODE_KWMESSAGE; t = ctr_clex_tok(); first = 1; while(1) { li = CTR_PARSER_CREATE_LISTITEM(); if (ctr_mode_debug) printf("Next arg, message so far: %s \n", msg); li->node = ctr_cparse_expr(1); if (ctr_mode_debug) printf("Argument of keyword message has been parsed.\n"); if (first) { m->nodes = li; curlistitem = m->nodes; first = 0; } else { curlistitem->next = li; curlistitem = li; } t = ctr_clex_tok(); if (ctr_mode_debug) printf("Next token after argument = %d \n", t); if (t == CTR_TOKEN_DOT) break; if (t == CTR_TOKEN_FIN) break; if (t == CTR_TOKEN_CHAIN) break; if (t == CTR_TOKEN_PARCLOSE) break; if (t == CTR_TOKEN_REF) { long l = ctr_clex_tok_value_length(); if ((msgpartlen + l) > 255) { printf("Message too long\n"); exit(1); } memcpy( (msg+msgpartlen), ctr_clex_tok_value(), l); msgpartlen = msgpartlen + l; *(msg + msgpartlen) = ':'; msgpartlen ++; t = ctr_clex_tok(); if (t != CTR_TOKEN_COLON) { printf("Expected colon. %s \n",msg); exit(1); } } } if (ctr_mode_debug) printf("Putting back.\n"); ctr_clex_putback(); /* not a colon so put back */ if (ctr_mode_debug) printf("Parsing keyword message: '%s' (mode: %d) \n", msg, mode); m->value = msg; m->vlen = msgpartlen; } else { m->type = CTR_AST_NODE_UNAMESSAGE; m->value = msg; m->vlen = msgpartlen; if (ctr_mode_debug) printf("Parsing unary message: '%s' (mode: %d) token = %d \n", msg, mode, lookAhead); } return m; }