9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] seq with hex, octal formats
@ 2010-02-27 19:01 erik quanstrom
  2010-02-28  0:12 ` Russ Cox
  0 siblings, 1 reply; 5+ messages in thread
From: erik quanstrom @ 2010-02-27 19:01 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 594 bytes --]

i've attached a little program that extends
seq to print sequences in hex or octal.  for example,

	;  seq.rc -f %.4x 0x3b1 0x3b2
	03b1
	03b2

i did it in rc (really awk) because it was too tedious
to get the details right in c.

as such, formats are as in printf(2) not as in print(2).
this is a bug, but i don't see a reasonable workaround.

even using awk and adding functionality, the new
program is *way* faster than seq:

	; >/dev/null time seq 1 100000
	1.90u 0.09s 1.99r 	 seq 1 100000
	; >/dev/null time seq.rc 1 100000
	0.28u 0.00s 0.29r 	 seq.rc 1 100000

- erik

[-- Attachment #2: seq.rc --]
[-- Type: text/plain, Size: 2291 bytes --]

#!/bin/rc

awk '
function hex(s,        base, r, n, i, k, c)
{
	base = 16;
	if(s ~ /^0[xX][0-9a-fA-F]+/)
		s = substr(str, 3);
	n = length(s)
  	r = 0
	for (i = 1; i <= n; i++) {
		c = tolower(substr(s, i, 1))
		k = index("0123456789abcdef", c) - 1;
		r = r * base + k
	}
     	return r
}

function mystrtonum(str0,        neg, base, str, r, n, i, k, c)
{
	base = 0;
	neg = 0;
	str = str0;
	if(str ~ /^\+/)
		str = substr(str, 2)
	if(str ~ /^-/){
		str = substr(str, 2)
		neg = 1
	}
	if(str ~ /^0[0-7]*$/)
		base = 8
	if(str ~ /^0[xX][0-9a-fA-F]+/){
		str = substr(str, 3);
		base = 16;
	}
	if(base != 0){
		n = length(str)
  		r = 0
		for (i = 1; i <= n; i++) {
			c = tolower(substr(str, i, 1))
			k = index("0123456789abcdef", c) - 1;
			r = r * base + k
		}
	}else if(str ~ /^[0-9]*([.][0-9]*)?([Ee][-+]?[0-9]+)?$/)
		r = str0 + 0
	else
		r = "NaN"
     	return r
}

function usage()
{
	print "usage: seq [-w] [-f fmt] min [inc] max" > "/fd/2"
	exit(1);
}

function EARGF()
{
	if(j + 1 < length(a))
		return substr(a, j+1, 100);
	i++;
	if(i >= ARGC)
		usage();
	return ARGV[i];
}

function args()
{
	for(i = 1; i < ARGC; i++){
		a = ARGV[i]
		if(a !~ /^-..*/)
			break;
		for(j = 2; j <= length(a); j++){
			c = substr(a, j, 1);
			if(c == "w")
				flagw = 1
			else if(c == "f"){
				format = EARGF()
				if(format !~ /\n$/)
					format = format "\n"
			}else
				usage()
		}
	}
	n = ARGC - i
	if(n != 2 && n != 3)
		usage()
	min = mystrtonum(ARGV[i++])
	incr = 1
	if(n == 3)
		incr = mystrtonum(ARGV[i++])
	max = mystrtonum(ARGV[i++])
}

function buildfmt()
{
	if(length(format) > 0)
		return;
	format = "%g\n";
	if(!flagw)
		return;
	maxw = 0;
	maxp = 0;
	for(val = min; val <= max; val += incr){
		buf = sprintf("%g", val)
		if(buf ~ /e/)
			return
		parts = split(buf, ary, "\.");
		w = length(ary[1]);
		p = length(ary[2]) + parts==2;
		if(w>maxw)
			maxw = w;
		if(p>maxp)
			maxp = p;
	}
	if(maxp > 0)
		maxw += maxp+1;
	format = sprintf("%%0%d.%df\n", maxw, maxp);
}

BEGIN{
	args();
	buildfmt()

	for(val = min;; val += incr){
		if(incr > 0 && val > max)
			break;
		if(incr < 0 && val < max)
			break;
		printf(format, val)
	}

	exit(0);
}' $*

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-02-28  2:15 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-27 19:01 [9fans] seq with hex, octal formats erik quanstrom
2010-02-28  0:12 ` Russ Cox
2010-02-28  1:59   ` erik quanstrom
2010-02-28  2:07     ` Lyndon Nerenberg (VE6BBM/VE7TFX)
2010-02-28  2:15       ` erik quanstrom

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).