mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	Add 64 bit integer support to printf and other formatting functions.
This commit is contained in:
		| @@ -2,6 +2,8 @@ | |||||||
| All notable changes to this project will be documented in this file. | All notable changes to this project will be documented in this file. | ||||||
|  |  | ||||||
| ## ??? - Unreleased | ## ??? - Unreleased | ||||||
|  | - Add the `u` format specifier to printf family functions. | ||||||
|  | - Allow printing 64 integer types in `printf` and `string/format` family functions. | ||||||
| - Allow importing modules from custom directories more easily with the `@` prefix | - Allow importing modules from custom directories more easily with the `@` prefix | ||||||
|   to module paths. For example, if there is a dynamic binding :custom-modules that |   to module paths. For example, if there is a dynamic binding :custom-modules that | ||||||
|   is a file system path to a directory of modules, import from that directory with |   is a file system path to a directory of modules, import from that directory with | ||||||
|   | |||||||
| @@ -30,6 +30,8 @@ | |||||||
|  |  | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
|  | #include <inttypes.h> | ||||||
|  | #include <assert.h> | ||||||
|  |  | ||||||
| /* Implements a pretty printer for Janet. The pretty printer | /* Implements a pretty printer for Janet. The pretty printer | ||||||
|  * is simple and not that flexible, but fast. */ |  * is simple and not that flexible, but fast. */ | ||||||
| @@ -750,14 +752,41 @@ static void pushtypes(JanetBuffer *buffer, int types) { | |||||||
|  |  | ||||||
| #define MAX_ITEM  256 | #define MAX_ITEM  256 | ||||||
| #define FMT_FLAGS "-+ #0" | #define FMT_FLAGS "-+ #0" | ||||||
|  | #define FMT_REPLACE_INTTYPES "diouxX" | ||||||
| #define MAX_FORMAT 32 | #define MAX_FORMAT 32 | ||||||
|  |  | ||||||
|  | struct FmtMapping { | ||||||
|  |     char c; | ||||||
|  |     const char *mapping; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* Janet uses fixed with integer types for most things, so map | ||||||
|  |  * format specifiers to these fixed sizes */ | ||||||
|  | static const struct FmtMapping format_mappings[] = { | ||||||
|  |     {'d', PRId64}, | ||||||
|  |     {'i', PRIi64}, | ||||||
|  |     {'o', PRIo64}, | ||||||
|  |     {'u', PRIu64}, | ||||||
|  |     {'x', PRIx64}, | ||||||
|  |     {'X', PRIX64}, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const char *get_fmt_mapping(char c) { | ||||||
|  |     for (size_t i = 0; i < (sizeof(format_mappings) / sizeof(struct FmtMapping)); i++) { | ||||||
|  |         if (format_mappings[i].c == c) | ||||||
|  |             return format_mappings[i].mapping; | ||||||
|  |     } | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
| static const char *scanformat( | static const char *scanformat( | ||||||
|     const char *strfrmt, |     const char *strfrmt, | ||||||
|     char *form, |     char *form, | ||||||
|     char width[3], |     char width[3], | ||||||
|     char precision[3]) { |     char precision[3]) { | ||||||
|     const char *p = strfrmt; |     const char *p = strfrmt; | ||||||
|  |  | ||||||
|  |     /* Parse strfrmt */ | ||||||
|     memset(width, '\0', 3); |     memset(width, '\0', 3); | ||||||
|     memset(precision, '\0', 3); |     memset(precision, '\0', 3); | ||||||
|     while (*p != '\0' && strchr(FMT_FLAGS, *p) != NULL) |     while (*p != '\0' && strchr(FMT_FLAGS, *p) != NULL) | ||||||
| @@ -776,10 +805,22 @@ static const char *scanformat( | |||||||
|     } |     } | ||||||
|     if (isdigit((int)(*p))) |     if (isdigit((int)(*p))) | ||||||
|         janet_panic("invalid format (width or precision too long)"); |         janet_panic("invalid format (width or precision too long)"); | ||||||
|  |  | ||||||
|  |     /* Write to form - replace characters with fixed size stuff */ | ||||||
|     *(form++) = '%'; |     *(form++) = '%'; | ||||||
|     memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char)); |     const char *p2 = strfrmt; | ||||||
|     form += (p - strfrmt) + 1; |     while (p2 <= p) { | ||||||
|  |         if (strchr(FMT_REPLACE_INTTYPES, *p2) != NULL) { | ||||||
|  |             const char *mapping = get_fmt_mapping(*p2++); | ||||||
|  |             size_t len = strlen(mapping); | ||||||
|  |             strcpy(form, mapping); | ||||||
|  |             form += len; | ||||||
|  |         } else { | ||||||
|  |             *(form++) = *(p2++); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     *form = '\0'; |     *form = '\0'; | ||||||
|  |  | ||||||
|     return p; |     return p; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -804,11 +845,16 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) { | |||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 case 'd': |                 case 'd': | ||||||
|                 case 'i': |                 case 'i': { | ||||||
|                 case 'o': |                     int64_t n = va_arg(args, long); | ||||||
|  |                     nb = snprintf(item, MAX_ITEM, form, n); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|                 case 'x': |                 case 'x': | ||||||
|                 case 'X': { |                 case 'X': | ||||||
|                     int32_t n = va_arg(args, long); |                 case 'o': | ||||||
|  |                 case 'u': { | ||||||
|  |                     uint64_t n = va_arg(args, unsigned long); | ||||||
|                     nb = snprintf(item, MAX_ITEM, form, n); |                     nb = snprintf(item, MAX_ITEM, form, n); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
| @@ -962,11 +1008,16 @@ void janet_buffer_format( | |||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 case 'd': |                 case 'd': | ||||||
|                 case 'i': |                 case 'i': { | ||||||
|                 case 'o': |                     int64_t n = janet_getinteger64(argv, arg); | ||||||
|  |                     nb = snprintf(item, MAX_ITEM, form, n); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|                 case 'x': |                 case 'x': | ||||||
|                 case 'X': { |                 case 'X': | ||||||
|                     int32_t n = janet_getinteger(argv, arg); |                 case 'o': | ||||||
|  |                 case 'u': { | ||||||
|  |                     uint64_t n = janet_getuinteger64(argv, arg); | ||||||
|                     nb = snprintf(item, MAX_ITEM, form, n); |                     nb = snprintf(item, MAX_ITEM, form, n); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose