1bf215546Sopenharmony_ci// 2bf215546Sopenharmony_ci// Copyright 2020 Serge Martin 3bf215546Sopenharmony_ci// 4bf215546Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci// copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci// to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci// the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci// and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci// Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci// 11bf215546Sopenharmony_ci// The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci// all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci// 14bf215546Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci// OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci// 22bf215546Sopenharmony_ci// Extract from Serge's printf clover code by airlied. 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <assert.h> 25bf215546Sopenharmony_ci#include <stdarg.h> 26bf215546Sopenharmony_ci#include <string.h> 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "macros.h" 29bf215546Sopenharmony_ci#include "u_printf.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci/* Some versions of MinGW are missing _vscprintf's declaration, although they 32bf215546Sopenharmony_ci * still provide the symbol in the import library. */ 33bf215546Sopenharmony_ci#ifdef __MINGW32__ 34bf215546Sopenharmony_ci_CRTIMP int _vscprintf(const char *format, va_list argptr); 35bf215546Sopenharmony_ci#endif 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#ifndef va_copy 38bf215546Sopenharmony_ci#ifdef __va_copy 39bf215546Sopenharmony_ci#define va_copy(dest, src) __va_copy((dest), (src)) 40bf215546Sopenharmony_ci#else 41bf215546Sopenharmony_ci#define va_copy(dest, src) (dest) = (src) 42bf215546Sopenharmony_ci#endif 43bf215546Sopenharmony_ci#endif 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_cisize_t util_printf_next_spec_pos(const char *str, size_t pos) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci if (str == NULL) 48bf215546Sopenharmony_ci return -1; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci const char *str_found = str + pos; 51bf215546Sopenharmony_ci do { 52bf215546Sopenharmony_ci str_found = strchr(str_found, '%'); 53bf215546Sopenharmony_ci if (str_found == NULL) 54bf215546Sopenharmony_ci return -1; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci ++str_found; 57bf215546Sopenharmony_ci if (*str_found == '%') { 58bf215546Sopenharmony_ci ++str_found; 59bf215546Sopenharmony_ci continue; 60bf215546Sopenharmony_ci } 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci char *spec_pos = strpbrk(str_found, "cdieEfFgGaAosuxXp%"); 63bf215546Sopenharmony_ci if (spec_pos == NULL) { 64bf215546Sopenharmony_ci return -1; 65bf215546Sopenharmony_ci } else if (*spec_pos == '%') { 66bf215546Sopenharmony_ci str_found = spec_pos; 67bf215546Sopenharmony_ci } else { 68bf215546Sopenharmony_ci return spec_pos - str; 69bf215546Sopenharmony_ci } 70bf215546Sopenharmony_ci } while (1); 71bf215546Sopenharmony_ci} 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_cisize_t u_printf_length(const char *fmt, va_list untouched_args) 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci int size; 76bf215546Sopenharmony_ci char junk; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci /* Make a copy of the va_list so the original caller can still use it */ 79bf215546Sopenharmony_ci va_list args; 80bf215546Sopenharmony_ci va_copy(args, untouched_args); 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci#ifdef _WIN32 83bf215546Sopenharmony_ci /* We need to use _vcsprintf to calculate the size as vsnprintf returns -1 84bf215546Sopenharmony_ci * if the number of characters to write is greater than count. 85bf215546Sopenharmony_ci */ 86bf215546Sopenharmony_ci size = _vscprintf(fmt, args); 87bf215546Sopenharmony_ci (void)junk; 88bf215546Sopenharmony_ci#else 89bf215546Sopenharmony_ci size = vsnprintf(&junk, 1, fmt, args); 90bf215546Sopenharmony_ci#endif 91bf215546Sopenharmony_ci assert(size >= 0); 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci va_end(args); 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci return size; 96bf215546Sopenharmony_ci} 97