1273929Sjmmv/* Copyright (c) 2008 The NetBSD Foundation, Inc. 2240116Smarcel * All rights reserved. 3240116Smarcel * 4240116Smarcel * Redistribution and use in source and binary forms, with or without 5240116Smarcel * modification, are permitted provided that the following conditions 6240116Smarcel * are met: 7240116Smarcel * 1. Redistributions of source code must retain the above copyright 8240116Smarcel * notice, this list of conditions and the following disclaimer. 9240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright 10240116Smarcel * notice, this list of conditions and the following disclaimer in the 11240116Smarcel * documentation and/or other materials provided with the distribution. 12240116Smarcel * 13240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 14240116Smarcel * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 15240116Smarcel * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16240116Smarcel * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17240116Smarcel * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 18240116Smarcel * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 20240116Smarcel * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21240116Smarcel * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22240116Smarcel * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23240116Smarcel * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24273929Sjmmv * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 25240116Smarcel 26273929Sjmmv#include "atf-c/detail/text.h" 27273929Sjmmv 28240116Smarcel#include <errno.h> 29240116Smarcel#include <limits.h> 30240116Smarcel#include <string.h> 31240116Smarcel#include <stdlib.h> 32240116Smarcel 33273929Sjmmv#include "atf-c/detail/dynstr.h" 34273929Sjmmv#include "atf-c/detail/sanity.h" 35240116Smarcel#include "atf-c/error.h" 36240116Smarcel 37240116Smarcelatf_error_t 38240116Smarcelatf_text_for_each_word(const char *instr, const char *sep, 39240116Smarcel atf_error_t (*func)(const char *, void *), 40240116Smarcel void *data) 41240116Smarcel{ 42240116Smarcel atf_error_t err; 43240116Smarcel char *str, *str2, *last; 44240116Smarcel 45240116Smarcel str = strdup(instr); 46240116Smarcel if (str == NULL) { 47240116Smarcel err = atf_no_memory_error(); 48240116Smarcel goto out; 49240116Smarcel } 50240116Smarcel 51240116Smarcel err = atf_no_error(); 52240116Smarcel str2 = strtok_r(str, sep, &last); 53240116Smarcel while (str2 != NULL && !atf_is_error(err)) { 54240116Smarcel err = func(str2, data); 55240116Smarcel str2 = strtok_r(NULL, sep, &last); 56240116Smarcel } 57240116Smarcel 58240116Smarcel free(str); 59240116Smarcelout: 60240116Smarcel return err; 61240116Smarcel} 62240116Smarcel 63240116Smarcelatf_error_t 64240116Smarcelatf_text_format(char **dest, const char *fmt, ...) 65240116Smarcel{ 66240116Smarcel atf_error_t err; 67240116Smarcel va_list ap; 68240116Smarcel 69240116Smarcel va_start(ap, fmt); 70240116Smarcel err = atf_text_format_ap(dest, fmt, ap); 71240116Smarcel va_end(ap); 72240116Smarcel 73240116Smarcel return err; 74240116Smarcel} 75240116Smarcel 76240116Smarcelatf_error_t 77240116Smarcelatf_text_format_ap(char **dest, const char *fmt, va_list ap) 78240116Smarcel{ 79240116Smarcel atf_error_t err; 80240116Smarcel atf_dynstr_t tmp; 81240116Smarcel va_list ap2; 82240116Smarcel 83240116Smarcel va_copy(ap2, ap); 84240116Smarcel err = atf_dynstr_init_ap(&tmp, fmt, ap2); 85240116Smarcel va_end(ap2); 86240116Smarcel if (!atf_is_error(err)) 87240116Smarcel *dest = atf_dynstr_fini_disown(&tmp); 88240116Smarcel 89240116Smarcel return err; 90240116Smarcel} 91240116Smarcel 92240116Smarcelatf_error_t 93240116Smarcelatf_text_split(const char *str, const char *delim, atf_list_t *words) 94240116Smarcel{ 95240116Smarcel atf_error_t err; 96240116Smarcel const char *end; 97240116Smarcel const char *iter; 98240116Smarcel 99240116Smarcel err = atf_list_init(words); 100240116Smarcel if (atf_is_error(err)) 101240116Smarcel goto err; 102240116Smarcel 103240116Smarcel end = str + strlen(str); 104240116Smarcel INV(*end == '\0'); 105240116Smarcel iter = str; 106240116Smarcel while (iter < end) { 107240116Smarcel const char *ptr; 108240116Smarcel 109240116Smarcel INV(iter != NULL); 110240116Smarcel ptr = strstr(iter, delim); 111240116Smarcel if (ptr == NULL) 112240116Smarcel ptr = end; 113240116Smarcel 114240116Smarcel INV(ptr >= iter); 115240116Smarcel if (ptr > iter) { 116240116Smarcel atf_dynstr_t word; 117240116Smarcel 118240116Smarcel err = atf_dynstr_init_raw(&word, iter, ptr - iter); 119240116Smarcel if (atf_is_error(err)) 120240116Smarcel goto err_list; 121240116Smarcel 122240116Smarcel err = atf_list_append(words, atf_dynstr_fini_disown(&word), true); 123240116Smarcel if (atf_is_error(err)) 124240116Smarcel goto err_list; 125240116Smarcel } 126240116Smarcel 127240116Smarcel iter = ptr + strlen(delim); 128240116Smarcel } 129240116Smarcel 130240116Smarcel INV(!atf_is_error(err)); 131240116Smarcel return err; 132240116Smarcel 133240116Smarcelerr_list: 134240116Smarcel atf_list_fini(words); 135240116Smarcelerr: 136240116Smarcel return err; 137240116Smarcel} 138240116Smarcel 139240116Smarcelatf_error_t 140240116Smarcelatf_text_to_bool(const char *str, bool *b) 141240116Smarcel{ 142240116Smarcel atf_error_t err; 143240116Smarcel 144240116Smarcel if (strcasecmp(str, "yes") == 0 || 145240116Smarcel strcasecmp(str, "true") == 0) { 146240116Smarcel *b = true; 147240116Smarcel err = atf_no_error(); 148240116Smarcel } else if (strcasecmp(str, "no") == 0 || 149240116Smarcel strcasecmp(str, "false") == 0) { 150240116Smarcel *b = false; 151240116Smarcel err = atf_no_error(); 152240116Smarcel } else { 153240116Smarcel /* XXX Not really a libc error. */ 154240116Smarcel err = atf_libc_error(EINVAL, "Cannot convert string '%s' " 155240116Smarcel "to boolean", str); 156240116Smarcel } 157240116Smarcel 158240116Smarcel return err; 159240116Smarcel} 160240116Smarcel 161240116Smarcelatf_error_t 162240116Smarcelatf_text_to_long(const char *str, long *l) 163240116Smarcel{ 164240116Smarcel atf_error_t err; 165240116Smarcel char *endptr; 166240116Smarcel long tmp; 167240116Smarcel 168240116Smarcel errno = 0; 169240116Smarcel tmp = strtol(str, &endptr, 10); 170240116Smarcel if (str[0] == '\0' || *endptr != '\0') 171240116Smarcel err = atf_libc_error(EINVAL, "'%s' is not a number", str); 172240116Smarcel else if (errno == ERANGE || (tmp == LONG_MAX || tmp == LONG_MIN)) 173240116Smarcel err = atf_libc_error(ERANGE, "'%s' is out of range", str); 174240116Smarcel else { 175240116Smarcel *l = tmp; 176240116Smarcel err = atf_no_error(); 177240116Smarcel } 178240116Smarcel 179240116Smarcel return err; 180240116Smarcel} 181