t_match lexer_match_string(t_string_reader *reader, size_t pos) { t_token_value token_value; t_match match; char c; size_t reader_pos; char *str; if (reader->string[pos] != '\"' && reader->string[pos] != '\'') return (lexer_gen_empty_match()); c = reader->string[pos]; while ((reader->string[++pos] && (reader->string[pos] != c)) || count_backslash(reader->string, pos) % 2 == 1); if (!reader->string[pos] || reader->string[pos] != c) return (lexer_gen_error_match()); my_memset(&token_value, 0, sizeof(t_token_value)); pos += 1; reader_pos = reader->pos; match = gen_match_from_token(reader, pos, TOKEN_STRING, token_value); if (!reader->string[reader_pos]) return (lexer_gen_error_match()); str = &reader->string[reader_pos + 1]; match.token.value.string = clear_string(my_strndup(str, pos - reader_pos - 2)); return (match); }
static BOOL fill_it(char *s, char **s1, char **s2, int no) { char get; *s1 = NULL; *s2 = NULL; if (empty(s)) return (FALSE); if ((*s1 = my_strndup(s, my_sstrlen(s, "= \t"))) == NULL) return (TRUE); s += my_sstrlen(s, "= \t") + (IN('=', s) || IN(' ', s) || IN('\t', s)); get = s[0]; if (IN(s[0], "\"'") && !(IN(s[0], s + 1))) printf("error in conf file at line #%d, in %s definition\n", no, *s1); if (IN(s[0], "\"'") && !(IN(s[0], s + 1))) return (FALSE); if (!IN(s[0], "'\"")) get = 0; *s2 = my_strndup(s + IN(s[0], "'\""), my_strilen(s + IN(s[0], "'\""), get)); if (IN(s[0], "'\"") && !empty(s + my_strlen(*s2) + 2 * IN(s[0], "'\""))) printf("error in conf file at line #%d, in %s definition\n", no, *s1); if (IN(s[0], "'\"") && !empty(s + my_strlen(*s2) + 2 * IN(s[0], "'\""))) return (FALSE); return (TRUE); }
int *parse_it(char *info, int size) { int *ret; int i; int j; int k; char *str; i = -1; j = 0; k = 0; if (!(ret = malloc(size * sizeof(int)))) return (NULL); while (info[++i]) if (info[i] == ' ') { if (!(str = my_strndup(info, j, i))) return (NULL); k < size ? ret[k++] = atoi(str) : write(1, "", 0); j = i; free(str); } if (!(str = my_strndup(info, j, i))) return (NULL); ret[k] = atoi(str); free(str); return (ret); }
static BOOL check(t_get *link, t_header *head, char *line) { line = link->line; if (NMATCH(NAME_CMD_STRING, line + hempty(line))) head->name = get(NAME_CMD_STRING, line, 0, link->no); else if (NMATCH(COMMENT_CMD_STRING, line + hempty(line))) head->comment = get(COMMENT_CMD_STRING, line, 1, link->no); else { if (nempty(line, my_strilen(line, COMMENT_CHAR))) return (ERROR); else if (nempty(line, my_strilen(line, SCOMMENT_CHAR))) return (ERROR); if (IN(line, COMMENT_CHAR)) { link->line = my_strndup(line, my_strilen(line, COMMENT_CHAR)); free(line); } line = link->line; if (IN(line, SCOMMENT_CHAR)) { link->line = my_strndup(line, my_strilen(line, SCOMMENT_CHAR)); free(line); } return (CLEAN); } return (ERROR); }
void auto_completion(char value, int *rev_c, char **cmd) { char *dir; char *s; (void)value; s = my_strndup(*cmd + lastoccur_bf(*cmd, ' ', *rev_c) + ((*cmd)[lastoccur_bf(*cmd, ' ', *rev_c)] == ' '), *rev_c - lastoccur_bf(*cmd, ' ', *rev_c)); if (!s || empty(s)) dir = (s = NULL); else dir = my_strndup(s, lastoccur_bf(s, '/', my_strlen(s)) + IN('/', s)); go_down_of_cmd_high(*cmd); printf("\n"); if (dir) print_complo(dir, s + IN('/', s) * (lastoccur_bf(s, '/', my_strlen(s)) + 1)); else print_complo(".", s); if (dir) free(dir); prompt(TRUE); }
static cmark_node *fixup_nodes(cmark_inline_parser *inline_parser, cmark_node *parent, int size) { int node_text_len; cmark_node *prev = NULL; cmark_node *tmp; int name_size = size; cmark_strbuf *name; for (prev = cmark_node_last_child(parent); prev; prev = cmark_node_previous(prev)) { if (cmark_node_get_type(prev) == CMARK_NODE_TEXT) { const char *text = cmark_node_get_literal(prev); node_text_len = strlen(text); size -= node_text_len; if (size <= 0) { if (size < 0) { char *split_text = my_strndup(text, size * -1); cmark_node *split = cmark_node_new(CMARK_NODE_TEXT); cmark_node_set_literal(split, split_text); free(split_text); split_text = my_strndup(text + (size * - 1), node_text_len - size); cmark_node_set_literal(prev, split_text); free(split_text); cmark_node_insert_before(prev, split); } break; } } else { return NULL; } } name = cmark_strbuf_new(name_size + 1); tmp = prev; while (tmp) { cmark_node *next = cmark_node_next(tmp); cmark_strbuf_puts(name, cmark_node_get_literal(tmp)); if (tmp != prev) cmark_node_free(tmp); tmp = next; } cmark_node_set_type(prev, CMARK_NODE_LINK); cmark_node_set_url(prev, cmark_strbuf_get(name)); cmark_strbuf_free(name); return prev; }
/*! * init the services structure. * \version 1 * \date July 2006 * \author Elie * @see setup_default() * @return nothing */ void services_init(void) { bzero(&services, sizeof(services)); services.arp.name = (char *)my_strndup("arp",3); services.ethernet.name = (char *)my_strndup("ethernet",8); services.ip.name = (char *)my_strndup("ip",2); services.icmp.name = (char *)my_strndup("icmp",4); services.unknown.name = (char *)my_strndup("unknown",7); }
static struct message *parse_message_string(struct message *new_message, char *str) { char *start; DBUG_ENTER("parse_message_string"); DBUG_PRINT("enter", ("str: %s", str)); /*skip space(s) and/or tabs in the beginning */ while (*str == ' ' || *str == '\t' || *str == '\n') str++; if (!*str) { /* It was not a message line, but an empty line. */ DBUG_PRINT("info", ("str: %s", str)); DBUG_RETURN(0); } /* reading the short lang */ start= str; while (*str != ' ' && *str != '\t' && *str) str++; if (!(new_message->lang_short_name= my_strndup(PSI_NOT_INSTRUMENTED, start, (uint) (str - start), MYF(MY_WME | MY_FAE)))) DBUG_RETURN(0); /* Fatal error */ DBUG_PRINT("info", ("msg_slang: %s", new_message->lang_short_name)); /*skip space(s) and/or tabs after the lang */ while (*str == ' ' || *str == '\t' || *str == '\n') str++; if (*str != '"') { fprintf(stderr, "Unexpected EOL"); DBUG_PRINT("info", ("str: %s", str)); DBUG_RETURN(0); } /* reading the text */ start= str + 1; str= parse_text_line(start); if (!(new_message->text= my_strndup(PSI_NOT_INSTRUMENTED, start, (uint) (str - start), MYF(MY_WME | MY_FAE)))) DBUG_RETURN(0); /* Fatal error */ DBUG_PRINT("info", ("msg_text: %s", new_message->text)); DBUG_RETURN(new_message); }
int cfg_read_line(Config cfg, const char* line) { size_t n; const char *p, *end; const char *eqpos, *keyend; const char *valbegin, *valend; char *key, *val; n = strlen(line); p = line; end = &line[n]; /* Trim leading whitespace */ while(p != end && isspace(*p)) p++; /* Ignore blank lines or lines that start with '#' */ if(p == end || p[0] == '#') return 0; /* Split string on '=' character */ eqpos = strchr(p, '='); if(eqpos == NULL || eqpos == p) { fprintf(stderr, "cfg_read_line: '%s' is not a valid configuration line\n", line); return CFG_PARSE_ERROR; } /* Trim trailing whitespace from key name */ keyend = eqpos; while(isspace(*(keyend - 1))) keyend--; key = my_strndup(p, keyend-p); /* Trim whitespace (and optionally quotes) from value */ valbegin = eqpos + 1; while(valbegin != end && isspace(*valbegin)) valbegin++; valend = end; while(isspace(*(valend - 1))) valend--; if(cfg->strip_quotes && valend - valbegin >= 2 && ((*valbegin == '"' && *(valend-1) == '"') || (*valbegin == '\'' && *(valend-1) == '\''))) { valbegin++; valend--; } val = (valbegin >= valend) ? strdup("") : my_strndup(valbegin, valend-valbegin); cfg_insert_entry(cfg, key, val); return CFG_OKAY; }
/************************************************************************** purpose: provide functionality of getBraceParam() for strings if s contains "aaa {stuff}cdef", then parameter = getStringBraceParam(&s) gives parameter = "stuff" s="cdef" \alpha\beta ---> "\beta" \bar \alpha ---> "\alpha" ^ ^ \bar{text} ---> "text" \bar text ---> "t" ^ ^ _\alpha ---> "\alpha" _{\alpha} ---> "\alpha" ^ ^ _2 ---> "2" _{2} ---> "2" ^ ^ ******************************************************************************/ char *getStringBraceParam(char **s) { char *p_start, *p, *parameter, last; int braces; if (*s == NULL) return strdup(""); /* skip white space ... and one possible newline*/ while (**s == ' ') (*s)++; if (**s == '\n') { while (**s == ' ') (*s)++; } p_start = *s; /* return simple command like \alpha */ if (**s == '\\') { do { (*s)++; } while (isalpha(**s)); diagnostics(1,"getstringbraceparam \\ before='%s'", *s); return my_strndup(p_start,(*s)-p_start); } /* no brace ... advance one and return next character */ if (**s != '{' ) { (*s)++; return my_strndup(p_start,1); } /* usual case, return contents between braces */ p_start++; p=p_start; last = '\0'; braces = 1; while (*p != '\0' && braces > 0) { if (*p == '{' && last != '\\') braces++; if (*p == '}' && last != '\\') braces--; last = *p; p++; } parameter = my_strndup(p_start, p-p_start-1); *s = p; diagnostics(6,"Extract parameter=<%s> after=<%s>", parameter, *s); return parameter; }
void delete_first_word_met(char value, int *rev_c, char **cmd) { char *save; int i; int save_rev_c; int len; (void)value; len = my_strlen(*cmd) - 1; i = (*rev_c); while (i < len && ((*cmd)[i] == ' ' || (*cmd)[i] == '\t')) i++; while (i < len && ((*cmd)[i] != ' ' && (*cmd)[i] != '\t')) i++; if (i != len) i--; save_rev_c = (*rev_c) + 1; save = my_strndup((*cmd) + save_rev_c - 1, i + 2 - save_rev_c); remind_save_str(1, &save); free(save); while (save_rev_c < i + 2) { del_letter_in_str(0, &save_rev_c, cmd); save_rev_c = (*rev_c) + 1; i--; } }
t_get *comment(t_get *w, t_get *prev) { char quote; char *s; if (!w) return (prev); if ((((quote = (w->word)[0]) == '"' || (w->word)[0] == '\'') && !w->inter)) { if ((s = my_strndup(w->word + 1, my_strilen(w->word + 1, quote))) == NULL) if (my_strilen(w->word + 1, quote)) { nullify_next(w->next); free(w); return (NULL); } free(w->word); fill(&(w->word), s); w->inter = TRUE; } if (comment(w->next, w) == NULL) { rm_word(w); return (NULL); } return (w); }
char * expand_strdup( const char *s ) { struct passwd *pw; const char *p, *q; char *r; if (*s == '~') { s++; if (!*s) { p = 0; q = Home; } else if (*s == '/') { p = s; q = Home; } else { if ((p = strchr( s, '/' ))) { r = my_strndup( s, (int)(p - s) ); pw = getpwnam( r ); free( r ); } else pw = getpwnam( s ); if (!pw) return 0; q = pw->pw_dir; } nfasprintf( &r, "%s%s", q, p ? p : "" ); return r; } else return nfstrdup( s ); }
t_get *subdivide(char *s, t_get *prev, char **bad_sintax) { size_t l; t_get *link; if (empty(s)) return (prev); if (s[0] == '\\' && prev) if ((!S_IN(prev->word, "\"'|;<>()`"))) return (echappment(s, prev, bad_sintax, 0)); if ((link = xmalloc(sizeof(*prev))) == NULL) return (NULL); link->word = (void*)(link->next = NULL); link->prev = prev; if (prev) prev->next = link; s += hempty(s); if (s[(link->inter = 0)] == '\\') return (echappment(s, link, bad_sintax, 1)); l = subdiv(s, bad_sintax); if (*bad_sintax) return (nullify_link(link, 0, 1)); if ((link->word = my_strndup(s, l)) == NULL) return (nullify_link(link, 0, 1)); if (subdivide(s + my_strlen(link->word), link, bad_sintax) == NULL) return (nullify_link(link, 1, 1)); return (link); }
static int load_vmis(const char *file) { FILE *fd = fopen(file, "r"); if ( fd ) { char buf[1024]; int line = 0; while(fgets(buf, sizeof(buf), fd)) { line++; if ( strncmp(buf, "VMI(", 4) == 0 ) { const char *s1 = skip_ws(buf+4); const char *e1 = skip_id(s1); const char *s2 = skip_ws(skip_over(e1, ',')); const char *e2 = skip_flags(s2); const char *s3 = skip_ws(skip_over(e2, ',')); const char *e3 = skip_flags(s3); const char *s4 = skip_over(skip_ws(skip_over(e3, ',')), '('); const char *e4 = skip_over(s4, ')'); if ( !e4 ) { fprintf(stderr, "Syntax error at %s:%d\n", file, line); exit(1); } else e4--; /* backspace over ) */ vmi_list[vmi_count].name = my_strndup(s1, e1-s1); vmi_list[vmi_count].flags = my_strndup(s2, e2-s2); vmi_list[vmi_count].argc = my_strndup(s3, e3-s3); vmi_list[vmi_count].args = my_strndup(s4, e4-s4); add_synopsis(s1, e1-s1); /* flags (s2) isn't needed for VM signature */ add_synopsis(s3, e3-s3); add_synopsis(s4, e4-s4); vmi_count++; } } fclose(fd); return 0; } return -1; }
char * keyvalue_pair(char *s, char **key, char **value) { char *k, *v; *key = NULL; *value = NULL; if (s==NULL) return NULL; /* skip any blanks at start */ while (*s == ' ') s++; if (*s=='\0') return NULL; /*possibly all blanks*/ /* find the end of the key */ k = s; while (*k != '=' && *k != ',' && *k != '\0') k++; /* allocate and copy string into the key */ *key = my_strndup(s, k-s); if (*k == '\0') return NULL; if (*k == ',') return k+1; /* '=' found, now parse value */ s = k+1; /* skip any blanks at start */ while (*s == ' ') s++; /* find the end of the value */ v = s; while (*v != ',' && *v != '\0') { if (*v == '{') while (*(++v) != '}') ; else v++; } /* allocate and copy this into the value */ *value = my_strndup(s, v-s); if (*v == '\0') return NULL; return v+1; }
static char *get_word(char **str) { char *start= *str; DBUG_ENTER("get_word"); *str= find_end_of_word(start); DBUG_RETURN(my_strndup(start, (uint) (*str - start), MYF(MY_WME | MY_FAE))); }
char *calc_new_str(char *str, int i, int i_save) { char *new_str; while (i > 0 && str[i - 1] == ' ') i--; if ((new_str = my_strndup(str + i_save, (i - i_save))) == NULL) return (NULL); return (new_str); }
void test_my_strndup(void) { { // Return value for a regular string and the length of that string should be a new // string whose contents are equal to the original. char * test_string = "potato"; char * result = my_strndup(test_string, 6); TEST_CHECK(test_string != result); TEST_CHECK(strcmp(test_string, result) == 0); free(result); } { // Return value for a regular string and zero should be a new empty string. char * test_string = "potato"; char * result = my_strndup(test_string, 0); TEST_CHECK(result == 0); } }
char *my_get_line(char *str) { char *line; int len; line = NULL; if (str == NULL || (len = my_len_line(str)) < 0 || (line = my_strndup(str, len)) == NULL) return (NULL); return (line); }
static char *get(char *type, char *line, int itype, int n) { int l; l = hempty(line) + my_strlen(type) + hempty(line + hempty(line) + my_strlen(type)); if (line[l] != '"') lerror(INVALID(itype), n); if (!IN(line + l + 1, '"')) lerror(INVALID(itype), n); return (my_strndup(line + l + 1, my_strilen(line + l + 1, '"'))); }
int get_word(char *line, int *i, t_tok *tok) { int len; len = word_len(line, (*i), tok); if (line == NULL || i == NULL || tok == NULL) return (false); if ((tok->word = my_strndup(&line[(*i)], len - 1)) == NULL) return (false); (*i) += (len > 0 ? (len - 1) : len); return (true); }
/* * Parse the sample fetch expression <text> and add a node to <list_format> upon * success. At the moment, sample converters are not yet supported but fetch arguments * should work. The curpx->conf.args.ctx must be set by the caller. */ void add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct proxy *curpx, struct list *list_format, int options, int cap, const char *file, int line) { char *cmd[2]; struct sample_expr *expr; struct logformat_node *node; int cmd_arg; char *errmsg = NULL; cmd[0] = text; cmd[1] = ""; cmd_arg = 0; expr = sample_parse_expr(cmd, &cmd_arg, file, line, &errmsg, &curpx->conf.args); if (!expr) { Warning("parsing [%s:%d] : '%s' : sample fetch <%s> failed with : %s\n", curpx->conf.args.file, curpx->conf.args.line, fmt_directive(curpx), text, errmsg); return; } node = calloc(1, sizeof(struct logformat_node)); node->type = LOG_FMT_EXPR; node->expr = expr; node->options = options; if (arg_len) { node->arg = my_strndup(arg, arg_len); parse_logformat_var_args(node->arg, node); } if (expr->fetch->val & cap & SMP_VAL_REQUEST) node->options |= LOG_OPT_REQ_CAP; /* fetch method is request-compatible */ if (expr->fetch->val & cap & SMP_VAL_RESPONSE) node->options |= LOG_OPT_RES_CAP; /* fetch method is response-compatible */ if (!(expr->fetch->val & cap)) Warning("parsing [%s:%d] : '%s' : sample fetch <%s> may not be reliably used here because it needs '%s' which is not available here.\n", curpx->conf.args.file, curpx->conf.args.line, fmt_directive(curpx), text, sample_src_names(expr->fetch->use)); /* check if we need to allocate an hdr_idx struct for HTTP parsing */ /* Note, we may also need to set curpx->to_log with certain fetches */ curpx->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY); /* FIXME: temporary workaround for missing LW_XPRT and LW_REQ flags * needed with some sample fetches (eg: ssl*). We always set it for * now on, but this will leave with sample capabilities soon. */ curpx->to_log |= LW_XPRT; curpx->to_log |= LW_REQ; LIST_ADDQ(list_format, &node->list); }
/* See http://stackoverflow.com/questions/1575278/function-to-split-a-filepath-into-path-and-file */ void split_path_file(char** dir, char** file, char *path) { char *slash = path, *next; #if defined(__WIN32) const char sep[] = "\\/"; // Windows allows either variant #else const char sep[] = "/"; #endif while ((next = strpbrk(slash + 1, sep))) slash = next; if (path != slash) slash++; *dir = my_strndup(path, slash - path); *file = strdup(slash); }
/* * Parse a variable '%varname' or '%{args}varname' in log-format. The caller * must pass the args part in the <arg> pointer with its length in <arg_len>, * and varname with its length in <var> and <var_len> respectively. <arg> is * ignored when arg_len is 0. Neither <var> nor <var_len> may be null. */ int parse_logformat_var(char *arg, int arg_len, char *var, int var_len, struct proxy *curproxy, struct list *list_format, int *defoptions) { int j; struct logformat_node *node; for (j = 0; logformat_keywords[j].name; j++) { // search a log type if (strlen(logformat_keywords[j].name) == var_len && strncmp(var, logformat_keywords[j].name, var_len) == 0) { if (logformat_keywords[j].mode != PR_MODE_HTTP || curproxy->mode == PR_MODE_HTTP) { node = calloc(1, sizeof(struct logformat_node)); node->type = logformat_keywords[j].type; node->options = *defoptions; if (arg_len) { node->arg = my_strndup(arg, arg_len); parse_logformat_var_args(node->arg, node); } if (node->type == LOG_FMT_GLOBAL) { *defoptions = node->options; free(node->arg); free(node); } else { if (logformat_keywords[j].config_callback && logformat_keywords[j].config_callback(node, curproxy) != 0) { return -1; } curproxy->to_log |= logformat_keywords[j].lw; LIST_ADDQ(list_format, &node->list); } if (logformat_keywords[j].replace_by) Warning("parsing [%s:%d] : deprecated variable '%s' in '%s', please replace it with '%s'.\n", curproxy->conf.args.file, curproxy->conf.args.line, logformat_keywords[j].name, fmt_directive(curproxy), logformat_keywords[j].replace_by); return 0; } else { Warning("parsing [%s:%d] : '%s' : format variable '%s' is reserved for HTTP mode.\n", curproxy->conf.args.file, curproxy->conf.args.line, fmt_directive(curproxy), logformat_keywords[j].name); return -1; } } } j = var[var_len]; var[var_len] = 0; Warning("parsing [%s:%d] : no such format variable '%s' in '%s'. If you wanted to emit the '%%' character verbatim, you need to use '%%%%' in log-format expressions.\n", curproxy->conf.args.file, curproxy->conf.args.line, var, fmt_directive(curproxy)); var[var_len] = j; return -1; }
char *my_strdown(const char *str, int len) { char *result, *s; return_val_if_fail(str != NULL, NULL); if (len < 0) len = strlen(str); result = my_strndup(str, len); for (s = result; *s; s++) *s = tolower(*s); return result; }
void multiple_cmd(t_cmd **my_list, char *cmd) { int i; int j; i = 0; while (cmd[i]) { j = i; while (cmd[i] && cmd[i] != ';') i++; add_cmd(my_list, my_strndup(cmd, j, i)); i++; } }
const int sp_operator(t_op *operation, int *i) { if ((operation->input[*i] == operation->operators[4]) || (operation->input[*i] == operation->operators[5]) || (operation->input[*i] == operation->operators[6])) { if ((push_back(operation->lexeme_list, my_strndup(&(operation->input[*i]), 1))) == RETURN_FAILURE) return (RETURN_FAILURE); _define_id(operation, i); *i += 1; return (RETURN_SUCCESS); } return (RETURN_FAILURE); }
my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) { char *end, *copy; char buff[FN_REFLEN]; DBUG_ENTER("init_tmpdir"); DBUG_PRINT("enter", ("pathlist: %s", pathlist ? pathlist : "NULL")); mysql_mutex_init(key_TMPDIR_mutex, &tmpdir->mutex, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&tmpdir->full_list, sizeof(char*), 1, 5)) goto err; if (!pathlist || !pathlist[0]) { /* Get default temporary directory */ pathlist=getenv("TMPDIR"); /* Use this if possible */ #if defined(_WIN32) if (!pathlist) pathlist=getenv("TEMP"); if (!pathlist) pathlist=getenv("TMP"); #endif if (!pathlist || !pathlist[0]) pathlist=(char*) P_tmpdir; } do { size_t length; end=strcend(pathlist, DELIM); strmake(buff, pathlist, (uint) (end-pathlist)); length= cleanup_dirname(buff, buff); if (!(copy= my_strndup(key_memory_MY_TMPDIR_full_list, buff, length, MYF(MY_WME))) || insert_dynamic(&tmpdir->full_list, ©)) DBUG_RETURN(TRUE); pathlist=end+1; } while (*end); freeze_size(&tmpdir->full_list); tmpdir->list=(char **)tmpdir->full_list.buffer; tmpdir->max=tmpdir->full_list.elements-1; tmpdir->cur=0; DBUG_RETURN(FALSE); err: delete_dynamic(&tmpdir->full_list); /* Safe to free */ mysql_mutex_destroy(&tmpdir->mutex); DBUG_RETURN(TRUE); }
static char *get_value(char *line, const char *item) { char *destination= 0; int item_len= (int)strlen(item); int line_len = (int)strlen(line); if ((strncasecmp(line, item, item_len) == 0)) { int start= 0; char *s= 0; s = line + item_len + 1; destination= my_strndup(s, line_len - start, MYF(MY_FAE)); destination[line_len - item_len - 2]= 0; } return destination; }