From mboxrd@z Thu Jan 1 00:00:00 1970 From: erik quanstrom Date: Sat, 27 Feb 2010 14:01:40 -0500 To: 9fans@9fans.net Message-ID: <2dfd9898fe7656a885285032d9727684@ladd.quanstro.net> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="upas-cglbouyhugddqmekrcgveotpff" Subject: [9fans] seq with hex, octal formats Topicbox-Message-UUID: dcdcfb62-ead5-11e9-9d60-3106f5b1d025 This is a multi-part message in MIME format. --upas-cglbouyhugddqmekrcgveotpff Content-Disposition: inline Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit 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 --upas-cglbouyhugddqmekrcgveotpff Content-Disposition: attachment; filename=seq.rc Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit #!/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); }' $* --upas-cglbouyhugddqmekrcgveotpff--