Skip to content

Commit c03407c

Browse files
Jim HsuChAoSUnItY
authored andcommitted
feat: Add snprintf
This patch adds snprintf. The second parameter "size" is expected to accept only zero or positive integer, otherwise as C11 specification states, it would be undefined behavior.
1 parent 6196ab1 commit c03407c

File tree

3 files changed

+98
-1
lines changed

3 files changed

+98
-1
lines changed

lib/c.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,3 +713,72 @@ void free(void *ptr)
713713
__freelist_head->prev = cur;
714714
__freelist_head = cur;
715715
}
716+
717+
void snprintf(char *buffer, int n, char *str, ...)
718+
{
719+
int *var_args = &str + 4;
720+
int si = 0, bi = 0, pi = 0;
721+
722+
if (n == 0)
723+
return;
724+
725+
while (str[si]) {
726+
if (bi >= n - 1) {
727+
break;
728+
} else if (str[si] != '%') {
729+
buffer[bi] = str[si];
730+
bi++;
731+
si++;
732+
} else {
733+
int w = 0, zp = 0, pp = 0;
734+
735+
si++;
736+
if (str[si] == '#') {
737+
pp = 1;
738+
si++;
739+
}
740+
if (str[si] == '0') {
741+
zp = 1;
742+
si++;
743+
}
744+
if (str[si] >= '1' && str[si] <= '9') {
745+
w = str[si] - '0';
746+
si++;
747+
if (str[si] >= '0' && str[si] <= '9') {
748+
w = w * 10;
749+
w += str[si] - '0';
750+
si++;
751+
}
752+
}
753+
switch (str[si]) {
754+
case 37: /* % */
755+
buffer[bi++] = '%';
756+
si++;
757+
continue;
758+
case 99: /* c */
759+
buffer[bi++] = var_args[pi];
760+
break;
761+
case 115: /* s */
762+
strcpy(buffer + bi, var_args[pi]);
763+
bi += strlen(var_args[pi]);
764+
break;
765+
case 111: /* o */
766+
bi += __format(buffer + bi, var_args[pi], w, zp, 8, pp);
767+
break;
768+
case 100: /* d */
769+
bi += __format(buffer + bi, var_args[pi], w, zp, 10, 0);
770+
break;
771+
case 120: /* x */
772+
bi += __format(buffer + bi, var_args[pi], w, zp, 16, pp);
773+
break;
774+
default:
775+
abort();
776+
break;
777+
}
778+
pi++;
779+
si++;
780+
}
781+
}
782+
783+
buffer[n - 1] = 0;
784+
}

src/defs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#define MAX_VAR_LEN 32
1818
#define MAX_TYPE_LEN 32
1919
#define MAX_PARAMS 8
20-
#define MAX_LOCALS 1500
20+
#define MAX_LOCALS 1800
2121
#define MAX_FIELDS 64
2222
#define MAX_FUNCS 512
2323
#define MAX_TYPES 64

tests/driver.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,4 +1611,32 @@ int main()
16111611
}
16121612
EOF
16131613

1614+
# snprintf, including truncation and zero size input
1615+
try_output 0 "Hello World 1123" << EOF
1616+
int main() {
1617+
char buffer[50];
1618+
snprintf(buffer, 50, "Hello %s %d", "World", 1123);
1619+
printf("%s", buffer);
1620+
return 0;
1621+
}
1622+
EOF
1623+
1624+
try_output 0 "" << EOF
1625+
int main() {
1626+
char buffer[20];
1627+
snprintf(buffer, 0, "Number: %d", -37);
1628+
printf("%s", buffer);
1629+
return 0;
1630+
}
1631+
EOF
1632+
1633+
try_output 0 "Number: -" << EOF
1634+
int main() {
1635+
char buffer[10];
1636+
snprintf(buffer, 10, "Number: %d", -37);
1637+
printf("%s", buffer);
1638+
return 0;
1639+
}
1640+
EOF
1641+
16141642
echo OK

0 commit comments

Comments
 (0)