Add strchr() and putchar() to local C library

Change-Id: I3659e119a242f8ef828e32bfdf5d0b4b7ac4f716
diff --git a/lib/stdlib/printf.c b/lib/stdlib/printf.c
index 3d62497..61361b9 100644
--- a/lib/stdlib/printf.c
+++ b/lib/stdlib/printf.c
@@ -31,14 +31,30 @@
 #include <stdio.h>
 #include <stdarg.h>
 
- // Choose max of 128 chars for now.
+/* Choose max of 128 chars for now. */
 #define PRINT_BUFFER_SIZE 128
 int printf(const char *fmt, ...)
 {
 	va_list args;
-	va_start(args, fmt);
 	char buf[PRINT_BUFFER_SIZE];
+	int count;
+
+	va_start(args, fmt);
 	vsnprintf(buf, sizeof(buf) - 1, fmt, args);
+	va_end(args);
+
+	/* Use putchar directly as 'puts()' adds a newline. */
 	buf[PRINT_BUFFER_SIZE - 1] = '\0';
-	return puts(buf);
+	count = 0;
+	while (buf[count])
+	{
+		if (putchar(buf[count]) != EOF) {
+			count++;
+		} else {
+			count = EOF;
+			break;
+		}
+	}
+
+	return count;
 }
diff --git a/lib/stdlib/putchar.c b/lib/stdlib/putchar.c
new file mode 100644
index 0000000..f4b517a
--- /dev/null
+++ b/lib/stdlib/putchar.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <console.h>
+
+/* Putchar() should either return the character printed or EOF in case of error.
+ * Our current console_putc() function assumes success and returns the
+ * character. Write all other printing functions in terms of putchar(), if
+ * possible, so they all benefit when this is improved.
+ */
+int putchar(int c)
+{
+	int res;
+	if (console_putc((unsigned char)c) >= 0)
+		res = c;
+	else
+		res = EOF;
+
+	return res;
+}
diff --git a/lib/stdlib/puts.c b/lib/stdlib/puts.c
index 069a64f..7549eb8 100644
--- a/lib/stdlib/puts.c
+++ b/lib/stdlib/puts.c
@@ -29,19 +29,27 @@
  */
 
 #include <stdio.h>
-#include <console.h>
 
 int puts(const char *s)
 {
 	int count = 0;
 	while(*s)
 	{
-		if (console_putc(*s++)) {
+		if (putchar(*s++) != EOF) {
 			count++;
 		} else {
-			count = EOF; // -1 in stdio.h
+			count = EOF;
 			break;
 		}
 	}
+
+	/* According to the puts(3) manpage, the function should write a
+	 * trailing newline.
+	 */
+	if ((count != EOF) && (putchar('\n') != EOF))
+		count++;
+	else
+		count = EOF;
+
 	return count;
 }
diff --git a/lib/stdlib/std.c b/lib/stdlib/std.c
index b6acf43..a9fc8ed 100644
--- a/lib/stdlib/std.c
+++ b/lib/stdlib/std.c
@@ -34,6 +34,8 @@
 #include "assert.c"
 #include "mem.c"
 #include "printf.c"
+#include "putchar.c"
 #include "puts.c"
+#include "strchr.c"
 #include "strlen.c"
 #include "subr_prf.c"
diff --git a/lib/stdlib/strchr.c b/lib/stdlib/strchr.c
new file mode 100644
index 0000000..36d273b
--- /dev/null
+++ b/lib/stdlib/strchr.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions copyright (c) 2013, ARM Limited and Contributors.
+ * All rights reserved.
+ */
+
+#include <sys/cdefs.h>
+#include <stddef.h>
+#include <string.h>
+
+char *
+strchr(const char *p, int ch)
+{
+	char c;
+
+	c = ch;
+	for (;; ++p) {
+		if (*p == c)
+			return ((char *)p);
+		if (*p == '\0')
+			return (NULL);
+	}
+	/* NOTREACHED */
+}