estream-printf.c 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110
  1. /* estream-printf.c - Versatile C-99 compliant printf formatting
  2. * Copyright (C) 2007, 2008 g10 Code GmbH
  3. *
  4. * This file is part of Libestream.
  5. *
  6. * Libestream is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published
  8. * by the Free Software Foundation; either version 2 of the License,
  9. * or (at your option) any later version.
  10. *
  11. * Libestream is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Libestream; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /* Required autoconf tests:
  20. AC_TYPE_LONG_LONG_INT defines HAVE_LONG_LONG_INT
  21. AC_TYPE_LONG_DOUBLE defines HAVE_LONG_DOUBLE
  22. AC_TYPE_INTMAX_T defines HAVE_INTMAX_T
  23. AC_TYPE_UINTMAX_T defines HAVE_UINTMAX_T
  24. AC_CHECK_TYPES([ptrdiff_t]) defines HAVE_PTRDIFF_T
  25. AC_CHECK_SIZEOF([unsigned long]) defines SIZEOF_UNSIGNED_LONG
  26. AC_CHECK_SIZEOF([void *]) defines SIZEOF_VOID_P
  27. HAVE_LANGINFO_THOUSANDS_SEP
  28. Note that the file estream.m4 provides the autoconf macro
  29. ESTREAM_PRINTF_INIT which runs all required checks.
  30. See estream-printf.h for ways to tune this code.
  31. Missing stuff: wchar and wint_t
  32. thousands_sep in pr_float.
  33. */
  34. #ifdef HAVE_CONFIG_H
  35. # include <config.h>
  36. #endif
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <unistd.h>
  41. #include <stdarg.h>
  42. #include <errno.h>
  43. #include <stddef.h>
  44. #include <assert.h>
  45. #if defined(HAVE_INTMAX_T) || defined(HAVE_UINTMAX_T)
  46. # include <stdint.h>
  47. #endif
  48. #ifdef HAVE_LANGINFO_THOUSANDS_SEP
  49. #include <langinfo.h>
  50. #endif
  51. #ifdef TEST
  52. # include <locale.h>
  53. #else
  54. # ifdef _ESTREAM_PRINTF_EXTRA_INCLUDE
  55. # include _ESTREAM_PRINTF_EXTRA_INCLUDE
  56. # endif
  57. #endif
  58. #include "estream-printf.h"
  59. /* Allow redefinition of asprintf used malloc functions. */
  60. #if defined(_ESTREAM_PRINTF_MALLOC) && !defined(TEST)
  61. #define my_printf_malloc(a) _ESTREAM_PRINTF_MALLOC((a))
  62. #else
  63. #define my_printf_malloc(a) malloc((a))
  64. #endif
  65. #if defined(_ESTREAM_PRINTF_FREE) && !defined(TEST)
  66. #define my_printf_free(a) _ESTREAM_PRINTF_FREE((a))
  67. #else
  68. #define my_printf_free(a) free((a))
  69. #endif
  70. /* Calculate array dimension. */
  71. #ifndef DIM
  72. #define DIM(array) (sizeof (array) / sizeof (*array))
  73. #endif
  74. /* We allow for that many args without requiring malloced memory. */
  75. #define DEFAULT_MAX_ARGSPECS 5
  76. /* We allow for that many values without requiring malloced memory. */
  77. #define DEFAULT_MAX_VALUES 8
  78. /* We allocate this many new array argspec elements each time. */
  79. #define ARGSPECS_BUMP_VALUE 10
  80. /* Special values for the field width and the precision. */
  81. #define NO_FIELD_VALUE (-1)
  82. #define STAR_FIELD_VALUE (-2)
  83. /* Bit valuues used for the conversion flags. */
  84. #define FLAG_GROUPING 1
  85. #define FLAG_LEFT_JUST 2
  86. #define FLAG_PLUS_SIGN 4
  87. #define FLAG_SPACE_PLUS 8
  88. #define FLAG_ALT_CONV 16
  89. #define FLAG_ZERO_PAD 32
  90. /* Constants used the length modifiers. */
  91. typedef enum
  92. {
  93. LENMOD_NONE = 0,
  94. LENMOD_CHAR, /* "hh" */
  95. LENMOD_SHORT, /* "h" */
  96. LENMOD_LONG, /* "l" */
  97. LENMOD_LONGLONG, /* "ll" */
  98. LENMOD_INTMAX, /* "j" */
  99. LENMOD_SIZET, /* "z" */
  100. LENMOD_PTRDIFF, /* "t" */
  101. LENMOD_LONGDBL /* "L" */
  102. } lenmod_t;
  103. /* All the conversion specifiers. */
  104. typedef enum
  105. {
  106. CONSPEC_UNKNOWN = 0,
  107. CONSPEC_DECIMAL,
  108. CONSPEC_OCTAL,
  109. CONSPEC_UNSIGNED,
  110. CONSPEC_HEX,
  111. CONSPEC_HEX_UP,
  112. CONSPEC_FLOAT,
  113. CONSPEC_FLOAT_UP,
  114. CONSPEC_EXP,
  115. CONSPEC_EXP_UP,
  116. CONSPEC_F_OR_G,
  117. CONSPEC_F_OR_G_UP,
  118. CONSPEC_HEX_EXP,
  119. CONSPEC_HEX_EXP_UP,
  120. CONSPEC_CHAR,
  121. CONSPEC_STRING,
  122. CONSPEC_POINTER,
  123. CONSPEC_STRERROR,
  124. CONSPEC_BYTES_SO_FAR
  125. } conspec_t;
  126. /* Constants describing all the suppoorted types. Note that we list
  127. all the types we know about even if certain types are not available
  128. on this system. */
  129. typedef enum
  130. {
  131. VALTYPE_UNSUPPORTED = 0, /* Artificial type for error detection. */
  132. VALTYPE_CHAR,
  133. VALTYPE_SCHAR,
  134. VALTYPE_UCHAR,
  135. VALTYPE_SHORT,
  136. VALTYPE_USHORT,
  137. VALTYPE_INT,
  138. VALTYPE_UINT,
  139. VALTYPE_LONG,
  140. VALTYPE_ULONG,
  141. VALTYPE_LONGLONG,
  142. VALTYPE_ULONGLONG,
  143. VALTYPE_DOUBLE,
  144. VALTYPE_LONGDOUBLE,
  145. VALTYPE_STRING,
  146. VALTYPE_INTMAX,
  147. VALTYPE_UINTMAX,
  148. VALTYPE_SIZE,
  149. VALTYPE_PTRDIFF,
  150. VALTYPE_POINTER,
  151. VALTYPE_CHAR_PTR,
  152. VALTYPE_SCHAR_PTR,
  153. VALTYPE_SHORT_PTR,
  154. VALTYPE_INT_PTR,
  155. VALTYPE_LONG_PTR,
  156. VALTYPE_LONGLONG_PTR,
  157. VALTYPE_INTMAX_PTR,
  158. VALTYPE_SIZE_PTR,
  159. VALTYPE_PTRDIFF_PTR
  160. } valtype_t;
  161. /* A union used to store the actual values. */
  162. typedef union
  163. {
  164. char a_char;
  165. signed char a_schar;
  166. unsigned char a_uchar;
  167. short a_short;
  168. unsigned short a_ushort;
  169. int a_int;
  170. unsigned int a_uint;
  171. long int a_long;
  172. unsigned long int a_ulong;
  173. #ifdef HAVE_LONG_LONG_INT
  174. long long int a_longlong;
  175. unsigned long long int a_ulonglong;
  176. #endif
  177. double a_double;
  178. #ifdef HAVE_LONG_DOUBLE
  179. long double a_longdouble;
  180. #endif
  181. const char *a_string;
  182. #ifdef HAVE_INTMAX_T
  183. intmax_t a_intmax;
  184. #endif
  185. #ifdef HAVE_UINTMAX_T
  186. intmax_t a_uintmax;
  187. #endif
  188. size_t a_size;
  189. #ifdef HAVE_PTRDIFF_T
  190. ptrdiff_t a_ptrdiff;
  191. #endif
  192. void *a_void_ptr;
  193. char *a_char_ptr;
  194. signed char *a_schar_ptr;
  195. short *a_short_ptr;
  196. int *a_int_ptr;
  197. long *a_long_ptr;
  198. #ifdef HAVE_LONG_LONG_INT
  199. long long int *a_longlong_ptr;
  200. #endif
  201. #ifdef HAVE_INTMAX_T
  202. intmax_t *a_intmax_ptr;
  203. #endif
  204. size_t *a_size_ptr;
  205. #ifdef HAVE_PTRDIFF_T
  206. ptrdiff_t *a_ptrdiff_ptr;
  207. #endif
  208. } value_t;
  209. /* An object used to keep track of a format option and arguments. */
  210. struct argspec_s
  211. {
  212. size_t length; /* The length of these args including the percent. */
  213. unsigned int flags; /* The conversion flags (bits defined by FLAG_foo). */
  214. int width; /* The field width. */
  215. int precision; /* The precision. */
  216. lenmod_t lenmod; /* The length modifier. */
  217. conspec_t conspec; /* The conversion specifier. */
  218. int arg_pos; /* The position of the argument. This one may
  219. be -1 to indicate that no value is expected
  220. (e.g. for "%m"). */
  221. int width_pos; /* The position of the argument for a field
  222. width star's value. 0 for not used. */
  223. int precision_pos; /* The position of the argument for the a
  224. precision star's value. 0 for not used. */
  225. valtype_t vt; /* The type of the corresponding argument. */
  226. };
  227. typedef struct argspec_s *argspec_t;
  228. /* An object to build up a table of values and their types. */
  229. struct valueitem_s
  230. {
  231. valtype_t vt; /* The type of the value. */
  232. value_t value; /* The value. */
  233. };
  234. typedef struct valueitem_s *valueitem_t;
  235. #ifdef TEST
  236. static int verbose;
  237. static void
  238. dump_argspecs (argspec_t arg, size_t argcount)
  239. {
  240. int idx;
  241. for (idx=0; argcount; argcount--, arg++, idx++)
  242. fprintf (stderr,
  243. "%2d: len=%u flags=%u width=%d prec=%d mod=%d "
  244. "con=%d vt=%d pos=%d-%d-%d\n",
  245. idx,
  246. (unsigned int)arg->length,
  247. arg->flags,
  248. arg->width,
  249. arg->precision,
  250. arg->lenmod,
  251. arg->conspec,
  252. arg->vt,
  253. arg->arg_pos,
  254. arg->width_pos,
  255. arg->precision_pos);
  256. }
  257. #endif /*TEST*/
  258. /* Set the vt field for ARG. */
  259. static void
  260. compute_type (argspec_t arg)
  261. {
  262. switch (arg->conspec)
  263. {
  264. case CONSPEC_UNKNOWN:
  265. arg->vt = VALTYPE_UNSUPPORTED;
  266. break;
  267. case CONSPEC_DECIMAL:
  268. switch (arg->lenmod)
  269. {
  270. case LENMOD_CHAR: arg->vt = VALTYPE_SCHAR; break;
  271. case LENMOD_SHORT: arg->vt = VALTYPE_SHORT; break;
  272. case LENMOD_LONG: arg->vt = VALTYPE_LONG; break;
  273. case LENMOD_LONGLONG: arg->vt = VALTYPE_LONGLONG; break;
  274. case LENMOD_INTMAX: arg->vt = VALTYPE_INTMAX; break;
  275. case LENMOD_SIZET: arg->vt = VALTYPE_SIZE; break;
  276. case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF; break;
  277. default: arg->vt = VALTYPE_INT; break;
  278. }
  279. break;
  280. case CONSPEC_OCTAL:
  281. case CONSPEC_UNSIGNED:
  282. case CONSPEC_HEX:
  283. case CONSPEC_HEX_UP:
  284. switch (arg->lenmod)
  285. {
  286. case LENMOD_CHAR: arg->vt = VALTYPE_UCHAR; break;
  287. case LENMOD_SHORT: arg->vt = VALTYPE_USHORT; break;
  288. case LENMOD_LONG: arg->vt = VALTYPE_ULONG; break;
  289. case LENMOD_LONGLONG: arg->vt = VALTYPE_ULONGLONG; break;
  290. case LENMOD_INTMAX: arg->vt = VALTYPE_UINTMAX; break;
  291. case LENMOD_SIZET: arg->vt = VALTYPE_SIZE; break;
  292. case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF; break;
  293. default: arg->vt = VALTYPE_UINT; break;
  294. }
  295. break;
  296. case CONSPEC_FLOAT:
  297. case CONSPEC_FLOAT_UP:
  298. case CONSPEC_EXP:
  299. case CONSPEC_EXP_UP:
  300. case CONSPEC_F_OR_G:
  301. case CONSPEC_F_OR_G_UP:
  302. case CONSPEC_HEX_EXP:
  303. case CONSPEC_HEX_EXP_UP:
  304. switch (arg->lenmod)
  305. {
  306. case LENMOD_LONGDBL: arg->vt = VALTYPE_LONGDOUBLE; break;
  307. case LENMOD_LONG: arg->vt = VALTYPE_DOUBLE; break;
  308. default: arg->vt = VALTYPE_DOUBLE; break;
  309. }
  310. break;
  311. case CONSPEC_CHAR:
  312. arg->vt = VALTYPE_INT;
  313. break;
  314. case CONSPEC_STRING:
  315. arg->vt = VALTYPE_STRING;
  316. break;
  317. case CONSPEC_POINTER:
  318. arg->vt = VALTYPE_POINTER;
  319. break;
  320. case CONSPEC_STRERROR:
  321. arg->vt = VALTYPE_STRING;
  322. break;
  323. case CONSPEC_BYTES_SO_FAR:
  324. switch (arg->lenmod)
  325. {
  326. case LENMOD_CHAR: arg->vt = VALTYPE_SCHAR_PTR; break;
  327. case LENMOD_SHORT: arg->vt = VALTYPE_SHORT_PTR; break;
  328. case LENMOD_LONG: arg->vt = VALTYPE_LONG_PTR; break;
  329. case LENMOD_LONGLONG: arg->vt = VALTYPE_LONGLONG_PTR; break;
  330. case LENMOD_INTMAX: arg->vt = VALTYPE_INTMAX_PTR; break;
  331. case LENMOD_SIZET: arg->vt = VALTYPE_SIZE_PTR; break;
  332. case LENMOD_PTRDIFF: arg->vt = VALTYPE_PTRDIFF_PTR; break;
  333. default: arg->vt = VALTYPE_INT_PTR; break;
  334. }
  335. break;
  336. }
  337. }
  338. /* Parse the FORMAT string and populate the specification array stored
  339. at the address ARGSPECS_ADDR. The caller has provided enough space
  340. to store up to MAX_ARGSPECS in that buffer. The function may
  341. however ignore the provided buffer and malloc a larger one. On
  342. success the addrrss of that larger buffer will be stored at
  343. ARGSPECS_ADDR. The actual number of specifications will be
  344. returned at R_ARGSPECS_COUNT. */
  345. static int
  346. parse_format (const char *format,
  347. argspec_t *argspecs_addr, size_t max_argspecs,
  348. size_t *r_argspecs_count)
  349. {
  350. const char *s;
  351. argspec_t argspecs = *argspecs_addr;
  352. argspec_t arg;
  353. size_t argcount = 0;
  354. if (!format)
  355. goto leave_einval;
  356. for (; *format; format++)
  357. {
  358. unsigned int flags;
  359. int width, precision;
  360. lenmod_t lenmod;
  361. conspec_t conspec;
  362. int arg_pos, width_pos, precision_pos;
  363. if (*format != '%')
  364. continue;
  365. s = ++format;
  366. if (!*s)
  367. goto leave_einval;
  368. if (*s == '%')
  369. continue; /* Just a quoted percent. */
  370. /* First check whether there is a positional argument. */
  371. arg_pos = 0; /* No positional argument given. */
  372. if (*s >= '1' && *s <= '9')
  373. {
  374. const char *save_s = s;
  375. arg_pos = (*s++ - '0');
  376. for (; *s >= '0' && *s <= '9'; s++)
  377. arg_pos = 10*arg_pos + (*s - '0');
  378. if (arg_pos < 0)
  379. goto leave_einval; /* Overflow during conversion. */
  380. if (*s == '$')
  381. s++;
  382. else
  383. {
  384. arg_pos = 0;
  385. s = save_s;
  386. }
  387. }
  388. /* Parse the flags. */
  389. flags = 0;
  390. for ( ; *s; s++)
  391. {
  392. switch (*s)
  393. {
  394. case '\'': flags |= FLAG_GROUPING; break;
  395. case '-': flags |= FLAG_LEFT_JUST; break;
  396. case '+': flags |= FLAG_PLUS_SIGN; break;
  397. case ' ': flags |= FLAG_SPACE_PLUS; break;
  398. case '#': flags |= FLAG_ALT_CONV; break;
  399. case '0': flags |= FLAG_ZERO_PAD; break;
  400. default:
  401. goto flags_parsed;
  402. }
  403. }
  404. flags_parsed:
  405. /* Parse the field width. */
  406. width_pos = 0;
  407. if (*s == '*')
  408. {
  409. width = STAR_FIELD_VALUE;
  410. s++;
  411. /* If we have a positional argument, another one might also
  412. be used to give the position of the star's value. */
  413. if (arg_pos && *s >= '1' && *s <= '9')
  414. {
  415. width_pos = (*s++ - '0');
  416. for (; *s >= '0' && *s <= '9'; s++)
  417. width_pos = 10*width_pos + (*s - '0');
  418. if (width_pos < 1)
  419. goto leave_einval; /* Overflow during conversion. */
  420. if (*s != '$')
  421. goto leave_einval; /* Not followed by $. */
  422. s++;
  423. }
  424. }
  425. else if ( *s >= '0' && *s <= '9')
  426. {
  427. width = (*s++ - '0');
  428. for (; *s >= '0' && *s <= '9'; s++)
  429. {
  430. if (!width && *s == '0')
  431. goto leave_einval; /* Leading zeroes are not allowed.
  432. Fixme: check what other
  433. implementations do. */
  434. width = 10*width + (*s - '0');
  435. }
  436. if (width < 0)
  437. goto leave_einval; /* Overflow during conversion. */
  438. }
  439. else
  440. width = NO_FIELD_VALUE;
  441. /* Parse the precision. */
  442. precision_pos = 0;
  443. precision = NO_FIELD_VALUE;
  444. if (*s == '.')
  445. {
  446. int ignore_value = (s[1] == '-');
  447. s++;
  448. if (*s == '*')
  449. {
  450. precision = STAR_FIELD_VALUE;
  451. s++;
  452. /* If we have a positional argument, another one might also
  453. be used to give the position of the star's value. */
  454. if (arg_pos && *s >= '1' && *s <= '9')
  455. {
  456. precision_pos = (*s++ - '0');
  457. for (; *s >= '0' && *s <= '9'; s++)
  458. precision_pos = 10*precision_pos + (*s - '0');
  459. if (precision_pos < 1)
  460. goto leave_einval; /* Overflow during conversion. */
  461. if (*s != '$')
  462. goto leave_einval; /* Not followed by $. */
  463. s++;
  464. }
  465. }
  466. else if ( *s >= '0' && *s <= '9')
  467. {
  468. precision = (*s++ - '0');
  469. for (; *s >= '0' && *s <= '9'; s++)
  470. {
  471. if (!precision && *s == '0')
  472. goto leave_einval; /* Leading zeroes are not allowed.
  473. Fixme: check what other
  474. implementations do. */
  475. precision = 10*precision + (*s - '0');
  476. }
  477. if (precision < 0)
  478. goto leave_einval; /* Overflow during conversion. */
  479. }
  480. else
  481. precision = 0;
  482. if (ignore_value)
  483. precision = NO_FIELD_VALUE;
  484. }
  485. /* Parse the length modifiers. */
  486. switch (*s)
  487. {
  488. case 'h':
  489. if (s[1] == 'h')
  490. {
  491. lenmod = LENMOD_CHAR;
  492. s++;
  493. }
  494. else
  495. lenmod = LENMOD_SHORT;
  496. s++;
  497. break;
  498. case 'l':
  499. if (s[1] == 'l')
  500. {
  501. lenmod = LENMOD_LONGLONG;
  502. s++;
  503. }
  504. else
  505. lenmod = LENMOD_LONG;
  506. s++;
  507. break;
  508. case 'j': lenmod = LENMOD_INTMAX; s++; break;
  509. case 'z': lenmod = LENMOD_SIZET; s++; break;
  510. case 't': lenmod = LENMOD_PTRDIFF; s++; break;
  511. case 'L': lenmod = LENMOD_LONGDBL; s++; break;
  512. default: lenmod = LENMOD_NONE; break;
  513. }
  514. /* Parse the conversion specifier. */
  515. switch (*s)
  516. {
  517. case 'd':
  518. case 'i': conspec = CONSPEC_DECIMAL; break;
  519. case 'o': conspec = CONSPEC_OCTAL; break;
  520. case 'u': conspec = CONSPEC_UNSIGNED; break;
  521. case 'x': conspec = CONSPEC_HEX; break;
  522. case 'X': conspec = CONSPEC_HEX_UP; break;
  523. case 'f': conspec = CONSPEC_FLOAT; break;
  524. case 'F': conspec = CONSPEC_FLOAT_UP; break;
  525. case 'e': conspec = CONSPEC_EXP; break;
  526. case 'E': conspec = CONSPEC_EXP_UP; break;
  527. case 'g': conspec = CONSPEC_F_OR_G; break;
  528. case 'G': conspec = CONSPEC_F_OR_G_UP; break;
  529. case 'a': conspec = CONSPEC_HEX_EXP; break;
  530. case 'A': conspec = CONSPEC_HEX_EXP_UP; break;
  531. case 'c': conspec = CONSPEC_CHAR; break;
  532. case 's': conspec = CONSPEC_STRING; break;
  533. case 'p': conspec = CONSPEC_POINTER; break;
  534. case 'n': conspec = CONSPEC_BYTES_SO_FAR; break;
  535. case 'C': conspec = CONSPEC_CHAR; lenmod = LENMOD_LONG; break;
  536. case 'S': conspec = CONSPEC_STRING; lenmod = LENMOD_LONG; break;
  537. case 'm': conspec = CONSPEC_STRERROR; arg_pos = -1; break;
  538. default: conspec = CONSPEC_UNKNOWN;
  539. }
  540. /* Save the args. */
  541. if (argcount >= max_argspecs)
  542. {
  543. /* We either need to allocate a new array instead of the
  544. caller provided one or realloc the array. Instead of
  545. using realloc we allocate a new one and release the
  546. original one then. */
  547. size_t n, newmax;
  548. argspec_t newarg;
  549. newmax = max_argspecs + ARGSPECS_BUMP_VALUE;
  550. if (newmax <= max_argspecs)
  551. goto leave_einval; /* Too many arguments. */
  552. newarg = calloc (newmax, sizeof *newarg);
  553. if (!newarg)
  554. goto leave;
  555. for (n=0; n < argcount; n++)
  556. newarg[n] = argspecs[n];
  557. if (argspecs != *argspecs_addr)
  558. free (argspecs);
  559. argspecs = newarg;
  560. max_argspecs = newmax;
  561. }
  562. arg = argspecs + argcount;
  563. arg->length = s - format + 2;
  564. arg->flags = flags;
  565. arg->width = width;
  566. arg->precision = precision;
  567. arg->lenmod = lenmod;
  568. arg->conspec = conspec;
  569. arg->arg_pos = arg_pos;
  570. arg->width_pos = width_pos;
  571. arg->precision_pos = precision_pos;
  572. compute_type (arg);
  573. argcount++;
  574. format = s;
  575. }
  576. *argspecs_addr = argspecs;
  577. *r_argspecs_count = argcount;
  578. return 0; /* Success. */
  579. leave_einval:
  580. errno = EINVAL;
  581. leave:
  582. if (argspecs != *argspecs_addr)
  583. free (argspecs);
  584. *argspecs_addr = NULL;
  585. return -1;
  586. }
  587. /* This function reads all the values as specified by VALUETABLE into
  588. VALUETABLE. The values are expected in VAARGS. The function
  589. returns -1 if a specified type is not supported. */
  590. static int
  591. read_values (valueitem_t valuetable, size_t valuetable_len, va_list vaargs)
  592. {
  593. int validx;
  594. for (validx=0; validx < valuetable_len; validx++)
  595. {
  596. value_t *value = &valuetable[validx].value;
  597. valtype_t vt = valuetable[validx].vt;
  598. switch (vt)
  599. {
  600. case VALTYPE_CHAR: value->a_char = va_arg (vaargs, int); break;
  601. case VALTYPE_CHAR_PTR:
  602. value->a_char_ptr = va_arg (vaargs, char *);
  603. break;
  604. case VALTYPE_SCHAR: value->a_schar = va_arg (vaargs, int); break;
  605. case VALTYPE_SCHAR_PTR:
  606. value->a_schar_ptr = va_arg (vaargs, signed char *);
  607. break;
  608. case VALTYPE_UCHAR: value->a_uchar = va_arg (vaargs, int); break;
  609. case VALTYPE_SHORT: value->a_short = va_arg (vaargs, int); break;
  610. case VALTYPE_USHORT: value->a_ushort = va_arg (vaargs, int); break;
  611. case VALTYPE_SHORT_PTR:
  612. value->a_short_ptr = va_arg (vaargs, short *);
  613. break;
  614. case VALTYPE_INT:
  615. value->a_int = va_arg (vaargs, int);
  616. break;
  617. case VALTYPE_INT_PTR:
  618. value->a_int_ptr = va_arg (vaargs, int *);
  619. break;
  620. case VALTYPE_UINT:
  621. value->a_uint = va_arg (vaargs, unsigned int);
  622. break;
  623. case VALTYPE_LONG:
  624. value->a_long = va_arg (vaargs, long);
  625. break;
  626. case VALTYPE_ULONG:
  627. value->a_ulong = va_arg (vaargs, unsigned long);
  628. break;
  629. case VALTYPE_LONG_PTR:
  630. value->a_long_ptr = va_arg (vaargs, long *);
  631. break;
  632. #ifdef HAVE_LONG_LONG_INT
  633. case VALTYPE_LONGLONG:
  634. value->a_longlong = va_arg (vaargs, long long int);
  635. break;
  636. case VALTYPE_ULONGLONG:
  637. value->a_ulonglong = va_arg (vaargs, unsigned long long int);
  638. break;
  639. case VALTYPE_LONGLONG_PTR:
  640. value->a_longlong_ptr = va_arg (vaargs, long long *);
  641. break;
  642. #endif
  643. case VALTYPE_DOUBLE:
  644. value->a_double = va_arg (vaargs, double);
  645. break;
  646. #ifdef HAVE_LONG_DOUBLE
  647. case VALTYPE_LONGDOUBLE:
  648. value->a_longdouble = va_arg (vaargs, long double);
  649. break;
  650. #endif
  651. case VALTYPE_STRING:
  652. value->a_string = va_arg (vaargs, const char *);
  653. break;
  654. case VALTYPE_POINTER:
  655. value->a_void_ptr = va_arg (vaargs, void *);
  656. break;
  657. #ifdef HAVE_INTMAX_T
  658. case VALTYPE_INTMAX:
  659. value->a_intmax = va_arg (vaargs, intmax_t);
  660. break;
  661. case VALTYPE_INTMAX_PTR:
  662. value->a_intmax_ptr = va_arg (vaargs, intmax_t *);
  663. break;
  664. #endif
  665. #ifdef HAVE_UINTMAX_T
  666. case VALTYPE_UINTMAX:
  667. value->a_uintmax = va_arg (vaargs, uintmax_t);
  668. break;
  669. #endif
  670. case VALTYPE_SIZE:
  671. value->a_size = va_arg (vaargs, size_t);
  672. break;
  673. case VALTYPE_SIZE_PTR:
  674. value->a_size_ptr = va_arg (vaargs, size_t *);
  675. break;
  676. #ifdef HAVE_PTRDIFF_T
  677. case VALTYPE_PTRDIFF:
  678. value->a_ptrdiff = va_arg (vaargs, ptrdiff_t);
  679. break;
  680. case VALTYPE_PTRDIFF_PTR:
  681. value->a_ptrdiff_ptr = va_arg (vaargs, ptrdiff_t *);
  682. break;
  683. #endif
  684. default: /* Unsupported type. */
  685. return -1;
  686. }
  687. }
  688. return 0;
  689. }
  690. /* Output COUNT padding characters PADCHAR and update NBYTES by the
  691. number of bytes actually written. */
  692. static int
  693. pad_out (estream_printf_out_t outfnc, void *outfncarg,
  694. int padchar, int count, size_t *nbytes)
  695. {
  696. char buf[32];
  697. size_t n;
  698. int rc;
  699. while (count > 0)
  700. {
  701. n = (count <= sizeof buf)? count : sizeof buf;
  702. memset (buf, padchar, n);
  703. rc = outfnc (outfncarg, buf, n);
  704. if (rc)
  705. return rc;
  706. *nbytes += n;
  707. count -= n;
  708. }
  709. return 0;
  710. }
  711. /* "d,i,o,u,x,X" formatting. OUTFNC and OUTFNCARG describes the
  712. output routine, ARG gives the argument description and VALUE the
  713. actual value (its type is available through arg->vt). */
  714. static int
  715. pr_integer (estream_printf_out_t outfnc, void *outfncarg,
  716. argspec_t arg, value_t value, size_t *nbytes)
  717. {
  718. int rc;
  719. #ifdef HAVE_LONG_LONG_INT
  720. unsigned long long aulong;
  721. #else
  722. unsigned long aulong;
  723. #endif
  724. char numbuf[100];
  725. char *p, *pend;
  726. size_t n;
  727. char signchar = 0;
  728. int n_prec; /* Number of extra precision digits required. */
  729. int n_extra; /* Extra number of prefix or sign characters. */
  730. if (arg->conspec == CONSPEC_DECIMAL)
  731. {
  732. #ifdef HAVE_LONG_LONG_INT
  733. long long along;
  734. #else
  735. long along;
  736. #endif
  737. switch (arg->vt)
  738. {
  739. case VALTYPE_SHORT: along = value.a_short; break;
  740. case VALTYPE_INT: along = value.a_int; break;
  741. case VALTYPE_LONG: along = value.a_long; break;
  742. #ifdef HAVE_LONG_LONG_INT
  743. case VALTYPE_LONGLONG: along = value.a_longlong; break;
  744. case VALTYPE_SIZE: along = value.a_size; break;
  745. # ifdef HAVE_INTMAX_T
  746. case VALTYPE_INTMAX: along = value.a_intmax; break;
  747. # endif
  748. # ifdef HAVE_PTRDIFF_T
  749. case VALTYPE_PTRDIFF: along = value.a_ptrdiff; break;
  750. # endif
  751. #endif /*HAVE_LONG_LONG_INT*/
  752. default:
  753. return -1;
  754. }
  755. if (along < 0)
  756. {
  757. aulong = -along;
  758. signchar = '-';
  759. }
  760. else
  761. aulong = along;
  762. }
  763. else
  764. {
  765. switch (arg->vt)
  766. {
  767. case VALTYPE_USHORT: aulong = value.a_ushort; break;
  768. case VALTYPE_UINT: aulong = value.a_uint; break;
  769. case VALTYPE_ULONG: aulong = value.a_ulong; break;
  770. #ifdef HAVE_LONG_LONG_INT
  771. case VALTYPE_ULONGLONG: aulong = value.a_ulonglong; break;
  772. case VALTYPE_SIZE: aulong = value.a_size; break;
  773. # ifdef HAVE_UINTMAX_T
  774. case VALTYPE_UINTMAX: aulong = value.a_uintmax; break;
  775. # endif
  776. # ifdef HAVE_PTRDIFF_T
  777. case VALTYPE_PTRDIFF: aulong = value.a_ptrdiff; break;
  778. # endif
  779. #endif /*HAVE_LONG_LONG_INT*/
  780. default:
  781. return -1;
  782. }
  783. }
  784. if (signchar == '-')
  785. ;
  786. else if ((arg->flags & FLAG_PLUS_SIGN))
  787. signchar = '+';
  788. else if ((arg->flags & FLAG_SPACE_PLUS))
  789. signchar = ' ';
  790. n_extra = !!signchar;
  791. /* We build the string up backwards. */
  792. p = pend = numbuf + DIM(numbuf);
  793. if ((!aulong && !arg->precision))
  794. ;
  795. else if (arg->conspec == CONSPEC_DECIMAL
  796. || arg->conspec == CONSPEC_UNSIGNED)
  797. {
  798. int grouping = -1;
  799. const char * grouping_string =
  800. #ifdef HAVE_LANGINFO_THOUSANDS_SEP
  801. nl_langinfo(THOUSANDS_SEP);
  802. #else
  803. "'";
  804. #endif
  805. do
  806. {
  807. if ((arg->flags & FLAG_GROUPING)
  808. && (++grouping == 3) && *grouping_string)
  809. {
  810. *--p = *grouping_string;
  811. grouping = 0;
  812. }
  813. *--p = '0' + (aulong % 10);
  814. aulong /= 10;
  815. }
  816. while (aulong);
  817. }
  818. else if (arg->conspec == CONSPEC_OCTAL)
  819. {
  820. do
  821. {
  822. *--p = '0' + (aulong % 8);
  823. aulong /= 8;
  824. }
  825. while (aulong);
  826. if ((arg->flags & FLAG_ALT_CONV) && *p != '0')
  827. *--p = '0';
  828. }
  829. else /* HEX or HEXUP */
  830. {
  831. const char *digits = ((arg->conspec == CONSPEC_HEX)
  832. ? "0123456789abcdef" : "0123456789ABCDEF");
  833. do
  834. {
  835. *--p = digits[(aulong % 16)];
  836. aulong /= 16;
  837. }
  838. while (aulong);
  839. if ((arg->flags & FLAG_ALT_CONV))
  840. n_extra += 2;
  841. }
  842. n = pend - p;
  843. if ((arg->flags & FLAG_ZERO_PAD)
  844. && arg->precision == NO_FIELD_VALUE && !(arg->flags & FLAG_LEFT_JUST)
  845. && n && arg->width - n_extra > n )
  846. n_prec = arg->width - n_extra - n;
  847. else if (arg->precision > 0 && arg->precision > n)
  848. n_prec = arg->precision - n;
  849. else
  850. n_prec = 0;
  851. if (!(arg->flags & FLAG_LEFT_JUST)
  852. && arg->width >= 0 && arg->width - n_extra > n
  853. && arg->width - n_extra - n >= n_prec )
  854. {
  855. rc = pad_out (outfnc, outfncarg, ' ',
  856. arg->width - n_extra - n - n_prec, nbytes);
  857. if (rc)
  858. return rc;
  859. }
  860. if (signchar)
  861. {
  862. rc = outfnc (outfncarg, &signchar, 1);
  863. if (rc)
  864. return rc;
  865. *nbytes += 1;
  866. }
  867. if ((arg->flags & FLAG_ALT_CONV)
  868. && (arg->conspec == CONSPEC_HEX || arg->conspec == CONSPEC_HEX_UP))
  869. {
  870. rc = outfnc (outfncarg, arg->conspec == CONSPEC_HEX? "0x": "0X", 2);
  871. if (rc)
  872. return rc;
  873. *nbytes += 2;
  874. }
  875. if (n_prec)
  876. {
  877. rc = pad_out (outfnc, outfncarg, '0', n_prec, nbytes);
  878. if (rc)
  879. return rc;
  880. }
  881. rc = outfnc (outfncarg, p, pend - p);
  882. if (rc)
  883. return rc;
  884. *nbytes += pend - p;
  885. if ((arg->flags & FLAG_LEFT_JUST)
  886. && arg->width >= 0 && arg->width - n_extra - n_prec > n)
  887. {
  888. rc = pad_out (outfnc, outfncarg, ' ',
  889. arg->width - n_extra - n_prec - n, nbytes);
  890. if (rc)
  891. return rc;
  892. }
  893. return 0;
  894. }
  895. /* "e,E,f,F,g,G,a,A" formatting. OUTFNC and OUTFNCARG describes the
  896. output routine, ARG gives the argument description and VALUE the
  897. actual value (its type is available through arg->vt). For
  898. portability reasons sprintf is used for the actual formatting.
  899. This is useful because sprint is the only standard function to
  900. convert a floating number into its ascii representation. To avoid
  901. using malloc we just pass the precision to sprintf and do the final
  902. formatting with our own code. */
  903. static int
  904. pr_float (estream_printf_out_t outfnc, void *outfncarg,
  905. argspec_t arg, value_t value, size_t *nbytes)
  906. {
  907. int rc;
  908. #ifdef HAVE_LONG_DOUBLE
  909. long double adblfloat = 0; /* Just to please gcc. */
  910. int use_dbl = 0;
  911. #endif
  912. double afloat;
  913. char numbuf[200];
  914. char formatstr[20];
  915. char *p, *pend;
  916. size_t n;
  917. char signchar = 0;
  918. int n_extra; /* Extra number of prefix or sign characters. */
  919. switch (arg->vt)
  920. {
  921. case VALTYPE_DOUBLE: afloat = value.a_double; break;
  922. #ifdef HAVE_LONG_DOUBLE
  923. case VALTYPE_LONGDOUBLE:
  924. afloat = 0; /* Just to please gcc. */
  925. adblfloat = value.a_longdouble;
  926. use_dbl=1; break;
  927. #endif
  928. default:
  929. return -1;
  930. }
  931. /* We build the string using sprint. */
  932. p = formatstr + sizeof formatstr;
  933. *--p = 0;
  934. switch (arg->conspec)
  935. {
  936. case CONSPEC_FLOAT: *--p = 'f'; break;
  937. case CONSPEC_FLOAT_UP: *--p = 'F'; break;
  938. case CONSPEC_EXP: *--p = 'e'; break;
  939. case CONSPEC_EXP_UP: *--p = 'E'; break;
  940. case CONSPEC_F_OR_G: *--p = 'g'; break;
  941. case CONSPEC_F_OR_G_UP: *--p = 'G'; break;
  942. case CONSPEC_HEX_EXP: *--p = 'a'; break;
  943. case CONSPEC_HEX_EXP_UP: *--p = 'A'; break;
  944. default:
  945. return -1; /* Actually a bug. */
  946. }
  947. #ifdef HAVE_LONG_DOUBLE
  948. if (use_dbl)
  949. *--p = 'L';
  950. #endif
  951. if (arg->precision != NO_FIELD_VALUE)
  952. {
  953. /* Limit it to a meaningful value so that even a stupid sprintf
  954. won't overflow our buffer. */
  955. n = arg->precision <= 100? arg->precision : 100;
  956. do
  957. {
  958. *--p = '0' + (n % 10);
  959. n /= 10;
  960. }
  961. while (n);
  962. *--p = '.';
  963. }
  964. if ((arg->flags & FLAG_ALT_CONV))
  965. *--p = '#';
  966. *--p = '%';
  967. #ifdef HAVE_LONG_DOUBLE
  968. if (use_dbl)
  969. sprintf (numbuf, p, adblfloat);
  970. else
  971. #endif /*HAVE_LONG_DOUBLE*/
  972. sprintf (numbuf, p, afloat);
  973. p = numbuf;
  974. n = strlen (numbuf);
  975. pend = p + n;
  976. if (*p =='-')
  977. {
  978. signchar = '-';
  979. p++;
  980. n--;
  981. }
  982. else if ((arg->flags & FLAG_PLUS_SIGN))
  983. signchar = '+';
  984. else if ((arg->flags & FLAG_SPACE_PLUS))
  985. signchar = ' ';
  986. n_extra = !!signchar;
  987. if (!(arg->flags & FLAG_LEFT_JUST)
  988. && arg->width >= 0 && arg->width - n_extra > n)
  989. {
  990. rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n, nbytes);
  991. if (rc)
  992. return rc;
  993. }
  994. if (signchar)
  995. {
  996. rc = outfnc (outfncarg, &signchar, 1);
  997. if (rc)
  998. return rc;
  999. *nbytes += 1;
  1000. }
  1001. rc = outfnc (outfncarg, p, pend - p);
  1002. if (rc)
  1003. return rc;
  1004. *nbytes += pend - p;
  1005. if ((arg->flags & FLAG_LEFT_JUST)
  1006. && arg->width >= 0 && arg->width - n_extra > n)
  1007. {
  1008. rc = pad_out (outfnc, outfncarg, ' ', arg->width - n_extra - n, nbytes);
  1009. if (rc)
  1010. return rc;
  1011. }
  1012. return 0;
  1013. }
  1014. /* "c" formatting. */
  1015. static int
  1016. pr_char (estream_printf_out_t outfnc, void *outfncarg,
  1017. argspec_t arg, value_t value, size_t *nbytes)
  1018. {
  1019. int rc;
  1020. char buf[1];
  1021. if (arg->vt != VALTYPE_INT)
  1022. return -1;
  1023. buf[0] = (unsigned int)value.a_int;
  1024. rc = outfnc (outfncarg, buf, 1);
  1025. if(rc)
  1026. return rc;
  1027. *nbytes += 1;
  1028. return 0;
  1029. }
  1030. /* "s" formatting. */
  1031. static int
  1032. pr_string (estream_printf_out_t outfnc, void *outfncarg,
  1033. argspec_t arg, value_t value, size_t *nbytes)
  1034. {
  1035. int rc;
  1036. size_t n;
  1037. const char *string, *s;
  1038. if (arg->vt != VALTYPE_STRING)
  1039. return -1;
  1040. string = value.a_string;
  1041. if (!string)
  1042. string = "(null)";
  1043. if (arg->precision >= 0)
  1044. {
  1045. for (n=0,s=string; *s && n < arg->precision; s++)
  1046. n++;
  1047. }
  1048. else
  1049. n = strlen (string);
  1050. if (!(arg->flags & FLAG_LEFT_JUST)
  1051. && arg->width >= 0 && arg->width > n )
  1052. {
  1053. rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes);
  1054. if (rc)
  1055. return rc;
  1056. }
  1057. rc = outfnc (outfncarg, string, n);
  1058. if (rc)
  1059. return rc;
  1060. *nbytes += n;
  1061. if ((arg->flags & FLAG_LEFT_JUST)
  1062. && arg->width >= 0 && arg->width > n)
  1063. {
  1064. rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes);
  1065. if (rc)
  1066. return rc;
  1067. }
  1068. return 0;
  1069. }
  1070. /* "p" formatting. */
  1071. static int
  1072. pr_pointer (estream_printf_out_t outfnc, void *outfncarg,
  1073. argspec_t arg, value_t value, size_t *nbytes)
  1074. {
  1075. int rc;
  1076. #ifdef HAVE_LONG_LONG_INT
  1077. unsigned long long aulong;
  1078. #else
  1079. unsigned long aulong;
  1080. #endif
  1081. char numbuf[100];
  1082. char *p, *pend;
  1083. if (arg->vt != VALTYPE_POINTER)
  1084. return -1;
  1085. /* We assume that a pointer can be converted to an unsigned long.
  1086. That is not correct for a 64 bit Windows, but then we assume that
  1087. long long is supported and usable for storing a pointer. */
  1088. #if defined(HAVE_LONG_LONG_INT) && (SIZEOF_UNSIGNED_LONG < SIZEOF_VOID_P)
  1089. aulong = (unsigned long long)value.a_void_ptr;
  1090. #else
  1091. aulong = (unsigned long)value.a_void_ptr;
  1092. #endif
  1093. p = pend = numbuf + DIM(numbuf);
  1094. do
  1095. {
  1096. *--p = "0123456789abcdefx"[(aulong % 16)];
  1097. aulong /= 16;
  1098. }
  1099. while (aulong);
  1100. while ((pend-p) < 2*sizeof (aulong))
  1101. *--p = '0';
  1102. *--p = 'x';
  1103. *--p = '0';
  1104. rc = outfnc (outfncarg, p, pend - p);
  1105. if (rc)
  1106. return rc;
  1107. *nbytes += pend - p;
  1108. return 0;
  1109. }
  1110. /* "n" pesudo format operation. */
  1111. static int
  1112. pr_bytes_so_far (estream_printf_out_t outfnc, void *outfncarg,
  1113. argspec_t arg, value_t value, size_t *nbytes)
  1114. {
  1115. (void)outfnc;
  1116. (void)outfncarg;
  1117. switch (arg->vt)
  1118. {
  1119. case VALTYPE_SCHAR_PTR:
  1120. *value.a_schar_ptr = (signed char)(unsigned int)(*nbytes);
  1121. break;
  1122. case VALTYPE_SHORT_PTR:
  1123. *value.a_short_ptr = (short)(unsigned int)(*nbytes);
  1124. break;
  1125. case VALTYPE_LONG_PTR:
  1126. *value.a_long_ptr = (long)(*nbytes);
  1127. break;
  1128. #ifdef HAVE_LONG_LONG_INT
  1129. case VALTYPE_LONGLONG_PTR:
  1130. *value.a_longlong_ptr = (long long)(*nbytes);
  1131. break;
  1132. #endif
  1133. #ifdef HAVE_INTMAX_T
  1134. case VALTYPE_INTMAX_PTR:
  1135. *value.a_intmax_ptr = (intmax_t)(*nbytes);
  1136. break;
  1137. #endif
  1138. case VALTYPE_SIZE_PTR:
  1139. *value.a_size_ptr = (*nbytes);
  1140. break;
  1141. #ifdef HAVE_PTRDIFF_T
  1142. case VALTYPE_PTRDIFF_PTR:
  1143. *value.a_ptrdiff_ptr = (ptrdiff_t)(*nbytes);
  1144. break;
  1145. #endif
  1146. case VALTYPE_INT_PTR:
  1147. *value.a_int_ptr = (int)(*nbytes);
  1148. break;
  1149. default:
  1150. return -1; /* An unsupported type has been used. */
  1151. }
  1152. return 0;
  1153. }
  1154. /* Run the actual formatting. OUTFNC and OUTFNCARG are the output
  1155. functions. FORMAT is format string ARGSPECS is the parsed format
  1156. string, ARGSPECS_LEN the number of items in ARGSPECS. VALUETABLE
  1157. holds the values and may be directly addressed using the position
  1158. arguments given by ARGSPECS. MYERRNO is used for the "%m"
  1159. conversion. NBYTES well be updated to reflect the number of bytes
  1160. send to the output function. */
  1161. static int
  1162. do_format (estream_printf_out_t outfnc, void *outfncarg,
  1163. const char *format, argspec_t argspecs, size_t argspecs_len,
  1164. valueitem_t valuetable, int myerrno, size_t *nbytes)
  1165. {
  1166. int rc = 0;
  1167. const char *s;
  1168. argspec_t arg = argspecs;
  1169. int argidx = 0; /* Only used for assertion. */
  1170. size_t n;
  1171. value_t value;
  1172. s = format;
  1173. while ( *s )
  1174. {
  1175. if (*s != '%')
  1176. {
  1177. s++;
  1178. continue;
  1179. }
  1180. if (s != format)
  1181. {
  1182. rc = outfnc (outfncarg, format, (n=s-format));
  1183. if (rc)
  1184. return rc;
  1185. *nbytes += n;
  1186. }
  1187. if (s[1] == '%')
  1188. {
  1189. /* Note that this code ignores one trailing percent escape -
  1190. this is however okay as the args parser must have
  1191. detected this already. */
  1192. rc = outfnc (outfncarg, s, 1);
  1193. if (rc)
  1194. return rc;
  1195. *nbytes += 1;
  1196. s += 2;
  1197. format = s;
  1198. continue;
  1199. }
  1200. /* Save the next start. */
  1201. s += arg->length;
  1202. format = s;
  1203. assert (argidx < argspecs_len);
  1204. argidx++;
  1205. /* Apply indirect field width and precision values. */
  1206. if (arg->width == STAR_FIELD_VALUE)
  1207. {
  1208. assert (valuetable[arg->width_pos-1].vt == VALTYPE_INT);
  1209. arg->width = valuetable[arg->width_pos-1].value.a_int;
  1210. if (arg->width < 0)
  1211. {
  1212. arg->width = -arg->width;
  1213. arg->flags |= FLAG_LEFT_JUST;
  1214. }
  1215. }
  1216. if (arg->precision == STAR_FIELD_VALUE)
  1217. {
  1218. assert (valuetable[arg->precision_pos-1].vt == VALTYPE_INT);
  1219. arg->precision = valuetable[arg->precision_pos-1].value.a_int;
  1220. if (arg->precision < 0)
  1221. arg->precision = NO_FIELD_VALUE;
  1222. }
  1223. if (arg->arg_pos == -1 && arg->conspec == CONSPEC_STRERROR)
  1224. value.a_string = strerror (myerrno);
  1225. else
  1226. {
  1227. assert (arg->vt == valuetable[arg->arg_pos-1].vt);
  1228. value = valuetable[arg->arg_pos-1].value;
  1229. }
  1230. switch (arg->conspec)
  1231. {
  1232. case CONSPEC_UNKNOWN: assert (!"bug"); break;
  1233. case CONSPEC_DECIMAL:
  1234. case CONSPEC_UNSIGNED:
  1235. case CONSPEC_OCTAL:
  1236. case CONSPEC_HEX:
  1237. case CONSPEC_HEX_UP:
  1238. rc = pr_integer (outfnc, outfncarg, arg, value, nbytes);
  1239. break;
  1240. case CONSPEC_FLOAT:
  1241. case CONSPEC_FLOAT_UP:
  1242. case CONSPEC_EXP:
  1243. case CONSPEC_EXP_UP:
  1244. case CONSPEC_F_OR_G:
  1245. case CONSPEC_F_OR_G_UP:
  1246. case CONSPEC_HEX_EXP:
  1247. case CONSPEC_HEX_EXP_UP:
  1248. rc = pr_float (outfnc, outfncarg, arg, value, nbytes);
  1249. break;
  1250. case CONSPEC_CHAR:
  1251. rc = pr_char (outfnc, outfncarg, arg, value, nbytes);
  1252. break;
  1253. case CONSPEC_STRING:
  1254. case CONSPEC_STRERROR:
  1255. rc = pr_string (outfnc, outfncarg, arg, value, nbytes);
  1256. break;
  1257. case CONSPEC_POINTER:
  1258. rc = pr_pointer (outfnc, outfncarg, arg, value, nbytes);
  1259. break;
  1260. case CONSPEC_BYTES_SO_FAR:
  1261. rc = pr_bytes_so_far (outfnc, outfncarg, arg, value, nbytes);
  1262. break;
  1263. }
  1264. if (rc)
  1265. return rc;
  1266. arg++;
  1267. }
  1268. /* Print out any trailing stuff. */
  1269. n = s - format;
  1270. rc = n? outfnc (outfncarg, format, n) : 0;
  1271. if (!rc)
  1272. *nbytes += n;
  1273. return rc;
  1274. }
  1275. /* The versatile printf formatting routine. It expects a callback
  1276. function OUTFNC and an opaque argument OUTFNCARG used for actual
  1277. output of the formatted stuff. FORMAT is the format specification
  1278. and VAARGS a variable argumemt list matching the arguments of
  1279. FORMAT. */
  1280. int
  1281. estream_format (estream_printf_out_t outfnc,
  1282. void *outfncarg,
  1283. const char *format, va_list vaargs)
  1284. {
  1285. /* Buffer to hold the argspecs and a pointer to it.*/
  1286. struct argspec_s argspecs_buffer[DEFAULT_MAX_ARGSPECS];
  1287. argspec_t argspecs = argspecs_buffer;
  1288. size_t argspecs_len; /* Number of specifications in ARGSPECS. */
  1289. /* Buffer to hold the description for the values. */
  1290. struct valueitem_s valuetable_buffer[DEFAULT_MAX_VALUES];
  1291. valueitem_t valuetable = valuetable_buffer;
  1292. int rc; /* Return code. */
  1293. size_t argidx; /* Used to index the argspecs array. */
  1294. size_t validx; /* Used to index the valuetable. */
  1295. int max_pos;/* Highest argument position. */
  1296. size_t nbytes = 0; /* Keep track of the number of bytes passed to
  1297. the output function. */
  1298. int myerrno = errno; /* Save the errno for use with "%m". */
  1299. /* Parse the arguments to come up with descriptive list. We can't
  1300. do this on the fly because we need to support positional
  1301. arguments. */
  1302. rc = parse_format (format, &argspecs, DIM(argspecs_buffer), &argspecs_len);
  1303. if (rc)
  1304. goto leave;
  1305. /* Check that all ARG_POS fields are set. */
  1306. for (argidx=0,max_pos=0; argidx < argspecs_len; argidx++)
  1307. {
  1308. if (argspecs[argidx].arg_pos != -1
  1309. && argspecs[argidx].arg_pos > max_pos)
  1310. max_pos = argspecs[argidx].arg_pos;
  1311. if (argspecs[argidx].width_pos > max_pos)
  1312. max_pos = argspecs[argidx].width_pos;
  1313. if (argspecs[argidx].precision_pos > max_pos)
  1314. max_pos = argspecs[argidx].precision_pos;
  1315. }
  1316. if (!max_pos)
  1317. {
  1318. /* Fill in all the positions. */
  1319. for (argidx=0; argidx < argspecs_len; argidx++)
  1320. {
  1321. if (argspecs[argidx].width == STAR_FIELD_VALUE)
  1322. argspecs[argidx].width_pos = ++max_pos;
  1323. if (argspecs[argidx].precision == STAR_FIELD_VALUE)
  1324. argspecs[argidx].precision_pos = ++max_pos;
  1325. if (argspecs[argidx].arg_pos != -1 )
  1326. argspecs[argidx].arg_pos = ++max_pos;
  1327. }
  1328. }
  1329. else
  1330. {
  1331. /* Check that they are all filled. More test are done later. */
  1332. for (argidx=0; argidx < argspecs_len; argidx++)
  1333. {
  1334. if (!argspecs[argidx].arg_pos
  1335. || (argspecs[argidx].width == STAR_FIELD_VALUE
  1336. && !argspecs[argidx].width_pos)
  1337. || (argspecs[argidx].precision == STAR_FIELD_VALUE
  1338. && !argspecs[argidx].precision_pos))
  1339. goto leave_einval;
  1340. }
  1341. }
  1342. /* Check that there is no overflow in max_pos and that it has a
  1343. reasonable length. There may never be more elements than the
  1344. number of characters in FORMAT. */
  1345. if (max_pos < 0 || max_pos >= strlen (format))
  1346. goto leave_einval;
  1347. #ifdef TEST
  1348. if (verbose > 1)
  1349. dump_argspecs (argspecs, argspecs_len);
  1350. #endif
  1351. /* Allocate a table to hold the values. If it is small enough we
  1352. use a stack allocated buffer. */
  1353. if (max_pos > DIM(valuetable_buffer))
  1354. {
  1355. valuetable = calloc (max_pos, sizeof *valuetable);
  1356. if (!valuetable)
  1357. goto leave_error;
  1358. }
  1359. else
  1360. {
  1361. for (validx=0; validx < DIM(valuetable_buffer); validx++)
  1362. valuetable[validx].vt = VALTYPE_UNSUPPORTED;
  1363. }
  1364. for (argidx=0; argidx < argspecs_len; argidx++)
  1365. {
  1366. if (argspecs[argidx].arg_pos != - 1)
  1367. {
  1368. validx = argspecs[argidx].arg_pos - 1;
  1369. if (valuetable[validx].vt)
  1370. goto leave_einval; /* Already defined. */
  1371. valuetable[validx].vt = argspecs[argidx].vt;
  1372. }
  1373. if (argspecs[argidx].width == STAR_FIELD_VALUE)
  1374. {
  1375. validx = argspecs[argidx].width_pos - 1;
  1376. if (valuetable[validx].vt)
  1377. goto leave_einval; /* Already defined. */
  1378. valuetable[validx].vt = VALTYPE_INT;
  1379. }
  1380. if (argspecs[argidx].precision == STAR_FIELD_VALUE)
  1381. {
  1382. validx = argspecs[argidx].precision_pos - 1;
  1383. if (valuetable[validx].vt)
  1384. goto leave_einval; /* Already defined. */
  1385. valuetable[validx].vt = VALTYPE_INT;
  1386. }
  1387. }
  1388. /* Read all the arguments. This will error out for unsupported
  1389. types and for not given positional arguments. */
  1390. rc = read_values (valuetable, max_pos, vaargs);
  1391. if (rc)
  1392. goto leave_einval;
  1393. /* for (validx=0; validx < max_pos; validx++) */
  1394. /* fprintf (stderr, "%2d: vt=%d\n", validx, valuetable[validx].vt); */
  1395. /* Everything has been collected, go ahead with the formatting. */
  1396. rc = do_format (outfnc, outfncarg, format,
  1397. argspecs, argspecs_len, valuetable, myerrno, &nbytes);
  1398. goto leave;
  1399. leave_einval:
  1400. errno = EINVAL;
  1401. leave_error:
  1402. rc = -1;
  1403. leave:
  1404. if (valuetable != valuetable_buffer)
  1405. free (valuetable);
  1406. if (argspecs != argspecs_buffer)
  1407. free (argspecs);
  1408. return rc;
  1409. }
  1410. /* A simple output handler utilizing stdio. */
  1411. static int
  1412. plain_stdio_out (void *outfncarg, const char *buf, size_t buflen)
  1413. {
  1414. FILE *fp = (FILE*)outfncarg;
  1415. if ( fwrite (buf, buflen, 1, fp) != 1 )
  1416. return -1;
  1417. return 0;
  1418. }
  1419. /* A replacement for printf. */
  1420. int
  1421. estream_printf (const char *format, ...)
  1422. {
  1423. int rc;
  1424. va_list arg_ptr;
  1425. va_start (arg_ptr, format);
  1426. rc = estream_format (plain_stdio_out, stderr, format, arg_ptr);
  1427. va_end (arg_ptr);
  1428. return rc;
  1429. }
  1430. /* A replacement for fprintf. */
  1431. int
  1432. estream_fprintf (FILE *fp, const char *format, ...)
  1433. {
  1434. int rc;
  1435. va_list arg_ptr;
  1436. va_start (arg_ptr, format);
  1437. rc = estream_format (plain_stdio_out, fp, format, arg_ptr);
  1438. va_end (arg_ptr);
  1439. return rc;
  1440. }
  1441. /* A replacement for vfprintf. */
  1442. int
  1443. estream_vfprintf (FILE *fp, const char *format, va_list arg_ptr)
  1444. {
  1445. return estream_format (plain_stdio_out, fp, format, arg_ptr);
  1446. }
  1447. /* Communication object used between estream_snprintf and
  1448. fixed_buffer_out. */
  1449. struct fixed_buffer_parm_s
  1450. {
  1451. size_t size; /* Size of the buffer. */
  1452. size_t count; /* Number of bytes requested for output. */
  1453. size_t used; /* Used size of the buffer. */
  1454. char *buffer; /* Provided buffer. */
  1455. };
  1456. /* A simple malloced buffer output handler. */
  1457. static int
  1458. fixed_buffer_out (void *outfncarg, const char *buf, size_t buflen)
  1459. {
  1460. struct fixed_buffer_parm_s *parm = outfncarg;
  1461. parm->count += buflen;
  1462. if (!parm->buffer)
  1463. ;
  1464. else if (parm->used + buflen < parm->size)
  1465. {
  1466. /* Handle the common case that everything fits into the buffer
  1467. separately. */
  1468. memcpy (parm->buffer + parm->used, buf, buflen);
  1469. parm->used += buflen;
  1470. }
  1471. else
  1472. {
  1473. /* The slow version of above. */
  1474. for ( ;buflen && parm->used < parm->size; buflen--)
  1475. parm->buffer[parm->used++] = *buf++;
  1476. }
  1477. return 0;
  1478. }
  1479. /* A replacement for vsnprintf. */
  1480. int
  1481. estream_vsnprintf (char *buf, size_t bufsize,
  1482. const char *format, va_list arg_ptr)
  1483. {
  1484. struct fixed_buffer_parm_s parm;
  1485. int rc;
  1486. parm.size = bufsize;
  1487. parm.count = 0;
  1488. parm.used = 0;
  1489. parm.buffer = bufsize?buf:NULL;
  1490. rc = estream_format (fixed_buffer_out, &parm, format, arg_ptr);
  1491. if (!rc)
  1492. rc = fixed_buffer_out (&parm, "", 1); /* Print terminating Nul. */
  1493. if (rc == -1)
  1494. return -1;
  1495. if (bufsize && buf && parm.size && parm.count >= parm.size)
  1496. buf[parm.size-1] = 0;
  1497. parm.count--; /* Do not count the trailing nul. */
  1498. return (int)parm.count; /* Return number of bytes which would have
  1499. been written. */
  1500. }
  1501. /* A replacement for snprintf. */
  1502. int
  1503. estream_snprintf (char *buf, size_t bufsize, const char *format, ...)
  1504. {
  1505. int rc;
  1506. va_list arg_ptr;
  1507. va_start (arg_ptr, format);
  1508. rc = estream_vsnprintf (buf, bufsize, format, arg_ptr);
  1509. va_end (arg_ptr);
  1510. return rc;
  1511. }
  1512. /* Communication object used between estream_asprintf and
  1513. dynamic_buffer_out. */
  1514. struct dynamic_buffer_parm_s
  1515. {
  1516. int error_flag; /* Internal helper. */
  1517. size_t alloced; /* Allocated size of the buffer. */
  1518. size_t used; /* Used size of the buffer. */
  1519. char *buffer; /* Malloced buffer. */
  1520. };
  1521. /* A simple malloced buffer output handler. */
  1522. static int
  1523. dynamic_buffer_out (void *outfncarg, const char *buf, size_t buflen)
  1524. {
  1525. struct dynamic_buffer_parm_s *parm = outfncarg;
  1526. if (parm->error_flag)
  1527. {
  1528. /* Just in case some formatting routine did not checked for an
  1529. error. */
  1530. errno = parm->error_flag;
  1531. return -1;
  1532. }
  1533. if (parm->used + buflen >= parm->alloced)
  1534. {
  1535. char *p;
  1536. parm->alloced += buflen + 512;
  1537. p = realloc (parm->buffer, parm->alloced);
  1538. if (!p)
  1539. {
  1540. parm->error_flag = errno ? errno : ENOMEM;
  1541. /* Wipe out what we already accumulated. This is useful in
  1542. case sensitive data is formated. */
  1543. memset (parm->buffer, 0, parm->used);
  1544. return -1;
  1545. }
  1546. parm->buffer = p;
  1547. }
  1548. memcpy (parm->buffer + parm->used, buf, buflen);
  1549. parm->used += buflen;
  1550. return 0;
  1551. }
  1552. /* A replacement for vasprintf. As with the BSD of vasprintf version -1
  1553. will be returned on error and NULL stored at BUFP. On success the
  1554. number of bytes printed will be returned. */
  1555. int
  1556. estream_vasprintf (char **bufp, const char *format, va_list arg_ptr)
  1557. {
  1558. struct dynamic_buffer_parm_s parm;
  1559. int rc;
  1560. parm.error_flag = 0;
  1561. parm.alloced = 512;
  1562. parm.used = 0;
  1563. parm.buffer = my_printf_malloc (parm.alloced);
  1564. if (!parm.buffer)
  1565. {
  1566. *bufp = NULL;
  1567. return -1;
  1568. }
  1569. rc = estream_format (dynamic_buffer_out, &parm, format, arg_ptr);
  1570. if (!rc)
  1571. rc = dynamic_buffer_out (&parm, "", 1); /* Print terminating Nul. */
  1572. /* Fixme: Should we shrink the resulting buffer? */
  1573. if (rc != -1 && parm.error_flag)
  1574. {
  1575. rc = -1;
  1576. errno = parm.error_flag;
  1577. }
  1578. if (rc == -1)
  1579. {
  1580. memset (parm.buffer, 0, parm.used);
  1581. my_printf_free (parm.buffer);
  1582. *bufp = NULL;
  1583. return -1;
  1584. }
  1585. assert (parm.used); /* We have at least the terminating Nul. */
  1586. *bufp = parm.buffer;
  1587. return parm.used - 1; /* Do not include that Nul. */
  1588. }
  1589. /* A replacement for asprintf. As with the BSD of asprintf version -1
  1590. will be returned on error and NULL stored at BUFP. On success the
  1591. number of bytes printed will be returned. */
  1592. int
  1593. estream_asprintf (char **bufp, const char *format, ...)
  1594. {
  1595. int rc;
  1596. va_list arg_ptr;
  1597. va_start (arg_ptr, format);
  1598. rc = estream_vasprintf (bufp, format, arg_ptr);
  1599. va_end (arg_ptr);
  1600. return rc;
  1601. }
  1602. #ifdef TEST
  1603. static int
  1604. one_test (const char *format, ...)
  1605. {
  1606. #ifdef _WIN32
  1607. {
  1608. static int show;
  1609. if (!show)
  1610. {
  1611. /* We do not have a system vasprintf. */
  1612. printf ("one-test: disabled under W32\n");
  1613. show = 1;
  1614. }
  1615. }
  1616. #else
  1617. int rc1, rc2;
  1618. va_list arg_ptr;
  1619. char *buf1, *buf2;
  1620. if (verbose)
  1621. printf ("format: ->%s<-\n", format);
  1622. va_start (arg_ptr, format);
  1623. rc1 = vasprintf (&buf1, format, arg_ptr);
  1624. va_end (arg_ptr);
  1625. if (rc1 == -1)
  1626. {
  1627. printf (" sys: errno=%d (%s)\n", errno, strerror (errno));
  1628. buf1 = NULL;
  1629. }
  1630. else if (verbose)
  1631. printf (" sys: ->%s<-\n", buf1);
  1632. va_start (arg_ptr, format);
  1633. rc2 = estream_vasprintf (&buf2, format, arg_ptr);
  1634. va_end (arg_ptr);
  1635. if (rc2 == -1)
  1636. printf (" our: errno=%d (%s)\n", errno, strerror (errno));
  1637. else if (verbose)
  1638. printf (" our: ->%s<-\n", buf2);
  1639. if (rc1 != -1 && rc2 != -1 && strcmp (buf1, buf2))
  1640. printf ("error: output does not match\n"
  1641. "format: ->%s<-\n sys: ->%s<-\n our: ->%s<-\n",
  1642. format, buf1, buf2);
  1643. else if ( rc1 != rc2 )
  1644. printf ("error: return codes are different: sys_rc=%d our_rc=%d\n",
  1645. rc1, rc2);
  1646. free (buf2);
  1647. free (buf1);
  1648. #endif
  1649. return 0;
  1650. }
  1651. static void
  1652. run_tests (void)
  1653. {
  1654. /*one_test ("%d %% %'d", 17, 19681977);*/
  1655. one_test ("%d %% %d", 17, 768114563);
  1656. one_test ("%d %% %d", 17, -768114563);
  1657. one_test ("%d", 17);
  1658. one_test ("%4d", 17);
  1659. one_test ("%40d", 17);
  1660. one_test ("%-d", 17);
  1661. one_test ("%-4d", 17);
  1662. one_test ("%-140d", 17);
  1663. one_test ("%d", -17);
  1664. one_test ("%4d", -17);
  1665. one_test ("%40d", -17);
  1666. one_test ("%-d", -17);
  1667. one_test ("%-4d", -17);
  1668. one_test ("%-40d", -17);
  1669. one_test ("%+4d", 17);
  1670. one_test ("%+4d", -17);
  1671. one_test ("%-+4d", 17);
  1672. one_test ("%-+4d", -17);
  1673. one_test ("% 4d", 17);
  1674. one_test ("% 4d", -17);
  1675. one_test ("%- +4d", 17);
  1676. one_test ("%- +4d", -17);
  1677. one_test ("%.4d", 17);
  1678. one_test ("%.0d", 17);
  1679. one_test ("%.0d", 0);
  1680. one_test ("%.4d", -17);
  1681. one_test ("%.0d", -17);
  1682. one_test ("%6.4d", 17);
  1683. one_test ("%6.4d", -17);
  1684. one_test ("%6.0d", 0);
  1685. one_test ("%4.6d", 17);
  1686. one_test ("%4.6d", -17);
  1687. one_test ("% 4.6d", 17);
  1688. one_test ("% 6.0d", 0);
  1689. one_test ("%.4d", 17);
  1690. one_test ("%04d", 17);
  1691. one_test ("%.4d", -17);
  1692. one_test ("%04d", -17);
  1693. one_test ("%0.d", 0);
  1694. one_test ("%*d", 7, 42);
  1695. one_test ("%*d", -7, 42);
  1696. one_test ("%.*d", 7, 42);
  1697. one_test ("%.*d", -7, 42);
  1698. one_test ("%*.*d", 10, 7, 42);
  1699. one_test ("%*.*d", 10, -7, 42);
  1700. one_test ("%*.*d", -10, 7, 42);
  1701. one_test ("%*.*d", -10, -7, 42);
  1702. one_test ("%*x", 7, 42);
  1703. one_test ("%*x", -7, 42);
  1704. one_test ("%.*x", 7, 42);
  1705. one_test ("%.*x", -7, 42);
  1706. one_test ("%*.*x", 10, 7, 42);
  1707. one_test ("%*.*x", 10, -7, 42);
  1708. one_test ("%*.*x", -10, 7, 42);
  1709. one_test ("%*.*x", -10, -7, 42);
  1710. one_test ("%#*x", 7, 42);
  1711. one_test ("%#*x", -7, 42);
  1712. one_test ("%#.*x", 7, 42);
  1713. one_test ("%#.*x", -7, 42);
  1714. one_test ("%#*.*x", 10, 7, 42);
  1715. one_test ("%#*.*x", 10, -7, 42);
  1716. one_test ("%#*.*x", -10, 7, 42);
  1717. one_test ("%#*.*x", -10, -7, 42);
  1718. one_test ("%*X", 7, 42);
  1719. one_test ("%*X", -7, 42);
  1720. one_test ("%.*X", 7, 42);
  1721. one_test ("%.*X", -7, 42);
  1722. one_test ("%*.*X", 10, 7, 42);
  1723. one_test ("%*.*X", 10, -7, 42);
  1724. one_test ("%*.*X", -10, 7, 42);
  1725. one_test ("%*.*X", -10, -7, 42);
  1726. one_test ("%#*X", 7, 42);
  1727. one_test ("%#*X", -7, 42);
  1728. one_test ("%#.*X", 7, 42);
  1729. one_test ("%#.*X", -7, 42);
  1730. one_test ("%#*.*X", 10, 7, 42);
  1731. one_test ("%#*.*X", 10, -7, 42);
  1732. one_test ("%#*.*X", -10, 7, 42);
  1733. one_test ("%#*.*X", -10, -7, 42);
  1734. one_test ("%*o", 7, 42);
  1735. one_test ("%*o", -7, 42);
  1736. one_test ("%.*o", 7, 42);
  1737. one_test ("%.*o", -7, 42);
  1738. one_test ("%*.*o", 10, 7, 42);
  1739. one_test ("%*.*o", 10, -7, 42);
  1740. one_test ("%*.*o", -10, 7, 42);
  1741. one_test ("%*.*o", -10, -7, 42);
  1742. one_test ("%#*o", 7, 42);
  1743. one_test ("%#*o", -7, 42);
  1744. one_test ("%#.*o", 7, 42);
  1745. one_test ("%#.*o", -7, 42);
  1746. one_test ("%#*.*o", 10, 7, 42);
  1747. one_test ("%#*.*o", 10, -7, 42);
  1748. one_test ("%#*.*o", -10, 7, 42);
  1749. one_test ("%#*.*o", -10, -7, 42);
  1750. one_test ("%s", "the quick brown fox jumps over the lazy dogs back");
  1751. one_test ("%.0s", "the quick brown fox jumps over the lazy dogs back");
  1752. one_test ("%.10s", "the quick brown fox jumps over the lazy dogs back");
  1753. one_test ("%.48s", "the quick brown fox jumps over the lazy dogs back");
  1754. one_test ("%.49s", "the quick brown fox jumps over the lazy dogs back");
  1755. one_test ("%.50s", "the quick brown fox jumps over the lazy dogs back");
  1756. one_test ("%.51s", "the quick brown fox jumps over the lazy dogs back");
  1757. one_test ("%48s", "the quick brown fox jumps over the lazy dogs back");
  1758. one_test ("%49s", "the quick brown fox jumps over the lazy dogs back");
  1759. one_test ("%50s", "the quick brown fox jumps over the lazy dogs back");
  1760. one_test ("%51s", "the quick brown fox jumps over the lazy dogs back");
  1761. one_test ("%-51s", "the quick brown fox jumps over the lazy dogs back");
  1762. one_test ("/%s=", "CN");
  1763. one_test ("%f", 3.1415926535);
  1764. one_test ("%f", -3.1415926535);
  1765. one_test ("%.10f", 3.1415926535);
  1766. one_test ("%.2f", 3.1415926535);
  1767. one_test ("%.1f", 3.1415926535);
  1768. one_test ("%.0f", 3.1415926535);
  1769. one_test ("%.20f", 3.1415926535);
  1770. one_test ("%10.10f", 3.1415926535);
  1771. one_test ("%10.2f", 3.1415926535);
  1772. one_test ("%10.1f", 3.1415926535);
  1773. one_test ("%10.0f", 3.1415926535);
  1774. one_test ("%30.20f", 3.1415926535);
  1775. one_test ("%10.10f", -3.1415926535);
  1776. one_test ("%10.2f", -3.1415926535);
  1777. one_test ("%10.1f", -3.1415926535);
  1778. one_test ("%10.0f", -3.1415926535);
  1779. one_test ("%30.20f", -3.1415926535);
  1780. one_test ("%-10f", 3.1415926535);
  1781. one_test ("%-10.10f", 3.1415926535);
  1782. one_test ("%-10.2f", 3.1415926535);
  1783. one_test ("%-10.1f", 3.1415926535);
  1784. one_test ("%-10.0f", 3.1415926535);
  1785. one_test ("%-30.20f", 3.1415926535);
  1786. one_test ("%-10f", -3.1415926535);
  1787. one_test ("%-10.10f", -3.1415926535);
  1788. one_test ("%-10.2f", -3.1415926535);
  1789. one_test ("%-10.1f", -3.1415926535);
  1790. one_test ("%-10.0f", -3.1415926535);
  1791. one_test ("%-30.20f", -3.1415926535);
  1792. one_test ("%#.0f", 3.1415926535);
  1793. one_test ("%#10.0f", 3.1415926535);
  1794. one_test ("%#10.0f", -3.1415926535);
  1795. one_test ("%-#10.0f", 3.1415926535);
  1796. one_test ("%-#10.0f", -3.1415926535);
  1797. one_test ("%e", 3.1415926535);
  1798. one_test ("%g", 3.1415926535);
  1799. one_test ("%a", 1);
  1800. one_test ("%a", -1);
  1801. one_test ("%a", 3.1415926535);
  1802. #ifdef HAVE_LONG_DOUBLE
  1803. one_test ("%La", 1);
  1804. one_test ("%La", -1);
  1805. one_test ("%La", 3.1415926535);
  1806. #endif
  1807. #ifdef __GLIBC__
  1808. /* "%m" is a glibc extension so this _test_ will only work on such a
  1809. system. */
  1810. errno = ENOENT;
  1811. one_test ("%m");
  1812. errno = ENOENT;
  1813. one_test ("%d=%m", 17);
  1814. errno = ENOENT;
  1815. one_test ("%2$d:%m:%1$d", 42, 17);
  1816. #endif /*__GLIBC__*/
  1817. }
  1818. static void
  1819. check_snprintf (void)
  1820. {
  1821. char buffer[20];
  1822. int rc, rc2;
  1823. size_t tmplen, blen, blen2;
  1824. rc = estream_snprintf (buffer, 0, "%*s", 18, "");
  1825. if (rc != 18)
  1826. printf ("rc=%d\n", rc );
  1827. rc = estream_snprintf (buffer, sizeof buffer, "%*s", 18, "");
  1828. if (rc != 18)
  1829. printf ("rc=%d, strlen(buffer)=%d\n", rc, (int)strlen (buffer));
  1830. rc = estream_snprintf (buffer, sizeof buffer, "%*s", 19, "");
  1831. if (rc != 19)
  1832. printf ("rc=%d, strlen(buffer)=%d\n", rc, (int)strlen (buffer));
  1833. rc = estream_snprintf (buffer, sizeof buffer, "%*s", 20, "");
  1834. if (rc != 20)
  1835. printf ("rc=%d, strlen(buffer)=%d\n", rc, (int)strlen (buffer));
  1836. rc = estream_snprintf (buffer, sizeof buffer, "%*s", 21, "");
  1837. if (rc != 21)
  1838. printf ("rc=%d, strlen(buffer)=%d\n", rc, (int)strlen (buffer));
  1839. for (tmplen = 0; tmplen <= sizeof buffer; tmplen++)
  1840. {
  1841. rc = estream_snprintf (buffer, tmplen, "%04d%02d%02dT%02d%02d%02d",
  1842. 1998, 9, 7, 16, 56, 05);
  1843. blen = strlen (buffer);
  1844. rc2 = snprintf (buffer, tmplen, "%04d%02d%02dT%02d%02d%02d",
  1845. 1998, 9, 7, 16, 56, 05);
  1846. blen2 = strlen (buffer);
  1847. if (rc != rc2 || blen != blen2)
  1848. printf ("snprintf test with len %u gives %d instead of %d (%d,%d)\n",
  1849. (unsigned int)tmplen, rc, rc2, blen, blen2);
  1850. }
  1851. }
  1852. int
  1853. main (int argc, char **argv)
  1854. {
  1855. int rc;
  1856. if (argc) {argc--; argv++; }
  1857. setlocale (LC_NUMERIC, "");
  1858. while (argc && !strcmp (*argv, "--verbose"))
  1859. {
  1860. verbose++;
  1861. argc--;
  1862. argv++;
  1863. }
  1864. if (!argc)
  1865. {
  1866. run_tests ();
  1867. check_snprintf () ;
  1868. }
  1869. else
  1870. {
  1871. rc = estream_vfprintf (stdout, argv[0], NULL);
  1872. fflush (stdout);
  1873. fprintf (stderr, "[estream_vfprintf returns: %d]\n", rc);
  1874. }
  1875. return 0;
  1876. }
  1877. #endif /*TEST*/
  1878. /*
  1879. Local Variables:
  1880. compile-command: "cc -Wall -O3 -g -I.. -DHAVE_CONFIG_H -DTEST -o estream-printf estream-printf.c"
  1881. End:
  1882. */