blob: ceb2d030b2ebff3f1bf48b740fbe6669c9afd8c1 [file] [log] [blame]
package xdc.rta;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import xdc.rov.ISymbolTable;
/*
* ======== Formatter ========
*/
public class Formatter {
private static ISymbolTable symTab = null;
private static IOFReader ofReader = null;
public static void setSymbolTable(ISymbolTable inSymTab)
{
symTab = inSymTab;
}
public static void setOFReader(IOFReader inOFReader)
{
ofReader = inOFReader;
}
public static ISymbolTable getSymbolTable()
{
return (symTab);
}
/*
* ======== ParseData ========
*/
static class ParseData {
public String ptr;
public boolean lJust;
public boolean lFlag;
public int zpad;
public int len;
public int width;
public int precis;
}
/*
* ======== doPrint ========
*/
public static String doPrint(String format, int [] args)
{
return (doPrint(format, args, 4));
}
public static String doPrint(String format, int [] args, int argSize)
{
if (format == null) {
return ("(null format)");
}
String res = "";
char [] fmt = format.toCharArray();
/* temp vars */
int base = 10;
char c;
int findex = 0; /* index into format string */
int aindex = 0; /* imdex into args array */
ParseData parse = new ParseData();
while (findex < fmt.length) {
c = fmt[findex++];
if (c != '%') {
res += Character.toString(c);
}
else {
c = fmt[findex++];
/* check for - flag (pad on right) */
if (c == '-') {
parse.lJust = true;
c = fmt[findex++];
}
else {
parse.lJust = false;
}
/* check for leading 0 pad */
if (c == '0') {
parse.zpad = 1;
c = fmt[findex++];
}
else {
parse.zpad = 0;
}
/* allow optional field width/precision specification */
parse.width = 0;
parse.precis = -1;
if (c == '*') {
parse.width = aindex >= args.length ? 0 : args[aindex++];
c = fmt[findex++];
if (parse.width < 0) {
parse.lJust = true;
parse.width = -parse.width;
}
}
else {
while (c >= '0' && c <= '9') {
parse.width = parse.width * 10 + c - '0';
c = fmt[findex++];
}
}
/* allow optional field precision specification */
if (c == '.') {
parse.precis = 0;
c = fmt[findex++];
if (c == '*') {
parse.precis = aindex >= args.length ? 0 : args[aindex++];
if (parse.precis < 0) {
parse.precis = 0;
}
c = fmt[findex++];
}
else {
while (c >= '0' && c <= '9') {
parse.precis = parse.precis * 10 + c - '0';
c = fmt[findex++];
}
}
}
/* setup for leading zero padding */
if (parse.zpad != 0) {
parse.zpad = parse.width;
}
if (parse.precis > parse.zpad) {
parse.zpad = parse.precis;
}
/* check for presence of l flag (e.g., %ld) */
if (c == 'l' || c == 'L') {
parse.lFlag = true;
c = fmt[findex++];
}
else {
parse.lFlag = false;
}
parse.ptr = "";
parse.len = 0;
int val = aindex >= args.length ? 0 : args[aindex++];
if (c == 'd' || c == 'i') {
/* signed decimal */
parse.ptr = formatNum(val, parse.zpad, -10, argSize);
parse.len = parse.ptr.length();
}
else if (c == 'u' || /* unsigned decimal */
c == 'x' || /* unsigned hex */
c == 'X' || /* uppercase hex */
c == 'o') { /* unsigned octal */
base = 10;
if (c == 'x' || c == 'X') {
base = 16;
}
else if (c == 'o') {
base = 8;
}
if (c == 'X') {
/* Parse using upper case digits */
parse.ptr = formatNum(val, parse.zpad, base, argSize, true);
}
else {
/* Parse using lower case digits */
parse.ptr = formatNum(val, parse.zpad, base, argSize, false);
}
parse.len = parse.ptr.length();
}
else if (c == 'p') {
base = 16;
parse.zpad = 2 * argSize;
parse.ptr = formatNum(
val,
parse.zpad, base,
argSize);
parse.ptr = "@" + parse.ptr;
parse.len = parse.ptr.length();
}
else if (c == 'c') {
/* character */
parse.ptr = Character.toString((char)val);
parse.len = 1;
}
else if (c == 'r') {
/* lookup symbol table symbol */
parse.ptr = lookupSymbol(val);
parse.len = parse.ptr.length();
}
else if (c == 's') {
/* string */
/* substitute (null) for NULL pointer */
if (val == 0) {
parse.ptr = "(null)";
}
else {
parse.ptr = lookupString(val);
}
parse.len = parse.ptr.length();
if (parse.precis != -1 && parse.precis < parse.len) {
parse.len = parse.precis;
}
}
else {
/* unknown format, just output the character */
parse.ptr = Character.toString(c);
parse.len = 1;
aindex--; /* unget the value */
}
/* compute number of characters left in field */
parse.width -= parse.len;
if (!parse.lJust) {
/* pad with blanks on left */
while (--parse.width >= 0) {
res += " ";
}
}
/* output number, character or string */
res += parse.ptr;
/* pad with blanks on right */
if (parse.lJust) {
while (--parse.width >= 0) {
res += " ";
}
}
} /* if */
} /* while */
return (res);
}
/*
* ======== formatNum ========
*/
static String formatNum(int val, int zpad, int base, int argSize)
{
return (formatNum(val, zpad, base, argSize, false));
}
/*
* ======== formatNum ========
*/
static String formatNum(int val, int zpad, int base, int argSize, boolean caps)
{
String res = "";
int i = 0;
char sign = '\0';
char[] upper = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
char[] lower = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'
};
char [] digtohex;
if (caps) {
digtohex = upper;
}
else {
digtohex = lower;
}
long n = val >= 0 ? (long)val : ((0x1L << (8 * argSize)) + val);
if (base < 0) {
/* treat val as a signed value */
base = -base;
if (val < 0) {
n = -val;
/* account for sign '-': ok since zpad is signed */
--zpad;
sign = '-';
}
}
/* compute digits in the number from right to left */
do {
res = digtohex[(int)(n % base)] + res;
n = n / base;
++i;
} while (n != 0);
/* pad with leading 0s on left */
while (i < zpad) {
res = '0' + res;
++i;
}
/* add sign indicator */
if (sign != '\0') {
res = sign + res;
}
return (res);
}
/*
* ======== lookupString ========
*/
private static String lookupString(long addr)
{
/*
* Convert address to unsigned.
* The arguments are signed IArgs, so the address may be negative and
* need to be converted.
*/
if (addr < 0) {
addr += Math.pow(2, 32);
}
if (ofReader != null) {
String str = ofReader.findString(addr);
if (str != null) {
return (str);
}
}
/* can't find a static string */
return ("<String @" + Long.toHexString(addr) + ">");
}
/*
* ======== lookupSymbol ========
* Lookup symbol name in symbol table
*/
private static String lookupSymbol(long addr)
{
/*
* Convert address to unsigned.
* The arguments are signed IArgs, so the address may be negative and
* need to be converted.
*/
if (addr < 0) {
addr += Math.pow(2, 32);
}
if (symTab != null) {
String symbols[] = null;
/* Try code symbol first. */
symbols = symTab.lookupFuncName(addr);
if ((symbols != null) && (symbols.length > 0)) {
return (symbols[0]);
}
/* If no code symbol, try data symbol. */
symbols = symTab.lookupDataSymbol(addr);
if ((symbols != null) && (symbols.length > 0)) {
return (symbols[0]);
}
}
/* can't find symbol name */
return ("<Symbol @" + Long.toHexString(addr) + ">");
}
/*
* ======== main ========
* Simple unit test of doPrint
*/
static public void main(String [] args)
{
String [] fmts = {
"%%d test: %0.3d, %.3d, %3d, '%-3d', '%-0.3d'\n",
"%%x test: %0.3x, %.3x, %3x, '%-3x', '%-0.3x'\n",
"%%X test: %0.3X, %.3X, %3X, '%-3X', '%-0.3X'\n",
"%%o test: %0.3o, %.3o, %3o, '%-3o', '%-0.3o'\n",
"%%p test: %0.3p, %.3p, %3p, '%-3p', '%-0.3p'\n",
"%%u test: %0.3u, %.3u, %3u, '%-3u', '%-0.3u'\n",
"too many %%'s test: %x, %x, %x, %x, %x, %x, %x\n",
"%%* test: '%0.*d', '%*.*d'\n",
};
int [] argv = {1, 2, 3, 4, 5};
for (int i = 0; i < fmts.length; i++) {
System.out.print(doPrint(fmts[i], argv));
System.out.print(doPrint(fmts[i], argv, 2));
}
argv = new int [] {-1, -2, -3, -4, -5};
for (int i = 0; i < fmts.length; i++) {
System.out.print(doPrint(fmts[i], argv));
System.out.print(doPrint(fmts[i], argv, 2));
}
System.out.print(doPrint(
"%%*x test: '%0.*x', '%*.*x', '%*.*x'\n",
new int [] {5, 0xcafe,
-7, 0, 0xbeef,
7, 0, 0xbabe}, 2));
System.out.print(doPrint(
"%%*x test: '%0.*x', '%*.*x', '%*.*x'\n",
new int [] {5, 0xcafe,
-7, 0, 0xbeef,
7, 0, 0xbabe}, 4));
System.out.print(doPrint(
"%%s test: '%*s', '%s'\n",
new int [] {10, 0, 17}, 4));
System.out.print(doPrint(
"%%r test: '%*r', '%r'\n",
new int [] {5, 0, 17}, 4));
}
}