14f4752eeSMichael Jones //===-- Format string parser implementation for printf ----------*- C++ -*-===//
24f4752eeSMichael Jones //
34f4752eeSMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44f4752eeSMichael Jones // See https://llvm.org/LICENSE.txt for license information.
54f4752eeSMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64f4752eeSMichael Jones //
74f4752eeSMichael Jones //===----------------------------------------------------------------------===//
84f4752eeSMichael Jones 
9945fa672SMichael Jones // #define LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE 1 // This will be a compile flag.
10945fa672SMichael Jones 
114f4752eeSMichael Jones #include "parser.h"
124f4752eeSMichael Jones 
134f4752eeSMichael Jones #include "src/__support/arg_list.h"
144f4752eeSMichael Jones 
154f4752eeSMichael Jones #include "src/__support/CPP/Bit.h"
166a22b185SMichael Jones #include "src/__support/FPUtil/FPBits.h"
174f4752eeSMichael Jones #include "src/__support/ctype_utils.h"
184f4752eeSMichael Jones #include "src/__support/str_to_integer.h"
194f4752eeSMichael Jones 
204f4752eeSMichael Jones namespace __llvm_libc {
214f4752eeSMichael Jones namespace printf_core {
224f4752eeSMichael Jones 
234f4752eeSMichael Jones #ifndef LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE
244f4752eeSMichael Jones #define GET_ARG_VAL_SIMPLEST(arg_type, index) get_arg_value<arg_type>(index)
254f4752eeSMichael Jones #else
264f4752eeSMichael Jones #define GET_ARG_VAL_SIMPLEST(arg_type, _) get_next_arg_value<arg_type>()
274f4752eeSMichael Jones #endif // LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE
284f4752eeSMichael Jones 
get_next_section()294f4752eeSMichael Jones FormatSection Parser::get_next_section() {
304f4752eeSMichael Jones   FormatSection section;
314f4752eeSMichael Jones   section.raw_string = str + cur_pos;
324f4752eeSMichael Jones   size_t starting_pos = cur_pos;
334f4752eeSMichael Jones   if (str[cur_pos] == '%') {
344f4752eeSMichael Jones     // format section
354f4752eeSMichael Jones     section.has_conv = true;
364f4752eeSMichael Jones 
374f4752eeSMichael Jones     ++cur_pos;
384f4752eeSMichael Jones     [[maybe_unused]] size_t conv_index = 0;
394f4752eeSMichael Jones 
40945fa672SMichael Jones #ifndef LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE
41945fa672SMichael Jones     conv_index = parse_index(&cur_pos);
42945fa672SMichael Jones #endif // LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE
43945fa672SMichael Jones 
444f4752eeSMichael Jones     section.flags = parse_flags(&cur_pos);
454f4752eeSMichael Jones 
464f4752eeSMichael Jones     // handle width
474f4752eeSMichael Jones     section.min_width = 0;
484f4752eeSMichael Jones     if (str[cur_pos] == '*') {
494f4752eeSMichael Jones       ++cur_pos;
504f4752eeSMichael Jones 
514f4752eeSMichael Jones       section.min_width = GET_ARG_VAL_SIMPLEST(int, parse_index(&cur_pos));
524f4752eeSMichael Jones     } else if (internal::isdigit(str[cur_pos])) {
534f4752eeSMichael Jones       char *int_end;
544f4752eeSMichael Jones       section.min_width =
554f4752eeSMichael Jones           internal::strtointeger<int>(str + cur_pos, &int_end, 10);
564f4752eeSMichael Jones       cur_pos = int_end - str;
574f4752eeSMichael Jones     }
584f4752eeSMichael Jones     if (section.min_width < 0) {
594f4752eeSMichael Jones       section.min_width = -section.min_width;
604f4752eeSMichael Jones       section.flags =
614f4752eeSMichael Jones           static_cast<FormatFlags>(section.flags | FormatFlags::LEFT_JUSTIFIED);
624f4752eeSMichael Jones     }
634f4752eeSMichael Jones 
644f4752eeSMichael Jones     // handle precision
654f4752eeSMichael Jones     section.precision = -1; // negative precisions are ignored.
664f4752eeSMichael Jones     if (str[cur_pos] == '.') {
674f4752eeSMichael Jones       ++cur_pos;
684f4752eeSMichael Jones       section.precision = 0; // if there's a . but no specified precision, the
694f4752eeSMichael Jones                              // precision is implicitly 0.
704f4752eeSMichael Jones       if (str[cur_pos] == '*') {
714f4752eeSMichael Jones         ++cur_pos;
724f4752eeSMichael Jones 
734f4752eeSMichael Jones         section.precision = GET_ARG_VAL_SIMPLEST(int, parse_index(&cur_pos));
744f4752eeSMichael Jones 
754f4752eeSMichael Jones       } else if (internal::isdigit(str[cur_pos])) {
764f4752eeSMichael Jones         char *int_end;
774f4752eeSMichael Jones         section.precision =
784f4752eeSMichael Jones             internal::strtointeger<int>(str + cur_pos, &int_end, 10);
794f4752eeSMichael Jones         cur_pos = int_end - str;
804f4752eeSMichael Jones       }
814f4752eeSMichael Jones     }
824f4752eeSMichael Jones 
834f4752eeSMichael Jones     LengthModifier lm = parse_length_modifier(&cur_pos);
844f4752eeSMichael Jones 
854f4752eeSMichael Jones     section.length_modifier = lm;
864f4752eeSMichael Jones     section.conv_name = str[cur_pos];
874f4752eeSMichael Jones     switch (str[cur_pos]) {
884f4752eeSMichael Jones     case ('%'):
894f4752eeSMichael Jones       break;
904f4752eeSMichael Jones     case ('c'):
914f4752eeSMichael Jones       section.conv_val_raw = GET_ARG_VAL_SIMPLEST(int, conv_index);
924f4752eeSMichael Jones       break;
934f4752eeSMichael Jones     case ('d'):
944f4752eeSMichael Jones     case ('i'):
954f4752eeSMichael Jones     case ('o'):
964f4752eeSMichael Jones     case ('x'):
974f4752eeSMichael Jones     case ('X'):
984f4752eeSMichael Jones     case ('u'):
994f4752eeSMichael Jones       switch (lm) {
1004f4752eeSMichael Jones       case (LengthModifier::hh):
1014f4752eeSMichael Jones       case (LengthModifier::h):
1024f4752eeSMichael Jones       case (LengthModifier::none):
1034f4752eeSMichael Jones         section.conv_val_raw = GET_ARG_VAL_SIMPLEST(int, conv_index);
1044f4752eeSMichael Jones         break;
1054f4752eeSMichael Jones       case (LengthModifier::l):
1064f4752eeSMichael Jones         section.conv_val_raw = GET_ARG_VAL_SIMPLEST(long, conv_index);
1074f4752eeSMichael Jones         break;
1084f4752eeSMichael Jones       case (LengthModifier::ll):
1094f4752eeSMichael Jones       case (LengthModifier::L): // This isn't in the standard, but is in other
1104f4752eeSMichael Jones                                 // libc implementations.
1114f4752eeSMichael Jones         section.conv_val_raw = GET_ARG_VAL_SIMPLEST(long long, conv_index);
1124f4752eeSMichael Jones         break;
1134f4752eeSMichael Jones       case (LengthModifier::j):
1144f4752eeSMichael Jones         section.conv_val_raw = GET_ARG_VAL_SIMPLEST(intmax_t, conv_index);
1154f4752eeSMichael Jones         break;
1164f4752eeSMichael Jones       case (LengthModifier::z):
1174f4752eeSMichael Jones         section.conv_val_raw = GET_ARG_VAL_SIMPLEST(size_t, conv_index);
1184f4752eeSMichael Jones         break;
1194f4752eeSMichael Jones       case (LengthModifier::t):
1204f4752eeSMichael Jones         section.conv_val_raw = GET_ARG_VAL_SIMPLEST(ptrdiff_t, conv_index);
1214f4752eeSMichael Jones         break;
1224f4752eeSMichael Jones       }
1234f4752eeSMichael Jones       break;
124*f9f8693bSMichael Jones #ifndef LLVM_LIBC_PRINTF_DISABLE_FLOAT
1254f4752eeSMichael Jones     case ('f'):
1264f4752eeSMichael Jones     case ('F'):
1274f4752eeSMichael Jones     case ('e'):
1284f4752eeSMichael Jones     case ('E'):
1294f4752eeSMichael Jones     case ('a'):
1304f4752eeSMichael Jones     case ('A'):
1314f4752eeSMichael Jones     case ('g'):
1324f4752eeSMichael Jones     case ('G'):
1334f4752eeSMichael Jones       if (lm != LengthModifier::L)
1344f4752eeSMichael Jones         section.conv_val_raw =
1354f4752eeSMichael Jones             bit_cast<uint64_t>(GET_ARG_VAL_SIMPLEST(double, conv_index));
1364f4752eeSMichael Jones       else
1376a22b185SMichael Jones         section.conv_val_raw = bit_cast<fputil::FPBits<long double>::UIntType>(
1384f4752eeSMichael Jones             GET_ARG_VAL_SIMPLEST(long double, conv_index));
1394f4752eeSMichael Jones       break;
140*f9f8693bSMichael Jones #endif // LLVM_LIBC_PRINTF_DISABLE_FLOAT
14188b80139SMichael Jones #ifndef LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
1424f4752eeSMichael Jones     case ('n'):
14388b80139SMichael Jones #endif // LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
1444f4752eeSMichael Jones     case ('p'):
1454f4752eeSMichael Jones     case ('s'):
1464f4752eeSMichael Jones       section.conv_val_ptr = GET_ARG_VAL_SIMPLEST(void *, conv_index);
1474f4752eeSMichael Jones       break;
1484f4752eeSMichael Jones     default:
1494f4752eeSMichael Jones       // if the conversion is undefined, change this to a raw section.
1504f4752eeSMichael Jones       section.has_conv = false;
1514f4752eeSMichael Jones       break;
1524f4752eeSMichael Jones     }
1534f4752eeSMichael Jones     ++cur_pos;
1544f4752eeSMichael Jones   } else {
1554f4752eeSMichael Jones     // raw section
1564f4752eeSMichael Jones     section.has_conv = false;
1574f4752eeSMichael Jones     while (str[cur_pos] != '%' && str[cur_pos] != '\0')
1584f4752eeSMichael Jones       ++cur_pos;
1594f4752eeSMichael Jones   }
1604f4752eeSMichael Jones   section.raw_len = cur_pos - starting_pos;
1614f4752eeSMichael Jones   return section;
1624f4752eeSMichael Jones }
1634f4752eeSMichael Jones 
parse_flags(size_t * local_pos)1644f4752eeSMichael Jones FormatFlags Parser::parse_flags(size_t *local_pos) {
1654f4752eeSMichael Jones   bool found_flag = true;
1664f4752eeSMichael Jones   FormatFlags flags = FormatFlags(0);
1674f4752eeSMichael Jones   while (found_flag) {
1684f4752eeSMichael Jones     switch (str[*local_pos]) {
1694f4752eeSMichael Jones     case '-':
1704f4752eeSMichael Jones       flags = static_cast<FormatFlags>(flags | FormatFlags::LEFT_JUSTIFIED);
1714f4752eeSMichael Jones       break;
1724f4752eeSMichael Jones     case '+':
1734f4752eeSMichael Jones       flags = static_cast<FormatFlags>(flags | FormatFlags::FORCE_SIGN);
1744f4752eeSMichael Jones       break;
1754f4752eeSMichael Jones     case ' ':
1764f4752eeSMichael Jones       flags = static_cast<FormatFlags>(flags | FormatFlags::SPACE_PREFIX);
1774f4752eeSMichael Jones       break;
1784f4752eeSMichael Jones     case '#':
1794f4752eeSMichael Jones       flags = static_cast<FormatFlags>(flags | FormatFlags::ALTERNATE_FORM);
1804f4752eeSMichael Jones       break;
1814f4752eeSMichael Jones     case '0':
1824f4752eeSMichael Jones       flags = static_cast<FormatFlags>(flags | FormatFlags::LEADING_ZEROES);
1834f4752eeSMichael Jones       break;
1844f4752eeSMichael Jones     default:
1854f4752eeSMichael Jones       found_flag = false;
1864f4752eeSMichael Jones     }
1874f4752eeSMichael Jones     if (found_flag)
1884f4752eeSMichael Jones       ++*local_pos;
1894f4752eeSMichael Jones   }
1904f4752eeSMichael Jones   return flags;
1914f4752eeSMichael Jones }
1924f4752eeSMichael Jones 
parse_length_modifier(size_t * local_pos)1934f4752eeSMichael Jones LengthModifier Parser::parse_length_modifier(size_t *local_pos) {
1944f4752eeSMichael Jones   switch (str[*local_pos]) {
1954f4752eeSMichael Jones   case ('l'):
1964f4752eeSMichael Jones     if (str[*local_pos + 1] == 'l') {
1974f4752eeSMichael Jones       *local_pos += 2;
1984f4752eeSMichael Jones       return LengthModifier::ll;
1994f4752eeSMichael Jones     } else {
2004f4752eeSMichael Jones       ++*local_pos;
2014f4752eeSMichael Jones       return LengthModifier::l;
2024f4752eeSMichael Jones     }
2034f4752eeSMichael Jones   case ('h'):
204945fa672SMichael Jones     if (str[*local_pos + 1] == 'h') {
2054f4752eeSMichael Jones       *local_pos += 2;
2064f4752eeSMichael Jones       return LengthModifier::hh;
2074f4752eeSMichael Jones     } else {
2084f4752eeSMichael Jones       ++*local_pos;
2094f4752eeSMichael Jones       return LengthModifier::h;
2104f4752eeSMichael Jones     }
2114f4752eeSMichael Jones   case ('L'):
2124f4752eeSMichael Jones     ++*local_pos;
2134f4752eeSMichael Jones     return LengthModifier::L;
2144f4752eeSMichael Jones   case ('j'):
2154f4752eeSMichael Jones     ++*local_pos;
2164f4752eeSMichael Jones     return LengthModifier::j;
2174f4752eeSMichael Jones   case ('z'):
2184f4752eeSMichael Jones     ++*local_pos;
2194f4752eeSMichael Jones     return LengthModifier::z;
2204f4752eeSMichael Jones   case ('t'):
2214f4752eeSMichael Jones     ++*local_pos;
2224f4752eeSMichael Jones     return LengthModifier::t;
2234f4752eeSMichael Jones   default:
2244f4752eeSMichael Jones     return LengthModifier::none;
2254f4752eeSMichael Jones   }
2264f4752eeSMichael Jones }
2274f4752eeSMichael Jones 
228945fa672SMichael Jones //----------------------------------------------------
229945fa672SMichael Jones // INDEX MODE ONLY FUNCTIONS AFTER HERE:
230945fa672SMichael Jones //----------------------------------------------------
231945fa672SMichael Jones 
232945fa672SMichael Jones #ifndef LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE
233945fa672SMichael Jones 
parse_index(size_t * local_pos)234945fa672SMichael Jones size_t Parser::parse_index(size_t *local_pos) {
235945fa672SMichael Jones   if (internal::isdigit(str[*local_pos])) {
236945fa672SMichael Jones     char *int_end;
237945fa672SMichael Jones     size_t index =
238945fa672SMichael Jones         internal::strtointeger<size_t>(str + *local_pos, &int_end, 10);
239945fa672SMichael Jones     if (int_end[0] != '$')
240945fa672SMichael Jones       return 0;
241945fa672SMichael Jones     *local_pos = 1 + int_end - str;
242945fa672SMichael Jones     return index;
243945fa672SMichael Jones   }
244945fa672SMichael Jones   return 0;
245945fa672SMichael Jones }
246945fa672SMichael Jones 
get_type_desc(size_t index)247945fa672SMichael Jones Parser::TypeDesc Parser::get_type_desc(size_t index) {
248945fa672SMichael Jones   // index mode is assumed, and the indicies start at 1, so an index
249945fa672SMichael Jones   // of 0 is invalid.
250945fa672SMichael Jones   size_t local_pos = 0;
251945fa672SMichael Jones 
252945fa672SMichael Jones   while (str[local_pos]) {
253945fa672SMichael Jones     if (str[local_pos] == '%') {
254945fa672SMichael Jones       ++local_pos;
255945fa672SMichael Jones 
256945fa672SMichael Jones       size_t conv_index = parse_index(&local_pos);
257945fa672SMichael Jones 
258945fa672SMichael Jones       // the flags aren't relevant for this situation, but I need to skip past
259945fa672SMichael Jones       // them so they're parsed but the result is discarded.
260945fa672SMichael Jones       parse_flags(&local_pos);
261945fa672SMichael Jones 
262945fa672SMichael Jones       // handle width
263945fa672SMichael Jones       if (str[local_pos] == '*') {
264945fa672SMichael Jones         ++local_pos;
265945fa672SMichael Jones 
266945fa672SMichael Jones         size_t width_index = parse_index(&local_pos);
267945fa672SMichael Jones         set_type_desc(width_index, TYPE_DESC<int>);
268945fa672SMichael Jones         if (width_index == index)
269945fa672SMichael Jones           return TYPE_DESC<int>;
270945fa672SMichael Jones 
271945fa672SMichael Jones       } else if (internal::isdigit(str[local_pos])) {
272945fa672SMichael Jones         while (internal::isdigit(str[local_pos]))
273945fa672SMichael Jones           ++local_pos;
274945fa672SMichael Jones       }
275945fa672SMichael Jones 
276945fa672SMichael Jones       // handle precision
277945fa672SMichael Jones       if (str[local_pos] == '.') {
278945fa672SMichael Jones         ++local_pos;
279945fa672SMichael Jones         if (str[local_pos] == '*') {
280945fa672SMichael Jones           ++local_pos;
281945fa672SMichael Jones 
282945fa672SMichael Jones           size_t precision_index = parse_index(&local_pos);
283945fa672SMichael Jones           set_type_desc(precision_index, TYPE_DESC<int>);
284945fa672SMichael Jones           if (precision_index == index)
285945fa672SMichael Jones             return TYPE_DESC<int>;
286945fa672SMichael Jones 
287945fa672SMichael Jones         } else if (internal::isdigit(str[local_pos])) {
288945fa672SMichael Jones           while (internal::isdigit(str[local_pos]))
289945fa672SMichael Jones             ++local_pos;
290945fa672SMichael Jones         }
291945fa672SMichael Jones       }
292945fa672SMichael Jones 
293945fa672SMichael Jones       LengthModifier lm = parse_length_modifier(&local_pos);
294945fa672SMichael Jones 
295945fa672SMichael Jones       // if we don't have an index for this conversion, then its position is
296945fa672SMichael Jones       // unknown and all this information is irrelevant. The rest of this logic
297945fa672SMichael Jones       // has been for skipping past this conversion properly to avoid
298945fa672SMichael Jones       // weirdness with %%.
299945fa672SMichael Jones       if (conv_index == 0) {
300945fa672SMichael Jones         ++local_pos;
301945fa672SMichael Jones         continue;
302945fa672SMichael Jones       }
303945fa672SMichael Jones 
304945fa672SMichael Jones       TypeDesc conv_size = TYPE_DESC<void>;
305945fa672SMichael Jones       switch (str[local_pos]) {
306945fa672SMichael Jones       case ('%'):
307945fa672SMichael Jones         conv_size = TYPE_DESC<void>;
308945fa672SMichael Jones         break;
309945fa672SMichael Jones       case ('c'):
310945fa672SMichael Jones         conv_size = TYPE_DESC<int>;
311945fa672SMichael Jones         break;
312945fa672SMichael Jones       case ('d'):
313945fa672SMichael Jones       case ('i'):
314945fa672SMichael Jones       case ('o'):
315945fa672SMichael Jones       case ('x'):
316945fa672SMichael Jones       case ('X'):
317945fa672SMichael Jones       case ('u'):
318945fa672SMichael Jones         switch (lm) {
319945fa672SMichael Jones         case (LengthModifier::hh):
320945fa672SMichael Jones         case (LengthModifier::h):
321945fa672SMichael Jones         case (LengthModifier::none):
322945fa672SMichael Jones           conv_size = TYPE_DESC<int>;
323945fa672SMichael Jones           break;
324945fa672SMichael Jones         case (LengthModifier::l):
325945fa672SMichael Jones           conv_size = TYPE_DESC<long>;
326945fa672SMichael Jones           break;
327945fa672SMichael Jones         case (LengthModifier::ll):
328945fa672SMichael Jones         case (LengthModifier::L): // This isn't in the standard, but is in other
329945fa672SMichael Jones                                   // libc implementations.
330945fa672SMichael Jones           conv_size = TYPE_DESC<long long>;
331945fa672SMichael Jones           break;
332945fa672SMichael Jones         case (LengthModifier::j):
333945fa672SMichael Jones           conv_size = TYPE_DESC<intmax_t>;
334945fa672SMichael Jones           break;
335945fa672SMichael Jones         case (LengthModifier::z):
336945fa672SMichael Jones           conv_size = TYPE_DESC<size_t>;
337945fa672SMichael Jones           break;
338945fa672SMichael Jones         case (LengthModifier::t):
339945fa672SMichael Jones           conv_size = TYPE_DESC<ptrdiff_t>;
340945fa672SMichael Jones           break;
341945fa672SMichael Jones         }
342945fa672SMichael Jones         break;
343*f9f8693bSMichael Jones #ifndef LLVM_LIBC_PRINTF_DISABLE_FLOAT
344945fa672SMichael Jones       case ('f'):
345945fa672SMichael Jones       case ('F'):
346945fa672SMichael Jones       case ('e'):
347945fa672SMichael Jones       case ('E'):
348945fa672SMichael Jones       case ('a'):
349945fa672SMichael Jones       case ('A'):
350945fa672SMichael Jones       case ('g'):
351945fa672SMichael Jones       case ('G'):
352945fa672SMichael Jones         if (lm != LengthModifier::L)
353945fa672SMichael Jones           conv_size = TYPE_DESC<double>;
354945fa672SMichael Jones         else
355945fa672SMichael Jones           conv_size = TYPE_DESC<long double>;
356945fa672SMichael Jones         break;
357*f9f8693bSMichael Jones #endif // LLVM_LIBC_PRINTF_DISABLE_FLOAT
35888b80139SMichael Jones #ifndef LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
359945fa672SMichael Jones       case ('n'):
36088b80139SMichael Jones #endif // LLVM_LIBC_PRINTF_DISABLE_WRITE_INT
361945fa672SMichael Jones       case ('p'):
362945fa672SMichael Jones       case ('s'):
363945fa672SMichael Jones         conv_size = TYPE_DESC<void *>;
364945fa672SMichael Jones         break;
365945fa672SMichael Jones       default:
366945fa672SMichael Jones         conv_size = TYPE_DESC<int>;
367945fa672SMichael Jones         break;
368945fa672SMichael Jones       }
369945fa672SMichael Jones 
370945fa672SMichael Jones       set_type_desc(conv_index, conv_size);
371945fa672SMichael Jones       if (conv_index == index)
372945fa672SMichael Jones         return conv_size;
373945fa672SMichael Jones     }
374945fa672SMichael Jones     ++local_pos;
375945fa672SMichael Jones   }
376945fa672SMichael Jones 
377945fa672SMichael Jones   // If there is no size for the requested index, then just guess that it's an
378945fa672SMichael Jones   // int.
379945fa672SMichael Jones   return TYPE_DESC<int>;
380945fa672SMichael Jones }
381945fa672SMichael Jones 
args_to_index(size_t index)382945fa672SMichael Jones void Parser::args_to_index(size_t index) {
383945fa672SMichael Jones   if (args_index > index) {
384945fa672SMichael Jones     args_index = 1;
385945fa672SMichael Jones     args_cur = args_start;
386945fa672SMichael Jones   }
387945fa672SMichael Jones 
388945fa672SMichael Jones   while (args_index < index) {
389945fa672SMichael Jones     Parser::TypeDesc cur_type_desc = TYPE_DESC<void>;
390945fa672SMichael Jones     if (args_index <= DESC_ARR_LEN)
391945fa672SMichael Jones       cur_type_desc = desc_arr[args_index - 1];
392945fa672SMichael Jones 
393945fa672SMichael Jones     if (cur_type_desc == TYPE_DESC<void>)
394945fa672SMichael Jones       cur_type_desc = get_type_desc(args_index);
395945fa672SMichael Jones 
396945fa672SMichael Jones     if (cur_type_desc == TYPE_DESC<uint32_t>)
397945fa672SMichael Jones       args_cur.next_var<uint32_t>();
398945fa672SMichael Jones     else if (cur_type_desc == TYPE_DESC<uint64_t>)
399945fa672SMichael Jones       args_cur.next_var<uint64_t>();
400*f9f8693bSMichael Jones #ifndef LLVM_LIBC_PRINTF_DISABLE_FLOAT
401945fa672SMichael Jones     // Floating point numbers are stored separately from the other arguments.
402945fa672SMichael Jones     else if (cur_type_desc == TYPE_DESC<double>)
403945fa672SMichael Jones       args_cur.next_var<double>();
404945fa672SMichael Jones     else if (cur_type_desc == TYPE_DESC<long double>)
405945fa672SMichael Jones       args_cur.next_var<long double>();
406*f9f8693bSMichael Jones #endif // LLVM_LIBC_PRINTF_DISABLE_FLOAT
407945fa672SMichael Jones     // pointers may be stored separately from normal values.
408945fa672SMichael Jones     else if (cur_type_desc == TYPE_DESC<void *>)
409945fa672SMichael Jones       args_cur.next_var<void *>();
410945fa672SMichael Jones     else
411945fa672SMichael Jones       args_cur.next_var<uint32_t>();
412945fa672SMichael Jones 
413945fa672SMichael Jones     ++args_index;
414945fa672SMichael Jones   }
415945fa672SMichael Jones }
416945fa672SMichael Jones 
417945fa672SMichael Jones #endif // LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE
418945fa672SMichael Jones 
4194f4752eeSMichael Jones } // namespace printf_core
4204f4752eeSMichael Jones } // namespace __llvm_libc
421