1/*-
2 * Copyright (c) 1998 Robert Nordier
3 * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms are freely
7 * permitted provided that the above copyright notice and this
8 * paragraph and the following disclaimer are duplicated in all
9 * such forms.
10 *
11 * This software is provided "AS IS" and without any express or
12 * implied warranties, including, without limitation, the implied
13 * warranties of merchantability and fitness for a particular
14 * purpose.
15 */
16
17#include <sys/cdefs.h>
18__FBSDID("$FreeBSD$");
19
20#include <sys/param.h>
21
22#include <stdarg.h>
23
24#include "cons.h"
25#include "util.h"
26
27void
28memcpy(void *dst, const void *src, int len)
29{
30	const char *s = src;
31	char *d = dst;
32
33	while (len--)
34		*d++ = *s++;
35}
36
37void
38memset(void *b, int c, size_t len)
39{
40	char *bp = b;
41
42	while (len--)
43		*bp++ = (unsigned char)c;
44}
45
46int
47memcmp(const void *b1, const void *b2, size_t len)
48{
49	const unsigned char *p1, *p2;
50
51	for (p1 = b1, p2 = b2; len > 0; len--, p1++, p2++) {
52		if (*p1 != *p2)
53			return ((*p1) - (*p2));
54	}
55	return (0);
56}
57
58int
59strcmp(const char *s1, const char *s2)
60{
61
62	for (; *s1 == *s2 && *s1 != '\0'; s1++, s2++)
63		;
64	return ((unsigned char)*s1 - (unsigned char)*s2);
65}
66
67int
68strncmp(const char *s1, const char *s2, size_t len)
69{
70
71	for (; len > 0 && *s1 == *s2 && *s1 != '\0'; len--, s1++, s2++)
72		;
73	return (len == 0 ? 0 : (unsigned char)*s1 - (unsigned char)*s2);
74}
75
76void
77strcpy(char *dst, const char *src)
78{
79
80	while (*src != '\0')
81		*dst++ = *src++;
82	*dst = '\0';
83}
84
85void
86strcat(char *dst, const char *src)
87{
88
89	while (*dst != '\0')
90		dst++;
91	while (*src != '\0')
92		*dst++ = *src++;
93	*dst = '\0';
94}
95
96char *
97strchr(const char *s, char ch)
98{
99
100	for (; *s != '\0'; s++) {
101		if (*s == ch)
102			return ((char *)(uintptr_t)(const void *)s);
103	}
104	return (NULL);
105}
106
107size_t
108strlen(const char *s)
109{
110	size_t len = 0;
111
112	while (*s++ != '\0')
113		len++;
114	return (len);
115}
116
117int
118printf(const char *fmt, ...)
119{
120	va_list ap;
121	const char *hex = "0123456789abcdef";
122	char buf[32], *s;
123	uint16_t *S;
124	unsigned long long u;
125	int c, l;
126
127	va_start(ap, fmt);
128	while ((c = *fmt++) != '\0') {
129		if (c != '%') {
130			putchar(c);
131			continue;
132		}
133		l = 0;
134nextfmt:
135		c = *fmt++;
136		switch (c) {
137		case 'l':
138			l++;
139			goto nextfmt;
140		case 'c':
141			putchar(va_arg(ap, int));
142			break;
143		case 's':
144			for (s = va_arg(ap, char *); *s != '\0'; s++)
145				putchar(*s);
146			break;
147		case 'S':	/* Assume console can cope with wide chars */
148			for (S = va_arg(ap, uint16_t *); *S != 0; S++)
149				putchar(*S);
150			break;
151		case 'd':	/* A lie, always prints unsigned */
152		case 'u':
153		case 'x':
154			switch (l) {
155			case 2:
156				u = va_arg(ap, unsigned long long);
157				break;
158			case 1:
159				u = va_arg(ap, unsigned long);
160				break;
161			default:
162				u = va_arg(ap, unsigned int);
163				break;
164			}
165			s = buf;
166			if (c == 'd' || c == 'u') {
167				do
168					*s++ = '0' + (u % 10U);
169				while (u /= 10);
170			} else {
171				do
172					*s++ = hex[u & 0xfu];
173				while (u >>= 4);
174			}
175			while (--s >= buf)
176				putchar(*s);
177			break;
178		}
179	}
180	va_end(ap);
181	return (0);
182}
183