text.c revision 240116
1193326Sed/* 2193326Sed * Automated Testing Framework (atf) 3193326Sed * 4193326Sed * Copyright (c) 2008 The NetBSD Foundation, Inc. 5193326Sed * All rights reserved. 6193326Sed * 7193326Sed * Redistribution and use in source and binary forms, with or without 8193326Sed * modification, are permitted provided that the following conditions 9193326Sed * are met: 10193326Sed * 1. Redistributions of source code must retain the above copyright 11193326Sed * notice, this list of conditions and the following disclaimer. 12193326Sed * 2. Redistributions in binary form must reproduce the above copyright 13193326Sed * notice, this list of conditions and the following disclaimer in the 14193326Sed * documentation and/or other materials provided with the distribution. 15193326Sed * 16193326Sed * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17193326Sed * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18252723Sdim * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19226890Sdim * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20252723Sdim * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21201361Srdivacky * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22193326Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23245431Sdim * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24218893Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25193326Sed * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26193326Sed * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27193326Sed * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28226890Sdim */ 29193326Sed 30193326Sed#include <errno.h> 31193326Sed#include <limits.h> 32193326Sed#include <string.h> 33218893Sdim#include <stdlib.h> 34218893Sdim 35198092Srdivacky#include "atf-c/error.h" 36193326Sed 37193326Sed#include "dynstr.h" 38193326Sed#include "sanity.h" 39193326Sed#include "text.h" 40193326Sed 41198092Srdivackyatf_error_t 42193326Sedatf_text_for_each_word(const char *instr, const char *sep, 43193326Sed atf_error_t (*func)(const char *, void *), 44193326Sed void *data) 45193326Sed{ 46198092Srdivacky atf_error_t err; 47193326Sed char *str, *str2, *last; 48198092Srdivacky 49235633Sdim str = strdup(instr); 50198092Srdivacky if (str == NULL) { 51193326Sed err = atf_no_memory_error(); 52245431Sdim goto out; 53245431Sdim } 54245431Sdim 55193326Sed err = atf_no_error(); 56193326Sed str2 = strtok_r(str, sep, &last); 57193326Sed while (str2 != NULL && !atf_is_error(err)) { 58193326Sed err = func(str2, data); 59193326Sed str2 = strtok_r(NULL, sep, &last); 60193326Sed } 61198092Srdivacky 62198092Srdivacky free(str); 63198092Srdivackyout: 64193326Sed return err; 65193326Sed} 66193326Sed 67193326Sedatf_error_t 68193326Sedatf_text_format(char **dest, const char *fmt, ...) 69235633Sdim{ 70235633Sdim atf_error_t err; 71235633Sdim va_list ap; 72193326Sed 73235633Sdim va_start(ap, fmt); 74235633Sdim err = atf_text_format_ap(dest, fmt, ap); 75235633Sdim va_end(ap); 76235633Sdim 77235633Sdim return err; 78235633Sdim} 79235633Sdim 80235633Sdimatf_error_t 81198092Srdivackyatf_text_format_ap(char **dest, const char *fmt, va_list ap) 82263509Sdim{ 83263509Sdim atf_error_t err; 84193326Sed atf_dynstr_t tmp; 85198092Srdivacky va_list ap2; 86193326Sed 87193326Sed va_copy(ap2, ap); 88193326Sed err = atf_dynstr_init_ap(&tmp, fmt, ap2); 89193326Sed va_end(ap2); 90193326Sed if (!atf_is_error(err)) 91198092Srdivacky *dest = atf_dynstr_fini_disown(&tmp); 92193326Sed 93193326Sed return err; 94193326Sed} 95193326Sed 96193326Sedatf_error_t 97201361Srdivackyatf_text_split(const char *str, const char *delim, atf_list_t *words) 98193326Sed{ 99198092Srdivacky atf_error_t err; 100198092Srdivacky const char *end; 101193326Sed const char *iter; 102198092Srdivacky 103263509Sdim err = atf_list_init(words); 104263509Sdim if (atf_is_error(err)) 105263509Sdim goto err; 106263509Sdim 107263509Sdim end = str + strlen(str); 108263509Sdim INV(*end == '\0'); 109263509Sdim iter = str; 110263509Sdim while (iter < end) { 111193326Sed const char *ptr; 112193326Sed 113193326Sed INV(iter != NULL); 114263509Sdim ptr = strstr(iter, delim); 115193326Sed if (ptr == NULL) 116193326Sed ptr = end; 117193326Sed 118198092Srdivacky INV(ptr >= iter); 119193326Sed if (ptr > iter) { 120193326Sed atf_dynstr_t word; 121193326Sed 122263509Sdim err = atf_dynstr_init_raw(&word, iter, ptr - iter); 123263509Sdim if (atf_is_error(err)) 124193326Sed goto err_list; 125193326Sed 126193326Sed err = atf_list_append(words, atf_dynstr_fini_disown(&word), true); 127198092Srdivacky if (atf_is_error(err)) 128193326Sed goto err_list; 129193326Sed } 130193326Sed 131263509Sdim iter = ptr + strlen(delim); 132193326Sed } 133193326Sed 134193326Sed INV(!atf_is_error(err)); 135198092Srdivacky return err; 136193326Sed 137193326Sederr_list: 138193326Sed atf_list_fini(words); 139263509Sdimerr: 140263509Sdim return err; 141193326Sed} 142193326Sed 143193326Sedatf_error_t 144198092Srdivackyatf_text_to_bool(const char *str, bool *b) 145193326Sed{ 146193326Sed atf_error_t err; 147193326Sed 148193326Sed if (strcasecmp(str, "yes") == 0 || 149193326Sed strcasecmp(str, "true") == 0) { 150193326Sed *b = true; 151226890Sdim err = atf_no_error(); 152193326Sed } else if (strcasecmp(str, "no") == 0 || 153193326Sed strcasecmp(str, "false") == 0) { 154235633Sdim *b = false; 155235633Sdim err = atf_no_error(); 156193326Sed } else { 157193326Sed /* XXX Not really a libc error. */ 158226890Sdim err = atf_libc_error(EINVAL, "Cannot convert string '%s' " 159226890Sdim "to boolean", str); 160193326Sed } 161193326Sed 162226890Sdim return err; 163226890Sdim} 164226890Sdim 165226890Sdimatf_error_t 166193326Sedatf_text_to_long(const char *str, long *l) 167193326Sed{ 168235633Sdim atf_error_t err; 169235633Sdim char *endptr; 170235633Sdim long tmp; 171235633Sdim 172235633Sdim errno = 0; 173193326Sed tmp = strtol(str, &endptr, 10); 174193326Sed if (str[0] == '\0' || *endptr != '\0') 175193326Sed err = atf_libc_error(EINVAL, "'%s' is not a number", str); 176193326Sed else if (errno == ERANGE || (tmp == LONG_MAX || tmp == LONG_MIN)) 177193326Sed err = atf_libc_error(ERANGE, "'%s' is out of range", str); 178193326Sed else { 179218893Sdim *l = tmp; 180218893Sdim err = atf_no_error(); 181218893Sdim } 182226890Sdim 183218893Sdim return err; 184193326Sed} 185193326Sed