BOOL fold_case;
BOOL ascii;
BOOL numeric;
+ BOOL hexmode;
} FIELD;
/* Field declarations. A total of FILEDS_LIMIT is allowed */
int compare(char *el1, char *el2);
int cmp(unsigned char *el1, unsigned char *el2, FIELD * field);
int digits(char *str1, char *str2, BOOL check_sign);
+int hexits(char *str1, char *str2);
void files_merge(int file_cnt);
void merge(int start_file, int limit_file);
void put_line(char *line);
field->numeric = TRUE;
field->blanks = TRUE;
break;
+ case 'x':
+ field->hexmode = TRUE;
+ field->blanks = TRUE;
+ break;
case 'r': /* Reverse comparisons */
field->reverse = TRUE;
break;
}
if (field->numeric) /* Compare numeric */
return digits((char *) el1, (char *) el2, TRUE);
+ if (field->hexmode) /* Compare hex */
+ return hexits((char *) el1, (char *) el2);
for (;;) {
while (*el1 == *el2) {
/* NOTREACHED */
}
+int hexits(char *str1, char *str2)
+{
+ unsigned long v1, v2;
+ int r1, r2;
+ r1 = sscanf(str1, "0x%lx", &v1);
+ r2 = sscanf(str2, "0x%lx", &v2);
+
+ /* ordering based on reasonable hex number */
+ if(r1 == 1 && r2 != 1) return HIGHER;
+ if(r1 != 1 && r2 == 1) return LOWER;
+ if(r1 != 1 && r2 != 1) return SAME;
+
+ if(v1 > v2) return HIGHER;
+ if(v1 < v2) return LOWER;
+
+ return SAME;
+}
+
/*
* Digits compares () the two strings that point to a number of digits followed
* by an optional decimal point.
# Look at /usr/pkg/bin first in case there is an old nm in /usr/bin
PATH=/usr/pkg/bin:$PATH:/usr/gnu/bin
+# Does procfs give us some extra 'symbols'?
+IPCVECS=/proc/ipcvecs
+if [ -f $IPCVECS ]
+then EXTRANM="cat $IPCVECS"
+fi
+
# Check usage
if [ $# -lt 1 ]
then echo "Usage: unstack <executable> [0x... [0x... ] ]"
- echo " datasizes <executable>"
exit 1
fi
# Check invocation mode
case "`basename $0`" in
datasizes)
- mode=data
+ echo "datasizes is obsolete; please use nm --size-sort instead."
+ exit 1
;;
unstack)
mode=stack
executable=$1
shift
-# gnu nm can be gnm or nm
-if which gnm >/dev/null 2>&1
-then GNM=gnm
-else GNM=nm
+if ! which gawk >/dev/null 2>&1
+then echo "Please install gawk."
+ exit 1
fi
-# Invoke gnu nm or ack nm?
-if file $executable | grep NSYM >/dev/null 2>&1
-then NM="$GNM --radix=d"
-elif file $executable | grep ELF >/dev/null 2>&1
-then NM="$GNM --radix=d"
-else NM="acknm -d"
+# Invoke binutils nm or ack nm?
+if file $executable | grep ELF >/dev/null 2>&1
+then NM="nm"
+else NM="acknm"
fi
-# Invoked as unstack?
-if [ $mode = stack ]
-then
- while [ $# -gt 0 ]
- do dec="`printf %d $1`"
- $NM -n $executable | grep ' [Tt] [^.]' | awk '
- { if($1 > '$dec') { printf "%s+0x%x\n", name, '$dec'-offset; exit }
- name=$3; offset=$1
- }'
- shift
- done
+SYMLIST=/tmp/unstack.$$
- exit 0
-fi
-
-# Invoked as datasizes?
-if [ $mode = data ]
-then
- $NM -n $executable |
- grep ' [bBdD] [^.]' | awk '{ if (lastpos) printf "%10ld kB %s\n", ($1-lastpos)/1024, lastname; lastpos=$1; lastname=$3 }' | sort -n
+# store sorted, filtered nm output once
+( $NM $executable ; $EXTRANM ) | sed 's/^/0x/' | sort -x | grep ' [Tt] [^.]' >$SYMLIST
- exit 0
-fi
+while [ $# -gt 0 ]
+do gawk <$SYMLIST --non-decimal-data -v symoffset=$1 '
+ { if($1 > symoffset) { printf "%s+0x%x\n", name, symoffset-prevoffset; exit }
+ name=$3; prevoffset=$1;
+ }'
+ shift
+done
-# Can't happen.
-echo "Impossible invocation."
+rm -f $SYMLIST
exit 1
# Merge presorted files
.TP 5
.B \-n
-# Numeric sort order
+# Numeric sort order (decimal)
+.TP 5
+.B \-x
+# Numeric sort order (hex)
.TP 5
.B \-o
# Next argument is output file