diff options
Diffstat (limited to 'autoopts/tpl/bits.tpl')
-rw-r--r-- | autoopts/tpl/bits.tpl | 721 |
1 files changed, 721 insertions, 0 deletions
diff --git a/autoopts/tpl/bits.tpl b/autoopts/tpl/bits.tpl new file mode 100644 index 0000000..6de0458 --- /dev/null +++ b/autoopts/tpl/bits.tpl @@ -0,0 +1,721 @@ +[= AutoGen5 Template -*- Mode: C -*- + +h +c + +#!/bin/sh + +## Time-stamp: "2011-12-30 08:28:20 bkorb" +## Author: Bruce Korb <bkorb@gnu.org> +## +## This file is part of AutoOpts, a companion to AutoGen. +## AutoOpts is free software. +## AutoOpts is Copyright (c) 1992-2012 by Bruce Korb - all rights reserved +## +## AutoOpts is available under any one of two licenses. The license +## in use must be one of these two and the choice is under the control +## of the user of the license. +## +## The GNU Lesser General Public License, version 3 or later +## See the files "COPYING.lgplv3" and "COPYING.gplv3" +## +## The Modified Berkeley Software Distribution License +## See the file "COPYING.mbsd" +## +## These files have the following md5sums: +## +## 43b91e8ca915626ed3818ffb1b71248b COPYING.gplv3 +## 06a1a2e4760c90ea5e1dad8dfaac4d39 COPYING.lgplv3 +## 66a5cedaf62c4b2637025f049f9b826f COPYING.mbsd + + (define base-name "") + (define BASE-NAME "") + (define element-type "") + (define init-done #f) + (define is-64-bit #f) + (define is-array #f) + (define name-width 0) + (define desc-width 0) + (define bit-list "") + (define bit-name "") + (define tmp-name "") + + (define id-name (lambda (sfx) + (string-append + prefix "_" (string-upcase! (string->c-name! (get "b-name"))) sfx + ) )) + + (define mask-name (lambda (sfx) + (string-append + prefix "_" (string-upcase! (string->c-name! (get "m-name"))) sfx + ) )) + +=][= + +INVOKE preamble + +=][= + +CASE (suffix) =][= + +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +== h + +=] +[= + (shell "sedcmd='s/$/_val} +/;s/^/${/'") + (make-header-guard "bit_mask") =] +#include [= (if (exist? "stdint-hdr") + (string-append "\"" (get "stdint-hdr") "\"") + "<stdint.h>" ) =] + +typedef [= + + (define type-name (string-append base-name "_bits_t")) + (define tmp + (if (< (high-lim "bit") 32) (begin + (set! element-type "uint32_t") + "uint32_t %s_bits_t") + (if (< (high-lim "bit") 64) (begin + (set! element-type "uint64_t") + (set! is-64-bit #t) + "uint64_t %s_bits_t" ) + (begin + (set! element-type "uint32_t") + (set! is-array #t) + (sprintf "uint32_t %%s_bits_t[%s]" + (shellf "mask_ct=`calc '( %d + 32 ) / 32'` ; echo $mask_ct" + (high-lim "bit")) ) )) )) + + (sprintf tmp base-name) + +=]; +typedef enum {[= + +FOR bit =][= + + (set! bit-name (string->c-name! (get "b-name"))) + (shellf + "%1$s_val=`calc '2 ^ %2$d'`\nmask_val=`calc \"${mask_val} + ${%1$s_val}\"`" + bit-name (for-index)) + + (set! tmp (string-length bit-name)) + (if (> tmp name-width) + (set! name-width tmp)) + (set! tmp (string-length (get "b-what"))) + (if (> tmp desc-width) + (set! desc-width tmp)) =][= + +ENDFOR bit =][= + + (define define-width (+ name-width 6 (string-length prefix))) + (define enum-fmt (sprintf "\n %%-%ds =%%4d%%s /* %%-%ds */" + define-width desc-width)) + +=][= + +FOR bit =][= + + (sprintf enum-fmt (id-name "_ID") (for-index) + (if (last-for?) " " ",") (get "b-what")) =][= +ENDFOR bit + += = = = = = = = = = = = = = = = =][= + +IF (ag-fprintf 0 "\n} %s_enum_t;\n" base-name) + (define def-fmt (sprintf "\n#define %%-%ds " define-width)) + + (< (high-lim "bit") 32) =][= + + INVOKE emit-word-macro one = 'U' mask-fmt = "%08XU" =][= + +ELIF (< (high-lim "bit") 64) =][= + + INVOKE emit-word-macro one = 'ULL' mask-fmt = "%016XULL" =][= + +ELSE more than 64 bits =][= + + INVOKE emit-multi-macros =][= + +ENDIF how many bits =][= + +IF (if (exist? "extra-defs") + (emit (string-append "\n\n" (get "extra-defs") "\n"))) + + (not (exist? "no-code")) =] +/* + * Return a string containing the names of the bits set. + */ +extern char * +[= (. base-name) =]_names([= (. type-name) =] bits); + +#define INV_[= (. BASE-NAME) =] -1 +#define DUP_[= (. BASE-NAME) =] -2 + +/* + * Set the bits in "bits" as specified by the input string "str". + * If any names are untranslatable (not in the name list or are + * ambiguous in that they match the initial portion of more than + * one entry), it will return -1 or -2, respectively. + * Otherwise, it returns the number of bits set in "bits". + */ +extern int +[= (. base-name) =]_bits( + [= (. type-name) =] * const bits, + char const * str); +[= ENDIF =] +#endif /* [= (. header-guard) =] */[= + +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +== c + + +=] +#include <ctype.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +[= + + (if (exist? "no-code") (out-delete)) + (ag-fprintf 0 "#include \"%s\"\n" header-file) + (string-table-new "nm") + (string-table-add "nm" "* INVALID *") + (define ix 0) + (define offset-list "") + (define sorted-off "") =][= + +FOR bit (for-from 0) (for-by 1) =][= + + (if (exist? "b-name") + (begin + (set! tmp (string-downcase! (string->c-name! (get "b-name")))) + (set! ix (string-table-add "nm" tmp)) + (set! offset-list (string-append offset-list (sprintf "%d\n" ix))) + (set! sorted-off (string-append sorted-off + (sprintf "%-40s { %3d, %3d }\n" tmp ix (for-index)))) + ) + + (set! offset-list (string-append offset-list "0\n" )) + ) =][= + +ENDFOR bit =][= + + (emit-string-table "nm") + (sprintf "\nchar *\n%1$s_names(%1$s_bits_t bits)\n{" base-name) +=] + static int const nm_ixa[ [= (+ 1 (high-lim "bit")) =] ] = { +[= + + (define string-table-size (lambda (st-name) + (hash-ref (hash-ref stt-table st-name) "current-index") )) + + (emit (shellf "columns -I8 -S, --spread=1 <<_EOF_\n%s_EOF_" offset-list)) +=] }; + + static char buf[ [= (+ (string-table-size "nm") (count "bit")) =] ]; + char * buf_p = buf; + int ix = 0; +[= + +IF (< (high-lim "bit") 64) + +=] + while (bits != 0) { + if ((bits & 1) != 0) { + char const * p = nm + nm_ixa[ix]; + + if (buf_p > buf) { + *(buf_p++) = ','; + *(buf_p++) = ' '; + } + + if (p == nm) { + Oops: + strncpy(buf_p, nm, sizeof (buf) - (buf_p - buf)); + break; + } + + while ((*(buf_p++) = *(p++)) != '\0') ; + buf_p--; + } + bits >>= 1; + if (++ix > [= (high-lim "bit") =]) { + if (bits != 0) + goto Oops; + break; + } + }[= + +ELSE more than 64: + +=] + int bix = 0; + int bit_lim = 32; + do { + uint32_t bit_word = bits[bix]; + int ix = bix * 32; + + while (bit_word != 0) { + if ((bit_word & 1) != 0) { + char const * p = nm + nm_ixa[ix]; + + if (buf_p > buf) { + *(buf_p++) = ','; + *(buf_p++) = ' '; + } + + if (p == nm) { + Oops: + strncpy(buf_p, nm, sizeof (buf) - (buf_p - buf)); + break; + } + + while ((*(buf_p++) = *(p++)) != '\0') ; + buf_p--; + } + bit_word >>= 1; + if (++ix > [= (high-lim "bit") =]) { + if (bit_word != 0) + goto Oops; + return buf; + } + } + } while (++bix < [= `echo $mask_ct` =]);[= + +ENDIF + +=] + + return buf; +} + +static int +str_to_id(char const * str, char const ** p_str) +{ + static char nm_buf[ [= (+ 1 name-width) =] ]; + int res = -1; + int part = 1; + size_t len = 0; + + /* + * Extract the lower cased name with '-' replaced with '_' + */ + { + char * p = nm_buf; + + for (;;) { + char ch = *(str++); + switch (ch) { + case '-': + ch = '_'; + /* FALLTHROUGH */ + + case '_': + break; + + default: + if (isupper(ch)) + ch = _tolower(ch); + else if (! isalnum(ch)) { + str--; + goto have_name; + } + } + + if (++len > [= (. name-width) =]) + return -1; + + *(p++) = ch; + } have_name :; + + *p = '\0'; + len = p - nm_buf; + if (len == 0) + return INV_[= (. BASE-NAME) =]; + } + + /* + * Search the alphabetized table + */ + do { + static struct { + unsigned short const nm_off, val; + } nm_ixa[ [= (count "bit") =] ] = { +[= + (shellf (string-append + "(sort | sed 's/.*{/{/' | columns -I8 -S, --spread=1)<<_EOF_\n" + sorted-off "_EOF_" + )) +=] }; + + int av; + int lo = 0; + int hi = [= (- (count "bit") 1) =]; + + /* + * Binary search for first match + */ + do { + char const * p; + int df; + + av = (lo + hi) / 2; + p = nm + nm_ixa[av].nm_off; + df = strncmp(p, nm_buf, len); + + if (df == 0) { + res = nm_ixa[av].val; + if (p[len] == '\0') + part = 0; + + break; + } + + if (df > 0) + hi = av - 1; + else lo = av + 1; + + } while (lo <= hi); + + if (res < 0) + return INV_[= (. BASE-NAME) =]; + + if (part == 0) + break; + + /* + * Partial match. Look for an earlier match. One may be a full match. + */ + lo = av; + while (lo > 0) { + char const * p = nm + nm_ixa[--lo].nm_off; + int df = strncmp(p, nm_buf, len); + if (df != 0) + break; + if (p[len] == '\0') { + part = 0; + res = nm_ixa[lo].val; + break; + } + part++; + } + + if (part > 1) { + *p_str = nm_buf; + return DUP_[= (. BASE-NAME) =]; + } + + if ((part == 0) || (av == [= (- (count "bit") 1) =])) + break; + + /* + * Look for a successor match. No full match possible. + */ + { + char const * p = nm + nm_ixa[av+1].nm_off; + int df = strncmp(p, nm_buf, len); + if (df == 0) { + *p_str = nm_buf; + return DUP_[= (. BASE-NAME) =]; + } + } + } while (0); + + while (isspace(*str)) str++; + *p_str = str; + return res; +} + +int +[= + +# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +(. base-name) =]_bits( + [= (. type-name) =] * const bits[= (if is-array "_p")=], + char const * str) +{[= + IF (. is-array) =] + [= (. element-type) =] * const bits = (void*)bits_p;[= + ENDIF =] + int ct = 0; + int res = 0; + + memset(bits, '\0', sizeof([= (. type-name) =])); + + another_bit: + + while (isspace(*str) || (*str == ',')) str++; + + for (;;) { + if (isdigit(*str)) { + [=(. element-type) =] num = + ([=(. element-type) =])strtoull(str, &str, 0); + *bits |= num; + ct += (num != 0); + + } else if (isalpha(*str)) { + res = str_to_id(str, &str); + if (res < 0) { + if (res == DUP_[= (. BASE-NAME) =]) + fprintf(stderr, "duplicate matches for '%s'\n", str); + goto fail_exit; + } + ct++; +[= + + IF (. is-array) =] + bits[res/32] |= 1 << (res & 0x1F);[= + ELIF (. is-64-bit) =] + *bits |= 1ULL << res;[= + ELSE =] + *bits |= 1 << res;[= + ENDIF + +=] + } else switch (*str) { + case ',': + goto another_bit; + + case '\0': + return ct; + + default: + res = INV_[= (. BASE-NAME) =]; + goto fail_exit; + } + } + + fail_exit: + memset(bits, '\0', sizeof(*bits)); + return res; +} + +#ifdef TEST_BITS + +static char const bit_names[] = +[= +(kr-string (string-append "The known " base-name " bit names are:\n" + (shellf (string-append + "(sort | columns -I2 --spread=1\n) <<_EOF_\n" + (string-downcase! (join "\n" (stack "bit.b-name"))) + "\n_EOF_")) + "\n" )) + =]; + +int +main(int argc, char** argv) +{ + static char const fmt_z[] = "'%s' yields: %s\n"; + [= (. type-name) =] bts; + if (argc != 2) { + fputs(bit_names, stderr); + return 1; + } + { + int ct = [= (. base-name) =]_bits(&bts, argv[1]); + if (ct <= 0) { + char const * pz; + switch (ct) { + case 0: pz = "no results"; break; + case INV_[= (. BASE-NAME) =]: pz = "invalid name"; break; + case DUP_[= (. BASE-NAME) =]: pz = "multiple match"; break; + } + fprintf(stderr, fmt_z, argv[1], pz); + fputs(bit_names, stderr); + return 1; + } + } + { + char * pz = [= (. base-name) =]_names(bts); + printf(fmt_z, argv[1], pz); + } + return 0; +} +#endif +[= + +ESAC =] +/* end of [= (out-name) =] */ +[=# + += = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE preamble =][= + + (if (not init-done) (begin + + (if (not (exist? "mask-name")) + (error "no defined bit mask name")) + + (shell "calc() { bc <<_EOF_ +$* +_EOF_ +} + mask_val=0") + (set! init-done #t) + (set! base-name (string-downcase! (string->c-name! (get "mask-name")))) + (set! BASE-NAME (string-upcase base-name)) + (set! prefix (string-upcase (string->c-name! + (if (exist? "prefix") (get "prefix") base-name) ))) + ) ) + + (dne " * " "/* ") =] + */ +[= + +ENDDEF preamble + += = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-bit-list =][= + + (if (exist? "b-name") + (set! bit-list (string-append (join "\n" (stack "b-name")) "\n")) + (set! bit-list "") + ) =][= + + FOR m-inc =][= + (set! tmp (string->c-name! (get "m-inc"))) + (set! bit-list (string-append bit-list + (shellf "echo \"${%s}\"" tmp) "\n")) + =][= + ENDFOR m-inc=][= + + (set! bit-list (string->c-name! bit-list)) + (shellf "%s='%s'" (string->c-name! (get "m-name")) bit-list) + + (emit (shell (string-append + + "(sort -u | columns -I8 --spread=1 -S' |' --format=" prefix "_%s_BIT " + "--line=' \\'\n) <<\\_EOF_\n" + (string-upcase bit-list) + "_EOF_" + + ))) + + (shell (string-append + "sum=`(sort -u | \ + sed -e \"${sedcmd}\"\n) <<\\_EOF_\n" + bit-list + "_EOF_\n`\n" + "sum=`eval calc ${sum} 0`\n" + "printf " + (if (>= (high-lim "bit") 32) + "' \\\\\\n /* 0x%016XULL */\\n'" + (if (>= (high-lim "bit") 16) + "' \\\\\\n /* 0x%08XU */\\n'" + "' \\\\\\n /* 0x%04XU */\\n'" )) + " ${sum}" + )) +=][= + +ENDDEF emit-bit-list + += = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-word-macro =][= + + (set! tmp-name (string-upcase! (string-append prefix "_" + (if (exist? "zero-name") (get "zero-name") "NO_BITS") ))) + (sprintf def-fmt tmp-name) =]0[= one =][= + + FOR bit =][= + + (sprintf def-fmt (id-name "_BIT")) =](1[=one=] << [= (id-name "_ID") =])[= + + ENDFOR =][= + + (ag-fprintf 0 def-fmt (string-append BASE-NAME "_MASK")) + (shellf "printf 0x%s ${mask_val}" (get "mask-fmt")) + + =][= + + FOR mask + + =] +[= (sprintf def-fmt (mask-name "_MASK")) =]( \ +[= INVOKE emit-bit-list =] )[= + + ENDFOR mask =][= + + FOR un-mask + + =] +[= (sprintf def-fmt (mask-name "_MASK")) =]([= + (string-append BASE-NAME "_MASK") =] & ~( \ +[= INVOKE emit-bit-list =]))[= + + ENDFOR un-mask=][= + + (if (exist? "defined") (string-append "\n\n" (get "defined"))) + +=][= IF (not (exist? "omit-test-n-set")) =] + +#define SET_[= (. BASE-NAME) =](_m, _b) \ + do { (_m) |= 1[= one =] << _b; } while (0) +#define CLEAR_[= (. BASE-NAME) =](_m, _b) \ + do { (_m) &= ~(1[= one =] << _b); } while (0) +#define TEST_[= (. BASE-NAME) =](_m, _b) (((_m) & (1[= one =] << _b)) != 0) +#define AND_[= (. BASE-NAME) =](_d, _s1, _s2) \ + do { (_d) = (_s1) & (_s2); } while (0) +#define OR_[= (. BASE-NAME) =](_d, _s1, _s2) \ + do { (_d) = (_s1) | (_s2); } while (0) +#define XOR_[= (. BASE-NAME) =](_d, _s1, _s2) \ + do { (_d) = (_s1) ^ (_s2); } while (0) +#define NOT_[= (. BASE-NAME) =](_d, _s) \ + do { (_d) = ~(_s); } while (0) +[= ENDIF omit-test-n-set =][= +ENDDEF emit-word-macro + += = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-loop-macro + +=][= + + (sprintf "#define %5s_%s" (get "mac-name") BASE-NAME) =][= + + CASE op-code =][= + == "~" =](_d, _s)[= (set! tmp one-arg-op)=][= + * =](_d, _s1, _s2)[= (set! tmp two-arg-op)=][= + ESAC op-code =] \ + [= (. iterate) =] \ + [= (sprintf tmp (get "op-code")) =][= + +ENDDEF emit-loop-macro + += = = = = = = = = = = = = = = = = = = =][= + +DEFINE emit-multi-macros + +=][= + +defined + +=][= IF (not (exist? "omit-test-n-set")) =] + +#define SET_[= +(define iterate (sprintf "do { int _ix_ = 0; for (;_ix_ < %s; _ix_++) {" + (shell "echo $mask_ct") )) +(define two-arg-op "(_d)[_ix_] = (_s1)[_ix_] %s (_s2)[_ix_]; } } while (0)") +(define one-arg-op "(_d)[_ix_] = %s(_s)[_ix_]; } } while (0)") + + BASE-NAME =](_m, _b) \ + do { (_m)[(_b)/32] |= 1U << ((_b) % 32); } while (0) +#define CLEAR_[= (. BASE-NAME) =](_m, _b) \ + do { (_m)[(_b)/32] &= ~(1U << ((_b) % 32)); } while (0) +#define TEST_[= (. BASE-NAME) =](_m, _b) \ + (((_m)[(_b)/32] & (1U << ((_b) % 32))) != 0) +[= INVOKE emit-loop-macro op-code = "&" mac-name = AND =] +[= INVOKE emit-loop-macro op-code = "|" mac-name = OR =] +[= INVOKE emit-loop-macro op-code = "^" mac-name = XOR =] +[= INVOKE emit-loop-macro op-code = "~" mac-name = NOT =] +[= ENDIF omit-test-n-set =][= + +ENDDEF emit-multi-macros =][= + +# End of bits.tpl \=] |