285 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			285 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
/* 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);
 | 
						|
}
 | 
						|
 | 
						|
/*---------------------------------------------------*/
 |