summaryrefslogtreecommitdiffstats
path: root/libgloss/microblaze/xil_printf.c
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2013-07-16 07:55:45 +0000
committerCorinna Vinschen <corinna@vinschen.de>2013-07-16 07:55:45 +0000
commit971a6c70a341a9abb8458ad6b694cc426680afd5 (patch)
tree316c6aee3a338573c1578e249c74dd43ffafe829 /libgloss/microblaze/xil_printf.c
parent6041792ec6b89f5e9eae79d8addbb0f706f9addd (diff)
downloadcygnal-971a6c70a341a9abb8458ad6b694cc426680afd5.tar.gz
cygnal-971a6c70a341a9abb8458ad6b694cc426680afd5.tar.bz2
cygnal-971a6c70a341a9abb8458ad6b694cc426680afd5.zip
* microblaze/Makefile.in: Add GENOBJS and target_makefile_frag.
* microblaze/configure.in: Add target_makefile_frag. * microblaze/configure: Regenerate. * microblaze/xil_printf.c: Add new file.
Diffstat (limited to 'libgloss/microblaze/xil_printf.c')
-rw-r--r--libgloss/microblaze/xil_printf.c284
1 files changed, 284 insertions, 0 deletions
diff --git a/libgloss/microblaze/xil_printf.c b/libgloss/microblaze/xil_printf.c
new file mode 100644
index 000000000..f18ee8446
--- /dev/null
+++ b/libgloss/microblaze/xil_printf.c
@@ -0,0 +1,284 @@
+/* Copyright (c) 1995-2013 Xilinx, Inc. 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 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.
+ *
+ * 3. Neither the name of Xilinx 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 HOLDER 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 <ctype.h>
+#include <string.h>
+#include <stdarg.h>
+
+extern void outbyte (char);
+
+/*----------------------------------------------------*/
+/* Use the following parameter passing structure to */
+/* make xil_printf re-entrant. */
+/*----------------------------------------------------*/
+typedef struct params_s {
+ int len;
+ int num1;
+ int num2;
+ char pad_character;
+ int do_padding;
+ int left_flag;
+} params_t;
+
+/*---------------------------------------------------*/
+/* The purpose of this routine is to output data the */
+/* same as the standard printf function without the */
+/* overhead most run-time libraries involve. Usually */
+/* the printf brings in many kilobytes of code and */
+/* that is unacceptable in most embedded systems. */
+/*---------------------------------------------------*/
+
+typedef char* charptr;
+typedef int (*func_ptr)(int c);
+
+/*---------------------------------------------------*/
+/* */
+/* This routine puts pad characters into the output */
+/* buffer. */
+/* */
+static void padding( const int l_flag, params_t *par)
+{
+ int i;
+
+ if (par->do_padding && l_flag && (par->len < par->num1))
+ for (i=par->len; i<par->num1; i++)
+ outbyte( par->pad_character);
+}
+
+/*---------------------------------------------------*/
+/* */
+/* This routine moves a string to the output buffer */
+/* as directed by the padding and positioning flags. */
+/* */
+static void outs( charptr lp, params_t *par)
+{
+ /* pad on left if needed */
+ par->len = strlen( lp);
+ padding( !(par->left_flag), par);
+
+ /* Move string to the buffer */
+ while (*lp && (par->num2)--)
+ outbyte( *lp++);
+
+ /* Pad on right if needed */
+ /* CR 439175 - elided next stmt. Seemed bogus. */
+ /* par->len = strlen( lp); */
+ padding( par->left_flag, par);
+}
+
+/*---------------------------------------------------*/
+/* */
+/* This routine moves a number to the output buffer */
+/* as directed by the padding and positioning flags. */
+/* */
+
+static void outnum( const long n, const long base, params_t *par)
+{
+ charptr cp;
+ int negative;
+ char outbuf[32];
+ const char digits[] = "0123456789ABCDEF";
+ unsigned long num;
+
+ /* Check if number is negative */
+ if (base == 10 && n < 0L) {
+ negative = 1;
+ num = -(n);
+ }
+ else{
+ num = (n);
+ negative = 0;
+ }
+
+ /* Build number (backwards) in outbuf */
+ cp = outbuf;
+ do {
+ *cp++ = digits[(int)(num % base)];
+ } while ((num /= base) > 0);
+ if (negative)
+ *cp++ = '-';
+ *cp-- = 0;
+
+ /* Move the converted number to the buffer and */
+ /* add in the padding where needed. */
+ par->len = strlen(outbuf);
+ padding( !(par->left_flag), par);
+ while (cp >= outbuf)
+ outbyte( *cp--);
+ padding( par->left_flag, par);
+}
+
+/*---------------------------------------------------*/
+/* */
+/* This routine gets a number from the format */
+/* string. */
+/* */
+static int getnum( charptr* linep)
+{
+ int n;
+ charptr cp;
+
+ n = 0;
+ cp = *linep;
+ while (isdigit(*cp))
+ n = n*10 + ((*cp++) - '0');
+ *linep = cp;
+ return(n);
+}
+
+/*---------------------------------------------------*/
+/* */
+/* This routine operates just like a printf/sprintf */
+/* routine. It outputs a set of data under the */
+/* control of a formatting string. Not all of the */
+/* standard C format control are supported. The ones */
+/* provided are primarily those needed for embedded */
+/* systems work. Primarily the floaing point */
+/* routines are omitted. Other formats could be */
+/* added easily by following the examples shown for */
+/* the supported formats. */
+/* */
+
+/* void esp_printf( const func_ptr f_ptr,
+ const charptr ctrl1, ...) */
+void xil_printf( const charptr ctrl1, ...)
+{
+
+ int long_flag;
+ int dot_flag;
+
+ params_t par;
+
+ char ch;
+ va_list argp;
+ charptr ctrl = ctrl1;
+
+ va_start( argp, ctrl1);
+
+ for ( ; *ctrl; ctrl++) {
+
+ /* move format string chars to buffer until a */
+ /* format control is found. */
+ if (*ctrl != '%') {
+ outbyte(*ctrl);
+ continue;
+ }
+
+ /* initialize all the flags for this format. */
+ dot_flag = long_flag = par.left_flag = par.do_padding = 0;
+ par.pad_character = ' ';
+ par.num2=32767;
+
+ try_next:
+ ch = *(++ctrl);
+
+ if (isdigit(ch)) {
+ if (dot_flag)
+ par.num2 = getnum(&ctrl);
+ else {
+ if (ch == '0')
+ par.pad_character = '0';
+
+ par.num1 = getnum(&ctrl);
+ par.do_padding = 1;
+ }
+ ctrl--;
+ goto try_next;
+ }
+
+ switch (tolower(ch)) {
+ case '%':
+ outbyte( '%');
+ continue;
+
+ case '-':
+ par.left_flag = 1;
+ break;
+
+ case '.':
+ dot_flag = 1;
+ break;
+
+ case 'l':
+ long_flag = 1;
+ break;
+
+ case 'd':
+ if (long_flag || ch == 'D') {
+ outnum( va_arg(argp, long), 10L, &par);
+ continue;
+ }
+ else {
+ outnum( va_arg(argp, int), 10L, &par);
+ continue;
+ }
+ case 'x':
+ outnum((long)va_arg(argp, int), 16L, &par);
+ continue;
+
+ case 's':
+ outs( va_arg( argp, charptr), &par);
+ continue;
+
+ case 'c':
+ outbyte( va_arg( argp, int));
+ continue;
+
+ case '\\':
+ switch (*ctrl) {
+ case 'a':
+ outbyte( 0x07);
+ break;
+ case 'h':
+ outbyte( 0x08);
+ break;
+ case 'r':
+ outbyte( 0x0D);
+ break;
+ case 'n':
+ outbyte( 0x0D);
+ outbyte( 0x0A);
+ break;
+ default:
+ outbyte( *ctrl);
+ break;
+ }
+ ctrl++;
+ break;
+
+ default:
+ continue;
+ }
+ goto try_next;
+ }
+ va_end( argp);
+}
+
+/*---------------------------------------------------*/