/* Copyright 1997 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef TRACE /* Undef USE_TML to use a debug file 'TMLDebug' in PipeFS rather */ /* than the TML card output routines. */ #define USE_TML #ifdef USE_TML /* -*-C-*- * * Copyright(c) 1994 Acorn Computers Ltd., Cambridge, England * * svcprint.c * * print debugging information down the TML tube link. * * provides: * %s - string * %C - character in range 20->7F (space printed if outside range) * %c - any character * %X - reverses order of bytes if >2 (or >4) specified as width * %x - hex * %B - reverses order of bytes if >2 (or >4) specified as width * %b - binary * %D - reverses order of bytes if >2 (or >4) specified as width * %d - decimal * %p - pointer ("@xxxxxxxx") * * field width can be specified by placing a decimal number after the "%" * character... if the width is started by a "0" then numbers are padded * with "0"... * * standard format specifiers o,u,e,f and g are NOT supported * */ #include "kernel.h" #include "swis.h" #include "svcprint.h" #include "inetlib.h" #ifndef NULL # define NULL ((void *)0) #endif #ifdef DEBUG /*int debug = 1;*/ #endif /**********************************************************************/ /* * call processor mode independant character output routine */ static void oswrch(unsigned char ch) { _kernel_swi_regs regset; /* * use HostFS_WriteC (SWI 0x40102) to print the character */ regset.r[0] = ch; (void)_kernel_swi(0x40102, ®set, ®set); } /**********************************************************************/ /* * Printn prints a number n in base b, minimum width w adding pad chars * if needed. */ static void printn(unsigned n, unsigned b, int w, char pad) { if( n >= b ) { printn(n / b, b, --w, pad); oswrch("0123456789abcdef"[n % b]); } else { while (--w > 0) oswrch(pad); oswrch("0123456789abcdef"[n]); } } /**********************************************************************/ static void prf(char *format, unsigned *argp, ...) { register int b; /* base to be used when displaying numbers */ register int c; /* current character read from format string */ register int w; /* field width */ char pad; /* field padding character */ unsigned val; /* value of argument */ loop: val = *argp; w = 0; pad = ' '; while( (c = *format++) != '%' ) { if( c == '\0' ) return; if( c == '\n' ) oswrch('\r'); oswrch(c); } again: /* * we have a special format command */ c = *format++; switch( c ) { case 's': { /* string */ char *p = (char *)*argp++; int width = 0; if (p != NULL) { /* NOT a NULL pointer */ while (*p) { oswrch(*p++); width++; } } while( width++ < w ) oswrch(' '); goto loop; } case 'C': if( (*argp < ' ') || (*argp > '~') ) { oswrch(' '); argp++; goto loop; } case 'c': /* character */ oswrch(*argp++); goto loop; case '0': if (w == 0) pad = '0'; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* field width */ w = (w * 10) + ((int) c - '0'); goto again; case 'X': /* hex number */ if (w > 4) val = (unsigned)ntohl(val); else { if (w > 2) val = (unsigned)ntohs(val); } /* * NB * * fall through to set base */ case 'x': /* hex number */ b = 16; goto number; case 'p': /* pointer */ oswrch('@'); w = 8; pad = '0'; b = 16; goto number; case 'B': /* binary number */ if (w > 4) val = (unsigned)ntohl(val); else { if( w > 2 ) val = (unsigned)ntohs(val); } /* * NB * * fall through to set base */ case 'b': /* binary number */ b = 2; goto number; case 'D': /* decimal number */ if (w > 4) val = (unsigned)ntohl(val); else { if (w > 2) val = (unsigned)ntohs(val); } /* * NB * * fall through to set base */ case 'd': b = 10; /* * NB * * fall through to write number */ number: printn(val,b,w,pad); argp++; break; } /* switch */ goto loop; } /**********************************************************************/ #if 0 # define USETUBE #endif /* 0/1 */ void Printf(char *format, ...) { unsigned *argp = (unsigned *)&format; static int inprf; #ifdef USETUBE _kernel_swi_regs reglist; _kernel_oserror *err; /* int s = splhi(); */ if( (err = _kernel_swi(0x40100, ®list, ®list)) != NULL ) { prf("HostVDU: ", 0); prf(err->errmess, 0); /* splx(s); */ return; } #endif /* USETUBE */ /*int s = splhi();*/ if (inprf) return; inprf=1; prf(format, (argp + 1)); inprf=0; /*splx(s);*/ #ifdef USETUBE if( (err = _kernel_swi(0x40101, ®list, ®list)) != NULL ) { prf("TubeVDU: ", 0); prf(err->errmess, 0); /* splx(s); */ return; } /* splx(s); */ #endif /* USETUBE */ } /**********************************************************************/ /* EOF svcprint.c */ #else /* Make Printf use a PipeFS file instead of outputting to a TML card. */ /* Because the routine calls fopen then fclose to avoid needing any */ /* initialisation or finalisation calls, do something like: */ /* */ /* REPEAT:OSCLI "Type Pipe:$.TMLDebug":UNTIL FALSE */ /* */ /* in a Task Window to list the output during run-time (assuming this */ /* was for a multitasking Wimp application). It isn't ideal, but it */ /* works out as better than nothing. */ /* */ /* History: */ /* */ /* 11/08/97 (ADH): Created */ #include <stdlib.h> #include <stdarg.h> #include <stdio.h> void Printf(char * format, ...) { va_list ptr; FILE * fp; #define Debug_FileName "Devices:Parallel" fp = fopen(Debug_FileName, "wab"); if (!fp) fp = fopen(Debug_FileName, "wb"); if (!fp) return; setvbuf(fp, NULL, _IONBF, 0); va_start(ptr, format); vfprintf(fp, format, ptr); va_end(ptr); fclose(fp); } #endif #else static void svcprint_keep_compiler_happy(void) { int a; a = 0; } #endif