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
#!/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);
}' $*

Reply via email to