parse_args-v0.6.3/0000755000175100017510000000000015176457625013464 5ustar runnerrunnerparse_args-v0.6.3/suppressions0000644000175100017510000000064515176457507016170 0ustar runnerrunner{ Tcl Memcheck:Leak ... fun:TclInitByteCode ... } { Tcl Memcheck:Leak ... fun:Tcl_ObjPrintf fun:Tcl_MainEx fun:main } { Tcl Memcheck:Leak ... fun:Tcl_CreateLiteral ... } { Tcl Memcheck:Leak ... fun:TclCreateLiteral ... } { Tcl Memcheck:Leak ... fun:Tcl_CompileCmdLiteral ... } { Tcl Memcheck:Leak ... fun:CompileCmdLiteral ... } { Tcl Memcheck:Leak ... fun:Tcl_CreateInterp fun:main } parse_args-v0.6.3/README.md0000644000175100017510000002406515176457625014752 0ustar runnerrunner# NAME parse_args - Core-style argument parsing for scripts # SYNOPSIS **package require parse_args** ?0.6.3? **parse_args::parse_args** *args* *argspec* ?*varname*? # DESCRIPTION The commands provided by the Tcl core follow a pattern of optional, named arguments (named with a leading “-” to indicate an option) in addition to positional arguments. They strongly prefer named arguments when the number of arguments and particularly optional arguments grows beyond about 3. Tcl scripts however have no access to standard argument parsing facilities to implement this pattern and have to build their named argument parsing machinery from scratch. This is slow to do in script, error prone, and creates noise in the code that distracts from the core task of the command implementation. This means that script-defined commands generally present half-baked argument handling APIs and tend to over-use positional arguments. This package aims to address this weakness by providing a robust argument parsing mechanism to script code that can implement the full set of patterns established by the core Tcl commands, is terse and readable to specify the arguments, and is fast enough to use in any situation. # COMMANDS **parse_args::parse_args** *args* *argspec* Parse the arguments supplied in *args* against the specification given in *argspec*, setting variables in the current scope as defined in the *argspec*. If the optional *varname* argument is supplied, it names a variable that will have a dictionary written to it containing the parsed arguments and no variables will be created for the arguments. See **ARGUMENT SPECIFICATION** below for the format of *argspec*. # ARGUMENT SPECIFICATION The syntax of the argument specification (given in the *argspec* argument to the **parse_args** command) is a dictionary, with the keys corresponding to the names by which the arguments will be available to the caller, either as variables created by the **parse_args** command or keys in the dictionary written to *varname* if that was specified. If the first character of the key is a “-” character it defines a named option, otherwise a positional parameter. Like in proc argument definitions the name `args` is special, and will consume all remaining arguments. The values of the dictionary contain the definition of the corresponding argument, such as `-required`, which marks that argument as being required (whether a named or positional argument). The options that are available to define the argument are: **-default** *val* Provides a default value for the argument if it wasn’t supplied. Without this an argument that wasn’t supplied won’t have its corresponding variable (or dictionary key) set. *val* is permitted to be a value that is outside of the range of possible values that would be accepted from the caller, by design. **-required** If this boolean option is given, the argument is flagged as required. Failing to supply the arg causes the **parse_args** to throw an exception similar to what would happen if a required positional argument to a proc was not provided. **-validate** *cmdprefix* Append the value supplied for this argument to the *cmdprefix* and run it. The value is rejected if an exception is thrown or the value returned isn’t a Tcl boolean true value. **-name** *newname* Change the name of the variable / dictionary key that will receive the value for this argument to *newname*. By default the name will be the argspec key (without the leading “-” for named arguments). **-boolean** Flag this argument as a boolean, similar to **-nocase** to `regexp`. The variable will always be defined and be a boolean, true if the argument was supplied and false if it wasn’t. **-args** *count* By default named arguments consume a single following argument as the value for that argument. This setting changes that to *count*, which will cause the following *count* arguments to be gathered into the variable holding this argument. If *count* is the special value “all”, then all remaining arguments are gathered into a list as the value of this argument. **-enum** *possible_values* Restrict the values that will be accepted for this argument to those in the *possible_values* list. Similar to using a validator that checks for inclusion in that list but with additional internal performance optimizations. **-#** *free_form_text* Embed a comment for this argument. The supplied *free_form_text* is ignored by **parse_args** and serves only to document the argument to programmers reading the code. In some future version this text may be incorporated into a usage error message that is generated when argument parsing fails. **-multi** Group a set of defined arguments together, so they act like mutually exclusive flags. Used to implement patterns like the arguments `-ascii`, `-dictionary`, `-integer` and `-real` arguments to the core **lsort** command. *name* will be the name of the variable that holds the value of the flag that was supplied. A **-default** setting on any of the linked **-multi** arguments (those that share a *name*) will supply a default value in *name* if none were passed. A **-required** setting on any of the linked **-multi** arguments will require that the caller supply at least one of them. If multiple different flags were given, the one last in the argument list applies, unless **-all** was specified (on any linked option), in which case all instances are grouped as a list in *name*, in the order they were specified. **-alias** Treat the value supplied for this argument as a variable name and bind the resulting variable for this argument to the variable of that name in the call frame above this one (upvar 1). **-all** Collect all the instances of this argument as a list, rather than the default behaviour of using the last instance as the value. **-end** Treat the remaining arguments as if **--** directly followed this option - that is: all words in *args* after those consumed by the current option are treated as positional arguments. # EXAMPLES Mimic the argument handling of the core `glob` command: ``` tcl proc glob args { parse_args::parse_args $args { -directory {} -join {-boolean} -nocomplain {-boolean} -path {} -tails {-boolean} -types {-default {}} args {-name patterns} } if {$join} { set patterns [list [file join {*}$patterns]] } if {[llength $patterns] == 0 && $nocomplain} return foreach pattern $patterns { if {[info exists directory]} { ... } } ... } ``` Mimic `regex`: ``` tcl proc regexp args { parse_args::parse_args $args { -about {-boolean} -expanded {-boolean} -indices {-boolean} -line {-boolean} -linestop {-boolean} -lineanchor {-boolean} -nocase {-boolean} -all {-boolean} -inline {-boolean} -start {-default 0} exp {-required} string {-required} matchvar {} args {-name submatchvars} } ... } ``` `lsort`: ``` tcl proc lsort args { parse_args::parse_args $args { -ascii {-name compare_as -multi -default ascii} -dictionary {-name compare_as -multi} -integer {-name compare_as -multi} -real {-name compare_as -multi} -command {} -increasing {-name order -multi -default increasing} -decreasing {-name order -multi} -indices {-boolean} -index {} -stride {-default 1} -nocase {-boolean} -unique {-boolean} list {-required} } if {![info exists command]} { switch -- $compare_as { ascii { set command {string compare} if {$nocase} { lappend command -nocase } } dictionary { ... } integer - real { set command tcl::mathop::- } } } } ``` `lsearch`: ``` tcl proc lsearch args { parse_args::parse_args $args { -exact {-name matchtype -multi} -glob {-name matchtype -multi -default glob} -regexp {-name matchtype -multi} -sorted {-boolean} -all {-boolean} -inline {-boolean} -not {-boolean} -start {-default 0} -ascii {-name compare_as -multi -default ascii} -dictionary {-name compare_as -multi} -integer {-name compare_as -multi} -real {-name compare_as -multi} -nocase {-boolean} -decreasing {-name order -multi} -increasing {-name order -multi -default increasing} -bisect {-boolean} -index {} -subindices {-boolean} } if {$sorted && $matchtype in {glob regexp}} { error "-sorted is mutually exclusive with -glob and -regexp" } } ``` A Tk widget - `entry`: ``` tcl proc entry {widget args} { parse_args::parse_args $args { -disabledbackground {-default {}} -disabledforeground {-default {}} -invalidcommand {-default {}} -readonlybackground {-default {}} -show {} -state {-default normal -enum { normal disabled readonly }} -validate {-default none -enum { none focus focusin focusout key all }} -validatecommand {-default {}} -width {-default 0} -textvariable {} } } ``` # SEE ALSO The paper presented at the 2016 Tcl Conference which discusses the approach and design choices made in this package in much greater depth: https://www.tcl-lang.org/community/tcl2016/assets/talk33/parse_args-paper.pdf # BUGS Please open an issue on the github tracker for the project if you encounter any problems: https://github.com/RubyLane/parse_args/issues # LICENSE This package is Copyright 2015-2026 Cyan Ogilvie, and is made available under the same license terms as the Tcl Core parse_args-v0.6.3/generic/0000755000175100017510000000000015176457507015077 5ustar runnerrunnerparse_args-v0.6.3/generic/.vimrc0000644000175100017510000000002015176457507016210 0ustar runnerrunnerset noexpandtab parse_args-v0.6.3/generic/tclstuff.h0000644000175100017510000001362015176457507017104 0ustar runnerrunner// Written by Cyan Ogilvie, and placed in the public domain #ifndef _TCLSTUFF_H #define _TCLSTUFF_H #include #define NEW_CMD( tcl_cmd, c_cmd ) \ Tcl_CreateObjCommand( interp, tcl_cmd, \ (Tcl_ObjCmdProc *) c_cmd, \ (ClientData *) NULL, NULL ) #define THROW_ERROR( ... ) \ do { \ if (interp) Tcl_AppendResult(interp, __VA_ARGS__, NULL); \ return TCL_ERROR; \ } while(0) #define THROW_PRINTF( fmtstr, ... ) \ do { \ if (interp) Tcl_SetObjResult(interp, Tcl_ObjPrintf((fmtstr), __VA_ARGS__)); \ return TCL_ERROR; \ } while(0) #define THROW_POSIX(msg) \ do { \ int err = Tcl_GetErrno(); \ const char* errstr = Tcl_ErrnoId(); \ if (interp) Tcl_SetErrorCode(interp, "POSIX", errstr, Tcl_ErrnoMsg(err), NULL); \ THROW_PRINTF("%s: %s %s", msg, errstr, Tcl_ErrnoMsg(err)); \ } while(0) #define THROW_ERROR_LABEL( label, var, ... ) \ do { \ if (interp) Tcl_AppendResult(interp, __VA_ARGS__, NULL); \ var = TCL_ERROR; \ goto label; \ } while(0) #define THROW_PRINTF_LABEL( label, var, fmtstr, ... ) \ do { \ if (interp) Tcl_SetObjResult(interp, Tcl_ObjPrintf((fmtstr), __VA_ARGS__)); \ var = TCL_ERROR; \ goto label; \ } while(0) #define THROW_POSIX_LABEL(label, code, msg) \ do { \ int err = Tcl_GetErrno(); \ const char* errstr = Tcl_ErrnoId(); \ if (interp) Tcl_SetErrorCode(interp, "POSIX", errstr, Tcl_ErrnoMsg(err), NULL); \ THROW_PRINTF_LABEL(label, code, "%s: %s %s", msg, errstr, Tcl_ErrnoMsg(err)); \ } while(0) // convenience macro to check the number of arguments passed to a function // implementing a tcl command against the number expected, and to throw // a tcl error if they don't match. Note that the value of expected does // not include the objv[0] object (the function itself) #define CHECK_ARGS(msg) \ do { \ if (objc != A_objc) { \ if (interp) Tcl_WrongNumArgs(interp, A_cmd+1, objv, msg); \ return TCL_ERROR; \ } \ } while(0) #define CHECK_MIN_ARGS(msg) \ do { \ if (objc < A_args) { \ if (interp) Tcl_WrongNumArgs(interp, A_cmd+1, objv, msg); \ return TCL_ERROR; \ } \ } while(0) #define CHECK_RANGE_ARGS(msg) \ do { \ if (objc < A_args || objc > A_objc) { \ if (interp) Tcl_WrongNumArgs(interp, A_cmd+1, objv, msg); \ return TCL_ERROR; \ } \ } while(0) #define CHECK_ARGS_LABEL2(label, rc) \ do { \ if (objc != A_objc) { \ if (interp) Tcl_WrongNumArgs(interp, A_cmd+1, objv, NULL); \ rc = TCL_ERROR; \ goto label; \ } \ } while(0) #define CHECK_ARGS_LABEL3(label, rc, msg) \ do { \ if (objc != A_objc) { \ if (interp) Tcl_WrongNumArgs(interp, A_cmd+1, objv, sizeof(msg) > 1 ? msg : NULL); \ rc = TCL_ERROR; \ goto label; \ } \ } while(0) #define GET_CHECK_ARGS_LABEL_MACRO(_1,_2,_3,NAME,...) NAME #define CHECK_ARGS_LABEL(...) GET_CHECK_ARGS_LABEL_MACRO(__VA_ARGS__, CHECK_ARGS_LABEL3, CHECK_ARGS_LABEL2)(__VA_ARGS__) #define CHECK_MIN_ARGS_LABEL(label, rc, msg) \ do { \ if (objc < A_args) { \ if (interp) Tcl_WrongNumArgs(interp, A_cmd+1, objv, sizeof(msg) > 1 ? msg : NULL); \ rc = TCL_ERROR; \ goto label; \ } \ } while(0) #define CHECK_RANGE_ARGS_LABEL(label, rc, msg) \ do { \ if (objc < A_args || objc > A_objc) { \ if (interp) Tcl_WrongNumArgs(interp, A_cmd+1, objv, sizeof(msg) > 1 ? msg : NULL); \ rc = TCL_ERROR; \ goto label; \ } \ } while(0) // A rather frivolous macro that just enhances readability for a common case #define TEST_OK( cmd ) \ if (cmd != TCL_OK) return TCL_ERROR #define TEST_OK_LABEL( label, var, cmd ) \ if (cmd != TCL_OK) { \ var = TCL_ERROR; \ goto label; \ } #define TEST_OK_BREAK(var, cmd) if (TCL_OK != (var=(cmd))) break static inline void release_tclobj(Tcl_Obj** obj) { if (*obj) { Tcl_DecrRefCount(*obj); *obj = NULL; } } #define RELEASE_MACRO(obj) if (obj) {Tcl_DecrRefCount(obj); obj=NULL;} #define REPLACE_MACRO(target, replacement) \ do { \ release_tclobj(&target); \ if (replacement) Tcl_IncrRefCount(target = replacement); \ } while(0) static inline void replace_tclobj(Tcl_Obj** target, Tcl_Obj* replacement) { Tcl_Obj* old = *target; #if DEBUG if (*target && (*target)->refCount <= 0) Tcl_Panic("replace_tclobj target exists but has refcount <= 0: %" TCL_SIZE_MODIFIER "d", (*target)->refCount); #endif *target = replacement; if (*target) Tcl_IncrRefCount(*target); if (old) { Tcl_DecrRefCount(old); old = NULL; } } #if DEBUG # include # include # include # include "names.h" # define DBG(...) fprintf(stdout, __VA_ARGS__) # define FDBG(...) fprintf(stdout, __VA_ARGS__) # define DEBUGGER raise(SIGTRAP) # define TIME(label, task) \ do { \ struct timespec first; \ struct timespec second; \ struct timespec after; \ double empty; \ double delta; \ clock_gettime(CLOCK_MONOTONIC, &first); /* Warm up the call */ \ clock_gettime(CLOCK_MONOTONIC, &first); \ clock_gettime(CLOCK_MONOTONIC, &second); \ task; \ clock_gettime(CLOCK_MONOTONIC, &after); \ empty = second.tv_sec - first.tv_sec + (second.tv_nsec - first.tv_nsec)/1e9; \ delta = after.tv_sec - second.tv_sec + (after.tv_nsec - second.tv_nsec)/1e9 - empty; \ DBG("Time for %s: %.1f microseconds\n", label, delta * 1e6); \ } while(0) #else # define DBG(...) /* nop */ # define FDBG(...) /* nop */ # define DEBUGGER /* nop */ # define TIME(label, task) task #endif #define OBJCMD(name) int (name)(ClientData cdata, Tcl_Interp* interp, int objc, Tcl_Obj *const objv[]) #define INIT int init(Tcl_Interp* interp) #define RELEASE void release(Tcl_Interp* interp) #endif parse_args-v0.6.3/generic/parse_argsInt.h0000644000175100017510000000050015176457507020044 0ustar runnerrunner#ifndef _PARSE_ARGS_MAIN_H #define _PARSE_ARGS_MAIN_H #if HAVE_CONFIG_H #include #endif #include #include "tclstuff.h" #include "tip445.h" #include #include #include #ifdef _MSC_VER #include /* Needed for _malloca and _freea */ #endif #endif parse_args-v0.6.3/generic/tip445.h0000644000175100017510000000531415176457507016304 0ustar runnerrunner#ifndef _TIP445_H #define _TIP445_H #if TIP445_SHIM #include #include #include #if HAVE_HEDLEY_H # include HEDLEY_DIAGNOSTIC_PUSH HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION #else # if defined(__GNUC__) _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wunused-function\"") # elif defined(__clang__) _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wunused-function\"") # endif #endif /* Just enough of TIP445 to build on Tcl 8.6 */ #ifndef Tcl_ObjInternalRep typedef union Tcl_ObjInternalRep { long longValue; double doubleValue; void* otherValuePtr; struct { void* ptr1; void* ptr2; } twoPtrValue; struct { void* ptr; unsigned long value; } ptrAndLongRep; struct { void* ptr; Tcl_Size size; } ptrAndSizeRep; } Tcl_ObjInternalRep; #endif #ifndef Tcl_FetchInternalRep # define Tcl_FetchInternalRep(obj, type) (Tcl_ObjInternalRep*)(((obj)->typePtr == (type)) ? &(obj)->internalRep : NULL) #endif #ifndef Tcl_FreeInternalRep static inline void Tcl_FreeInternalRep(Tcl_Obj* obj) { if (obj->typePtr) { if (obj->typePtr && obj->typePtr->freeIntRepProc) obj->typePtr->freeIntRepProc(obj); obj->typePtr = NULL; } } #endif #ifndef Tcl_StoreInternalRep static inline void Tcl_StoreInternalRep(Tcl_Obj* objPtr, const Tcl_ObjType* typePtr, const Tcl_ObjInternalRep* irPtr) { Tcl_FreeInternalRep(objPtr); objPtr->typePtr = typePtr; memcpy(&objPtr->internalRep, irPtr, sizeof(Tcl_ObjInternalRep)); } #endif #ifndef Tcl_HasStringRep # define Tcl_HasStringRep(obj) ((obj)->bytes != NULL) #endif #ifndef Tcl_InitStringRep static char* Tcl_InitStringRep(Tcl_Obj* objPtr, const char* bytes, unsigned numBytes) { assert(objPtr->bytes == NULL || bytes == NULL); if (numBytes > INT_MAX) { Tcl_Panic("max size of a Tcl value (%d bytes) exceeded", INT_MAX); } /* Allocate */ if (objPtr->bytes == NULL) { /* Allocate only as empty - extend later if bytes copied */ objPtr->length = 0; if (numBytes) { objPtr->bytes = (char*)attemptckalloc(numBytes + 1); if (objPtr->bytes == NULL) return NULL; if (bytes) { /* Copy */ memcpy(objPtr->bytes, bytes, numBytes); objPtr->length = (int)numBytes; } } else { //TclInitStringRep(objPtr, NULL, 0); objPtr->bytes = ""; objPtr->length = 0; } } else { objPtr->bytes = (char*)ckrealloc(objPtr->bytes, numBytes + 1); objPtr->length = (int)numBytes; } /* Terminate */ objPtr->bytes[objPtr->length] = '\0'; return objPtr->bytes; } #endif #if HAVE_HEDLEY_H HEDLEY_DIAGNOSTIC_POP #else # if defined(__GNUC__) _Pragma("GCC diagnostic pop") # elif defined(__clang__) _Pragma("clang diagnostic pop") # endif #endif #endif // TIP445_SHIM #endif // _TI445_H parse_args-v0.6.3/generic/parse_args.c0000644000175100017510000010321515176457507017373 0ustar runnerrunner/* TODO: * - Better error messages */ #include "parse_argsInt.h" static void free_internal_rep(Tcl_Obj* obj); static void dup_internal_rep(Tcl_Obj* src, Tcl_Obj* dest); // Micro Tcl_ObjType - enum_choices {{{ static void free_enum_choices_intrep(Tcl_Obj* obj); Tcl_ObjType enum_choices_type = { "parse_spec_enum_choices", free_enum_choices_intrep, NULL, NULL, NULL }; static void free_enum_choices_intrep(Tcl_Obj* obj) { Tcl_ObjInternalRep* ir = Tcl_FetchInternalRep(obj, &enum_choices_type); if (ir->twoPtrValue.ptr1) { ckfree(ir->twoPtrValue.ptr1); ir->twoPtrValue.ptr1 = NULL; } } static int GetEnumChoicesFromObj(Tcl_Interp* interp, Tcl_Obj* obj, char*** res) { int code = TCL_OK; Tcl_ObjInternalRep* ir = Tcl_FetchInternalRep(obj, &enum_choices_type); if (ir == NULL) { const char** table; Tcl_Size len; Tcl_ObjInternalRep newir; TEST_OK_LABEL(finally, code, Tcl_SplitList(interp, Tcl_GetString(obj), &len, &table)); newir.twoPtrValue.ptr1 = table; Tcl_StoreInternalRep(obj, &enum_choices_type, &newir); ir = Tcl_FetchInternalRep(obj, &enum_choices_type); } *res = (char**)ir->twoPtrValue.ptr1; finally: return code; } // Micro Tcl_ObjType - enum_choices }}} Tcl_ObjType parse_spec_type = { "parse_spec", free_internal_rep, dup_internal_rep, NULL, // update_string_rep - we never invalidate our string rep NULL // set_from_any - we don't register this objtype }; /* Allocate static Tcl_Objs for these strings for each interp */ static const char* static_str[] = { "0", "1", "idx", "required", "default", "validate", "choices", "all", NULL }; enum static_objs { L_FALSE=0, L_TRUE, L_IDX, L_REQUIRED, L_DEFAULT, L_VALIDATE, L_CHOICES, L_ALL, L_end }; struct interp_cx { Tcl_Obj* obj[L_end]; Tcl_Obj* enums; }; struct parse_spec { char** options; struct option_info* option; int option_count; Tcl_Obj* usage_msg; struct option_info* positional; int positional_arg_count; struct option_info* multi; int multi_count; Tcl_Obj** all; int all_count; }; struct option_info { int arg_count; // -1: store the option name in -name if present; -2: comsume all remaining args int supplied; int is_args; // args style processing - consume all remaining arguments int required; int multi_idx; // If this option is part of a multi select Tcl_Obj* param; // What this param is called in the spec Tcl_Obj* name; // The name that will store this params value Tcl_Obj* default_val; // NULL if no default Tcl_Obj* validator; // NULL if no validator Tcl_Obj* enum_choices; // NULL if not an enum, also stores multi_choices for a multi Tcl_Obj* comment; // NULL if no comment int alias; // boolean int all_idx; // >= 0 - collect all instances of this option as a list, accumulated in a list at this index int end_options; // boolean. Treat seeing this option as if -- followed immediately after it }; // Fast unsigned int to string conversion from the talk by Alexandrescu: "Three Optimization Tips for C++" {{{ uint32_t digits10(uint64_t v) //{{{ { #define P01 10 #define P02 100 #define P03 1000 #define P04 10000 #define P05 100000 #define P06 1000000 #define P07 10000000 #define P08 100000000 #define P09 1000000000 #define P10 10000000000 #define P11 100000000000 #define P12 1000000000000 if (v < P01) return 1; if (v < P02) return 2; if (v < P03) return 3; if (v < P12) { if (v < P08) { if (v < P06) { if (v < P04) return 4; return 5 + (v >= P05); } return 7 + (v >= P07); } if (v < P10) { return 9 + (v >= P09); } return 11 + (v >= P11); } return 12 + digits10(v / P12); } //}}} int u64toa(uint64_t value, char* restrict dst) //{{{ { // TODO: benchmark this against TclFormatInt and replace the latter with this if it's faster static const char digits[201] = "0001020304050607080910111213141516171819" "2021222324252627282930313233343536373839" "4041424344454647484950515253545556575859" "6061626364656667686970717273747576777879" "8081828384858687888990919293949596979899"; const uint32_t length = digits10(value); uint32_t next = length-1; while (value >= 100) { const int i = (value % 100) * 2; value /= 100; memcpy(dst+next-1, digits+i, 2); //dst[next] = digits[i+1]; //dst[next-1] = digits[i]; next -= 2; } if (value < 10) { dst[next] = '0' + (uint32_t)value; } else { const int i = (uint32_t)value * 2; memcpy(dst+next-1, digits+i, 2); //dst[next] = digits[i + 1]; //dst[next-1] = digits[i]; } return length; } //}}} //}}} static const char* static_numstr(uint64_t v) //{{{ { static char staticbuf[21]; // 21 - max length of decimal representation of uint64_t + null terminator staticbuf[u64toa(v, staticbuf)] = 0; return staticbuf; } //}}} static void free_option_info(struct option_info* option) //{{{ { if (option) { replace_tclobj(&option->param, NULL); replace_tclobj(&option->name, NULL); replace_tclobj(&option->default_val, NULL); replace_tclobj(&option->validator, NULL); replace_tclobj(&option->enum_choices, NULL); replace_tclobj(&option->comment, NULL); } } //}}} static void free_parse_spec(struct parse_spec** specPtr) //{{{ { struct parse_spec* spec = *specPtr; int i; if (*specPtr != NULL) { //fprintf(stderr, "Freeing: %p\n", spec); if (spec->options) { for (i=0; i < spec->option_count; i++) { if (spec->options[i]) { free(spec->options[i]); spec->options[i] = NULL; } } ckfree(spec->options); spec->options = NULL; } if (spec->option != NULL) { for (i=0; i < spec->option_count; i++) free_option_info(&spec->option[i]); ckfree(spec->option); spec->option = NULL; } replace_tclobj(&spec->usage_msg, NULL); if (spec->positional) { for (i=0; i < spec->positional_arg_count; i++) free_option_info(&spec->positional[i]); ckfree(spec->positional); spec->positional = NULL; } if (spec->multi) { for (i=0; i < spec->multi_count; i++) free_option_info(&spec->multi[i]); ckfree(spec->multi); spec->multi = NULL; } if (spec->all) { for (i=0; i < spec->all_count; i++) replace_tclobj(spec->all+i, NULL); ckfree(spec->all); } ckfree(spec); *specPtr = NULL; } } //}}} static void free_internal_rep(Tcl_Obj* obj) //{{{ { Tcl_ObjInternalRep* ir = Tcl_FetchInternalRep(obj, &parse_spec_type); free_parse_spec((struct parse_spec**)&ir->twoPtrValue.ptr1); } //}}} static void dup_internal_rep(Tcl_Obj* src, Tcl_Obj* dest) // This shouldn't actually ever be called I think {{{ { Tcl_ObjInternalRep* ir = Tcl_FetchInternalRep(src, &parse_spec_type); Tcl_ObjInternalRep newir; struct parse_spec* spec = (struct parse_spec*)ckalloc(sizeof(struct parse_spec)); struct parse_spec* old = (struct parse_spec*)ir->twoPtrValue.ptr1; int i; //fprintf(stderr, "in dup_internal_rep\n"); memset(spec, 0, sizeof(struct parse_spec)); //fprintf(stderr, "Allocated spec: %p: \"%s\"\n", spec, Tcl_GetString(src)); spec->option_count = old->option_count; spec->positional_arg_count = old->positional_arg_count; spec->multi_count = old->positional_arg_count; spec->options = ckalloc(sizeof(char*) * (spec->option_count+1)); spec->option = ckalloc(sizeof(struct option_info) * spec->option_count); spec->positional = ckalloc(sizeof(struct option_info) * spec->positional_arg_count); spec->multi = ckalloc(sizeof(struct option_info) * spec->multi_count); memset(spec->options, 0, sizeof(char*) * (spec->option_count+1)); memset(spec->option, 0, sizeof(struct option_info) * spec->option_count); memset(spec->positional, 0, sizeof(struct option_info) * spec->positional_arg_count); memset(spec->multi, 0, sizeof(struct option_info) * spec->multi_count); replace_tclobj(&spec->usage_msg, old->usage_msg); #define INCREF_OPTION(opt) \ if ((opt).name != NULL) Tcl_IncrRefCount((opt).name); \ if ((opt).default_val != NULL) Tcl_IncrRefCount((opt).default_val); \ if ((opt).validator != NULL) Tcl_IncrRefCount((opt).validator); \ if ((opt).enum_choices != NULL) Tcl_IncrRefCount((opt).enum_choices); for (i=0; i < spec->option_count; i++) { // strdup is safe because the value came from Tcl_GetString, which // always returns properly \0 terminated strings spec->options[i] = strdup(old->options[i]); spec->option[i] = old->option[i]; INCREF_OPTION(spec->option[i]); } for (i=0; i < spec->positional_arg_count; i++) { spec->positional[i] = old->positional[i]; INCREF_OPTION(spec->positional[i]); } for (i=0; i < spec->multi_count; i++) { spec->multi[i] = old->multi[i]; INCREF_OPTION(spec->multi[i]); } newir.twoPtrValue.ptr1 = spec; Tcl_StoreInternalRep(dest, &parse_spec_type, &newir); } //}}} static int compile_parse_spec(Tcl_Interp* interp, Tcl_Obj* obj, struct parse_spec** res) //{{{ { struct interp_cx* l = (struct interp_cx*)Tcl_GetAssocData(interp, "parse_args", NULL); Tcl_Obj** ov; Tcl_Size oc, str_len, settingc; int i, j, code=TCL_OK, index, o_i=0, p_i=0; const char* str; Tcl_Obj* name; Tcl_Obj** settingv; struct parse_spec* spec = NULL; const char* settings[] = { "-default", "-required", "-validate", "-name", "-boolean", "-args", "-enum", "-#", "-multi", "-alias", "-all", "-end", (char*)NULL }; enum { SETTING_DEFAULT, SETTING_REQUIRED, SETTING_VALIDATE, SETTING_NAME, SETTING_BOOLEAN, SETTING_ARGS, SETTING_ENUM, SETTING_COMMENT, SETTING_MULTI, SETTING_ALIAS, SETTING_ALL, SETTING_END }; Tcl_DictSearch search; Tcl_Obj* multis = NULL; replace_tclobj(&multis, Tcl_NewDictObj()); TEST_OK_LABEL(err, code, Tcl_ListObjGetElements(interp, obj, &oc, &ov)); if (oc % 2 != 0) THROW_ERROR_LABEL(err, code, "argspec must be a dictionary"); spec = ckalloc(sizeof(struct parse_spec)); memset(spec, 0, sizeof(struct parse_spec)); //fprintf(stderr, "Allocated spec: %p: \"%s\"\n", spec, Tcl_GetString(obj)); for (i=0; i 0 && str[0] == '-') { spec->option_count++; } else { spec->positional_arg_count++; } } spec->options = ckalloc(sizeof(char*) * (spec->option_count+1)); spec->option = ckalloc(sizeof(struct option_info) * spec->option_count); spec->positional = ckalloc(sizeof(struct option_info) * spec->positional_arg_count); memset(spec->options, 0, sizeof(char*) * (spec->option_count+1)); memset(spec->option, 0, sizeof(struct option_info) * spec->option_count); memset(spec->positional, 0, sizeof(struct option_info) * spec->positional_arg_count); for (i=0; i 0 && str[0] == '-') { // strdup is safe because Tcl_GetString always returns a properly // \0 terminated string spec->options[o_i] = strdup(str); //fprintf(stderr, "Storing option %d/%d: %p \"%s\"\n", o_i, spec->option_count, spec->options[o_i], str); option = &spec->option[o_i++]; } else { //fprintf(stderr, "Storing positional param %d/%d: \"%s\"\n", p_i, spec->positional_arg_count, str); option = &spec->positional[p_i++]; } Tcl_IncrRefCount(option->param = name); option->arg_count = 1; option->multi_idx = -1; option->all_idx = -1; TEST_OK_LABEL(err, code, Tcl_ListObjGetElements(interp, ov[i+1], &settingc, &settingv)); j = 0; //fprintf(stderr, "Checking %d setting elements: \"%s\"\n", settingc, Tcl_GetString(ov[i+1])); while (j= settingc) THROW_ERROR_LABEL(err, code, Tcl_GetString(settingv[j-1]), " needs a value"); break; } switch (index) { case SETTING_DEFAULT: Tcl_IncrRefCount(option->default_val = settingv[j++]); break; case SETTING_REQUIRED: option->required = 1; break; case SETTING_VALIDATE: { Tcl_Obj* validatorobj = settingv[j++]; Tcl_Obj** ov; Tcl_Size oc; TEST_OK_LABEL(err, code, Tcl_ListObjGetElements(interp, validatorobj, &oc, &ov)); if (oc > 0) Tcl_IncrRefCount(option->validator = validatorobj); } break; case SETTING_NAME: Tcl_IncrRefCount(option->name = settingv[j++]); break; case SETTING_BOOLEAN: option->arg_count = 0; break; case SETTING_ARGS: if (strcmp("all", Tcl_GetString(settingv[j])) == 0) { option->arg_count = -2; } else { TEST_OK_LABEL(err, code, Tcl_GetIntFromObj(interp, settingv[j], &option->arg_count)); if (option->arg_count < 0) THROW_ERROR_LABEL(err, code, "-args cannot be negative"); } j++; break; case SETTING_ENUM: { /* enums are validated using Tcl_GetIndexFromObj, which * shimmers its input obj to record the table and index * info, so make an effort to unify enums across parse_specs */ Tcl_Obj* enum_choices = settingv[j++]; Tcl_Obj* shared_enum_choices = NULL; Tcl_Size size; if (l->enums == NULL) { code = TCL_ERROR; goto err; } TEST_OK_LABEL(err, code, Tcl_DictObjGet(interp, l->enums, enum_choices, &shared_enum_choices)); if (shared_enum_choices == NULL) { if (Tcl_IsShared(l->enums)) replace_tclobj(&l->enums, Tcl_DuplicateObj(l->enums)); TEST_OK_LABEL(err, code, Tcl_DictObjPut(interp, l->enums, enum_choices, shared_enum_choices = enum_choices)); } TEST_OK_LABEL(err, code, Tcl_DictObjSize(interp, l->enums, &size)); if (size > 1000) { // Paranoia - prevent the speculative enum cache from growing too large replace_tclobj(&l->enums, Tcl_NewDictObj()); } replace_tclobj(&option->enum_choices, shared_enum_choices); } break; case SETTING_COMMENT: replace_tclobj(&option->comment, settingv[j++]); break; case SETTING_MULTI: if (str[0] != '-') THROW_ERROR_LABEL(err, code, "Cannot use -multi on positional argument \"", Tcl_GetString(option->param), "\""); option->arg_count = -1; break; case SETTING_ALIAS: option->alias = 1; break; case SETTING_ALL: all_specified = 1; // Just raise a flag here to prevent multiple -all specs from excessively incrementing all_count break; case SETTING_END: option->end_options = 1; break; default: { char buf[3*sizeof(index)+2]; sprintf(buf, "%d", index); THROW_ERROR_LABEL(err, code, "Invalid setting: ", buf); } } } if (option->name == NULL) { if (str[0] == '-') { replace_tclobj(&option->name, Tcl_NewStringObj(str+1, str_len-1)); } else { replace_tclobj(&option->name, name); } } if (option->arg_count == -1) { int multi_idx; Tcl_Obj* multi_choices; const char* multi_val; Tcl_Size multi_val_len; Tcl_Obj* multi_config_loan = NULL; Tcl_Obj* multi_all = NULL; //fprintf(stderr, "multis: %s\n", Tcl_GetString(multis)); TEST_OK_LABEL(err, code, Tcl_DictObjGet(interp, multis, option->name, &multi_config_loan)); if (multi_config_loan == NULL) { multi_idx = spec->multi_count++; multi_config_loan = Tcl_NewDictObj(); TEST_OK_LABEL(err, code, Tcl_DictObjPut(interp, multi_config_loan, l->obj[L_IDX], Tcl_NewIntObj(multi_idx))); TEST_OK_LABEL(err, code, Tcl_DictObjPut(interp, multis, option->name, multi_config_loan)); multi_choices = Tcl_NewListObj(0, NULL); } else { Tcl_Obj* idx_obj = NULL; TEST_OK_LABEL(err, code, Tcl_DictObjGet(interp, multi_config_loan, l->obj[L_IDX], &idx_obj)); TEST_OK_LABEL(err, code, Tcl_GetIntFromObj(interp, idx_obj, &multi_idx)); TEST_OK_LABEL(err, code, Tcl_DictObjGet(interp, multi_config_loan, l->obj[L_CHOICES], &multi_choices)); } TEST_OK_LABEL(err, code, Tcl_ListObjAppendElement(interp, multi_choices, option->param)); TEST_OK_LABEL(err, code, Tcl_DictObjPut(interp, multi_config_loan, l->obj[L_CHOICES], multi_choices)); option->multi_idx = multi_idx; // TODO: throw errors if -boolean or -args are mixed with -multi if (option->enum_choices != NULL) THROW_ERROR_LABEL(err, code, "Cannot use -multi and -enum together"); if (option->required) TEST_OK_LABEL(err, code, Tcl_DictObjPut(interp, multi_config_loan, l->obj[L_REQUIRED], l->obj[L_TRUE])); if (option->default_val != NULL) TEST_OK_LABEL(err, code, Tcl_DictObjPut(interp, multi_config_loan, l->obj[L_DEFAULT], option->default_val)); if (option->validator != NULL) TEST_OK_LABEL(err, code, Tcl_DictObjPut(interp, multi_config_loan, l->obj[L_VALIDATE], option->validator)); TEST_OK_LABEL(err, code, Tcl_DictObjGet(interp, multi_config_loan, l->obj[L_ALL], &multi_all)); if (all_specified || multi_all) { int all_idx; if (multi_all) { TEST_OK_LABEL(err, code, Tcl_GetIntFromObj(interp, multi_all, &all_idx)); } else { all_idx = spec->all_count++; } option->all_idx = all_idx; if (!multi_all) TEST_OK_LABEL(err, code, Tcl_DictObjPut(interp, multi_config_loan, l->obj[L_ALL], Tcl_NewIntObj(all_idx))); } // Repurpose option->default_val to store the value this option will set in the multi output multi_val = Tcl_GetStringFromObj(option->param, &multi_val_len); replace_tclobj(&option->default_val, Tcl_NewStringObj(multi_val+1, multi_val_len-1)); } else if (all_specified) { option->all_idx = spec->all_count++; } } // This is only known after parsing the options if (spec->multi_count > 0) { Tcl_Obj* name; Tcl_Obj* val; Tcl_Obj* idx_obj; Tcl_Obj* multi_config_loan = NULL; int done, idx; spec->multi = ckalloc(sizeof(struct option_info) * spec->multi_count); memset(spec->multi, 0, sizeof(struct option_info) * spec->multi_count); TEST_OK_LABEL(err, code, Tcl_DictObjFirst(interp, multis, &search, &name, &multi_config_loan, &done)); for (; !done; Tcl_DictObjNext(&search, &name, &multi_config_loan, &done)) { struct option_info* multi; //fprintf(stderr, "multi config for %s: %s\n", Tcl_GetString(name), Tcl_GetString(multi_config_loan)); TEST_OK_LABEL(err_search, code, Tcl_DictObjGet(interp, multi_config_loan, l->obj[L_IDX], &idx_obj)); TEST_OK_LABEL(err_search, code, Tcl_GetIntFromObj(interp, idx_obj, &idx)); if (idx < 0 || idx >= spec->multi_count) { THROW_ERROR_LABEL(err_search, code, "Got out of bounds multi_count ", Tcl_GetString(idx_obj), " for option \"", Tcl_GetString(name)); } multi = &spec->multi[idx]; //fprintf(stderr, "Setting multi %d name: \"%s\"\n", idx, Tcl_GetString(name)); replace_tclobj(&multi->name, name); multi->arg_count = -1; // set -required TEST_OK_LABEL(err_search, code, Tcl_DictObjGet(interp, multi_config_loan, l->obj[L_REQUIRED], &val)); if (val != NULL) multi->required = 1; // set -default TEST_OK_LABEL(err_search, code, Tcl_DictObjGet(interp, multi_config_loan, l->obj[L_DEFAULT], &val)); replace_tclobj(&multi->default_val, val); // set -validate TEST_OK_LABEL(err_search, code, Tcl_DictObjGet(interp, multi_config_loan, l->obj[L_VALIDATE], &val)); replace_tclobj(&multi->validator, val); // set multi choices (for error message if required and not set) TEST_OK_LABEL(err_search, code, Tcl_DictObjGet(interp, multi_config_loan, l->obj[L_CHOICES], &val)); replace_tclobj(&multi->enum_choices, val); TEST_OK_LABEL(err_search, code, Tcl_DictObjGet(interp, multi_config_loan, l->obj[L_ALL], &val)); if (val) { TEST_OK_LABEL(err_search, code, Tcl_GetIntFromObj(interp, val, &multi->all_idx)); } else { multi->all_idx = -1; } } Tcl_DictObjDone(&search); } if (spec->positional_arg_count > 0) { struct option_info* last = &spec->positional[spec->positional_arg_count - 1]; // Create special "args" behaviour for last positional param named "args" // strcmp is safe because Tcl_GetString always gives us a properly // \0 terminated string if (strcmp("args", Tcl_GetString(last->param)) == 0) { last->is_args = 1; if (last->default_val == NULL) replace_tclobj(&last->default_val, Tcl_NewObj()); } } if (spec->all_count) { spec->all = ckalloc(sizeof(Tcl_Obj*) * spec->all_count); memset(spec->all, 0, sizeof(Tcl_Obj*) * spec->all_count); } // TODO: better usage_msg replace_tclobj(&spec->usage_msg, Tcl_ObjPrintf("Invalid args, should be ?-option ...? %s", "?arg ...?")); *res = spec; goto finally; err_search: Tcl_DictObjDone(&search); err: //fprintf(stderr, "compile_parse_spec failed, freeing spec\n"); free_parse_spec(&spec); finally: replace_tclobj(&multis, NULL); return code; } //}}} static int GetParseSpecFromObj(Tcl_Interp* interp, Tcl_Obj* spec, struct parse_spec** res) //{{{ { int code = TCL_OK; Tcl_ObjInternalRep* ir = Tcl_FetchInternalRep(spec, &parse_spec_type); if (ir == NULL) { Tcl_ObjInternalRep newir; struct parse_spec* compiled_spec = NULL; TEST_OK_LABEL(finally, code, compile_parse_spec(interp, spec, &compiled_spec)); newir.twoPtrValue.ptr1 = compiled_spec; Tcl_StoreInternalRep(spec, &parse_spec_type, &newir); ir = Tcl_FetchInternalRep(spec, &parse_spec_type); } if (res) *res = (struct parse_spec*)ir->twoPtrValue.ptr1; finally: return code; } //}}} static int validate(Tcl_Interp* interp, struct option_info* option, Tcl_Obj* val) //{{{ { Tcl_Obj* verdict = NULL; if (option->enum_choices != NULL) { int dummy; char** enum_table; TEST_OK(GetEnumChoicesFromObj(interp, option->enum_choices, &enum_table)); TEST_OK(Tcl_GetIndexFromObj(interp, val, enum_table, Tcl_GetString(option->param), TCL_EXACT, &dummy)); } if (option->validator != NULL) { int res, passed; Tcl_Obj** ov; Tcl_Size oc; TEST_OK(Tcl_ListObjGetElements(interp, option->validator, &oc, &ov)); { #ifdef _MSC_VER /* * VC++ does not support C99 varsize arrays. * Use _malloca to allocate stack space * (recommended over _alloca) instead. Note this will * die on stack overflow just like varsize arrays. * Also note the corresponding _freea to free memory. */ Tcl_Obj** cmd = _malloca((oc+1)*sizeof(*cmd)); #else Tcl_Obj* cmd[oc+1]; #endif int i; for (i=0; iparam), Tcl_GetString(verdict) )); Tcl_SetErrorCode(interp, "PARSE_ARGS", "VALIDATION", Tcl_GetString(option->param), NULL); res = TCL_ERROR; } Tcl_DecrRefCount(verdict); verdict = NULL; return res; } return TCL_OK; } //}}} static inline int _put_option_value(Tcl_Interp* interp, Tcl_Obj* res, struct parse_spec* spec, struct option_info* option, Tcl_Obj* val, int dictmode) //{{{ { int code = TCL_OK; const int all_idx = option->all_idx; if (all_idx >= 0) { if (spec->all[all_idx] == NULL) replace_tclobj(&spec->all[all_idx], Tcl_NewListObj(1, NULL)); TEST_OK_LABEL(finally, code, Tcl_ListObjAppendElement(interp, spec->all[all_idx], val)); } else { if (dictmode) { TEST_OK_LABEL(finally, code, Tcl_DictObjPut(interp, res, option->name, val)); } else { if (Tcl_ObjSetVar2(interp, option->name, NULL, val, TCL_LEAVE_ERR_MSG) == NULL) { code = TCL_ERROR; goto finally; } } } finally: return code; } //}}} static int parse_args(ClientData cdata, Tcl_Interp* interp, int objc, Tcl_Obj *const objv[]) //{{{ { int code = TCL_OK; struct interp_cx* l = (struct interp_cx*)cdata; Tcl_Obj** av; Tcl_Size ac; int i, check_options=1, positional_arg=0; struct parse_spec* spec = NULL; Tcl_Obj* res = NULL; Tcl_Obj* val = NULL; const int dictmode = objc >= 4; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 1, objv, "args args_spec ?dict?"); code = TCL_ERROR; goto finally; } TEST_OK_LABEL(finally, code, Tcl_ListObjGetElements(interp, objv[1], &ac, &av)); //fprintf(stderr, "Getting parse_spec from (%s)\n", Tcl_GetString(objv[2])); TEST_OK_LABEL(finally, code, GetParseSpecFromObj(interp, objv[2], &spec)); for (i=0; ioption_count; i++) spec->option[i].supplied = 0; for (i=0; imulti_count; i++) spec->multi[i].supplied = 0; for (i=0; iall_count; i++) replace_tclobj(spec->all+i, NULL); if (dictmode) replace_tclobj(&res, Tcl_NewDictObj()); #define OUTPUT(option, val) TEST_OK_LABEL(finally, code, _put_option_value(interp, res, spec, option, val, dictmode)) #define OUTPUT_DIRECT(name, val) \ do { \ if (dictmode) { \ TEST_OK_LABEL(finally, code, Tcl_DictObjPut(interp, res, (name), (val))); \ } else { \ if (Tcl_ObjSetVar2(interp, (name), NULL, (val), TCL_LEAVE_ERR_MSG) == NULL) { \ code = TCL_ERROR; \ goto finally; \ } \ } \ } while(0) #define VALIDATE(option, val) \ if ((option)->validator != NULL || (option)->enum_choices != NULL) { \ TEST_OK_LABEL(finally, code, validate(interp, (option), (val))); \ } for (i=0; i 0 && str[0] == '-') { struct option_info* option; struct option_info* src_option; int index; // strcmp is safe because Tcl_GetString always returns properly // \0 terminated strings if (str_len == 2 && strcmp(str, "--") == 0) { check_options = 0; continue; } TEST_OK_LABEL(finally, code, Tcl_GetIndexFromObj(interp, av[i], spec->options, "option", TCL_EXACT, &index)); option = src_option = &spec->option[index]; if (option->multi_idx >= 0) option = &spec->multi[src_option->multi_idx]; option->supplied = 1; //fprintf(stderr, "Option \"%s\" arg_count: %d\n", // Tcl_GetString(option->name), option->arg_count); if (option->arg_count > 0 && ac - i - 1 < option->arg_count) { // This option requires args and not enough remain Tcl_WrongNumArgs(interp, 1, objv, Tcl_GetString(spec->usage_msg)); code = TCL_ERROR; goto finally; } switch (option->arg_count) { case -2: // All remaining args i++; val = Tcl_NewListObj(ac-i, av+i); VALIDATE(option, val); OUTPUT(option, val); i += ac-i; break; case -1: OUTPUT(option, src_option->default_val); break; case 0: OUTPUT(option, l->obj[L_TRUE]); break; case 1: val = av[++i]; VALIDATE(option, val); if (option->alias == 0) { OUTPUT(option, val); } else { if (dictmode) { // TODO: fetch the value from the variable called option->name in the parent callframe THROW_ERROR_LABEL(finally, code, "-alias is not yet supported in dictionary mode"); } else { TEST_OK_LABEL(finally, code, Tcl_UpVar(interp, "1", Tcl_GetString(val), Tcl_GetString(option->name), 0)); } } break; default: val = Tcl_NewListObj(option->arg_count, av+i+1); VALIDATE(option, val); OUTPUT(option, val); i += option->arg_count; break; } if (option->end_options) check_options = 0; continue; } else { check_options = 0; } } if (positional_arg >= spec->positional_arg_count) { // Too many positional args Tcl_WrongNumArgs(interp, 1, objv, Tcl_GetString(spec->usage_msg)); code = TCL_ERROR; goto finally; } if (spec->positional[positional_arg].is_args || spec->positional[positional_arg].arg_count == -2) { val = Tcl_NewListObj(ac-i, av+i); VALIDATE(&spec->positional[positional_arg], val); OUTPUT_DIRECT(spec->positional[positional_arg].name, val); i = ac; } else if (spec->positional[positional_arg].arg_count > 1) { const int arg_count = spec->positional[positional_arg].arg_count; if (arg_count > 0 && ac - i - 1 < arg_count) { // This arg requires arg_count args and not enough remain Tcl_SetErrorCode(interp, "PARSE_ARGS", "WRONGARGS", Tcl_GetString(spec->positional[positional_arg].name), NULL); THROW_ERROR_LABEL(finally, code, "Expecting ", static_numstr(arg_count), " arguments for ", Tcl_GetString(spec->positional[positional_arg].name)); } val = Tcl_NewListObj(arg_count, av+i); VALIDATE(&spec->positional[positional_arg], val); OUTPUT_DIRECT(spec->positional[positional_arg].name, val); i += arg_count-1; // -1: the for loop will increment by 1 } else { VALIDATE(&spec->positional[positional_arg], av[i]); if (spec->positional[positional_arg].alias == 0) { OUTPUT_DIRECT(spec->positional[positional_arg].name, av[i]); } else { if (dictmode) { // TODO: fetch the value from the variable called option->name in the parent callframe THROW_ERROR_LABEL(finally, code, "-alias is not yet supported in dictionary mode"); } else { TEST_OK_LABEL(finally, code, Tcl_UpVar(interp, "1", Tcl_GetString(av[i]), Tcl_GetString(spec->positional[positional_arg].name), 0)); } } } positional_arg++; } // Check -required, set -default for options that weren't specified, and set the -all lists for (i=0; i < spec->option_count; i++) { struct option_info* option = &spec->option[i]; if (option->all_idx >= 0) { const int all_idx = option->all_idx; if (spec->all[all_idx]) { OUTPUT_DIRECT(option->name, spec->all[all_idx]); replace_tclobj(spec->all + all_idx, NULL); } } if (option->supplied) continue; if (option->multi_idx >= 0) continue; if (option->default_val != NULL) { OUTPUT_DIRECT(option->name, option->default_val); } else if (option->arg_count == 0) { OUTPUT_DIRECT(option->name, l->obj[L_FALSE]); } else { if (option->required) { Tcl_SetErrorCode(interp, "PARSE_ARGS", "REQUIRED", Tcl_GetString(option->param), NULL); THROW_ERROR_LABEL(finally, code, "option ", Tcl_GetString(option->param), " is required"); } } } // Check -required and set -default for multi options that weren't specified //fprintf(stderr, "-multi post check, count: %d\n", spec->multi_count); for (i=0; i < spec->multi_count; i++) { struct option_info* option = &spec->multi[i]; //fprintf(stderr, "\t%d, %s supplied? %d, default_val: %p\n", i, Tcl_GetString(option->name), option->supplied, option->default_val); if (option->supplied) continue; if (option->default_val != NULL) { OUTPUT(option, option->default_val); } else if (option->required) { Tcl_SetErrorCode(interp, "PARSE_ARGS", "REQUIRED_ONE_OF", Tcl_GetString(option->enum_choices), NULL); THROW_ERROR_LABEL(finally, code, "one of ", Tcl_GetString(option->enum_choices), " are required"); } } // Set default values for positional params that need them for (; positional_arg < spec->positional_arg_count; positional_arg++) { struct option_info* option = &spec->positional[positional_arg]; if (option->default_val != NULL) { // Don't need to validate here - the default was baked in at // definition time and it might be useful to allow it to be outside // the valid domain OUTPUT_DIRECT(option->name, option->default_val); } else { // Missing some positional args if (option->required) { Tcl_SetErrorCode(interp, "PARSE_ARGS", "REQUIRED", Tcl_GetString(option->param), NULL); THROW_ERROR_LABEL(finally, code, "argument ", Tcl_GetString(option->name), " is required"); } } } if (dictmode) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, res, TCL_LEAVE_ERR_MSG) == NULL) { code = TCL_ERROR; goto finally; } } finally: if (spec) for (i=0; iall_count; i++) replace_tclobj(spec->all + i, NULL); replace_tclobj(&res, NULL); return code; } //}}} static void free_interp_cx(ClientData cdata, Tcl_Interp* interp) //{{{ { struct interp_cx* l = (struct interp_cx*)cdata; int i; (void)interp; if (l) { for (i=0; iobj[i], NULL); replace_tclobj(&l->enums, NULL); ckfree(l); l = NULL; } } //}}} #ifdef WIN32 extern DLLEXPORT #endif int Parse_args_Init(Tcl_Interp* interp) //{{{ { int code = TCL_OK; struct interp_cx* l = NULL; Tcl_Namespace* ns = NULL; int i; /* Require 8.6 or later (9.0 also ok) */ #ifdef USE_TCL_STUBS if (NULL == Tcl_InitStubs(interp, TCL_VERSION, 0)) #else if (NULL == Tcl_PkgRequire(interp, "Tcl", "8.6-", 0)) #endif { code = TCL_ERROR; goto finally; } l = ckalloc(sizeof(struct interp_cx)); if (l == NULL) THROW_ERROR_LABEL(finally, code, "Couldn't allocate per-interp data"); memset(l, 0, sizeof *l); for (i=0; iobj[i], Tcl_NewStringObj(static_str[i], -1)); replace_tclobj(&l->enums, Tcl_NewDictObj()); Tcl_SetAssocData(interp, "parse_args", free_interp_cx, l); ns = Tcl_CreateNamespace(interp, "::parse_args", NULL, NULL); TEST_OK_LABEL(finally, code, Tcl_Export(interp, ns, "*", 0)); Tcl_CreateObjCommand(interp, "::parse_args::parse_args", parse_args, l, NULL); TEST_OK_LABEL(finally, code, Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION)); finally: if (code != TCL_OK) { if (l) { free_interp_cx(l, interp); l = NULL; } } return code; } //}}} int Parse_args_SafeInit(Tcl_Interp* interp) //{{{ { // No unsafe features return Parse_args_Init(interp); } //}}} // vim: foldmethod=marker foldmarker={{{,}}} ts=4 shiftwidth=4 parse_args-v0.6.3/Makefile.in0000644000175100017510000004521115176457507015533 0ustar runnerrunner# Makefile.in -- # # This file is a Makefile for Sample TEA Extension. If it has the name # "Makefile.in" then it is a template for a Makefile; to generate the # actual Makefile, run "./configure", which is a configuration script # generated by the "autoconf" program (constructs like "@foo@" will get # replaced in the actual Makefile. # # Copyright (c) 1999 Scriptics Corporation. # Copyright (c) 2002-2005 ActiveState Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. #======================================================================== # Add additional lines to handle any additional AC_SUBST cases that # have been added in a customized configure script. #======================================================================== #SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@ #======================================================================== # Nothing of the variables below this line should need to be changed. # Please check the TARGETS section below to make sure the make targets # are correct. #======================================================================== #======================================================================== # The names of the source files is defined in the configure script. # The object files are used for linking into the final library. # This will be used when a dist target is added to the Makefile. # It is not important to specify the directory, as long as it is the # $(srcdir) or in the generic, win or unix subdirectory. #======================================================================== PKG_SOURCES = @PKG_SOURCES@ PKG_OBJECTS = @PKG_OBJECTS@ PKG_STUB_SOURCES = @PKG_STUB_SOURCES@ PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@ #======================================================================== # PKG_TCL_SOURCES identifies Tcl runtime files that are associated with # this package that need to be installed, if any. #======================================================================== PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ #======================================================================== # This is a list of public header files to be installed, if any. #======================================================================== PKG_HEADERS = @PKG_HEADERS@ #======================================================================== # "PKG_LIB_FILE" refers to the library (dynamic or static as per # configuration options) composed of the named objects. #======================================================================== PKG_LIB_FILE = @PKG_LIB_FILE@ PKG_LIB_FILE8 = @PKG_LIB_FILE8@ PKG_LIB_FILE9 = @PKG_LIB_FILE9@ PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@ lib_BINARIES = $(PKG_LIB_FILE) BINARIES = $(lib_BINARIES) SHELL = @SHELL@ srcdir = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ includedir = @includedir@ datarootdir = @datarootdir@ runstatedir = @runstatedir@ datadir = @datadir@ mandir = @mandir@ DESTDIR = PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) pkgdatadir = $(datadir)/$(PKG_DIR) pkglibdir = $(libdir)/$(PKG_DIR) pkgincludedir = $(includedir)/$(PKG_DIR) top_builddir = @abs_top_builddir@ INSTALL_OPTIONS = INSTALL = @INSTALL@ $(INSTALL_OPTIONS) INSTALL_DATA_DIR = @INSTALL_DATA_DIR@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_LIBRARY = @INSTALL_LIBRARY@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ CC = @CC@ CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ CFLAGS_WARNING = @CFLAGS_WARNING@ EXEEXT = @EXEEXT@ LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ MAKE_LIB = @MAKE_LIB@ MAKE_STUB_LIB = @MAKE_STUB_LIB@ OBJEXT = @OBJEXT@ RANLIB = @RANLIB@ RANLIB_STUB = @RANLIB_STUB@ SHLIB_CFLAGS = @SHLIB_CFLAGS@ SHLIB_LD = @SHLIB_LD@ SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ STLIB_LD = @STLIB_LD@ #TCL_DEFS = @TCL_DEFS@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_SRC_DIR = @TCL_SRC_DIR@ #TK_BIN_DIR = @TK_BIN_DIR@ #TK_SRC_DIR = @TK_SRC_DIR@ # Not used, but retained for reference of what libs Tcl required #TCL_LIBS = @TCL_LIBS@ #======================================================================== # TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our # package without installing. The other environment variables allow us # to test against an uninstalled Tcl. Add special env vars that you # require for testing here (like TCLX_LIBRARY). #======================================================================== EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) #EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR) TCLLIBPATH = $(top_builddir) TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ PATH="$(EXTRA_PATH):$(PATH)" \ TCLLIBPATH="$(TCLLIBPATH)" TCLSH_PROG = @TCLSH_PROG@ TCLSH = $(TCLSH_ENV) $(PKG_ENV) $(TCLSH_PROG) #WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` #WISH_PROG = @WISH_PROG@ #WISH = $(TCLSH_ENV) $(WISH_ENV) $(PKG_ENV) $(WISH_PROG) SHARED_BUILD = @SHARED_BUILD@ INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ -I. #INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ PKG_CFLAGS = @PKG_CFLAGS@ # TCL_DEFS is not strictly need here, but if you remove it, then you # must make sure that configure.ac checks for the necessary components # that your library may use. TCL_DEFS can actually be a problem if # you do not compile with a similar machine setup as the Tcl core was # compiled with. #DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) DEFS = @DEFS@ $(PKG_CFLAGS) # Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl CLEANFILES = @CLEANFILES@ CPPFLAGS = @CPPFLAGS@ LIBS = @PKG_LIBS@ @LIBS@ AR = @AR@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) \ $(CFLAGS_DEFAULT) $(CFLAGS_WARNING) $(SHLIB_CFLAGS) $(CFLAGS) GDB = gdb VALGRIND = valgrind VALGRINDEXTRA = VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \ --leak-check=yes -v --suppressions=suppressions --keep-debuginfo=yes \ --trace-children=yes $(VALGRINDEXTRA) PGOGEN_BUILD = -fprofile-generate=prof PGO_BUILD = @PGO_BUILD@ PGO= CFLAGS += $(PGO) .SUFFIXES: .c .$(OBJEXT) #======================================================================== # Start of user-definable TARGETS section #======================================================================== #======================================================================== # TEA TARGETS. Please note that the "libraries:" target refers to platform # independent files, and the "binaries:" target includes executable programs and # platform-dependent libraries. Modify these targets so that they install # the various pieces of your package. The make and install rules # for the BINARIES that you specified above have already been done. #======================================================================== all: binaries libraries doc #======================================================================== # The binaries target builds executable programs, Windows .dll's, unix # shared/static libraries, and any other platform-dependent files. # The list of targets to build for "binaries:" is specified at the top # of the Makefile, in the "BINARIES" variable. #======================================================================== binaries: $(BINARIES) libraries: #======================================================================== # Your doc target should differentiate from doc builds (by the developer) # and doc installs (see install-doc), which just install the docs on the # end user machine when building from source. #======================================================================== doc: doc/parse_args.n README.md doc/parse_args.n: doc/parse_args.md pandoc --standalone --from markdown --to man doc/parse_args.md --output doc/parse_args.n README.md: doc/parse_args.md pandoc --standalone --from markdown --to gfm doc/parse_args.md --output README.md sed --in-place 's/\/parse\\_args/\/parse_args/g' README.md install: all install-binaries install-libraries install-doc install-binaries: binaries install-lib-binaries install-bin-binaries #======================================================================== # This rule installs platform-independent files, such as header files. # The list=...; for p in $$list handles the empty list case x-platform. #======================================================================== install-libraries: libraries @$(INSTALL_DATA_DIR) "$(DESTDIR)$(includedir)" @echo "Installing header files in $(DESTDIR)$(includedir)" @list='$(PKG_HEADERS)'; for i in $$list; do \ echo "Installing $(srcdir)/$$i" ; \ $(INSTALL_DATA) $(srcdir)/$$i "$(DESTDIR)$(includedir)" ; \ done; #======================================================================== # Install documentation. Unix manpages should go in the $(mandir) # directory. #======================================================================== install-doc: doc @$(INSTALL_DATA_DIR) "$(DESTDIR)$(mandir)/mann" @echo "Installing documentation in $(DESTDIR)$(mandir)" @list='$(srcdir)/doc/*.n'; for i in $$list; do \ echo "Installing $$i"; \ $(INSTALL_DATA) $$i "$(DESTDIR)$(mandir)/mann" ; \ done test: binaries libraries $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ -load "apply {{} {set dir `@CYGPATH@ $(srcdir)`; source [file join `@CYGPATH@ $(srcdir)` $$dir pkgIndex.tcl]; package require -exact $(PACKAGE_NAME) $(PACKAGE_VERSION)}}" shell: binaries libraries @$(TCLSH) $(SCRIPT) vim-gdb: binaries libraries $(TCLSH_ENV) $(PKG_ENV) vim -c "set number" -c "set mouse=a" -c "set foldlevel=100" -c "Termdebug --args $(TCLSH_PROG) tests/all.tcl $(TESTFLAGS) -singleproc 1 -load apply\ {{}\ {set\ dir\ `@CYGPATH@ $(srcdir)`;\ source\ [file\ join\ `@CYGPATH@ $(srcdir)`\ $$dir\ pkgIndex.tcl];\ package\ require\ -exact\ $(PACKAGE_NAME)\ $(PACKAGE_VERSION)}}" generic/parse_args.c vim-core: $(TCLSH_ENV) $(PKG_ENV) vim -c 'packadd termdebug' -c "set mouse=a" -c "set number" -c "set foldlevel=100" -c "Termdebug -ex layout\ asm -ex layout\ regs -ex focus\ cmd $(TCLSH_PROG) core" -c Winbar generic/main.c vim-gdb-benchmark: binaries libraries $(TCLSH_ENV) $(PKG_ENV) vim -c "set number" -c "set mouse=a" -c "set foldlevel=100" -c "Termdebug --args $(TCLSH_PROG) bench/run.tcl $(TESTFLAGS) -load apply\ {{}\ {set\ dir\ `@CYGPATH@ $(srcdir)`;\ source\ [file\ join\ `@CYGPATH@ $(srcdir)`\ $$dir\ pkgIndex.tcl];\ package\ require\ -exact\ $(PACKAGE_NAME)\ $(PACKAGE_VERSION)}}" generic/parse_args.c gdb: $(TCLSH_ENV) $(PKG_ENV) $(GDB) $(TCLSH_PROG) $(SCRIPT) gdb-test: binaries libraries $(TCLSH_ENV) $(PKG_ENV) $(GDB) \ --args $(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` \ $(TESTFLAGS) -singleproc 1 \ -load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \ [list load `@CYGPATH@ $(PKG_LIB_FILE)` [string totitle $(PACKAGE_NAME)]]" valgrind: binaries libraries $(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) \ `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) valgrindshell: binaries libraries $(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT) depend: #======================================================================== # $(PKG_LIB_FILE) should be listed as part of the BINARIES variable # mentioned above. That will ensure that this target is built when you # run "make binaries". # # The $(PKG_OBJECTS) objects are created and linked into the final # library. In most cases these object files will correspond to the # source files above. #======================================================================== $(PKG_LIB_FILE): $(PKG_OBJECTS) -rm -f $(PKG_LIB_FILE) ${MAKE_LIB} $(RANLIB) $(PKG_LIB_FILE) $(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS) -rm -f $(PKG_STUB_LIB_FILE) ${MAKE_STUB_LIB} $(RANLIB_STUB) $(PKG_STUB_LIB_FILE) #======================================================================== # We need to enumerate the list of .c to .o lines here. # # In the following lines, $(srcdir) refers to the toplevel directory # containing your extension. If your sources are in a subdirectory, # you will have to modify the paths to reflect this: # # sample.$(OBJEXT): $(srcdir)/generic/sample.c # $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@ # # Setting the VPATH variable to a list of paths will cause the makefile # to look into these paths when resolving .c to .obj dependencies. # As necessary, add $(srcdir):$(srcdir)/compat:.... #======================================================================== VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx .c.@OBJEXT@: $(COMPILE) -c `@CYGPATH@ $<` -o $@ $(srcdir)/manifest.uuid: printf "git-" >$(srcdir)/manifest.uuid (cd $(srcdir); git rev-parse HEAD >>manifest.uuid || \ (printf "svn-r" >manifest.uuid ; \ svn info --show-item last-changed-revision >>manifest.uuid) || \ printf "unknown" >manifest.uuid) myExtensionUuid.h: $(srcdir)/manifest.uuid echo "#define MYEXTENSION_VERSION_UUID \\" >$@ cat $(srcdir)/manifest.uuid >>$@ echo "" >>$@ #======================================================================== # Distribution creation # You may need to tweak this target to make it work correctly. #======================================================================== #COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) DIST_ROOT = /tmp/dist DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) DIST_INSTALL_DATA = CPPROG='cp -p' $(INSTALL) -m 644 DIST_INSTALL_SCRIPT = CPPROG='cp -p' $(INSTALL) -m 755 dist-clean: rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* dist: dist-clean $(srcdir)/manifest.uuid $(INSTALL_DATA_DIR) $(DIST_DIR) # TEA files $(DIST_INSTALL_DATA) $(srcdir)/Makefile.in \ $(srcdir)/aclocal.m4 $(srcdir)/configure.ac \ $(DIST_DIR)/ $(DIST_INSTALL_SCRIPT) $(srcdir)/configure $(DIST_DIR)/ $(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig $(DIST_INSTALL_DATA) $(srcdir)/tclconfig/README.txt \ $(srcdir)/manifest.uuid \ $(srcdir)/tclconfig/tcl.m4 $(srcdir)/tclconfig/install-sh \ $(DIST_DIR)/tclconfig/ # Extension files $(DIST_INSTALL_DATA) \ $(srcdir)/ChangeLog \ $(srcdir)/README.sha \ $(srcdir)/license.terms \ $(srcdir)/README \ $(srcdir)/pkgIndex.tcl.in \ $(DIST_DIR)/ list='demos doc generic library macosx tests unix win'; \ for p in $$list; do \ if test -d $(srcdir)/$$p ; then \ $(INSTALL_DATA_DIR) $(DIST_DIR)/$$p; \ $(DIST_INSTALL_DATA) $(srcdir)/$$p/* $(DIST_DIR)/$$p/; \ fi; \ done (cd $(DIST_ROOT); $(COMPRESS);) #======================================================================== # End of user-definable section #======================================================================== #======================================================================== # Don't modify the file to clean here. Instead, set the "CLEANFILES" # variable in configure.ac #======================================================================== clean: -test -z "$(BINARIES)" || rm -f $(BINARIES) -rm -f *.$(OBJEXT) core *.core -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean: clean -rm -f *.tab.c -rm -f $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log config.status #======================================================================== # Install binary object libraries. On Windows this includes both .dll and # .lib files. Because the .lib files are not explicitly listed anywhere, # we need to deduce their existence from the .dll file of the same name. # Library files go into the lib directory. # In addition, this will generate the pkgIndex.tcl # file in the install location (assuming it can find a usable tclsh shell) # # You should not have to modify this target. #======================================================================== install-lib-binaries: binaries @$(INSTALL_DATA_DIR) "$(DESTDIR)$(pkglibdir)" @list='$(lib_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ $(INSTALL_LIBRARY) $$p "$(DESTDIR)$(pkglibdir)/$$p"; \ stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \ if test "x$$stub" = "xstub"; then \ echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \ $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \ else \ echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \ $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \ fi; \ ext=`echo $$p|sed -e "s/.*\.//"`; \ if test "x$$ext" = "xdll"; then \ lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ if test -f $$lib; then \ echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \ $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \ fi; \ fi; \ fi; \ done @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ if test -f $(srcdir)/$$p; then \ destp=`basename $$p`; \ echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \ $(INSTALL_DATA) $(srcdir)/$$p "$(DESTDIR)$(pkglibdir)/$$destp"; \ fi; \ done @if test "x$(SHARED_BUILD)" = "x1"; then \ echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \ $(INSTALL_DATA) pkgIndex.tcl "$(DESTDIR)$(pkglibdir)"; \ fi #======================================================================== # Install binary executables (e.g. .exe files and dependent .dll files) # This is for files that must go in the bin directory (located next to # wish and tclsh), like dependent .dll files on Windows. # # You should not have to modify this target, except to define bin_BINARIES # above if necessary. #======================================================================== install-bin-binaries: binaries @$(INSTALL_DATA_DIR) "$(DESTDIR)$(bindir)" @list='$(bin_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \ $(INSTALL_PROGRAM) $$p "$(DESTDIR)$(bindir)/$$p"; \ fi; \ done Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status uninstall-binaries: list='$(lib_BINARIES)'; for p in $$list; do \ rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \ done list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ p=`basename $$p`; \ rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \ done list='$(bin_BINARIES)'; for p in $$list; do \ rm -f "$(DESTDIR)$(bindir)/$$p"; \ done tags: ctags-exuberant generic/* .PHONY: all binaries clean depend distclean doc install libraries test .PHONY: gdb gdb-test valgrind valgrindshell tags .PHONY: vim-gdb vim-core vim-gdb-benchmark # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: parse_args-v0.6.3/tests/0000755000175100017510000000000015176457507014625 5ustar runnerrunnerparse_args-v0.6.3/tests/multi.test0000644000175100017510000001602615176457507016665 0ustar runnerrunnerif {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import ::tcltest::test } ::tcltest::loadTestedCommands test multi-1.1 {basic usage} -body { #<<< parse_args::parse_args {-dictionary} { -ascii {-multi -name compare_as} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} } set compare_as } -cleanup { unset -nocomplain compare_as } -result dictionary #>>> test multi-1.2 {no value, default on first} -body { #<<< parse_args::parse_args {} { -ascii {-multi -name compare_as -default foo} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} } set compare_as } -cleanup { unset -nocomplain compare_as } -result foo #>>> test multi-1.3 {no value, default on second} -body { #<<< parse_args::parse_args {} { -ascii {-multi -name compare_as} -dictionary {-multi -name compare_as -default foo} -integer {-multi -name compare_as} } set compare_as } -cleanup { unset -nocomplain compare_as } -result foo #>>> test multi-1.4 {no value, no default} -body { #<<< parse_args::parse_args {} { -ascii {-multi -name compare_as} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} } info exists compare_as } -cleanup { unset -nocomplain compare_as } -result 0 #>>> test multi-1.5 {no value, required on first} -body { #<<< set code [catch { parse_args::parse_args {} { -ascii {-multi -name compare_as -required} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {one of -ascii -dictionary -integer are required} {PARSE_ARGS REQUIRED_ONE_OF {-ascii -dictionary -integer}}} #>>> test multi-1.6 {no value, required on last} -body { #<<< set code [catch { parse_args::parse_args {} { -ascii {-multi -name compare_as} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as -required} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {one of -ascii -dictionary -integer are required} {PARSE_ARGS REQUIRED_ONE_OF {-ascii -dictionary -integer}}} #>>> test multi-1.7 {supplied value, default on first} -body { #<<< parse_args::parse_args {-dictionary} { -ascii {-multi -name compare_as -default foo} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} } set compare_as } -cleanup { unset -nocomplain compare_as } -result dictionary #>>> test multi-2.1 {throw error for -multi and -enum} -body { #<<< set code [catch { parse_args::parse_args {} { -ascii {-multi -name compare_as -enum {foo bar}} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as -required} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {Cannot use -multi and -enum together} NONE} #>>> test multi-2.2 {throw error for -multi and -boolean} -constraints knownBug -body { #<<< set code [catch { parse_args::parse_args {} { -ascii {-multi -name compare_as -boolean} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {Cannot use -multi and -boolean together} NONE} #>>> test multi-2.3 {throw error for -multi and -args} -constraints knownBug -body { #<<< set code [catch { parse_args::parse_args {} { -ascii {-multi -name compare_as -args 2} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {Cannot use -multi and -args together} NONE} #>>> test multi-3.1 {two -multis, both default} -body { #<<< parse_args::parse_args {} { -ascii {-multi -name compare_as -default ascii} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} -increasing {-multi -name order} -decreasing {-multi -name order -default increasing} } list $compare_as $order } -cleanup { unset -nocomplain compare_as order } -result {ascii increasing} #>>> test multi-3.2 {two -multis, first set, second default} -body { #<<< parse_args::parse_args {-dictionary} { -ascii {-multi -name compare_as -default ascii} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} -increasing {-multi -name order} -decreasing {-multi -name order -default increasing} } list $compare_as $order } -cleanup { unset -nocomplain compare_as order } -result {dictionary increasing} #>>> test multi-3.3 {two -multis, first default, second set} -body { #<<< parse_args::parse_args {-decreasing} { -ascii {-multi -name compare_as -default ascii} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} -increasing {-multi -name order} -decreasing {-multi -name order -default increasing} } list $compare_as $order } -cleanup { unset -nocomplain compare_as order } -result {ascii decreasing} #>>> test multi-4.1 {two -multis, both required, neither set} -body { #<<< list [catch { parse_args::parse_args {} { -ascii {-multi -name compare_as -required} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} -increasing {-multi -name order -required} -decreasing {-multi -name order} } } r o] $r [dict get $o -errorcode] } -cleanup { unset -nocomplain r o compare_as order } -result [list 1 "one of -ascii -dictionary -integer are required" {PARSE_ARGS REQUIRED_ONE_OF {-ascii -dictionary -integer}}] #>>> test multi-4.2 {two -multis, first set, second missing} -body { #<<< list [catch { parse_args::parse_args {-dictionary} { -ascii {-multi -name compare_as -required} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} -increasing {-multi -name order -required} -decreasing {-multi -name order} } } r o] $r [dict get $o -errorcode] } -cleanup { unset -nocomplain r o compare_as order } -result [list 1 "one of -increasing -decreasing are required" {PARSE_ARGS REQUIRED_ONE_OF {-increasing -decreasing}}] #>>> test multi-4.3 {two -multis, first missing, second set} -body { #<<< list [catch { parse_args::parse_args {-decreasing} { -ascii {-multi -name compare_as -required} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} -increasing {-multi -name order -required} -decreasing {-multi -name order} } } r o] $r [dict get $o -errorcode] } -cleanup { unset -nocomplain r o compare_as order } -result [list 1 "one of -ascii -dictionary -integer are required" {PARSE_ARGS REQUIRED_ONE_OF {-ascii -dictionary -integer}}] #>>> test multi-5.1 {throw error for -multi on positional param} -body { #<<< list [catch { parse_args::parse_args {} { foo {-multi -name compare_as} } } r o] $r [dict get $o -errorcode] } -cleanup { unset -nocomplain r o compare_as order } -result [list 1 {Cannot use -multi on positional argument "foo"} NONE] #>>> # cleanup ::tcltest::cleanupTests return # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 parse_args-v0.6.3/tests/validate.test0000644000175100017510000000711215176457507017320 0ustar runnerrunnerif {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import ::tcltest::test } ::tcltest::loadTestedCommands # Options test validate-1.1 {basic usage, valid} -body { #<<< parse_args::parse_args {-rating 1.2} { -rating {-validate {string is double -strict}} } set rating } -cleanup { unset -nocomplain rating } -result 1.2 #>>> test validate-1.2 {basic usage, invalid} -body { #<<< list [catch { parse_args::parse_args {-rating x1.2} { -rating {-validate {string is double -strict}} } } r o] $r [dict get $o -errorcode] } -cleanup { unset -nocomplain r o } -result {1 {Validation failed for "-rating": 0} {PARSE_ARGS VALIDATION -rating}} #>>> test validate-1.3 {basic usage, blank} -body { #<<< list [catch { parse_args::parse_args {-rating ""} { -rating {-validate {string is double -strict}} } } r o] $r [dict get $o -errorcode] } -cleanup { unset -nocomplain r o } -result {1 {Validation failed for "-rating": 0} {PARSE_ARGS VALIDATION -rating}} #>>> test validate-1.4 {basic usage, missing} -body { #<<< parse_args::parse_args {} { -rating {-validate {string is double -strict}} } info exists rating } -cleanup { unset -nocomplain rating } -result 0 #>>> test validate-2.1 {validator throws error} -body { #<<< parse_args::parse_args {-rating 0} { -rating {-validate {tcl::mathop::+ 1}} } set rating } -cleanup { unset -nocomplain rating } -result 0 #>>> test validate-2.2 {validator throws error} -body { #<<< parse_args::parse_args {-rating ""} { -rating {-validate {tcl::mathop::+ 1}} } } -returnCodes error -errorCode {PARSE_ARGS VALIDATION -rating} -match regexp -result {^Validation failed for "-rating": (cannot|can't) use (non-numeric|empty) string( "")? as (right )?operand of "\+"$} #>>> test validate-3.1 {validator with apply, throws error} -body { #<<< list [catch { parse_args::parse_args {-rating ""} { -rating {-validate {apply { val { if {[string length $val] < 3} { error "Must be at least 3 characters long" } return 1 } } }} } } r o] $r [dict get $o -errorcode] } -cleanup { unset -nocomplain r o } -result {1 {Validation failed for "-rating": Must be at least 3 characters long} {PARSE_ARGS VALIDATION -rating}} #>>> test validate-3.2 {validator with apply, returns blank} -body { #<<< parse_args::parse_args {-rating foo} { -rating {-validate {apply { val { if {[string length $val] < 3} { error "Must be at least 3 characters long" } return "" } } }} } set rating } -cleanup { unset -nocomplain rating } -result foo #>>> test validate-3.3 {validator with apply, throws error} -body { #<<< list [catch { parse_args::parse_args {-rating ""} { -rating {-validate {apply { val { if {[string length $val] < 3} { return "Must be at least 3 characters long" } } } }} } } r o] $r [dict get $o -errorcode] } -cleanup { unset -nocomplain r o } -result {1 {Validation failed for "-rating": Must be at least 3 characters long} {PARSE_ARGS VALIDATION -rating}} #>>> test validate-3.4 {blank validator} -body { #<<< parse_args::parse_args {-rating foo} { -rating {-validate {}} } set rating } -cleanup { unset -nocomplain rating } -result foo #>>> test validate-3.5 {local vars} -body { #<<< set ref foo parse_args::parse_args {-rating foo} { -rating {-validate {apply { val { upvar 1 ref ref expr {$val eq $ref} } }}} } set rating } -cleanup { unset -nocomplain rating } -result foo #>>> # Positional params # cleanup ::tcltest::cleanupTests return # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 parse_args-v0.6.3/tests/alias.test0000644000175100017510000001574315176457507016631 0ustar runnerrunnerif {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import ::tcltest::test } ::tcltest::loadTestedCommands # Options test alias-1.1 {alias scalar, option, exists} -setup { #<<< set target alias-1.1-testval } -body { list {*}[apply {args { parse_args::parse_args $args { -aliased {-alias -required} } set existed [info exists aliased] set was $aliased append aliased -updated list $existed $was }} -aliased target] $target } -cleanup { unset -nocomplain target } -result {1 alias-1.1-testval alias-1.1-testval-updated} #>>> test alias-1.2 {alias scalar, option, doesn't exist} -setup { #<<< unset -nocomplain target } -body { list [info exists target] {*}[apply {args { parse_args::parse_args $args { -aliased {-alias -required} } list [info exists aliased] [set aliased alias-1.2-testval] }} -aliased target] $target } -cleanup { unset -nocomplain target } -result {0 0 alias-1.2-testval alias-1.2-testval} #>>> test alias-2.1 {alias array, option, exists} -setup { #<<< array set target {foo alias-2.1-testval} } -body { list {*}[apply {args { parse_args::parse_args $args { -aliased {-alias -required} } set existed [info exists aliased(foo)] set was $aliased(foo) append aliased(foo) -updated list $existed $was }} -aliased target] $target(foo) } -cleanup { unset -nocomplain target } -result {1 alias-2.1-testval alias-2.1-testval-updated} #>>> test alias-2.2 {alias array, option, doesn't exist} -setup { #<<< unset -nocomplain target } -body { list [info exists target] {*}[apply {args { parse_args::parse_args $args { -aliased {-alias -required} } list [info exists aliased] [set aliased(foo) alias-2.2-testval] }} -aliased target] $target(foo) } -cleanup { unset -nocomplain target } -result {0 0 alias-2.2-testval alias-2.2-testval} #>>> test alias-3.1 {alias array element, option, exists} -setup { #<<< array set target {foo alias-3.1-testval} } -body { list {*}[apply {args { parse_args::parse_args $args { -aliased {-alias -required} } set existed [info exists aliased] set was $aliased append aliased -updated list $existed $was }} -aliased target(foo)] $target(foo) } -cleanup { unset -nocomplain target } -result {1 alias-3.1-testval alias-3.1-testval-updated} #>>> test alias-3.2 {alias array element, option, doesn't exist} -setup { #<<< unset -nocomplain target } -body { list [info exists target(foo)] {*}[apply {args { parse_args::parse_args $args { -aliased {-alias -required} } list [info exists aliased] [set aliased alias-3.2-testval] }} -aliased target(foo)] $target(foo) } -cleanup { unset -nocomplain target } -result {0 0 alias-3.2-testval alias-3.2-testval} #>>> test alias-4.1 {default handling, option, supplied, exists} -setup { #<<< set target alias-4.1-testval } -body { list {*}[apply {args { parse_args::parse_args $args { -aliased {-alias -default alias-4.1-default} } set was $aliased append aliased -updated list [info exists aliased] $was }} -aliased target] $target } -cleanup { unset -nocomplain target } -result {1 alias-4.1-testval alias-4.1-testval-updated} #>>> test alias-4.2 {default handling, option, not supplied, exists} -setup { #<<< set target alias-4.2-testval } -body { list {*}[apply {args { parse_args::parse_args $args { -aliased {-alias -default alias-4.2-default} } set was $aliased append aliased -updated list [info exists aliased] $was }}] $target } -cleanup { unset -nocomplain target } -result {1 alias-4.2-default alias-4.2-testval} #>>> # Positional params test alias-11.1 {alias scalar, positional, exists} -setup { #<<< set target alias-11.1-testval } -body { list {*}[apply {args { parse_args::parse_args $args { aliased {-alias -required} } set existed [info exists aliased] set was $aliased append aliased -updated list $existed $was }} target] $target } -cleanup { unset -nocomplain target } -result {1 alias-11.1-testval alias-11.1-testval-updated} #>>> test alias-11.2 {alias scalar, positional, doesn't exist} -setup { #<<< unset -nocomplain target } -body { list [info exists target] {*}[apply {args { parse_args::parse_args $args { aliased {-alias -required} } list [info exists aliased] [set aliased alias-11.2-testval] }} target] $target } -cleanup { unset -nocomplain target } -result {0 0 alias-11.2-testval alias-11.2-testval} #>>> test alias-12.1 {alias array, positional, exists} -setup { #<<< array set target {foo alias-12.1-testval} } -body { list {*}[apply {args { parse_args::parse_args $args { aliased {-alias -required} } set existed [info exists aliased(foo)] set was $aliased(foo) append aliased(foo) -updated list $existed $was }} target] $target(foo) } -cleanup { unset -nocomplain target } -result {1 alias-12.1-testval alias-12.1-testval-updated} #>>> test alias-12.2 {alias array, positional, doesn't exist} -setup { #<<< unset -nocomplain target } -body { list [info exists target] {*}[apply {args { parse_args::parse_args $args { aliased {-alias -required} } list [info exists aliased] [set aliased(foo) alias-12.2-testval] }} target] $target(foo) } -cleanup { unset -nocomplain target } -result {0 0 alias-12.2-testval alias-12.2-testval} #>>> test alias-13.1 {alias array element, positional, exists} -setup { #<<< array set target {foo alias-13.1-testval} } -body { list {*}[apply {args { parse_args::parse_args $args { aliased {-alias -required} } set existed [info exists aliased] set was $aliased append aliased -updated list $existed $was }} target(foo)] $target(foo) } -cleanup { unset -nocomplain target } -result {1 alias-13.1-testval alias-13.1-testval-updated} #>>> test alias-13.2 {alias array element, positional, doesn't exist} -setup { #<<< unset -nocomplain target } -body { list [info exists target(foo)] {*}[apply {args { parse_args::parse_args $args { aliased {-alias -required} } list [info exists aliased] [set aliased alias-13.2-testval] }} target(foo)] $target(foo) } -cleanup { unset -nocomplain target } -result {0 0 alias-13.2-testval alias-13.2-testval} #>>> test alias-14.1 {default handling, positional, supplied, exists} -setup { #<<< set target alias-14.1-testval } -body { list {*}[apply {args { parse_args::parse_args $args { aliased {-alias -default alias-14.1-default} } set was $aliased append aliased -updated list [info exists aliased] $was }} target] $target } -cleanup { unset -nocomplain target } -result {1 alias-14.1-testval alias-14.1-testval-updated} #>>> test alias-14.2 {default handling, option, not supplied, exists} -setup { #<<< set target alias-14.2-testval } -body { list {*}[apply {args { parse_args::parse_args $args { aliased {-alias -default alias-14.2-default} } set was $aliased append aliased -updated list [info exists aliased] $was }}] $target } -cleanup { unset -nocomplain target } -result {1 alias-14.2-default alias-14.2-testval} #>>> # cleanup ::tcltest::cleanupTests return # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 parse_args-v0.6.3/tests/enum.test0000644000175100017510000001400315176457507016470 0ustar runnerrunnerif {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import ::tcltest::test } ::tcltest::loadTestedCommands # Options test enum-1.1 {basic usage} -body { #<<< parse_args::parse_args {-state disabled} { -state {-enum {normal disabled readonly}} } set state } -cleanup { unset -nocomplain state } -result disabled #>>> test enum-2.1 {invalid value} -body { #<<< set code [catch { parse_args::parse_args {-state new} { -state {-enum {normal disabled readonly}} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {bad -state "new": must be normal, disabled, or readonly} {TCL LOOKUP INDEX -state new}} #>>> test enum-3.1 {valid value, with default} -body { #<<< parse_args::parse_args {-state disabled} { -state {-enum {normal disabled readonly} -default normal} } set state } -cleanup { unset -nocomplain state } -result disabled #>>> test enum-3.2 {no value, with default} -body { #<<< parse_args::parse_args {} { -state {-enum {normal disabled readonly} -default normal} } set state } -cleanup { unset -nocomplain state } -result normal #>>> test enum-3.3 {no value, with invalid default} -body { #<<< parse_args::parse_args {} { -state {-enum {normal disabled readonly} -default new} } set state } -cleanup { unset -nocomplain state } -result new #>>> test enum-4.3 {no value, required, with default} -body { #<<< parse_args::parse_args {} { -state {-enum {normal disabled readonly} -default normal -required} } set state } -cleanup { unset -nocomplain state } -result normal #>>> test enum-4.4 {no value, required, no default} -body { #<<< set code [catch { parse_args::parse_args {} { -state {-enum {normal disabled readonly} -required} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain state } -result {1 {option -state is required} {PARSE_ARGS REQUIRED -state}} #>>> test enum-5.1 {specified twice, both valid} -body { #<<< parse_args::parse_args {-state disabled -state readonly} { -state {-enum {normal disabled readonly}} } set state } -cleanup { unset -nocomplain state } -result readonly #>>> test enum-5.2 {specified twice, first invalid} -body { #<<< set code [catch { parse_args::parse_args {-state new -state readonly} { -state {-enum {normal disabled readonly}} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {bad -state "new": must be normal, disabled, or readonly} {TCL LOOKUP INDEX -state new}} #>>> test enum-5.3 {specified twice, second invalid} -body { #<<< set code [catch { parse_args::parse_args {-state readonly -state new} { -state {-enum {normal disabled readonly}} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {bad -state "new": must be normal, disabled, or readonly} {TCL LOOKUP INDEX -state new}} #>>> test enum-6.1 {two enums} -body { #<<< parse_args::parse_args {-state disabled -validate focusout} { -state {-enum {normal disabled readonly}} -validate {-enum {none focus focusin focusout key all}} } list $state $validate } -cleanup { unset -nocomplain state validate } -result {disabled focusout} #>>> test enum-6.2 {prefix values} -body { #<<< set code [catch { parse_args::parse_args {-state d} { -state {-enum {normal disabled readonly}} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {bad -state "d": must be normal, disabled, or readonly} {TCL LOOKUP INDEX -state d}} #>>> # Positional params test enum-11.1 {basic usage} -body { #<<< parse_args::parse_args disabled { state {-enum {normal disabled readonly}} } set state } -cleanup { unset -nocomplain state } -result disabled #>>> test enum-12.1 {invalid value} -body { #<<< set code [catch { parse_args::parse_args new { state {-enum {normal disabled readonly}} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {bad state "new": must be normal, disabled, or readonly} {TCL LOOKUP INDEX state new}} #>>> test enum-13.1 {valid value, with default} -body { #<<< parse_args::parse_args disabled { state {-enum {normal disabled readonly} -default normal} } set state } -cleanup { unset -nocomplain state } -result disabled #>>> test enum-13.2 {no value, with default} -body { #<<< parse_args::parse_args {} { state {-enum {normal disabled readonly} -default normal} } set state } -cleanup { unset -nocomplain state } -result normal #>>> test enum-13.3 {no value, with invalid default} -body { #<<< parse_args::parse_args {} { state {-enum {normal disabled readonly} -default new} } set state } -cleanup { unset -nocomplain state } -result new #>>> test enum-14.3 {no value, required, with default} -body { #<<< parse_args::parse_args {} { state {-enum {normal disabled readonly} -default normal -required} } set state } -cleanup { unset -nocomplain state } -result normal #>>> test enum-14.4 {no value, required, no default} -body { #<<< set code [catch { parse_args::parse_args {} { state {-enum {normal disabled readonly} -required} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain state } -result {1 {argument state is required} {PARSE_ARGS REQUIRED state}} #>>> test enum-16.1 {two enums} -body { #<<< parse_args::parse_args {disabled focusout} { state {-enum {normal disabled readonly}} validate {-enum {none focus focusin focusout key all}} } list $state $validate } -cleanup { unset -nocomplain state validate } -result {disabled focusout} #>>> test enum-16.2 {prefix values} -body { #<<< set code [catch { parse_args::parse_args d { state {-enum {normal disabled readonly}} } } r o] list $code $r [dict get $o -errorcode] } -cleanup { unset -nocomplain code state r o } -result {1 {bad state "d": must be normal, disabled, or readonly} {TCL LOOKUP INDEX state d}} #>>> # cleanup ::tcltest::cleanupTests return # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 parse_args-v0.6.3/tests/all.tcl0000644000175100017510000000356015176457507016105 0ustar runnerrunner# all.tcl -- # # This file contains a top-level script to run all of the Tcl # tests. Execute it by invoking "source all.test" when running tcltest # in this directory. # # Copyright (c) 1998-2000 by Scriptics Corporation. # All rights reserved. if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import ::tcltest::* } set ::tcltest::testSingleFile false set ::tcltest::testsDirectory [file dir [info script]] # We need to ensure that the testsDirectory is absolute if {[catch {::tcltest::normalizePath ::tcltest::testsDirectory}]} { # The version of tcltest we have here does not support # 'normalizePath', so we have to do this on our own. set oldpwd [pwd] catch {cd $::tcltest::testsDirectory} set ::tcltest::testsDirectory [pwd] cd $oldpwd } set chan $::tcltest::outputChannel puts $chan "Tests running in interp: [info nameofexecutable]" puts $chan "Tests running with pwd: [pwd]" puts $chan "Tests running in working dir: $::tcltest::testsDirectory" if {[llength $::tcltest::skip] > 0} { puts $chan "Skipping tests that match: $::tcltest::skip" } if {[llength $::tcltest::match] > 0} { puts $chan "Only running tests that match: $::tcltest::match" } if {[llength $::tcltest::skipFiles] > 0} { puts $chan "Skipping test files that match: $::tcltest::skipFiles" } if {[llength $::tcltest::matchFiles] > 0} { puts $chan "Only sourcing test files that match: $::tcltest::matchFiles" } set timeCmd {clock format [clock seconds]} puts $chan "Tests began at [eval $timeCmd]" # source each of the specified tests foreach file [lsort [::tcltest::getMatchingFiles]] { set tail [file tail $file] puts $chan $tail if {[catch {source $file} msg]} { puts $chan $msg } } # cleanup puts $chan "\nTests ended at [eval $timeCmd]" ::tcltest::cleanupTests 1 return parse_args-v0.6.3/tests/parse_args.test0000644000175100017510000002177415176457507017667 0ustar runnerrunnerif {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import ::tcltest::test } ::tcltest::loadTestedCommands test parse_args-1.1 {no args, dict mode} -body { #<<< parse_args::parse_args {} {} d set d } -cleanup { unset -nocomplain d } -result {} #>>> test parse_args-1.2 {no args, vars mode} -body { #<<< parse_args::parse_args {} {} } -result {} #>>> test parse_args-2.1 {basic option, dict mode} -body { #<<< parse_args::parse_args {-foo bar} {-foo {}} d set d } -cleanup { unset -nocomplain d } -result {foo bar} #>>> test parse_args-2.2 {basic option, vars mode} -body { #<<< parse_args::parse_args {-foo bar} {-foo {}} set foo } -cleanup { unset -nocomplain foo } -result bar #>>> test parse_args-3.2 {option escape} -body { #<<< parse_args::parse_args {-foo bar -- -baz quux} { -foo {} -bar {} -baz {-default def} a {} b {} } list $foo [info exists bar] $baz $a $b } -cleanup { unset -nocomplain foo bar baz a b } -result {bar 0 def -baz quux} #>>> test parse_args-3.3 {default positional arg} -body { #<<< parse_args::parse_args {a b} { -foo {} first {} second {-default default_second} third {-default default_third} } list $first $second $third } -cleanup { unset -nocomplain foo first second third } -result {a b default_third} #>>> test parse_args-4.1 {-all} -body { #<<< parse_args::parse_args {-ex first -foo a -iex First -ex second -iex Second -ex third -foo b} { -ex {-all} -iex {-all} -foo {} } list $ex $iex $foo } -cleanup { unset -nocomplain ex iex foo } -result {{first second third} {First Second} b} #>>> test parse_args-4.2 {-all -multi} -body { #<<< parse_args::parse_args {-ascii -dictionary -ascii -increasing -decreasing} { -ascii {-multi -name mode -all} -dictionary {-multi -name mode} -increasing {-multi -name order} -decreasing {-multi -name order -all} } list $mode $order } -cleanup { unset -nocomplain mode order } -result {{ascii dictionary ascii} {increasing decreasing}} #>>> test parse_args-4.3 {-all} -body { #<<< parse_args::parse_args {-foo "hello, multi"} { -foo {-all} } set foo } -cleanup { unset -nocomplain foo } -result {{hello, multi}} #>>> test parse_args-4.4 {-all, omitted, default} -body { #<<< parse_args::parse_args {} { -foo {-all -default {}} } set foo } -cleanup { unset -nocomplain foo } -result {} #>>> test parse_args-10.1 {reject negative -args} -body { #<<< parse_args::parse_args {-foo bar} { -foo {-args -1} } set foo } -cleanup { unset -nocomplain foo } -returnCodes error -result {-args cannot be negative} #>>> test parse_args-10.2 {-args 0, supplied} -body { #<<< parse_args::parse_args {-foo} { -foo {-args 0} } set foo } -cleanup { unset -nocomplain foo } -result 1 #>>> test parse_args-10.3 {-args 0, omitted} -body { #<<< parse_args::parse_args {-bar ""} { -foo {-args 0} -bar {} } set foo } -cleanup { unset -nocomplain foo bar } -result 0 #>>> test parse_args-10.4 {-args 3, enough} -body { #<<< parse_args::parse_args {-foo a "b c" d e f g h i j} { -foo {-args 3} -bar {} p1 {} p2 {} args {} } list $foo $p1 $p2 $args } -cleanup { unset -nocomplain foo bar args } -result [list [list a "b c" d] e f {g h i j}] #>>> test parse_args-10.5 {-args 3, too few} -body { #<<< parse_args::parse_args {-foo a "b c"} { -foo {-args 3} -bar {} } } -cleanup { unset -nocomplain foo bar } -returnCodes error -match glob -result * #>>> test parse_args-10.6 {-args all, omitted, no default} -body { #<<< parse_args::parse_args {-bar ""} { -foo {-args all} -bar {} } info exists foo } -cleanup { unset -nocomplain foo bar } -result 0 #>>> test parse_args-10.7 {-args all, omitted, default} -body { #<<< parse_args::parse_args {-bar ""} { -foo {-args all -default {foo bar}} -bar {} } set foo } -cleanup { unset -nocomplain foo bar } -result {foo bar} #>>> test parse_args-10.8 {-args all, omitted, required} -body { #<<< parse_args::parse_args {-bar ""} { -foo {-args all -required} -bar {} } } -cleanup { unset -nocomplain foo bar } -returnCodes error -errorCode {PARSE_ARGS REQUIRED -foo} -result {option -foo is required} #>>> test parse_args-10.9 {-args all, 0 supplied, default} -body { #<<< parse_args::parse_args {-bar "" -foo} { -foo {-args all -default {foo bar}} -bar {} } set foo } -cleanup { unset -nocomplain foo bar } -result {} #>>> test parse_args-10.10 {-args all, 1 supplied, default} -body { #<<< parse_args::parse_args {-bar "" -foo "hello, world"} { -foo {-args all -default {foo bar}} -bar {} } set foo } -cleanup { unset -nocomplain foo bar } -result {{hello, world}} #>>> test parse_args-10.11 {-args all, 4 supplied, required} -body { #<<< parse_args::parse_args {-bar "" -foo "hello, world" x y z} { -foo {-args all -required} -bar {} } set foo } -cleanup { unset -nocomplain foo bar } -result {{hello, world} x y z} #>>> test parse_args-10.12 {-args all, 4 supplied, looks like option} -body { #<<< parse_args::parse_args {-foo "hello, world" -bar "" z} { -foo {-args all} -bar {} } list [info exists bar] $foo } -cleanup { unset -nocomplain foo bar } -result {0 {{hello, world} -bar {} z}} #>>> test parse_args-10.13 {-args 3, positional, supplied} -body { #<<< parse_args::parse_args {a b c d e} { foo {-required} bar {-args 3 -required} baz {-required} } list $foo $bar $baz } -cleanup { unset -nocomplain foo bar baz } -result {a {b c d} e} #>>> test parse_args-10.14 {-args 3, positional, omitted, required} -body { #<<< parse_args::parse_args {a} { foo {-required} bar {-args 3 -required} } } -cleanup { unset -nocomplain foo bar } -returnCodes error -errorCode {PARSE_ARGS REQUIRED bar} -result {argument bar is required} #>>> test parse_args-10.15 {-args 3, positional, omitted, optional} -body { #<<< parse_args::parse_args {a} { foo {-required} bar {-args 3} } list [info exists foo] [info exists bar] } -cleanup { unset -nocomplain foo bar } -result {1 0} #>>> test parse_args-10.16 {-args 3, positional, omitted, default} -body { #<<< parse_args::parse_args {a} { foo {-required} bar {-args 3 -default {x y z}} } list $foo $bar } -cleanup { unset -nocomplain foo bar } -result {a {x y z}} #>>> test parse_args-10.17 {-args 3, positional, insufficient, required} -body { #<<< parse_args::parse_args {a b c} { foo {-required} bar {-args 3 -required} } } -cleanup { unset -nocomplain foo bar } -returnCodes error -errorCode {PARSE_ARGS WRONGARGS bar} -result {Expecting 3 arguments for bar} #>>> test parse_args-10.18 {-args 3, positional, insufficient, optional} -body { #<<< parse_args::parse_args {a b c} { foo {-required} bar {-args 3} } } -cleanup { unset -nocomplain foo bar } -returnCodes error -errorCode {PARSE_ARGS WRONGARGS bar} -result {Expecting 3 arguments for bar} #>>> test parse_args-10.18 {-args 3, positional, insufficient, default} -body { #<<< parse_args::parse_args {a b c} { foo {-required} bar {-args 3 -default {x y z}} } } -cleanup { unset -nocomplain foo bar } -returnCodes error -errorCode {PARSE_ARGS WRONGARGS bar} -result {Expecting 3 arguments for bar} #>>> test parse_args-11.1 {invalid setting} -body { #<<< parse_args::parse_args {} { -foo {-foo 3} -bar {} } } -cleanup { unset -nocomplain foo bar } -returnCodes error -result {bad setting "-foo": must be -default, -required, -validate, -name, -boolean, -args, -enum, -#, -multi, -alias, -all, or -end} #>>> test parse_args-12.1 {-end, -boolean, supplied} -body { #<<< parse_args::parse_args {-ex a --args -ex e c d} { -ex {-all -default {}} --args {-name se_args -boolean -end} first {} second {} rest {-args all} } list $ex $se_args $first $second $rest } -cleanup { unset -nocomplain ex se_args first second rest } -result {a 1 -ex e {c d}} #>>> test parse_args-12.2 {-end, -boolean, omitted} -body { #<<< parse_args::parse_args {-ex a -ex e c d} { -ex {-all -default {}} --args {-name se_args -boolean -end} first {} second {} rest {-args all} } list $ex $se_args $first $second [info exists rest] } -cleanup { unset -nocomplain ex se_args first second rest } -result {{a e} 0 c d 0} #>>> test parse_args-20.1 {no args} -body { #<<< parse_args::parse_args } -returnCodes error -result {wrong # args: should be "parse_args::parse_args args args_spec ?dict?"} #>>> test parse_args-30.1 {Doesn't generate string rep} -constraints knownBug -body { # Known to fail currently - it's an still open problem to find a way to avoid this <<< set i [expr {2-1}] parse_args::parse_args [list $i] { foo {} } tcl::unsupported::representation $i } -cleanup { unset -nocomplain i foo } -match glob -result {value is a int * no string representation} #>>> test parse_args-40.1 {namespace import} -body { #<<< set interp [interp create] $interp eval { load {} Parse_args namespace import ::parse_args::* parse_args {-foo foo-parse_args-40.1} { -foo {-default x} } set foo } } -cleanup { interp delete $interp unset -nocomplain interp } -result foo-parse_args-40.1 #>>> # cleanup ::tcltest::cleanupTests return # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 parse_args-v0.6.3/tests/comment.test0000644000175100017510000000135315176457507017172 0ustar runnerrunnerif {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import ::tcltest::test } ::tcltest::loadTestedCommands # Options test comment-1.1 {basic usage} -body { #<<< parse_args::parse_args {-state disabled} { -state {-enum {normal disabled readonly} -# {This is a comment}} } set state } -cleanup { unset -nocomplain state } -result disabled #>>> # Positional params test comment-2.1 {basic usage} -body { #<<< parse_args::parse_args disabled { state {-enum {normal disabled readonly} -# {This is a comment}} } set state } -cleanup { unset -nocomplain state } -result disabled #>>> # cleanup ::tcltest::cleanupTests return # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 parse_args-v0.6.3/tests/safeinterp.test0000644000175100017510000000206515176457507017671 0ustar runnerrunnerif {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import ::tcltest::test } ::tcltest::loadTestedCommands test safeinterp-1.1 {Loading into safe interp} -setup { #<<< set slave [interp create -safe] } -body { $slave invokehidden load {} Parse_args $slave eval { parse_args::parse_args {-test foo-1.1} { -test {-required} } set test } } -cleanup { if {[info exists slave]} { interp delete $slave unset slave } } -result foo-1.1 #>>> test safeinterp-1.2 {Loading into safe interp using package require} -setup { #<<< set slave [safe::interpCreate] } -body { $slave eval [list set ::auto_path [list [file normalize [file join [info script] .. ..]] {*}$::auto_path]] $slave eval { package require parse_args parse_args::parse_args {-test foo-1.2} { -test {-required} } set test } } -cleanup { if {[info exists slave]} { safe::interpDelete $slave unset slave } } -result foo-1.2 #>>> # cleanup ::tcltest::cleanupTests return # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 parse_args-v0.6.3/pkgIndex.tcl.in0000644000175100017510000000024115176457507016342 0ustar runnerrunner# # Tcl package index file # package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ \ [list load [file join $dir @PKG_LIB_FILE@] [string totitle @PACKAGE_NAME@]] parse_args-v0.6.3/library/0000755000175100017510000000000015176457507015127 5ustar runnerrunnerparse_args-v0.6.3/library/parse_args.tcl0000644000175100017510000000000015176457507017747 0ustar runnerrunnerparse_args-v0.6.3/teabase/0000755000175100017510000000000015176457625015070 5ustar runnerrunnerparse_args-v0.6.3/teabase/dbench.tcl0000755000175100017510000000142615176457507017024 0ustar runnerrunner#!/usr/local/bin/tclsh file mkdir /tmp/build cd /tmp/build foreach file [glob -nocomplain /src/local/*] { set fqfn [file join /src/local $file] if {[file exists $fqfn]} { exec cp -a $fqfn . } } exec -ignorestderr autoconf >@ stdout # Without --enable-symbols, tcl.m4 hard codes the flags in tclConfig.sh's CFLAGS_OPTIMIZE /after/ any value we can configure exec -ignorestderr ./configure --enable-symbols {*}[lindex $argv 1] --with-tcl=/usr/local/lib --enable-testmode >@ stdout file delete -- {*}[glob -nocomplain tools/bin/*] switch -- [lindex $argv 2] { pgo { exec -ignorestderr make clean pgo >@ stdout exec -ignorestderr make benchmark BENCHFLAGS=[lindex $argv 0] >@ stdout } default { exec -ignorestderr make clean benchmark BENCHFLAGS=[lindex $argv 0] >@ stdout } } parse_args-v0.6.3/teabase/polyfill.h0000644000175100017510000000075115176457507017075 0ustar runnerrunner#ifndef POLYFILL #define POLYFILL #ifndef Tcl_DStringToObj static Tcl_Obj* Tcl_DStringToObj(Tcl_DString* ds) { Tcl_Obj* res = NULL; if (ds->string == ds->staticSpace) { return ds->length ? Tcl_NewStringObj(ds->string, ds->length) : Tcl_NewObj(); } else { res = Tcl_NewObj(); res->bytes = ds->string; res->length = ds->length; } ds->string = ds->staticSpace; ds->spaceAvl = TCL_DSTRING_STATIC_SIZE; ds->length = 0; ds->staticSpace[0] = 0; return res; } #endif #endif parse_args-v0.6.3/teabase/Makefile.in0000644000175100017510000000571615176457507017145 0ustar runnerrunnerVALGRINDEXTRA = VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \ --leak-check=yes -v --suppressions=suppressions --keep-debuginfo=yes \ --trace-children=yes --error-exitcode=2 $(VALGRINDEXTRA) PGOGEN_BUILD = -fprofile-generate=prof PGO_BUILD = @PGO_BUILD@ PGO= CFLAGS += $(PGO) CONFIGUREFLAGS = {CFLAGS=-O3 -flto -march=native} PACKAGE_LOAD = "apply {dir {source [file join \$$dir pkgIndex.tcl]; package require -exact $(PACKAGE_NAME) $(PACKAGE_VERSION)}} `@CYGPATH@ $(top_builddir)`" PACKAGE_LOAD_EMBED = apply\ {dir\ {source\ [file\ join\ \$$dir\ pkgIndex.tcl];\ package\ require\ -exact\ $(PACKAGE_NAME)\ $(PACKAGE_VERSION)}}\ `@CYGPATH@\ $(top_builddir)` CONTAINER = cyanogilvie/alpine-tcl:v0.9.118-gdb benchmark: binaries libraries $(TCLSH) `@CYGPATH@ $(srcdir)/bench/run.tcl` $(BENCHFLAGS) -load $(PACKAGE_LOAD) tags: generic/* ctags-exuberant --langmap=c:+.re generic/* vim-core: $(TCLSH_ENV) $(PKG_ENV) vim -c 'packadd termdebug' -c "set mouse=a" -c "set number" -c "set foldlevel=100" -c "Termdebug $(TCLSH_PROG) core" -c Winbar generic/ vim-gdb: binaries libraries $(TCLSH_ENV) $(PKG_ENV) vim -c "set number" -c "set mouse=a" -c "set foldlevel=100" -c "Termdebug -ex set\ print\ pretty\ on --args $(TCLSH_PROG) tests/all.tcl -singleproc 1 -load $(PACKAGE_LOAD_EMBED) $(TESTFLAGS)" -c "2windo set nonumber" -c "1windo set nonumber" vim-benchmark-gdb: binaries libraries $(TCLSH_ENV) $(PKG_ENV) vim -c "set number" -c "set mouse=a" -c "set foldlevel=100" -c "Termdebug -ex set\ print\ pretty\ on --args $(TCLSH_PROG) bench/run.tcl -load $(PACKAGE_LOAD_EMBED) $(BENCHFLAGS)" -c "2windo set nonumber" -c "1windo set nonumber" pgo: rm -rf prof make -C . PGO="$(PGOGEN_BUILD)" clean binaries libraries test benchmark make -C . PGO="$(PGO_BUILD)" clean binaries libraries coverage: make -C . PGO="--coverage" clean binaries libraries test TESTFLAGS="$(TESTFLAGS)" test-container: docker run --rm -it $(DOCKER_ARGS) -v "$(realpath $(srcdir)):/src/local:ro" $(CONTAINER) /src/local/teabase/dtest.tcl "$(TESTFLAGS)" build-container: mkdir -p "$(top_builddir)/dockerbuild" docker run --rm -it $(DOCKER_ARGS) -v "$(realpath $(srcdir)):/src/local:ro" -v "$(top_builddir)/dockerbuild:/install" $(CONTAINER) /src/local/teabase/dbuild.tcl "$(shell id -u)" "$(shell id -g)" benchmark-container: mkdir -p "$(top_builddir)/rundata" docker run --rm -it $(DOCKER_ARGS) -v "$(realpath $(srcdir)):/src/local:ro" -v "$(realpath $(srcdir))/rundata:/src/local/rundata" $(CONTAINER) /src/local/teabase/dbench.tcl "-rundata /src/local/rundata $(BENCHFLAGS)" "$(CONFIGUREFLAGS)" benchmark-container-pgo: mkdir -p "$(top_builddir)/rundata" docker run --rm -it $(DOCKER_ARGS) -v "$(realpath $(srcdir)):/src/local:ro" -v "$(realpath $(srcdir))/rundata:/src/local/rundata" $(CONTAINER) /src/local/teabase/dbench.tcl "-rundata /src/local/rundata $(BENCHFLAGS)" "$(CONFIGUREFLAGS)" pgo .PHONY: vim-gdb vim-core pgo coverage benchmark test-container build-container benchmark-container parse_args-v0.6.3/teabase/teabase_bench-0.1.tm0000644000175100017510000003632515176457507020501 0ustar runnerrunnerpackage require math::statistics namespace eval ::teabase_bench { namespace export * variable match * variable run {} variable skipped {} variable skip {} # Override this to a new lambda to capture the output variable output { {lvl msg} {puts $msg} } namespace path [concat [namespace path] { ::tcl::mathop }] proc output {lvl msg} { #<<< variable output tailcall apply $output $lvl $msg } #>>> proc _intersect3 {list1 list2} { #<<< set firstonly {} set intersection {} set secondonly {} set list1 [lsort -unique $list1] set list2 [lsort -unique $list2] foreach item $list1 { if {[lsearch -sorted $list2 $item] == -1} { lappend firstonly $item } else { lappend intersection $item } } foreach item $list2 { if {[lsearch -sorted $intersection $item] == -1} { lappend secondonly $item } } list $firstonly $intersection $secondonly } #>>> proc _readfile fn { #<<< set h [open $fn r] try { read $h } finally { close $h } } #>>> proc _writefile {fn dat} { #<<< set h [open $fn w] try { puts -nonewline $h $dat } finally { close $h } } #>>> proc _run_if_set script { #<<< if {$script eq ""} return uplevel 2 $script } #>>> proc _pick {mode variant patterns} { #<<< set chain 0 set found 0 set res [lmap {pat e} $patterns { if {!$chain && ![string match $pat $variant]} continue if {$e eq "-"} { set chain 1 continue } set chain 0 switch -exact -- $mode { first - first! {return $e} all - all! {set found 1; set e} default {error "Invalid _pick mode: ($mode)"} } }] if {!$found && [string match *! $mode]} { error "No pattern matches for \"$variant\"" } set res } #>>> proc _verify_res {variant retcodes expected match_mode got options} { #<<< variable current_bench if {[dict get $options -code] ni $retcodes} { teabase_bench::output error "Error: $got\n[dict get $options -errorinfo]" throw [list BENCH BAD_CODE $current_bench $variant $retcodes [dict get $options -code]] \ "$current_bench/$variant: Expected codes [list $retcodes], got [dict get $options -code]" } switch -- $match_mode { exact { if {$got eq $expected} return } glob { if {[string match $expected $got]} return } regexp { if {[regexp $expected $got]} return } default { throw [list BENCH BAD_MATCH_MODE $match_mode] \ "Invalid match mode \"$match_mode\", should be one of exact, glob, regexp" } } throw [list BENCH BAD_RESULT $current_bench $variant $match_mode $expected $got] \ "$current_bench/$variant: Expected ($match_mode): -----------\n$expected\nGot: ----------\n$got" } #>>> proc _make_stats times { #<<< set res {} foreach stat { arithmetic_mean min max number_of_data sample_stddev sample_var population_stddev population_var } val [math::statistics::basic-stats $times] { dict set res $stat $val } dict set res median [math::statistics::median $times] dict set res harmonic_mean [/ [llength $times] [+ {*}[lmap time $times { / 1.0 $time }]]] dict set res cv [expr {[dict get $res population_stddev] / [dict get $res arithmetic_mean]}] } #>>> proc bench {name desc args} { #<<< variable match variable skip variable run variable skipped variable output variable current_bench # -target_cv - Run until the coefficient of variation is below this, up to -max_time # -max_time - Maximum number of seconds to keep running while the cv is converging # -min_time - Keep accumulating samples for at least this many seconds # -batch - The number of samples to take in a tight loop and average to count as a single sample. "auto" guesses a reasonable value to make a batch take at least 1000 usec. # -window - Consider at most the previous -window measurements for target_cv and the results array set opts { -setup {} -compare {} -cleanup {} -batch auto -match exact -returnCodes {ok return} -target_cv {0.0015} -min_time 0.0 -max_time 4.0 -min_it 30 -window 30 -overhead {} -deps {} } array set opts $args set badargs [lindex [_intersect3 [array names opts] { -setup -compare -cleanup -batch -match -result -results -returnCodes -target_cv -min_time -max_time -min_it -window -overhead -deps }] 0] if {[llength $badargs] > 0} { error "Unrecognised arguments: [join $badargs {, }]" } if {![string match $match $name] || [string match $skip $name]} { lappend skipped $name return } set normalized_codes [lmap e $opts(-returnCodes) { switch -- $e { ok {list 0} error {list 1} return {list 2} break {list 3} continue {list 4} default {set e} } }] set make_script { {batch script} { format {set __bench_i %d; while {[incr __bench_i -1] >= 0} %s} \ [list $batch] [list $script] } } set variant_stats {} set current_bench $name _run_if_set $opts(-setup) try { dict for {variant script} $opts(-compare) { try [join [_pick all $variant $opts(-deps)] \n] on error {errmsg options} { apply $output notice "Skipping variant $current_bench/$variant: $errmsg" continue } # Verify the first result against -result (if given), and estimate an appropriate batchsize to target a batch time of 1 ms to reduce quantization noise <<< set hint [lindex [time { catch {uplevel 1 $script} r o }] 0] unset -nocomplain expected if {[info exists opts(-results)]} { set expected [_pick first! $variant $opts(-results)] } elseif {[info exists opts(-result)]} { set expected $opts(-result) } if {[info exists expected]} { #apply $output debug "Verifying expected output for $current_bench/$variant" _verify_res $variant $normalized_codes $expected $opts(-match) $r $o } set single_empty [list uplevel 1 {}] set single_ex_s [list uplevel 1 $script] if 1 $single_empty ;# throw the first away if 1 $single_ex_s ;# throw the first away set single_overhead [lindex [time $single_empty 1000] 0] #puts stderr "single overhead: $single_overhead" set est_it [expr { max(1, int(round( 100.0/$hint ))) }] #puts stderr "hint: $hint, est_it: $est_it" set extime [lindex [time $single_ex_s $est_it] 0] set extime_comp [expr {$extime - $single_overhead}] #puts stderr "extime: $extime, extime comp: $extime_comp" if {$opts(-batch) eq "auto"} { if {$extime_comp <= 0} { # Can happen for very low overhead set batch 10000 } else { set batch [expr {int(round(max(1, 1000.0/$extime_comp)))}] } #puts stderr "Guessed batch size of $batch based on sample execution time $extime_comp usec" } else { set batch $opts(-batch) } #>>> # Measure the instrumentation overhead to compensate for it <<< #apply $output debug "Measuring overhead for $current_bench/$variant" set times {} set start [clock microseconds] ;# Prime [clock microseconds], start var set overhead_script [join [_pick all $variant $opts(-overhead)] \n] set bscript [apply $make_script $batch $overhead_script] set est [lindex [time {uplevel 1 $bscript} 1] 0] #apply $output debug "Initial overhead estimate: $est" for {set i 0} {$i < int(100000 / $est)} {incr i} { set start [clock microseconds] uplevel 1 $bscript lappend times [- [clock microseconds] $start] } set overhead [::tcl::mathfunc::min {*}[lmap e $times {expr {$e / double($batch)}}]] #apply $output debug [format {%s Overhead: %.3f usec, mean: %.3f for batch %d: %s} $variant $overhead [expr {double([+ {*}$times]) / ([llength $times]*$batch)}] $batch [list $overhead_script]] # Measure the instrumentation overhead to compensate for it >>> set cv {data { # Calculate the coefficient of variation of $data <<< lassign [::math::statistics::basic-stats $data] \ arithmetic_mean min max number_of_data sample_stddev sample_var population_stddev population_var expr { $population_stddev / double($arithmetic_mean) } }} #>>> set begin [clock microseconds] ;# Don't count the first run time or the overhead measurement into the total elapsed time set it 0 set times {} set means {} set cvmeans {} set cvtimes {} set elapsed 0 set bscript [apply $make_script $batch $script] #puts stderr "bscript $variant: $bscript" # Run at least: # - -min_it times # - for half a second # - until the coefficient of variability of the means has fallen below -target_cv, or a max of -max_time seconds while { [llength $times] < $opts(-min_it) || $elapsed < $opts(-min_time) || ($elapsed < $opts(-max_time) && $cvmeans > $opts(-target_cv)) } { set start [clock microseconds] uplevel 1 $bscript set batchtime [- [clock microseconds] $start] lappend times [expr { $batchtime / double($batch) - $overhead }] set elapsed [expr {([clock microseconds] - $begin)/1e6}] set cvtimes [lrange $times end-[+ 1 $opts(-window)] end] ;# Consider the last $opts(-window) data in estimating the variation lappend means [expr {[+ {*}$cvtimes]/[llength $cvtimes]}] set _cv [apply $cv $cvtimes] set cvmeans [apply $cv [lrange $means end-[+ 1 $opts(-window)] end]] #puts stderr "Got time for $variant batch($batch), batchtime $batchtime usec: [format %.4f [lindex $times end]], elapsed: [format %.3f $elapsed] sec[if {[info exists cvmeans]} {format {, cvmeans: %.3f} $cvmeans}][if {[info exists _cv]} {format {, cv: %.3f} $_cv}], mean: [format %.5f [lindex $means end]]" } dict set variant_stats $variant [_make_stats $cvtimes] dict set variant_stats $variant cvmeans $cvmeans dict set variant_stats $variant cv [apply $cv $cvtimes] dict set variant_stats $variant runtime $elapsed dict set variant_stats $variant it [llength $cvtimes] } lappend run $name $desc $variant_stats } finally { _run_if_set $opts(-cleanup) unset current_bench } }; namespace export bench #>>> namespace eval display_bench { namespace export * namespace ensemble create namespace path [concat [namespace path] { ::tcl::mathop }] proc _heading {txt {char -}} { #<<< format {%s %s %s} \ [string repeat $char 2] \ $txt \ [string repeat $char [- 80 5 [string length $txt]]] } #>>> proc short {name desc variant_stats relative {pick median}} { #<<< variable output teabase_bench::output notice [_heading [format {%s: "%s"} $name $desc]] # Gather the union of all the variant names from this and past runs set variants [dict keys $variant_stats] foreach {label past_run} $relative { foreach past_variant [dict keys $past_run] { if {$past_variant ni $variants} { lappend variants $past_variant } } } # Assemble the tabular data lappend rows [list "" "This run" {*}[dict keys $relative]] lappend rows {*}[lmap variant $variants { unset -nocomplain baseline set past_stats [dict values $relative] list $variant {*}[lmap stats [list $variant_stats {*}$past_stats] { if {![dict exists $stats $variant]} { #string cat -- set _ -- } else { set val [dict get $stats $variant $pick] if {![info exists baseline]} { set baseline $val format {%.3f%s} $val [expr { [dict exists $stats $variant cv] ? [format { cv:%.1f%%} [expr {100*[dict get $stats $variant cv]}]] : "" }] } elseif {$baseline == 0} { format x%s inf } else { format {x%.3f%s} [/ $val $baseline] [expr { [dict exists $stats $variant cv] ? [format { cv:%.1f%%} [expr {100*[dict get $stats $variant cv]}]] : "" }] } } }] }] # Determine the column widths set colsize {} foreach row $rows { set cols [llength $row] for {set c 0} {$c < $cols} {incr c} { set this_colsize [string length [lindex $row $c]] if { ![dict exists $colsize $c] || [dict get $colsize $c] < $this_colsize } { dict set colsize $c $this_colsize } } } # Construct the row format description set col_fmts [lmap {c size} $colsize { #string cat %${size}s set _ %${size}s }] set fmt " [join $col_fmts { | }]" set col_count [llength $col_fmts] # Output the row data foreach row $rows { set data [list {*}$row {*}[lrepeat [- $col_count [llength $row]] --]] teabase_bench::output notice [format $fmt {*}$data] } teabase_bench::output notice "" } #>>> } proc run_benchmarks {dir args} { #<<< variable skipped variable run variable match variable skip variable output set match * set skip {} set relative {} set display_mode short set display_mode_args {} set rundata . set consume_args [list \ count { upvar 1 i i args args set from $i incr i $count lrange $args $from [+ $from $count -1] } [namespace current] \ ] # Automatically save and compare with the previous run set args [list {*}{ -relative last last } {*}$args] set i 0 while {$i < [llength $args]} { lassign [apply $consume_args 1] next switch -- $next { -rundata { lassign [apply $consume_args 1] rundata } -load { lassign [apply $consume_args 1] load_script namespace eval :: $load_script } -match { lassign [apply $consume_args 1] match } -skip { lassign [apply $consume_args 1] skip } -relative { lassign [apply $consume_args 2] label rel_fn set rel_fn [file join $rundata $rel_fn] if {[file readable $rel_fn]} { dict set relative $label [_readfile [file join $rundata $rel_fn]] } } -save { lassign [apply $consume_args 1] save_fn set save_fn [file join $rundata $save_fn] } -display { lassign [apply $consume_args 1] display_mode set display_mode_args {} while {[string index [lindex $args $i] 0] ni {"-" ""}} { lappend display_mode_args [apply $consume_args 1] } } default { throw [list BENCH INVALID_ARG $next] \ "Invalid argument: \"$next\"" } } } set stats {} foreach f [glob -nocomplain -type f -dir $dir -tails *.bench] { try { namespace eval _bench_private {namespace path {::teabase_bench}} namespace eval _bench_private [list source [file join $dir $f]] } finally { namespace delete _bench_private } } set save [list {save_fn run} { set save_data $run if {[file readable $save_fn]} { # If the save file already exists, merge this run's data with it # rather than replacing it (keeps old tests that weren't executed # in this run) set newkeys [lmap {relname - -} $save_data {set relname}] set old [_readfile $save_fn] foreach {relname reldesc relstats} $old { if {$relname in $newkeys} continue lappend save_data $relname $reldesc $relstats } } _writefile $save_fn $save_data } [namespace current]] apply $save [file join $rundata last] $run ;# Always save as "last", even if explicitly saving as something else too if {[info exists save_fn]} { apply $save $save_fn $run } foreach {name desc variant_stats} $run { set relative_stats {} foreach {label relinfo} $relative { foreach {relname reldesc relstats} $relinfo { if {$relname eq $name} { lappend relative_stats $label $relstats break } } } try { display_bench $display_mode $name $desc $variant_stats $relative_stats {*}$display_mode_args } trap {TCL LOOKUP SUBCOMMAND} {errmsg options} { puts $options apply $output error "Invalid display mode: \"$display_mode\"" exit 1 } trap {TCL WRONGARGS} {errmsg options} { apply $output error "Invalid display mode params: $errmsg" exit 1 } } } #>>> } # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 parse_args-v0.6.3/teabase/ax_cc_for_build.m40000644000175100017510000000570615176457507020443 0ustar runnerrunner# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_cc_for_build.html # =========================================================================== # # SYNOPSIS # # AX_CC_FOR_BUILD # # DESCRIPTION # # Find a build-time compiler. Sets CC_FOR_BUILD and EXEEXT_FOR_BUILD. # # LICENSE # # Copyright (c) 2010 Reuben Thomas # Copyright (c) 1999 Richard Henderson # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 2 dnl Get a default for CC_FOR_BUILD to put into Makefile. AC_DEFUN([AX_CC_FOR_BUILD], [# Put a plausible default for CC_FOR_BUILD in Makefile. if test -z "$CC_FOR_BUILD"; then if test "x$cross_compiling" = "xno"; then CC_FOR_BUILD='$(CC)' else CC_FOR_BUILD=gcc fi fi AC_SUBST(CC_FOR_BUILD) # Also set EXEEXT_FOR_BUILD. if test "x$cross_compiling" = "xno"; then EXEEXT_FOR_BUILD='$(EXEEXT)' else AC_CACHE_CHECK([for build system executable suffix], bfd_cv_build_exeext, [rm -f conftest* echo 'int main () { return 0; }' > conftest.c bfd_cv_build_exeext= ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5 for file in conftest.*; do case $file in *.c | *.o | *.obj | *.ilk | *.pdb) ;; *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;; esac done rm -f conftest* test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no]) EXEEXT_FOR_BUILD="" test x"${bfd_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext} fi AC_SUBST(EXEEXT_FOR_BUILD)])dnl parse_args-v0.6.3/teabase/tools/0000755000175100017510000000000015176457507016227 5ustar runnerrunnerparse_args-v0.6.3/teabase/tools/interned_deps.py0000755000175100017510000004113115176457507021427 0ustar runnerrunner#!/usr/bin/env python3 """ Build version-pinned interned static dependencies from a JSON manifest. Designed to be called from meson custom_targets (or autotools Makefile rules) as a single unified entry point for building C library dependencies that get statically linked into a Tcl extension. The driving goal is reproducibility: a given git rev of the parent package should strictly imply the exact source and build parameters for its dependencies, independent of the developer's shell environment. This script enforces that by: * sanitizing the environment (dropping CFLAGS / CXXFLAGS / LDFLAGS / CPPFLAGS / MAKEFLAGS before invoking cmake / configure / make); * always wiping any stale cmake build dir before re-configuring, which defends against cached flags from a previous run that had environment variables set; * pinning CMAKE_C_FLAGS / CMAKE_CXX_FLAGS to the manifest values (empty by default) so env CFLAGS can't leak into cmake's cache; * hashing the manifest + submodule SHAs + host triple into a stamp file and short-circuiting when nothing relevant has changed. Manifest schema (JSON): { "deps": { "": { "source": "", "builder": "cmake" | "autoconf" | "make", "depends": ["", ...], # optional "defines": { "CMAKE_VAR": "value", ... }, # cmake only "configure_flags": ["--with-foo", ...], # autoconf only "make_env": { "FOO": "bar", ... }, # make only "makefile": "makefile.shared", # make only, default "makefile" "post_install": [ # optional, any builder { "type": "sed", "file": "${prefix}/lib/foo.cmake", "replace": [["search", "replace"], ...] } ] } }, "unsupported_hosts": ["*-*-mingw*", ...] # optional fnmatch patterns } String values in 'defines', 'configure_flags', 'make_env', and 'post_install' may reference ${prefix}, ${host}, or ${source} (the resolved source directory of the current dep) and these will be expanded at runtime. """ import argparse import fnmatch import hashlib import json import os import platform import re import shutil import subprocess import sys from pathlib import Path # Environment variables that would leak build configuration into the # interned dep build if propagated. These are dropped from the env before # every subprocess invocation. If a dep's build genuinely needs one of # these (rare), the manifest should pass it explicitly as a cmake define or # configure flag. ENV_BLOCK = frozenset({ 'CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS', 'CMAKE_C_FLAGS', 'CMAKE_CXX_FLAGS', 'MAKEFLAGS', 'MAKELEVEL', }) def sanitized_env(): return {k: v for k, v in os.environ.items() if k not in ENV_BLOCK} def detect_host(): """Return a gcc-style triplet for the current build host.""" for cc in ('cc', 'gcc', 'clang'): try: r = subprocess.run([cc, '-dumpmachine'], capture_output=True, text=True, check=True) return r.stdout.strip() except (subprocess.CalledProcessError, FileNotFoundError): continue # No C compiler found in PATH — fall back to a coarse uname-based triple. m = platform.machine() s = platform.system().lower() if s == 'linux': return f'{m}-pc-linux-gnu' if s == 'darwin': return f'{m}-apple-darwin' if s == 'windows': return f'{m}-pc-mingw64' return f'{m}-unknown-{s}' def host_matches(host, patterns): return any(fnmatch.fnmatch(host, p) for p in patterns) def git_sha(source_dir): """Return HEAD SHA of source_dir as a git tree, or a deep content hash.""" try: r = subprocess.run( ['git', '-C', str(source_dir), 'rev-parse', 'HEAD'], capture_output=True, text=True, check=True) sha = r.stdout.strip() # Also fold in whether the working tree is dirty, so a dev who # hacks on the dep source without committing still gets rebuilds. dirty = subprocess.run( ['git', '-C', str(source_dir), 'status', '--porcelain'], capture_output=True, text=True, check=False).stdout if dirty.strip(): sha += '-dirty-' + hashlib.sha256(dirty.encode()).hexdigest()[:8] return sha except (subprocess.CalledProcessError, FileNotFoundError): pass # Fall back: hash the tree contents. Slow on large trees but correct. h = hashlib.sha256() for p in sorted(Path(source_dir).rglob('*')): if p.is_file(): h.update(str(p.relative_to(source_dir)).encode()) h.update(p.read_bytes()) return h.hexdigest() _INTERP_RE = re.compile(r'\$\{([^}]+)\}') def interpolate(value, vars): """Recursively expand ${name} references in strings inside value.""" if isinstance(value, str): return _INTERP_RE.sub(lambda m: vars.get(m.group(1), m.group(0)), value) if isinstance(value, list): return [interpolate(v, vars) for v in value] if isinstance(value, dict): return {k: interpolate(v, vars) for k, v in value.items()} return value def topo_sort(deps): """Return dep names in build order, respecting 'depends' edges.""" order = [] seen = set() def visit(name, path): if name in seen: return if name in path: raise ValueError(f'dependency cycle: {" -> ".join(path + [name])}') for d in deps[name].get('depends', []): if d not in deps: raise ValueError( f'{name}: depends on unknown {d!r}') visit(d, path + [name]) seen.add(name) order.append(name) for name in deps: visit(name, []) return order class Builder: def __init__(self, name, spec, source_dir, build_dir, prefix, vars, jobs): self.name = name self.spec = spec self.source_dir = source_dir self.build_dir = build_dir self.prefix = prefix self.vars = vars self.jobs = jobs def _log(self, msg): print(f'[interned_deps:{self.name}] {msg}', flush=True) def _run(self, cmd, cwd=None): self._log(' '.join(str(c) for c in cmd)) subprocess.run(cmd, check=True, env=sanitized_env(), cwd=cwd) def build(self): raise NotImplementedError class CmakeBuilder(Builder): def build(self): # Always wipe the build dir before re-configuring. cmake caches # CMAKE_C_FLAGS on first run and never re-evaluates environment on # subsequent runs, so a stale cache from a previous run with env # CFLAGS set (e.g. -fsanitize=address) would silently contaminate # every future build. if self.build_dir.exists(): shutil.rmtree(self.build_dir) self.build_dir.mkdir(parents=True) defines = interpolate(self.spec.get('defines', {}), self.vars) # Pin CMAKE_C_FLAGS / CMAKE_CXX_FLAGS to the manifest values (empty # by default). This overrides whatever cmake would otherwise # inherit from the environment on first configure. defines.setdefault('CMAKE_C_FLAGS', '') defines.setdefault('CMAKE_CXX_FLAGS', '') # Ensure a sensible install prefix is set unless the manifest # supplied one. defines.setdefault('CMAKE_INSTALL_PREFIX', str(self.prefix)) cmd = ['cmake', '-B', str(self.build_dir), '-S', str(self.source_dir)] for k, v in defines.items(): cmd.append(f'-D{k}={v}') self._run(cmd) self._run(['cmake', '--build', str(self.build_dir), '-j', str(self.jobs)]) self._run(['cmake', '--install', str(self.build_dir)]) class AutoconfBuilder(Builder): def build(self): if self.build_dir.exists(): shutil.rmtree(self.build_dir) self.build_dir.mkdir(parents=True) configure = self.source_dir / 'configure' if not configure.exists(): raise FileNotFoundError( f'{self.name}: {configure} not found (run autoreconf?)') args = [str(configure), f'--prefix={self.prefix}'] args.extend(interpolate(self.spec.get('configure_flags', []), self.vars)) self._run(args, cwd=self.build_dir) self._run(['make', f'-j{self.jobs}'], cwd=self.build_dir) self._run(['make', 'install'], cwd=self.build_dir) class MakeBuilder(Builder): def build(self): # 'make' builds happen in-tree (the source dir IS the build dir), # so a stale object from a previous run could otherwise corrupt # the build. Default to running `make clean` first; the manifest # can override with pre_build to a different list of targets, or # disable with an empty list. # # If the manifest doesn't specify a makefile, omit -f and let make # use its standard search order (GNUmakefile, makefile, Makefile). make_base = ['make'] makefile = self.spec.get('makefile') if makefile: make_base += ['-f', makefile] make_env = interpolate(self.spec.get('make_env', {}), self.vars) common = [f'{k}={v}' for k, v in make_env.items()] common.append(f'PREFIX={self.prefix}') for target in self.spec.get('pre_build', ['clean']): self._run(make_base + common + [target], cwd=self.source_dir) self._run(make_base + [f'-j{self.jobs}'] + common, cwd=self.source_dir) self._run(make_base + ['install'] + common, cwd=self.source_dir) BUILDERS = { 'cmake': CmakeBuilder, 'autoconf': AutoconfBuilder, 'make': MakeBuilder, } def sed_hook(hook, vars): file = Path(interpolate(hook['file'], vars)) content = file.read_text() for pattern, replacement in hook['replace']: content = content.replace( interpolate(pattern, vars), interpolate(replacement, vars)) file.write_text(content) HOOKS = { 'sed': sed_hook, } def compute_stamp_hash(manifest_path, deps, host): h = hashlib.sha256() h.update(manifest_path.read_bytes()) h.update(b'\n__host__\n') h.update(host.encode()) for name in sorted(deps): spec = deps[name] sha = git_sha(spec['source']) h.update(f'\n{name}:{sha}'.encode()) return h.hexdigest() def read_stamp(stamp_path): if not stamp_path.exists(): return None try: return json.loads(stamp_path.read_text()) except (json.JSONDecodeError, OSError): return None def write_stamp(stamp_path, stamp_hash, prefix): stamp_path.parent.mkdir(parents=True, exist_ok=True) stamp_path.write_text(json.dumps({ 'hash': stamp_hash, 'prefix': str(prefix), }, indent=2) + '\n') def main(): ap = argparse.ArgumentParser(description=__doc__.strip().split('\n\n')[0]) ap.add_argument('--manifest', required=True, type=Path, help='Path to the JSON manifest') ap.add_argument('--source-root', type=Path, default=Path.cwd(), help='Root directory that dep "source" paths are relative to') ap.add_argument('--prefix', required=True, type=Path, help='Shared install prefix for all deps') ap.add_argument('--build', required=True, type=Path, help='Root directory for per-dep build trees') ap.add_argument('--stamp', required=True, type=Path, help='Stamp file written on success') ap.add_argument('--jobs', type=int, default=os.cpu_count() or 1, help='Parallel build jobs (default: nproc)') ap.add_argument('--host', default=None, help='Target host triple (default: detect)') ap.add_argument('--force', action='store_true', help='Rebuild even if the stamp is up-to-date') ap.add_argument('--copy-artifact', action='append', default=[], metavar='SRC:DEST', help='After a successful build, copy / to ' '. Used to flatten cmake\'s lib/ install layout ' 'into a meson custom_target output namespace. May be ' 'repeated.') args = ap.parse_args() try: manifest = json.loads(args.manifest.read_text()) except (json.JSONDecodeError, OSError) as e: print(f'ERROR: cannot read manifest {args.manifest}: {e}', file=sys.stderr) return 1 deps = manifest.get('deps', {}) if not deps: print(f'ERROR: manifest {args.manifest} has no deps', file=sys.stderr) return 1 host = args.host or detect_host() unsupported = manifest.get('unsupported_hosts', []) if host_matches(host, unsupported): print(f'ERROR: host {host!r} is declared unsupported in ' f'{args.manifest} (matched pattern in unsupported_hosts)', file=sys.stderr) return 1 # Resolve source paths against --source-root. source_root = args.source_root.resolve() for name, spec in deps.items(): spec['source'] = (source_root / spec['source']).resolve() if not spec['source'].is_dir(): print(f'ERROR: {name}: source {spec["source"]} not found', file=sys.stderr) return 1 # Validate --copy-artifact specs up front so a bad arg fails fast. copy_specs = [] for spec in args.copy_artifact: if ':' not in spec: print(f'ERROR: --copy-artifact must be SRC:DEST, got {spec!r}', file=sys.stderr) return 1 src_rel, dest = spec.split(':', 1) copy_specs.append((src_rel, Path(dest))) def do_copy_artifacts(prefix): for src_rel, dest_path in copy_specs: src = prefix / src_rel if not src.is_file(): print(f'ERROR: --copy-artifact source {src} not found', file=sys.stderr) return False dest_path.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(src, dest_path) print(f'[interned_deps] copied {src} -> {dest_path}', flush=True) return True prefix = args.prefix.resolve() stamp_hash = compute_stamp_hash(args.manifest, deps, host) # Stamp is valid only if hash matches AND prefix exists AND every # --copy-artifact destination still exists. This handles the case # where the meson custom_target outputs were wiped (deps-clean) but # the install prefix was somehow left intact. def all_copy_dests_present(): return all(dest.is_file() for _, dest in copy_specs) prior = read_stamp(args.stamp) if (not args.force and prior and prior.get('hash') == stamp_hash and prior.get('prefix') == str(prefix) and prefix.exists() and all_copy_dests_present()): print(f'[interned_deps] stamp up-to-date for {host}, skipping', flush=True) return 0 order = topo_sort(deps) print(f'[interned_deps] host={host} order={order}', flush=True) build_root = args.build.resolve() build_root.mkdir(parents=True, exist_ok=True) prefix.mkdir(parents=True, exist_ok=True) vars = { 'prefix': str(prefix), 'host': host, 'jobs': str(args.jobs), } for name in order: spec = deps[name] vars['source'] = str(spec['source']) builder_cls = BUILDERS.get(spec.get('builder')) if not builder_cls: print(f'ERROR: {name}: unknown builder ' f'{spec.get("builder")!r}', file=sys.stderr) return 1 build_dir = build_root / name b = builder_cls(name, spec, spec['source'], build_dir, prefix, dict(vars), args.jobs) try: b.build() except subprocess.CalledProcessError as e: print(f'ERROR: {name}: build failed ({e})', file=sys.stderr) return 1 for hook in spec.get('post_install', []): hook_fn = HOOKS.get(hook.get('type')) if not hook_fn: print(f'ERROR: {name}: unknown post_install type ' f'{hook.get("type")!r}', file=sys.stderr) return 1 try: hook_fn(hook, vars) except OSError as e: print(f'ERROR: {name}: post_install {hook["type"]} failed: {e}', file=sys.stderr) return 1 if not do_copy_artifacts(prefix): return 1 write_stamp(args.stamp, stamp_hash, prefix) print(f'[interned_deps] build complete, stamp written to {args.stamp}', flush=True) return 0 if __name__ == '__main__': sys.exit(main()) parse_args-v0.6.3/teabase/tools/check_ver.tcl0000644000175100017510000000004515176457507020663 0ustar runnerrunnerpackage require Tcl [lindex $argv 0] parse_args-v0.6.3/teabase/tools/make_termdebug_arg.tcl0000644000175100017510000000072515176457507022543 0ustar runnerrunnerlassign $argv build_dir source_root tclsh package_name package_version puts -nonewline {Termdebug -ex set\ print\ pretty\ on --args } puts -nonewline [string map {{ } {\ }} $tclsh] puts -nonewline " [file join $source_root tests/all.tcl] -singleproc 1 -load " puts -nonewline [string map {{ } {\ }} {apply {{dir n v} {source [file join $dir pkgIndex.tcl]; package require -exact $n $v}} }] puts [string map {{ } {\ }} [list $build_dir $package_name $package_version]] parse_args-v0.6.3/teabase/tools/test_preamble.tcl0000644000175100017510000000246315176457507021566 0ustar runnerrunner# teabase test launcher preamble. # # Invoked as `tclsh test_preamble.tcl `. # Pops off $::argv, appends any $env(TESTFLAGS) tokens # (backwards compatibility with the older runtests.tcl wrapper — a # whitespace-separated list of tcltest configure options), and sources # the real test script in-process. # # Runs in-process (not a subprocess) so `meson test --test-args` flows # through to the test script's argv and `meson test --wrapper valgrind` # follows the tclsh that actually runs the tests (no --trace-children # needed). tcltest's per-file subprocesses under `singleProcess 0` are # spawned with [info nameofexecutable] directly against each .test file, # so this preamble only participates in the top-level process — TESTFLAGS # applied here becomes tcltest config, which tcltest then propagates to # its children via its own Configure-passthrough. if {[llength $argv] < 1} { puts stderr "usage: [info script] \[tcltest_args...\]" exit 2 } set argv [lassign $argv argv0] if {[info exists env(TESTFLAGS)]} { lappend argv {*}$env(TESTFLAGS) } if {"-singleproc" ni $argv} {lappend argv -singleproc 1} # Make [info script] / $argv0 look like the test script was invoked # directly, so any relative-path idioms in it keep working. source $argv0 parse_args-v0.6.3/teabase/tools/genStubs.tcl0000644000175100017510000010322015176457507020523 0ustar runnerrunner# Copied from the Tcl sources # # genStubs.tcl -- # # This script generates a set of stub files for a given # interface. # # # Copyright © 1998-1999 Scriptics Corporation. # Copyright © 2007 Daniel A. Steffen # # This software is copyrighted by the Regents of the University of # California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState # Corporation and other parties. The following terms apply to all files # associated with the software unless explicitly disclaimed in # individual files. # # The authors hereby grant permission to use, copy, modify, distribute, # and license this software and its documentation for any purpose, provided # that existing copyright notices are retained in all copies and that this # notice is included verbatim in any distributions. No written agreement, # license, or royalty fee is required for any of the authorized uses. # Modifications to this software may be copyrighted by their authors # and need not follow the licensing terms described here, provided that # the new terms are clearly indicated on the first page of each file where # they apply. # # IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY # DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE # IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE # NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR # MODIFICATIONS. # # GOVERNMENT USE: If you are acquiring this software on behalf of the # U.S. government, the Government shall have only "Restricted Rights" # in the software and related documentation as defined in the Federal # Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you # are acquiring the software on behalf of the Department of Defense, the # software shall be classified as "Commercial Computer Software" and the # Government shall have only "Restricted Rights" as defined in Clause # 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the # authors grant the U.S. Government and others acting in its behalf # permission to use and distribute the software in accordance with the # terms specified in this license. namespace eval genStubs { # libraryName -- # # The name of the entire library. This value is used to compute # the USE_*_STUBS macro and the name of the init file. variable libraryName "UNKNOWN" # interfaces -- # # An array indexed by interface name that is used to maintain # the set of valid interfaces. The value is empty. array set interfaces {} # curName -- # # The name of the interface currently being defined. variable curName "UNKNOWN" # scspec -- # # Storage class specifier for external function declarations. # Normally "EXTERN", may be set to something like XYZAPI # variable scspec "EXTERN" # epoch, revision -- # # The epoch and revision numbers of the interface currently being defined. # (@@@TODO: should be an array mapping interface names -> numbers) # variable epoch {} variable revision 0 # hooks -- # # An array indexed by interface name that contains the set of # subinterfaces that should be defined for a given interface. array set hooks {} # stubs -- # # This three dimensional array is indexed first by interface name, # second by platform name, and third by a numeric offset or the # constant "lastNum". The lastNum entry contains the largest # numeric offset used for a given interface/platform combo. Each # numeric offset contains the C function specification that # should be used for the given entry in the stub table. The spec # consists of a list in the form returned by parseDecl. array set stubs {} # outDir -- # # The directory where the generated files should be placed. variable outDir . } # genStubs::library -- # # This function is used in the declarations file to set the name # of the library that the interfaces are associated with (e.g. "tcl"). # This value will be used to define the inline conditional macro. # # Arguments: # name The library name. # # Results: # None. proc genStubs::library {name} { variable libraryName $name } # genStubs::interface -- # # This function is used in the declarations file to set the name # of the interface currently being defined. # # Arguments: # name The name of the interface. # # Results: # None. proc genStubs::interface {name} { variable curName $name variable interfaces set interfaces($name) {} return } # genStubs::scspec -- # # Define the storage class macro used for external function declarations. # Typically, this will be a macro like XYZAPI or EXTERN that # expands to either DLLIMPORT or DLLEXPORT, depending on whether # -DBUILD_XYZ has been set. # proc genStubs::scspec {value} { variable scspec $value } # genStubs::epoch -- # # Define the epoch number for this library. The epoch # should be incrememented when a release is made that # contains incompatible changes to the public API. # proc genStubs::epoch {value} { variable epoch $value } # genStubs::hooks -- # # This function defines the subinterface hooks for the current # interface. # # Arguments: # names The ordered list of interfaces that are reachable through the # hook vector. # # Results: # None. proc genStubs::hooks {names} { variable curName variable hooks set hooks($curName) $names return } # genStubs::declare -- # # This function is used in the declarations file to declare a new # interface entry. # # Arguments: # index The index number of the interface. # platform The platform the interface belongs to. Should be one # of generic, win, unix, or macosx or aqua or x11. # decl The C function declaration, or {} for an undefined # entry. # # Results: # None. proc genStubs::declare {args} { variable stubs variable curName variable revision incr revision if {[llength $args] == 2} { lassign $args index decl set platformList generic } elseif {[llength $args] == 3} { lassign $args index platformList decl } else { puts stderr "wrong # args: declare $args" return } # Check for duplicate declarations, then add the declaration and # bump the lastNum counter if necessary. foreach platform $platformList { if {[info exists stubs($curName,$platform,$index)]} { puts stderr "Duplicate entry: declare $args" } } regsub -all "\[ \t\n\]+" [string trim $decl] " " decl set decl [parseDecl $decl] if {([lindex $platformList 0] eq "deprecated")} { set stubs($curName,deprecated,$index) [lindex $platformList 1] set stubs($curName,generic,$index) $decl if {![info exists stubs($curName,generic,lastNum)] \ || ($index > $stubs($curName,generic,lastNum))} { set stubs($curName,generic,lastNum) $index } } elseif {([lindex $platformList 0] eq "nostub")} { set stubs($curName,nostub,$index) [lindex $platformList 1] set stubs($curName,generic,$index) $decl if {![info exists stubs($curName,generic,lastNum)] \ || ($index > $stubs($curName,generic,lastNum))} { set stubs($curName,generic,lastNum) $index } } else { foreach platform $platformList { if {$decl ne ""} { set stubs($curName,$platform,$index) $decl if {![info exists stubs($curName,$platform,lastNum)] \ || ($index > $stubs($curName,$platform,lastNum))} { set stubs($curName,$platform,lastNum) $index } } } } return } # genStubs::export -- # # This function is used in the declarations file to declare a symbol # that is exported from the library but is not in the stubs table. # # Arguments: # decl The C function declaration, or {} for an undefined # entry. # # Results: # None. proc genStubs::export {args} { if {[llength $args] != 1} { puts stderr "wrong # args: export $args" } return } # genStubs::rewriteFile -- # # This function replaces the machine generated portion of the # specified file with new contents. It looks for the !BEGIN! and # !END! comments to determine where to place the new text. # # If the file does not exist, it is created from scratch using the # optional before and after text to supply the boilerplate that # would normally surround the generated section. # # Arguments: # file The name of the file to modify. # text The new text to place in the file. # before (optional) Default text before !BEGIN! when creating a new file. # after (optional) Default text after !END! when creating a new file. # # Results: # None. proc genStubs::rewriteFile {file text {before ""} {after ""}} { if {![file exists $file]} { set out [open $file w] fconfigure $out -translation lf -encoding utf-8 if {$before ne ""} { puts $out $before } puts $out "/* !BEGIN!: Do not edit below this line. */" puts $out $text puts $out "/* !END!: Do not edit above this line. */" if {$after ne ""} { puts -nonewline $out $after } close $out return } set in [open ${file} r] fconfigure $in -eofchar "\x1A {}" -encoding utf-8 set out [open ${file}.new w] fconfigure $out -translation lf -encoding utf-8 while {![eof $in]} { set line [gets $in] if {[string match "*!BEGIN!*" $line]} { break } puts $out $line } puts $out "/* !BEGIN!: Do not edit below this line. */" puts $out $text while {![eof $in]} { set line [gets $in] if {[string match "*!END!*" $line]} { break } } puts $out "/* !END!: Do not edit above this line. */" puts -nonewline $out [read $in] close $in close $out file rename -force ${file}.new ${file} return } # genStubs::addPlatformGuard -- # # Wrap a string inside a platform #ifdef. # # Arguments: # plat Platform to test. # # Results: # Returns the original text inside an appropriate #ifdef. proc genStubs::addPlatformGuard {plat iftxt {eltxt {}} {withCygwin 0}} { set text "" switch $plat { win { append text "#if defined(_WIN32)" if {$withCygwin} { append text " || defined(__CYGWIN__)" } append text " /* WIN */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* WIN */\n${eltxt}" } append text "#endif /* WIN */\n" } unix { append text "#if !defined(_WIN32)" if {$withCygwin} { append text " && !defined(__CYGWIN__)" } append text " && !defined(MAC_OSX_TCL)\ /* UNIX */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* UNIX */\n${eltxt}" } append text "#endif /* UNIX */\n" } macosx { append text "#ifdef MAC_OSX_TCL /* MACOSX */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* MACOSX */\n${eltxt}" } append text "#endif /* MACOSX */\n" } aqua { append text "#ifdef MAC_OSX_TK /* AQUA */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* AQUA */\n${eltxt}" } append text "#endif /* AQUA */\n" } x11 { append text "#if !(defined(_WIN32)" if {$withCygwin} { append text " || defined(__CYGWIN__)" } append text " || defined(MAC_OSX_TK))\ /* X11 */\n${iftxt}" if {$eltxt ne ""} { append text "#else /* X11 */\n${eltxt}" } append text "#endif /* X11 */\n" } default { append text "${iftxt}${eltxt}" } } return $text } # genStubs::emitSlots -- # # Generate the stub table slots for the given interface. If there # are no generic slots, then one table is generated for each # platform, otherwise one table is generated for all platforms. # # Arguments: # name The name of the interface being emitted. # textVar The variable to use for output. # # Results: # None. proc genStubs::emitSlots {name textVar} { upvar $textVar text forAllStubs $name makeSlot 1 text {" void (*reserved$i)(void);\n"} return } # genStubs::parseDecl -- # # Parse a C function declaration into its component parts. # # Arguments: # decl The function declaration. # # Results: # Returns a list of the form {returnType name args}. The args # element consists of a list of type/name pairs, or a single # element "void". If the function declaration is malformed # then an error is displayed and the return value is {}. proc genStubs::parseDecl {decl} { if {![regexp {^(.*)\((.*)\)$} $decl all prefix args]} { set prefix $decl set args {} } set prefix [string trim $prefix] if {![regexp {^(.+[ ][*]*)([^ *]+)$} $prefix all rtype fname]} { puts stderr "Bad return type: $decl" return } set rtype [string trim $rtype] if {$args eq ""} { return [list $rtype $fname {}] } foreach arg [split $args ,] { lappend argList [string trim $arg] } if {![string compare [lindex $argList end] "..."]} { set args TCL_VARARGS foreach arg [lrange $argList 0 end-1] { set argInfo [parseArg $arg] if {[llength $argInfo] == 2 || [llength $argInfo] == 3} { lappend args $argInfo } else { puts stderr "Bad argument: '$arg' in '$decl'" return } } } else { set args {} foreach arg $argList { set argInfo [parseArg $arg] if {![string compare $argInfo "void"]} { lappend args "void" break } elseif {[llength $argInfo] == 2 || [llength $argInfo] == 3} { lappend args $argInfo } else { puts stderr "Bad argument: '$arg' in '$decl'" return } } } return [list $rtype $fname $args] } # genStubs::parseArg -- # # This function parses a function argument into a type and name. # # Arguments: # arg The argument to parse. # # Results: # Returns a list of type and name with an optional third array # indicator. If the argument is malformed, returns "". proc genStubs::parseArg {arg} { if {![regexp {^(.+[ ][*]*)([^][ *]+)(\[\])?$} $arg all type name array]} { if {$arg eq "void"} { return $arg } else { return } } set result [list [string trim $type] $name] if {$array ne ""} { lappend result $array } return $result } # genStubs::makeDecl -- # # Generate the prototype for a function. # # Arguments: # name The interface name. # decl The function declaration. # index The slot index for this function. # # Results: # Returns the formatted declaration string. proc genStubs::makeDecl {name decl index} { variable scspec variable stubs variable libraryName lassign $decl rtype fname args append text "/* $index */\n" if {[info exists stubs($name,deprecated,$index)]} { append text "[string toupper $libraryName]_DEPRECATED(\"$stubs($name,deprecated,$index)\")\n" set line "$rtype" } elseif {[string range $rtype end-5 end] eq "MP_WUR"} { set line "$scspec [string trim [string range $rtype 0 end-6]]" } else { set line "$scspec $rtype" } set count [expr {2 - ([string length $line] / 8)}] if {$count >= 0} { append line [string range "\t\t\t" 0 $count] } set pad [expr {24 - [string length $line]}] if {$pad <= 0} { append line " " set pad 0 } if {$args eq ""} { append line $fname append text $line append text ";\n" return $text } append line $fname set arg1 [lindex $args 0] switch -exact $arg1 { void { append line "(void)" } TCL_VARARGS { set sep "(" foreach arg [lrange $args 1 end] { append line $sep set next {} append next [lindex $arg 0] if {[string index $next end] ne "*"} { append next " " } append next [lindex $arg 1] [lindex $arg 2] if {[string length $line] + [string length $next] \ + $pad > 76} { append text [string trimright $line] \n set line "\t\t\t\t" set pad 28 } append line $next set sep ", " } append line ", ...)" if {[lindex $args end] eq "{const char *} format"} { append line " TCL_FORMAT_PRINTF(" [expr {[llength $args] - 1}] ", " [llength $args] ")" } } default { set sep "(" foreach arg $args { append line $sep set next {} append next [lindex $arg 0] if {[string index $next end] ne "*"} { append next " " } append next [lindex $arg 1] [lindex $arg 2] if {[string length $line] + [string length $next] \ + $pad > 76} { append text [string trimright $line] \n set line "\t\t\t\t" set pad 28 } append line $next set sep ", " } append line ")" } } if {[string range $rtype end-5 end] eq "MP_WUR"} { append line " MP_WUR" } return "$text$line;\n" } # genStubs::makeMacro -- # # Generate the inline macro for a function. # # Arguments: # name The interface name. # decl The function declaration. # index The slot index for this function. # # Results: # Returns the formatted macro definition. proc genStubs::makeMacro {name decl index} { lassign $decl rtype fname args set lfname [string tolower [string index $fname 0]] append lfname [string range $fname 1 end] set text "#define $fname \\\n\t(" if {$args eq ""} { append text "*" } append text "${name}StubsPtr->$lfname)" append text " /* $index */\n" return $text } # genStubs::makeSlot -- # # Generate the stub table entry for a function. # # Arguments: # name The interface name. # decl The function declaration. # index The slot index for this function. # # Results: # Returns the formatted table entry. proc genStubs::makeSlot {name decl index} { lassign $decl rtype fname args variable stubs set lfname [string tolower [string index $fname 0]] append lfname [string range $fname 1 end] set text " " if {[info exists stubs($name,deprecated,$index)]} { append text "TCL_DEPRECATED_API(\"$stubs($name,deprecated,$index)\") " } elseif {[info exists stubs($name,nostub,$index)]} { append text "TCL_DEPRECATED_API(\"$stubs($name,nostub,$index)\") " } if {$args eq ""} { append text $rtype " *" $lfname "; /* $index */\n" return $text } if {[string range $rtype end-8 end] eq "__stdcall"} { append text [string trim [string range $rtype 0 end-9]] " (__stdcall *" $lfname ") " } elseif {[string range $rtype 0 11] eq "TCL_NORETURN"} { append text "TCL_NORETURN1 " [string trim [string range $rtype 12 end]] " (*" $lfname ") " } elseif {[string range $rtype end-5 end] eq "MP_WUR"} { append text [string trim [string range $rtype 0 end-6]] " (*" $lfname ") " } else { append text $rtype " (*" $lfname ") " } set arg1 [lindex $args 0] switch -exact $arg1 { void { append text "(void)" } TCL_VARARGS { set sep "(" foreach arg [lrange $args 1 end] { append text $sep [lindex $arg 0] if {[string index $text end] ne "*"} { append text " " } append text [lindex $arg 1] [lindex $arg 2] set sep ", " } append text ", ...)" if {[lindex $args end] eq "{const char *} format"} { append text " TCL_FORMAT_PRINTF(" [expr {[llength $args] - 1}] ", " [llength $args] ")" } } default { set sep "(" foreach arg $args { append text $sep [lindex $arg 0] if {[string index $text end] ne "*"} { append text " " } append text [lindex $arg 1] [lindex $arg 2] set sep ", " } append text ")" } } if {[string range $rtype end-5 end] eq "MP_WUR"} { append text " MP_WUR" } append text "; /* $index */\n" return $text } # genStubs::makeInit -- # # Generate the prototype for a function. # # Arguments: # name The interface name. # decl The function declaration. # index The slot index for this function. # # Results: # Returns the formatted declaration string. proc genStubs::makeInit {name decl index} { if {[lindex $decl 2] eq ""} { append text " &" [lindex $decl 1] ", /* " $index " */\n" } else { append text " " [lindex $decl 1] ", /* " $index " */\n" } return $text } # genStubs::forAllStubs -- # # This function iterates over all of the platforms and invokes # a callback for each slot. The result of the callback is then # placed inside appropriate platform guards. # # Arguments: # name The interface name. # slotProc The proc to invoke to handle the slot. It will # have the interface name, the declaration, and # the index appended. # onAll If 1, emit the skip string even if there are # definitions for one or more platforms. # textVar The variable to use for output. # skipString The string to emit if a slot is skipped. This # string will be subst'ed in the loop so "$i" can # be used to substitute the index value. # # Results: # None. proc genStubs::forAllStubs {name slotProc onAll textVar {skipString {"/* Slot $i is reserved */\n"}}} { variable stubs upvar $textVar text set plats [array names stubs $name,*,lastNum] if {[info exists stubs($name,generic,lastNum)]} { # Emit integrated stubs block set lastNum -1 foreach plat [array names stubs $name,*,lastNum] { if {$stubs($plat) > $lastNum} { set lastNum $stubs($plat) } } for {set i 0} {$i <= $lastNum} {incr i} { set slots [array names stubs $name,*,$i] set emit 0 if {[info exists stubs($name,deprecated,$i)]} { append text [$slotProc $name $stubs($name,generic,$i) $i] set emit 1 } elseif {[info exists stubs($name,nostub,$i)]} { append text [$slotProc $name $stubs($name,generic,$i) $i] set emit 1 } elseif {[info exists stubs($name,generic,$i)]} { if {[llength $slots] > 1} { puts stderr "conflicting generic and platform entries:\ $name $i" } append text [$slotProc $name $stubs($name,generic,$i) $i] set emit 1 } elseif {[llength $slots] > 0} { array set slot {unix 0 x11 0 win 0 macosx 0 aqua 0} foreach s $slots { set slot([lindex [split $s ,] 1]) 1 } # "aqua", "macosx" and "x11" are special cases: # "macosx" implies "unix", "aqua" implies "macosx" and "x11" # implies "unix", so we need to be careful not to emit # duplicate stubs entries: if {($slot(unix) && $slot(macosx)) || ( ($slot(unix) || $slot(macosx)) && ($slot(x11) || $slot(aqua)))} { puts stderr "conflicting platform entries: $name $i" } ## unix ## set temp {} set plat unix if {!$slot(aqua) && !$slot(x11)} { if {$slot($plat)} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } elseif {$onAll} { eval {append temp} $skipString } } if {$temp ne ""} { append text [addPlatformGuard $plat $temp] set emit 1 } ## x11 ## set temp {} set plat x11 if {!$slot(unix) && !$slot(macosx)} { if {$slot($plat)} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } elseif {$onAll} { eval {append temp} $skipString } } if {$temp ne ""} { append text [addPlatformGuard $plat $temp] set emit 1 } ## win ## set temp {} set plat win if {$slot($plat)} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } elseif {$onAll} { eval {append temp} $skipString } if {$temp ne ""} { append text [addPlatformGuard $plat $temp] set emit 1 } ## macosx ## set temp {} set plat macosx if {!$slot(aqua) && !$slot(x11)} { if {$slot($plat)} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } elseif {$slot(unix)} { append temp [$slotProc $name $stubs($name,unix,$i) $i] } elseif {$onAll} { eval {append temp} $skipString } } if {$temp ne ""} { append text [addPlatformGuard $plat $temp] set emit 1 } ## aqua ## set temp {} set plat aqua if {!$slot(unix) && !$slot(macosx)} { if {[string range $skipString 1 2] ne "/*"} { # genStubs.tcl previously had a bug here causing it to # erroneously generate both a unix entry and an aqua # entry for a given stubs table slot. To preserve # backwards compatibility, generate a dummy stubs entry # before every aqua entry (note that this breaks the # correspondence between emitted entry number and # actual position of the entry in the stubs table, e.g. # TkIntStubs entry 113 for aqua is in fact at position # 114 in the table, entry 114 at position 116 etc). eval {append temp} $skipString set temp "# if TCL_MAJOR_VERSION < 9\n[string range $temp 0 end-1] /*\ Dummy entry for stubs table backwards\ compatibility */\n# endif /* TCL_MAJOR_VERSION < 9 */\n" } if {$slot($plat)} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } elseif {$onAll} { eval {append temp} $skipString } } if {$temp ne ""} { append text [addPlatformGuard $plat $temp] set emit 1 } } if {!$emit} { eval {append text} $skipString } } } else { # Emit separate stubs blocks per platform array set block {unix 0 x11 0 win 0 macosx 0 aqua 0} foreach s [array names stubs $name,*,lastNum] { set block([lindex [split $s ,] 1]) 1 } ## unix ## if {$block(unix) && !$block(x11)} { set temp {} set plat unix set lastNum $stubs($name,$plat,lastNum) for {set i 0} {$i <= $lastNum} {incr i} { if {[info exists stubs($name,$plat,$i)]} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } else { eval {append temp} $skipString } } append text [addPlatformGuard $plat $temp {} true] } ## win ## if {$block(win)} { set temp {} set plat win set lastNum $stubs($name,$plat,lastNum) for {set i 0} {$i <= $lastNum} {incr i} { if {[info exists stubs($name,$plat,$i)]} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] } else { eval {append temp} $skipString } } append text [addPlatformGuard $plat $temp {} true] } ## macosx ## if {($block(unix) || $block(macosx)) && !$block(aqua) && !$block(x11)} { set temp {} set lastNum -1 foreach plat {unix macosx} { if {$block($plat)} { set lastNum [expr {$lastNum > $stubs($name,$plat,lastNum) ? $lastNum : $stubs($name,$plat,lastNum)}] } } for {set i 0} {$i <= $lastNum} {incr i} { set emit 0 foreach plat {unix macosx} { if {[info exists stubs($name,$plat,$i)]} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] set emit 1 break } } if {!$emit} { eval {append temp} $skipString } } append text [addPlatformGuard macosx $temp] } ## aqua ## if {$block(aqua)} { set temp {} set lastNum -1 foreach plat {unix macosx aqua} { if {$block($plat)} { set lastNum [expr {$lastNum > $stubs($name,$plat,lastNum) ? $lastNum : $stubs($name,$plat,lastNum)}] } } for {set i 0} {$i <= $lastNum} {incr i} { set emit 0 foreach plat {unix macosx aqua} { if {[info exists stubs($name,$plat,$i)]} { append temp [$slotProc $name $stubs($name,$plat,$i) $i] set emit 1 break } } if {!$emit} { eval {append temp} $skipString } } append text [addPlatformGuard aqua $temp] } ## x11 ## if {$block(x11)} { set temp {} set lastNum -1 foreach plat {unix macosx x11} { if {$block($plat)} { set lastNum [expr {$lastNum > $stubs($name,$plat,lastNum) ? $lastNum : $stubs($name,$plat,lastNum)}] } } for {set i 0} {$i <= $lastNum} {incr i} { set emit 0 foreach plat {unix macosx x11} { if {[info exists stubs($name,$plat,$i)]} { if {$plat ne "macosx"} { append temp [$slotProc $name \ $stubs($name,$plat,$i) $i] } else { eval {set etxt} $skipString append temp [addPlatformGuard $plat [$slotProc \ $name $stubs($name,$plat,$i) $i] $etxt true] } set emit 1 break } } if {!$emit} { eval {append temp} $skipString } } append text [addPlatformGuard x11 $temp {} true] } } } # genStubs::emitDeclarations -- # # This function emits the function declarations for this interface. # # Arguments: # name The interface name. # textVar The variable to use for output. # # Results: # None. proc genStubs::emitDeclarations {name textVar} { upvar $textVar text append text "\n/*\n * Exported function declarations:\n */\n\n" forAllStubs $name makeDecl 0 text return } # genStubs::emitMacros -- # # This function emits the inline macros for an interface. # # Arguments: # name The name of the interface being emitted. # textVar The variable to use for output. # # Results: # None. proc genStubs::emitMacros {name textVar} { variable libraryName upvar $textVar text set upName [string toupper $libraryName] append text "\n#if defined(USE_${upName}_STUBS)\n" append text "\n/*\n * Inline function declarations:\n */\n\n" forAllStubs $name makeMacro 0 text append text "\n#endif /* defined(USE_${upName}_STUBS) */\n" return } # genStubs::emitHeader -- # # This function emits the body of the Decls.h file for # the specified interface. # # Arguments: # name The name of the interface being emitted. # # Results: # None. proc genStubs::emitHeader {name} { variable outDir variable hooks variable epoch variable revision set capName [string toupper [string index $name 0]] append capName [string range $name 1 end] if {$epoch ne ""} { set CAPName [string toupper $name] append text "\n" append text "#define ${CAPName}_STUBS_EPOCH $epoch\n" append text "#define ${CAPName}_STUBS_REVISION $revision\n" } append text "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n" emitDeclarations $name text if {[info exists hooks($name)]} { append text "\ntypedef struct {\n" foreach hook $hooks($name) { set capHook [string toupper [string index $hook 0]] append capHook [string range $hook 1 end] append text " const struct ${capHook}Stubs *${hook}Stubs;\n" } append text "} ${capName}StubHooks;\n" } append text "\ntypedef struct ${capName}Stubs {\n" append text " int magic;\n" if {$epoch ne ""} { append text " int epoch;\n" append text " int revision;\n" } if {[info exists hooks($name)]} { append text " const ${capName}StubHooks *hooks;\n\n" } else { append text " void *hooks;\n\n" } emitSlots $name text append text "} ${capName}Stubs;\n\n" append text "extern const ${capName}Stubs *${name}StubsPtr;\n\n" append text "#ifdef __cplusplus\n}\n#endif\n" emitMacros $name text set guard _[string toupper ${name}]DECLS_H rewriteFile [file join $outDir ${name}Decls.h] $text \ "#ifndef $guard\n#define $guard\n" \ "#endif /* $guard */\n" return } # genStubs::emitInit -- # # Generate the table initializers for an interface. # # Arguments: # name The name of the interface to initialize. # textVar The variable to use for output. # # Results: # Returns the formatted output. proc genStubs::emitInit {name textVar} { variable hooks variable interfaces variable epoch upvar $textVar text set root 1 set capName [string toupper [string index $name 0]] append capName [string range $name 1 end] if {[info exists hooks($name)]} { append text "\nstatic const ${capName}StubHooks ${name}StubHooks = \{\n" set sep " " foreach sub $hooks($name) { append text $sep "&${sub}Stubs" set sep ",\n " } append text "\n\};\n" } foreach intf [array names interfaces] { if {[info exists hooks($intf)]} { if {$name in $hooks($intf)} { set root 0 break } } } append text "\n" if {!$root} { append text "static " } append text "const ${capName}Stubs ${name}Stubs = \{\n TCL_STUB_MAGIC,\n" if {$epoch ne ""} { set CAPName [string toupper $name] append text " ${CAPName}_STUBS_EPOCH,\n" append text " ${CAPName}_STUBS_REVISION,\n" } if {[info exists hooks($name)]} { append text " &${name}StubHooks,\n" } else { append text " 0,\n" } forAllStubs $name makeInit 1 text {" 0, /* $i */\n"} append text "\};\n" return } # genStubs::emitInits -- # # This function emits the body of the StubInit.c file for # the specified interface. # # Arguments: # name The name of the interface being emitted. # # Results: # None. proc genStubs::emitInits {} { variable hooks variable outDir variable libraryName variable interfaces # Assuming that dependencies only go one level deep, we need to emit # all of the leaves first to avoid needing forward declarations. set leaves {} set roots {} foreach name [lsort [array names interfaces]] { if {[info exists hooks($name)]} { lappend roots $name } else { lappend leaves $name } } foreach name $leaves { emitInit $name text } foreach name $roots { emitInit $name text } set capName [string toupper [string index $libraryName 0]] append capName [string range $libraryName 1 end] set before "#include \"${libraryName}.h\"\n" set after [join [list \ "" "" \ "MODULE_SCOPE const ${capName}Stubs* const ${libraryName}ConstStubsPtr;" \ "const ${capName}Stubs* const ${libraryName}ConstStubsPtr = &${libraryName}Stubs;" \ "" \ ] "\n"] rewriteFile [file join $outDir ${libraryName}StubInit.c] $text $before $after } # genStubs::init -- # # This is the main entry point. # # Arguments: # None. # # Results: # None. proc genStubs::init {} { global argv argv0 variable outDir variable interfaces if {[llength $argv] < 2} { puts stderr "usage: $argv0 outDir declFile ?declFile...?" exit 1 } set outDir [lindex $argv 0] foreach file [lrange $argv 1 end] { source -encoding utf-8 $file } foreach name [lsort [array names interfaces]] { #puts "Emitting $name" emitHeader $name } emitInits } # lassign -- # # This function emulates the TclX lassign command. # # Arguments: # valueList A list containing the values to be assigned. # args The list of variables to be assigned. # # Results: # Returns any values that were not assigned to variables. if {[namespace which lassign] ne ""} { proc lassign {valueList args} { if {[llength $args] == 0} { error "wrong # args: should be \"lassign list varName ?varName ...?\"" } uplevel [list foreach $args $valueList {break}] return [lrange $valueList [llength $args] end] } } genStubs::init parse_args-v0.6.3/teabase/tclstuff.h0000644000175100017510000000000015176457507025454 1parse_args-v0.6.3/generic/tclstuff.hustar runnerrunnerparse_args-v0.6.3/teabase/ax_gcc_builtin.m40000644000175100017510000001334615176457507020312 0ustar runnerrunner# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html # =========================================================================== # # SYNOPSIS # # AX_GCC_BUILTIN(BUILTIN) # # DESCRIPTION # # This macro checks if the compiler supports one of GCC's built-in # functions; many other compilers also provide those same built-ins. # # The BUILTIN parameter is the name of the built-in function. # # If BUILTIN is supported define HAVE_. Keep in mind that since # builtins usually start with two underscores they will be copied over # into the HAVE_ definition (e.g. HAVE___BUILTIN_EXPECT for # __builtin_expect()). # # The macro caches its result in the ax_cv_have_ variable (e.g. # ax_cv_have___builtin_expect). # # The macro currently supports the following built-in functions: # # __builtin_assume_aligned # __builtin_bswap16 # __builtin_bswap32 # __builtin_bswap64 # __builtin_choose_expr # __builtin___clear_cache # __builtin_clrsb # __builtin_clrsbl # __builtin_clrsbll # __builtin_clz # __builtin_clzl # __builtin_clzll # __builtin_complex # __builtin_constant_p # __builtin_ctz # __builtin_ctzl # __builtin_ctzll # __builtin_expect # __builtin_ffs # __builtin_ffsl # __builtin_ffsll # __builtin_fpclassify # __builtin_huge_val # __builtin_huge_valf # __builtin_huge_vall # __builtin_inf # __builtin_infd128 # __builtin_infd32 # __builtin_infd64 # __builtin_inff # __builtin_infl # __builtin_isinf_sign # __builtin_nan # __builtin_nand128 # __builtin_nand32 # __builtin_nand64 # __builtin_nanf # __builtin_nanl # __builtin_nans # __builtin_nansf # __builtin_nansl # __builtin_object_size # __builtin_parity # __builtin_parityl # __builtin_parityll # __builtin_popcount # __builtin_popcountl # __builtin_popcountll # __builtin_powi # __builtin_powif # __builtin_powil # __builtin_prefetch # __builtin_trap # __builtin_types_compatible_p # __builtin_unreachable # # Unsupported built-ins will be tested with an empty parameter set and the # result of the check might be wrong or meaningless so use with care. # # LICENSE # # Copyright (c) 2013 Gabriele Svelto # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 6 AC_DEFUN([AX_GCC_BUILTIN], [ AS_VAR_PUSHDEF([ac_var], [ax_cv_have_$1]) AC_CACHE_CHECK([for $1], [ac_var], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [ m4_case([$1], [__builtin_assume_aligned], [$1("", 0)], [__builtin_bswap16], [$1(0)], [__builtin_bswap32], [$1(0)], [__builtin_bswap64], [$1(0)], [__builtin_choose_expr], [$1(0, 0, 0)], [__builtin___clear_cache], [$1("", "")], [__builtin_clrsb], [$1(0)], [__builtin_clrsbl], [$1(0)], [__builtin_clrsbll], [$1(0)], [__builtin_clz], [$1(0)], [__builtin_clzl], [$1(0)], [__builtin_clzll], [$1(0)], [__builtin_complex], [$1(0.0, 0.0)], [__builtin_constant_p], [$1(0)], [__builtin_ctz], [$1(0)], [__builtin_ctzl], [$1(0)], [__builtin_ctzll], [$1(0)], [__builtin_expect], [$1(0, 0)], [__builtin_ffs], [$1(0)], [__builtin_ffsl], [$1(0)], [__builtin_ffsll], [$1(0)], [__builtin_fpclassify], [$1(0, 1, 2, 3, 4, 0.0)], [__builtin_huge_val], [$1()], [__builtin_huge_valf], [$1()], [__builtin_huge_vall], [$1()], [__builtin_inf], [$1()], [__builtin_infd128], [$1()], [__builtin_infd32], [$1()], [__builtin_infd64], [$1()], [__builtin_inff], [$1()], [__builtin_infl], [$1()], [__builtin_isinf_sign], [$1(0.0)], [__builtin_nan], [$1("")], [__builtin_nand128], [$1("")], [__builtin_nand32], [$1("")], [__builtin_nand64], [$1("")], [__builtin_nanf], [$1("")], [__builtin_nanl], [$1("")], [__builtin_nans], [$1("")], [__builtin_nansf], [$1("")], [__builtin_nansl], [$1("")], [__builtin_object_size], [$1("", 0)], [__builtin_parity], [$1(0)], [__builtin_parityl], [$1(0)], [__builtin_parityll], [$1(0)], [__builtin_popcount], [$1(0)], [__builtin_popcountl], [$1(0)], [__builtin_popcountll], [$1(0)], [__builtin_powi], [$1(0, 0)], [__builtin_powif], [$1(0, 0)], [__builtin_powil], [$1(0, 0)], [__builtin_prefetch], [$1("")], [__builtin_trap], [$1()], [__builtin_types_compatible_p], [$1(int, int)], [__builtin_unreachable], [$1()], [m4_warn([syntax], [Unsupported built-in $1, the test may fail]) $1()] ) ])], [AS_VAR_SET([ac_var], [yes])], [AS_VAR_SET([ac_var], [no])]) ]) AS_IF([test yes = AS_VAR_GET([ac_var])], [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), 1, [Define to 1 if the system has the `$1' built-in function])], []) AS_VAR_POPDEF([ac_var]) ]) parse_args-v0.6.3/teabase/defer.h0000644000175100017510000000240515176457507016326 0ustar runnerrunner#ifndef _DEFER_H #define _DEFER_H #if HAVE_NATIVE_DEFER /* Compiler supports _Defer natively (e.g. clang 22+ with -fdefer-ts). * Guard against already providing this macro per the TS. */ # ifndef defer # define defer _Defer # endif #elif HAVE_DEFER_POLYFILL /* GCC polyfill using nested functions + __attribute__((cleanup)). * Credit: Jens Gustedt (author of the C2y defer proposal). * Always use braces: defer { ... } */ # define defer _Defer # define _Defer _Defer_A(__COUNTER__) # define _Defer_A(N) _Defer_B(N) # define _Defer_B(N) _Defer_C(_Defer_func_ ## N, _Defer_var_ ## N) # define _Defer_C(F, V) \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wpedantic\"") \ auto void F(int*); \ __attribute__((__cleanup__(F), __deprecated__, __unused__)) \ int V; \ __attribute__((__always_inline__, __deprecated__, __unused__)) \ inline auto void F(__attribute__((__unused__)) int*V) #else # error "No defer support available" #endif #endif /* _DEFER_H */ parse_args-v0.6.3/teabase/__builddir.in0000644000175100017510000000001215176457507017504 0ustar runnerrunner@BUILDDIR@parse_args-v0.6.3/teabase/names.h0000644000175100017510000000027315176457507016345 0ustar runnerrunner#ifndef _NAMES_H #define _NAMES_H const char* name(const void *const thing); // name given thing void* thing(const char *const name); // thing given name void names_shutdown(); #endif parse_args-v0.6.3/teabase/__srcdir.in0000644000175100017510000000001315176457507017175 0ustar runnerrunner@SOURCEDIR@parse_args-v0.6.3/teabase/ax_check_compile_flag.m40000644000175100017510000000407015176457507021600 0ustar runnerrunner# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the current language's compiler # or gives an error. (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_COMPILE_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 6 AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_COMPILE_FLAGS parse_args-v0.6.3/teabase/dbuild.tcl0000755000175100017510000000170615176457507017045 0ustar runnerrunner#!/usr/local/bin/tclsh package require platform puts "dbuild.tcl platform: [platform::generic]" switch -glob -- [platform::generic] { *-x86_64 { set cflags {-O3 -march=haswell} } *-aarch64 { set cflags {-O3 -moutline-atomics -march=armv8.2-a} } default { set cflags {-O3} } } file mkdir /tmp/build cd /tmp/build foreach file [glob -nocomplain /src/local/*] { set fqfn [file join /src/local $file] if {[file exists $fqfn]} { exec cp -a $fqfn . } } exec -ignorestderr autoconf >@ stdout exec -ignorestderr ./configure --enable-symbols --with-tcl=/usr/local/lib >@ stdout file delete -- {*}[glob -nocomplain tools/bin/*] exec -ignorestderr make clean install-binaries install-libraries DESTDIR=/tmp/install >@ stdout set target [file join /install [platform::generic]] file mkdir $target exec -ignorestderr sh -c "cp -a /tmp/install/usr/local/lib/* $target" >@ stdout exec -ignorestderr chown -R [lindex $argv 0]:[lindex $argv 1] $target >@ stdout parse_args-v0.6.3/teabase/meson.build0000644000175100017510000002522615176457507017240 0ustar runnerrunnerif not is_variable('teabase_initialized') subdir('init') endif inc += include_directories('.') if tclver_major.to_int() >= 9 _pkg_so_name = 'tcl9' + meson.project_name() else _pkg_so_name = meson.project_name() endif inc += include_directories('pkg_config_h') if is_variable('tea_genstubs') genstubs = custom_target('genstubs', output: [meson.project_name() + 'StubInit.c', meson.project_name() + 'Decls.h'], command: [ build_tclsh, files('tools/genStubs.tcl'), meson.current_build_dir(), tea_genstubs[0] ], install: true, install_tag: [false, meson.is_subproject() ? 'deps' : 'runtime'], install_dir: [false, pkg_dir], env: tea_build_env, ) deps += declare_dependency(sources: genstubs) # Build and install stubs library for dependent extensions stubs_lib = static_library(meson.project_name() + 'stub', tea_genstubs[1], dependencies: deps, include_directories: inc, install: true, install_dir: pkg_dir, install_tag: meson.is_subproject() ? 'deps' : 'runtime', ) endif pkg_so = shared_module(_pkg_so_name, pkg_sources, install: true, install_dir: pkg_dir, install_tag: meson.is_subproject() ? 'deps' : 'runtime', dependencies: deps, include_directories: inc, ) _pkg_lib_file = fs.name(pkg_so.full_path()) _pname = meson.project_name() teaconf.set('PKG_LIB_FILE', _pkg_lib_file) # Also expose as a C string macro for extensions that need to know their # own on-disk filename at runtime (e.g. to advertise a link-name matching # the in-memory copy for consumers that generate and load code dynamically). conf.set_quoted('PKG_LIB_FILE', _pkg_lib_file) # TEA convention: Tcl 8 libs are "lib.so", Tcl 9 are "libtcl9.so". # Both names are always provided so that two builds (one per Tcl major version) # can be installed side by side in the same package directory. if tclver_major.to_int() >= 9 _base = _pkg_lib_file.replace('tcl9' + _pname, _pname) else _base = _pkg_lib_file endif teaconf.set('PKG_LIB_FILE8', _base) teaconf.set('PKG_LIB_FILE9', _base.replace(_pname, 'tcl9' + _pname)) if not is_variable('teaconf_files') teaconf_files = [] endif teaconf_files += files('../pkgIndex.tcl.in') foreach f : teaconf_files fname = fs.name(f) configure_file(input: f, output: fname.endswith('.in') ? '@BASENAME@' : fname, configuration: teaconf, install: true, install_dir: pkg_dir, install_tag: meson.is_subproject() ? 'deps' : 'runtime', ) endforeach # Arrange for our the package path to be first in $::auto_path and to be # able to load any subproject packages. # Mirror this build dir into the host env (so devenv tclsh and # configure-time run_command can find the just-built package), and # record the same op so derived test/bench envs replay it. tea_host_env.prepend('TCLLIBPATH', meson.current_build_dir(), separator: ' ') tea_host_env_ops += {'var': 'TCLLIBPATH', 'value': meson.current_build_dir()} # Translate a list of tea_*_deps dependency() objects into env-mod ops: # tcl_pkg_path -> TCLLIBPATH (binary `package require` packages) # tcl_tm_path -> TCL__TM_PATH (pure-Tcl .tm modules) # Same variable names land in pkg-config (.pc) files and in subproject # declare_dependency(variables: {...}), so this works uniformly for # system installs and fallbacks. Deps exporting neither (e.g. plain C # libraries like libtcc) are silently skipped. _tm_path_var = 'TCL' + tclver_major + '_' + tclver_minor + '_TM_PATH' _test_dep_ops = [] _bench_dep_ops = [] foreach _dep : tea_test_deps _pkg_path = _dep.get_variable('tcl_pkg_path', default_value: '') if _pkg_path != '' _test_dep_ops += {'var': 'TCLLIBPATH', 'value': _pkg_path} endif _tm_path = _dep.get_variable('tcl_tm_path', default_value: '') if _tm_path != '' _test_dep_ops += {'var': _tm_path_var, 'value': _tm_path} endif endforeach foreach _dep : tea_bench_deps _pkg_path = _dep.get_variable('tcl_pkg_path', default_value: '') if _pkg_path != '' _bench_dep_ops += {'var': 'TCLLIBPATH', 'value': _pkg_path} endif _tm_path = _dep.get_variable('tcl_tm_path', default_value: '') if _tm_path != '' _bench_dep_ops += {'var': _tm_path_var, 'value': _tm_path} endif endforeach # Write a sentinel file with the meson build root so that package init # scripts can locate build-dir or source artifacts. Not installed. _builddir_conf = configuration_data() _builddir_conf.set('BUILDDIR', meson.project_build_root()) _builddir_conf.set('SOURCEDIR', meson.global_source_root()) configure_file( output: '__builddir', configuration: _builddir_conf, input: '__builddir.in', ) configure_file( output: '__srcdir', configuration: _builddir_conf, input: '__srcdir.in', ) if tclsh.found() and not meson.is_subproject() # Build test_env and bench_env as fresh environment() objects rather # than aliasing tea_host_env. meson stores the env arg to test() by # reference (not as a snapshot), so any later modification — like # adding bench-only deps for benchmark() — would leak back into the # already-registered test(). Replaying tea_host_env_ops keeps base # PATH/TCLLIBPATH/TCL_LIBRARY content intact in both, while each env # gets only the dep additions appropriate for its scope. test_env = environment() foreach _op : tea_host_env_ops + _test_dep_ops if 'op' in _op and _op['op'] == 'set' test_env.set(_op['var'], _op['value']) else # 'prepend' if _op['var'] == 'TCLLIBPATH' test_env.prepend(_op['var'], _op['value'], separator: ' ') else test_env.prepend(_op['var'], _op['value']) endif endif endforeach test_env.set('ERROR_ON_FAILURES', '1') bench_env = environment() foreach _op : tea_host_env_ops + _test_dep_ops + _bench_dep_ops if 'op' in _op and _op['op'] == 'set' bench_env.set(_op['var'], _op['value']) else # 'prepend' if _op['var'] == 'TCLLIBPATH' bench_env.prepend(_op['var'], _op['value'], separator: ' ') else bench_env.prepend(_op['var'], _op['value']) endif endif endforeach bench_env.set('ERROR_ON_FAILURES', '1') # Compose the tcltest -load script: source the generated pkgIndex.tcl # from the build dir and require the package under test. Driving # tclsh directly (via the thin test_preamble.tcl below — in-process # `source`, not a subprocess) means `meson test --test-args` flows # through to tcltest's configure, and `meson test --wrapper valgrind` # instruments the tclsh running the tests without --trace-children. # The -load script itself gets re-used verbatim by tcltest when it # spawns per-file subprocesses under `singleProcess 0`, so keep it # self-contained (no reliance on anything the preamble sets up). # # Path and package name are interpolated inside Tcl {...} brace # quoting, which is literal except for brace matching — so we only # need to backslash-escape any braces they contain. # # The pkgIndex.tcl file expects `$dir` to be the directory that # contains it (Tcl's normal package-require machinery sets this). # Source it via [apply] with a dir argument so `$dir` is bound # locally to the build dir; otherwise the source fails with # "can't read $dir", tcltest swallows it, and the fallback # `package require` in loadtdom.tcl silently loads an installed # copy of the package instead of the one we just built. _pkgdir_esc = meson.current_build_dir() \ .replace('{', '\\{').replace('}', '\\}') _pname_esc = meson.project_name() \ .replace('{', '\\{').replace('}', '\\}') _loadscript = 'apply {dir {' \ + 'source [file join $dir pkgIndex.tcl]; ' \ + 'package require -exact {' + _pname_esc + '} ' \ + meson.project_version() \ + '}} {' + _pkgdir_esc + '}' _test_deps_met = true foreach _dep : tea_test_deps if not _dep.found() _test_deps_met = false endif endforeach if _test_deps_met test('tcltest', tclsh, args: [ # test_preamble.tcl splices $env(TESTFLAGS) onto $::argv before # sourcing tests/all.tcl, preserving the backwards-compatible way # of injecting top-level tcltest options (like -match / -file) — # those have to land in argv *before* the test script's own # `configure {*}$argv` runs, which is too early for the -load # script hook to reach. meson.current_source_dir() / 'tools/test_preamble.tcl', meson.project_source_root() / 'tests/all.tcl', '-load', _loadscript, ], verbose: true, depends: [pkg_so] + tea_extra_depends, env: test_env, ) endif _bench_deps_met = true foreach _dep : tea_bench_deps if not _dep.found() _bench_deps_met = false endif endforeach if _bench_deps_met benchmark('bench', tclsh, depends: [pkg_so] + tea_extra_depends + tea_bench_extra_depends, args: meson.project_source_root() / 'teabase/run_bench.tcl', verbose: true, workdir: meson.project_source_root() / 'bench', timeout: 120, env: bench_env, ) endif vim = find_program('vim', version: '>=8.1', native: true, required: false) if not vim.found() vim = find_program('nvim', version: '>=0.4', native: true, required: false) endif if vim.found() and not tcl_is_internal and is_variable('build_tclsh') and build_tclsh.found() termdebug_arg = run_command(build_tclsh, meson.current_source_dir() / 'tools/make_termdebug_arg.tcl', meson.current_build_dir(), meson.project_source_root(), tclsh.full_path(), meson.project_name(), meson.project_version(), check: true, env: tea_build_env, ).stdout().strip() td_conf = configuration_data() td_conf.set('TERMDEBUG_ARG', termdebug_arg) termdebug_vim = configure_file( input: 'termdebug.vim.in', output: 'termdebug.vim', configuration: td_conf, ) message('Found Vim/Neovim: ' + vim.full_path() + ' for vim-gdb target') run_target('vim-gdb', command: [vim, '-S', termdebug_vim], ) endif endif subdir('pkg_config_h') # Fold test/bench dep additions into tea_host_env now that test/bench # environments have been built fresh (so they aren't affected by these # late mutations). devenv-launched tclsh ought to see the same package # search paths as bench_env — important for subproject-fallback deps # that aren't system-installed. foreach _op : _test_dep_ops + _bench_dep_ops if 'op' in _op and _op['op'] == 'set' tea_host_env.set(_op['var'], _op['value']) else if _op['var'] == 'TCLLIBPATH' tea_host_env.prepend(_op['var'], _op['value'], separator: ' ') else tea_host_env.prepend(_op['var'], _op['value']) endif endif endforeach meson.add_devenv(tea_host_env) parse_args-v0.6.3/teabase/pkg_config_h/0000755000175100017510000000000015176457507017504 5ustar runnerrunnerparse_args-v0.6.3/teabase/pkg_config_h/meson.build0000644000175100017510000000021715176457507021646 0ustar runnerrunner# Generate the config.h in a private location that is not in the exported include path configure_file(output: 'config.h', configuration: conf) parse_args-v0.6.3/teabase/getbytes.h0000644000175100017510000000363615176457507017076 0ustar runnerrunner#ifndef _GETBYTES_H #define _GETBYTES_H #if GETBYTES_SHIM #include #include /* * Polyfill for Tcl_GetBytesFromObj, added in Tcl 8.7/9.0. Returns the * byte-array interpretation of obj, or NULL (with a TCL VALUE BYTES * errorCode and readable error message) if the string representation * contains any characters outside the 0..255 range. * * This matches Tcl 9's Tcl_GetBytesFromObj semantics. Older * Tcl_GetByteArrayFromObj accepted any string, silently truncating * Unicode characters to their low 8 bits — which is usually wrong when * the caller wanted "bytes or error". */ static inline uint8_t* Tcl_GetBytesFromObj(Tcl_Interp* interp, Tcl_Obj* obj, Tcl_Size* lenPtr) { Tcl_Size bytelen; uint8_t* bytes; /* Already a bytearray internal rep — no validation needed. */ if (obj->typePtr != NULL && strcmp(obj->typePtr->name, "bytearray") == 0) { bytes = Tcl_GetByteArrayFromObj(obj, &bytelen); if (lenPtr) *lenPtr = bytelen; return bytes; } /* * Validate the string rep is pure-byte before shimmering to bytearray. * The error message matches Tcl 9's Tcl_GetBytesFromObj: the index * is the number of valid bytes seen so far (one per ch<=0xFF), and * the bad-character field is the tail of the string starting at the * offending character. */ int strlen_int; const char* str = Tcl_GetStringFromObj(obj, &strlen_int); int good = 0; for (int i=0; i < strlen_int; ) { Tcl_UniChar ch; int chlen = Tcl_UtfToUniChar(str + i, &ch); if (ch > 0xFF) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "expected byte sequence but character %d was '%s' (U+%06X)", good, str + i, (int)ch)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "BYTES", NULL); } return NULL; } i += chlen; good++; } bytes = Tcl_GetByteArrayFromObj(obj, &bytelen); if (lenPtr) *lenPtr = bytelen; return bytes; } #endif /* GETBYTES_SHIM */ #endif /* _GETBYTES_H */ parse_args-v0.6.3/teabase/dtest.tcl0000755000175100017510000000073215176457507016723 0ustar runnerrunner#!/usr/local/bin/tclsh file mkdir /tmp/build cd /tmp/build foreach file [glob -nocomplain /src/local/*] { set fqfn [file join /src/local $file] if {[file exists $fqfn]} { exec cp -r $fqfn . } } exec -ignorestderr autoconf >@ stdout exec -ignorestderr ./configure --enable-symbols --with-tcl=/usr/local/lib --enable-testmode >@ stdout file delete -force -- {*}[glob -nocomplain tools/bin/*] local exec -ignorestderr make clean test TESTFLAGS=[lindex $argv 0] >@ stdout parse_args-v0.6.3/teabase/.gitignore0000644000175100017510000000001715176457507017055 0ustar runnerrunnerMakefile *.swp parse_args-v0.6.3/teabase/names.c0000644000175100017510000005706015176457507016346 0ustar runnerrunner#define _POSIX_C_SOURCE 200809L #define _XOPEN_SOURCE 700 #include #include "names.h" #include #include #include #include int adjectivesc = 0; static const char* adjectives[] = { "Different", "Used", "Important", "Every", "Large", "Available", "Popular", "Able", "Basic", "Known", "Various", "Difficult", "Several", "United", "Historical", "Hot", "Useful", "Mental", "Scared", "Additional", "Emotional", "Old", "Political", "Similar", "Healthy", "Financial", "Medical", "Traditional", "Federal", "Entire", "Strong", "Actual", "Significant", "Successful", "Electrical", "Expensive", "Pregnant", "Intelligent", "Interesting", "Poor", "Happy", "Responsible", "Cute", "Helpful", "Recent", "Willing", "Nice", "Wonderful", "Impossible", "Serious", "Huge", "Rare", "Technical", "Typical", "Competitive", "Critical", "Electronic", "Immediate", "Aware", "Educational", "Environmental", "Global", "Legal", "Relevant", "Accurate", "Capable", "Dangerous", "Dramatic", "Efficient", "Powerful", "Foreign", "Hungry", "Practical", "Psychological", "Severe", "Suitable", "Numerous", "Sufficient", "Unusual", "Consistent", "Cultural", "Existing", "Famous", "Pure", "Afraid", "Obvious", "Careful", "Latter", "Unhappy", "Acceptable", "Aggressive", "Boring", "Distinct", "Eastern", "Logical", "Reasonable", "Strict", "Administrative", "Automatic", "Civil", "Former", "Massive", "Southern", "Unfair", "Visible", "Alive", "Angry", "Desperate", "Exciting", "Friendly", "Lucky", "Realistic", "Sorry", "Ugly", "Unlikely", "Anxious", "Comprehensive", "Curious", "Impressive", "Informal", "Inner", "Pleasant", "Sexual", "Sudden", "Terrible", "Unable", "Weak", "Wooden", "Asleep", "Confident", "Conscious", "Decent", "Embarrassed", "Guilty", "Lonely", "Mad", "Nervous", "Odd", "Remarkable", "Substantial", "Suspicious", "Tall", "Tiny", "More", "Some", "One", "All", "Many", "Most", "Other", "Such", "Even", "New", "Just", "Good", "Any", "Each", "Much", "Own", "Great", "Another", "Same", "Few", "Free", "Right", "Still", "Best", "Public", "Human", "Both", "Local", "Sure", "Better", "General", "Specific", "Enough", "Long", "Small", "Less", "High", "Certain", "Little", "Common", "Next", "Simple", "Hard", "Past", "Big", "Possible", "Particular", "Real", "Major", "Personal", "Current", "Left", "National", "Least", "Natural", "Physical", "Short", "Last", "Single", "Individual", "Main", "Potential", "Professional", "International", "Lower", "Open", "According", "Alternative", "Special", "Working", "True", "Whole", "Clear", "Dry", "Easy", "Cold", "Commercial", "Full", "Low", "Primary", "Worth", "Necessary", "Positive", "Present", "Close", "Creative", "Green", "Late", "Fit", "Glad", "Proper", "Complex", "Content", "Due", "Effective", "Middle", "Regular", "Fast", "Independent", "Original", "Wide", "Beautiful", "Complete", "Active", "Negative", "Safe", "Visual", "Wrong", "Ago", "Quick", "Ready", "Straight", "White", "Direct", "Excellent", "Extra", "Junior", "Pretty", "Unique", "Classic", "Final", "Overall", "Private", "Separate", "Western", "Alone", "Familiar", "Official", "Perfect", "Bright", "Broad", "Comfortable", "Flat", "Rich", "Warm", "Young", "Heavy", "Valuable", "Correct", "Leading", "Slow", "Clean", "Fresh", "Normal", "Secret", "Tough", "Brown", "Cheap", "Deep", "Objective", "Secure", "Thin", "Chemical", "Cool", "Extreme", "Exact", "Fair", "Fine", "Formal", "Opposite", "Remote", "Total", "Vast", "Lost", "Smooth", "Dark", "Double", "Equal", "Firm", "Frequent", "Internal", "Sensitive", "Constant", "Minor", "Previous", "Raw", "Soft", "Solid", "Weird", "Amazing", "Annual", "Busy", "Dead", "False", "Round", "Sharp", "Thick", "Wise", "Equivalent", "Initial", "Narrow", "Nearby", "Proud", "Spiritual", "Wild", "Adult", "Apart", "Brief", "Crazy", "Prior", "Rough", "Sad", "Sick", "Strange", "External", "Illegal", "Loud", "Mobile", "Nasty", "Ordinary", "Royal", "Senior", "Super", "Tight", "Upper", "Yellow", "Dependent", "Funny", "Gross", "Ill", "Spare", "Sweet", "Upstairs", "Usual", "Brave", "Calm", "Dirty", "Downtown", "Grand", "Honest", "Loose", "Male", "Quiet", "Brilliant", "Dear", "Drunk", "Empty", "Female", "Inevitable", "Neat", "Ok", "Representative", "Silly", "Slight", "Smart", "Stupid", "Temporary", "Weekly", "That", "This", "What", "Which", "Time", "These", "Work", "No", "Only", "Then", "First", "Money", "Over", "Business", "His", "Game", "Think", "After", "Life", "Day", "Home", "Economy", "Away", "Either", "Fat", "Key", "Training", "Top", "Level", "Far", "Fun", "House", "Kind", "Future", "Action", "Live", "Period", "Subject", "Mean", "Stock", "Chance", "Beginning", "Upset", "Chicken", "Head", "Material", "Salt", "Car", "Appropriate", "Inside", "Outside", "Standard", "Medium", "Choice", "North", "Square", "Born", "Capital", "Shot", "Front", "Living", "Plastic", "Express", "Feeling", "Otherwise", "Plus", "Savings", "Animal", "Budget", "Minute", "Character", "Maximum", "Novel", "Plenty", "Select", "Background", "Forward", "Glass", "Joint", "Master", "Red", "Vegetable", "Ideal", "Kitchen", "Mother", "Party", "Relative", "Signal", "Street", "Connect", "Minimum", "Sea", "South", "Status", "Daughter", "Hour", "Trick", "Afternoon", "Gold", "Mission", "Agent", "Corner", "East", "Neither", "Parking", "Routine", "Swimming", "Winter", "Airline", "Designer", "Dress", "Emergency", "Evening", "Extension", "Holiday", "Horror", "Mountain", "Patient", "Proof", "West", "Wine", "Expert", "Native", "Opening", "Silver", "Waste", "Plane", "Leather", "Purple", "Specialist", "Bitter", "Incident", "Motor", "Pretend", "Prize", "Resident", NULL }; int nounsc = 0; static const char* nouns[] = { "People", "History", "Way", "Art", "World", "Information", "Map", "Two", "Family", "Government", "Health", "System", "Computer", "Meat", "Year", "Thanks", "Music", "Person", "Reading", "Method", "Data", "Food", "Understanding", "Theory", "Law", "Bird", "Literature", "Problem", "Software", "Control", "Knowledge", "Power", "Ability", "Economics", "Love", "Internet", "Television", "Science", "Library", "Nature", "Fact", "Product", "Idea", "Temperature", "Investment", "Area", "Society", "Activity", "Story", "Industry", "Media", "Thing", "Oven", "Community", "Definition", "Safety", "Quality", "Development", "Language", "Management", "Player", "Variety", "Video", "Week", "Security", "Country", "Exam", "Movie", "Organization", "Equipment", "Physics", "Analysis", "Policy", "Series", "Thought", "Basis", "Boyfriend", "Direction", "Strategy", "Technology", "Army", "Camera", "Freedom", "Paper", "Environment", "Child", "Instance", "Month", "Truth", "Marketing", "University", "Writing", "Article", "Department", "Difference", "Goal", "News", "Audience", "Fishing", "Growth", "Income", "Marriage", "User", "Combination", "Failure", "Meaning", "Medicine", "Philosophy", "Teacher", "Communication", "Night", "Chemistry", "Disease", "Disk", "Energy", "Nation", "Road", "Role", "Soup", "Advertising", "Location", "Success", "Addition", "Apartment", "Education", "Math", "Moment", "Painting", "Politics", "Attention", "Decision", "Event", "Property", "Shopping", "Student", "Wood", "Competition", "Distribution", "Entertainment", "Office", "Population", "President", "Unit", "Category", "Cigarette", "Context", "Introduction", "Opportunity", "Performance", "Driver", "Flight", "Length", "Magazine", "Newspaper", "Relationship", "Teaching", "Cell", "Dealer", "Finding", "Lake", "Member", "Message", "Phone", "Scene", "Appearance", "Association", "Concept", "Customer", "Death", "Discussion", "Housing", "Inflation", "Insurance", "Mood", "Woman", "Advice", "Blood", "Effort", "Expression", "Importance", "Opinion", "Payment", "Reality", "Responsibility", "Situation", "Skill", "Statement", "Wealth", "Application", "City", "County", "Depth", "Estate", "Foundation", "Grandmother", "Heart", "Perspective", "Photo", "Recipe", "Studio", "Topic", "Collection", "Depression", "Imagination", "Passion", "Percentage", "Resource", "Setting", "Ad", "Agency", "College", "Connection", "Criticism", "Debt", "Description", "Memory", "Patience", "Secretary", "Solution", "Administration", "Aspect", "Attitude", "Director", "Personality", "Psychology", "Recommendation", "Response", "Selection", "Storage", "Version", "Alcohol", "Argument", "Complaint", "Contract", "Emphasis", "Highway", "Loss", "Membership", "Possession", "Preparation", "Steak", "Union", "Agreement", "Cancer", "Currency", "Employment", "Engineering", "Entry", "Interaction", "Mixture", "Preference", "Region", "Republic", "Tradition", "Virus", "Actor", "Classroom", "Delivery", "Device", "Difficulty", "Drama", "Election", "Engine", "Football", "Guidance", "Hotel", "Owner", "Priority", "Protection", "Suggestion", "Tension", "Variation", "Anxiety", "Atmosphere", "Awareness", "Bath", "Bread", "Candidate", "Climate", "Comparison", "Confusion", "Construction", "Elevator", "Emotion", "Employee", "Employer", "Guest", "Height", "Leadership", "Mall", "Manager", "Operation", "Recording", "Sample", "Transportation", "Charity", "Cousin", "Disaster", "Editor", "Efficiency", "Excitement", "Extent", "Feedback", "Guitar", "Homework", "Leader", "Mom", "Outcome", "Permission", "Presentation", "Promotion", "Reflection", "Refrigerator", "Resolution", "Revenue", "Session", "Singer", "Tennis", "Basket", "Bonus", "Cabinet", "Childhood", "Church", "Clothes", "Coffee", "Dinner", "Drawing", "Hair", "Hearing", "Initiative", "Judgment", "Lab", "Measurement", "Mode", "Mud", "Orange", "Poetry", "Police", "Possibility", "Procedure", "Queen", "Ratio", "Relation", "Restaurant", "Satisfaction", "Sector", "Signature", "Significance", "Song", "Tooth", "Town", "Vehicle", "Volume", "Wife", "Accident", "Airport", "Appointment", "Arrival", "Assumption", "Baseball", "Chapter", "Committee", "Conversation", "Database", "Enthusiasm", "Error", "Explanation", "Farmer", "Gate", "Girl", "Hall", "Historian", "Hospital", "Injury", "Instruction", "Maintenance", "Manufacturer", "Meal", "Perception", "Pie", "Poem", "Presence", "Proposal", "Reception", "Replacement", "Revolution", "River", "Son", "Speech", "Tea", "Village", "Warning", "Winner", "Worker", "Writer", "Assistance", "Breath", "Buyer", "Chest", "Chocolate", "Conclusion", "Contribution", "Cookie", "Courage", "Dad", "Desk", "Drawer", "Establishment", "Examination", "Garbage", "Grocery", "Honey", "Impression", "Improvement", "Independence", "Insect", "Inspection", "Inspector", "King", "Ladder", "Menu", "Penalty", "Piano", "Potato", "Profession", "Professor", "Quantity", "Reaction", "Requirement", "Salad", "Sister", "Supermarket", "Tongue", "Weakness", "Wedding", "Affair", "Ambition", "Analyst", "Apple", "Assignment", "Assistant", "Bathroom", "Bedroom", "Beer", "Birthday", "Celebration", "Championship", "Cheek", "Client", "Consequence", "Departure", "Diamond", "Dirt", "Ear", "Fortune", "Friendship", "Funeral", "Gene", "Girlfriend", "Hat", "Indication", "Intention", "Lady", "Midnight", "Negotiation", "Obligation", "Passenger", "Pizza", "Platform", "Poet", "Pollution", "Recognition", "Reputation", "Shirt", "Sir", "Speaker", "Stranger", "Surgery", "Sympathy", "Tale", "Throat", "Trainer", "Uncle", "Youth", "Time", "Work", "Film", "Water", "Money", "Example", "While", "Business", "Study", "Game", "Life", "Form", "Air", "Day", "Place", "Number", "Part", "Field", "Fish", "Back", "Process", "Heat", "Hand", "Experience", "Job", "Book", "End", "Point", "Type", "Home", "Economy", "Value", "Body", "Market", "Guide", "Interest", "State", "Radio", "Course", "Company", "Price", "Size", "Card", "List", "Mind", "Trade", "Line", "Care", "Group", "Risk", "Word", "Fat", "Force", "Key", "Light", "Training", "Name", "School", "Top", "Amount", "Level", "Order", "Practice", "Research", "Sense", "Service", "Piece", "Web", "Boss", "Sport", "Fun", "House", "Page", "Term", "Test", "Answer", "Sound", "Focus", "Matter", "Kind", "Soil", "Board", "Oil", "Picture", "Access", "Garden", "Range", "Rate", "Reason", "Future", "Site", "Demand", "Exercise", "Image", "Case", "Cause", "Coast", "Action", "Age", "Bad", "Boat", "Record", "Result", "Section", "Building", "Mouse", "Cash", "Class", "Nothing", "Period", "Plan", "Store", "Tax", "Side", "Subject", "Space", "Rule", "Stock", "Weather", "Chance", "Figure", "Man", "Model", "Source", "Beginning", "Earth", "Program", "Chicken", "Design", "Feature", "Head", "Material", "Purpose", "Question", "Rock", "Salt", "Act", "Birth", "Car", "Dog", "Object", "Scale", "Sun", "Note", "Profit", "Rent", "Speed", "Style", "War", "Bank", "Craft", "Half", "Inside", "Outside", "Standard", "Bus", "Exchange", "Eye", "Fire", "Position", "Pressure", "Stress", "Advantage", "Benefit", "Box", "Frame", "Issue", "Step", "Cycle", "Face", "Item", "Metal", "Paint", "Review", "Room", "Screen", "Structure", "View", "Account", "Ball", "Discipline", "Medium", "Share", "Balance", "Bit", "Black", "Bottom", "Choice", "Gift", "Impact", "Machine", "Shape", "Tool", "Wind", "Address", "Average", "Career", "Culture", "Morning", "Pot", "Sign", "Table", "Task", "Condition", "Contact", "Credit", "Egg", "Hope", "Ice", "Network", "North", "Square", "Attempt", "Date", "Effect", "Link", "Post", "Star", "Voice", "Capital", "Challenge", "Friend", "Self", "Shot", "Brush", "Couple", "Debate", "Exit", "Front", "Function", "Lack", "Living", "Plant", "Plastic", "Spot", "Summer", "Taste", "Theme", "Track", "Wing", "Brain", "Button", "Click", "Desire", "Foot", "Gas", "Influence", "Notice", "Rain", "Wall", "Base", "Damage", "Distance", "Feeling", "Pair", "Savings", "Staff", "Sugar", "Target", "Text", "Animal", "Author", "Budget", "Discount", "File", "Ground", "Lesson", "Minute", "Officer", "Phase", "Reference", "Register", "Sky", "Stage", "Stick", "Title", "Trouble", "Bowl", "Bridge", "Campaign", "Character", "Club", "Edge", "Evidence", "Fan", "Letter", "Lock", "Maximum", "Novel", "Option", "Pack", "Park", "Plenty", "Quarter", "Skin", "Sort", "Weight", "Baby", "Background", "Carry", "Dish", "Factor", "Fruit", "Glass", "Joint", "Master", "Muscle", "Red", "Strength", "Traffic", "Trip", "Vegetable", "Appeal", "Chart", "Gear", "Ideal", "Kitchen", "Land", "Log", "Mother", "Net", "Party", "Principle", "Relative", "Sale", "Season", "Signal", "Spirit", "Street", "Tree", "Wave", "Belt", "Bench", "Commission", "Copy", "Drop", "Minimum", "Path", "Progress", "Project", "Sea", "South", "Status", "Stuff", "Ticket", "Tour", "Angle", "Blue", "Breakfast", "Confidence", "Daughter", "Degree", "Doctor", "Dot", "Dream", "Duty", "Essay", "Father", "Fee", "Finance", "Hour", "Juice", "Limit", "Luck", "Milk", "Mouth", "Peace", "Pipe", "Seat", "Stable", "Storm", "Substance", "Team", "Trick", "Afternoon", "Bat", "Beach", "Blank", "Catch", "Chain", "Consideration", "Cream", "Crew", "Detail", "Gold", "Interview", "Kid", "Mark", "Match", "Mission", "Pain", "Pleasure", "Score", "Screw", "Sex", "Shop", "Shower", "Suit", "Tone", "Window", "Agent", "Band", "Block", "Bone", "Calendar", "Cap", "Coat", "Contest", "Corner", "Court", "Cup", "District", "Door", "East", "Finger", "Garage", "Guarantee", "Hole", "Hook", "Implement", "Layer", "Lecture", "Lie", "Manner", "Meeting", "Nose", "Parking", "Partner", "Profile", "Respect", "Rice", "Routine", "Schedule", "Swimming", "Telephone", "Tip", "Winter", "Airline", "Bag", "Battle", "Bed", "Bill", "Bother", "Cake", "Code", "Curve", "Designer", "Dimension", "Dress", "Ease", "Emergency", "Evening", "Extension", "Farm", "Fight", "Gap", "Grade", "Holiday", "Horror", "Horse", "Host", "Husband", "Loan", "Mistake", "Mountain", "Nail", "Noise", "Occasion", "Package", "Patient", "Pause", "Phrase", "Proof", "Race", "Relief", "Sand", "Sentence", "Shoulder", "Smoke", "Stomach", "String", "Tourist", "Towel", "Vacation", "West", "Wheel", "Wine", "Arm", "Aside", "Associate", "Bet", "Blow", "Border", "Branch", "Breast", "Brother", "Buddy", "Bunch", "Chip", "Coach", "Cross", "Document", "Draft", "Dust", "Expert", "Floor", "God", "Golf", "Habit", "Iron", "Judge", "Knife", "Landscape", "League", "Mail", "Mess", "Native", "Opening", "Parent", "Pattern", "Pin", "Pool", "Pound", "Request", "Salary", "Shame", "Shelter", "Shoe", "Silver", "Tackle", "Tank", "Trust", "Assist", "Bake", "Bar", "Bell", "Bike", "Blame", "Boy", "Brick", "Chair", "Closet", "Clue", "Collar", "Comment", "Conference", "Devil", "Diet", "Fear", "Fuel", "Glove", "Jacket", "Lunch", "Monitor", "Mortgage", "Nurse", "Pace", "Panic", "Peak", "Plane", "Reward", "Row", "Sandwich", "Shock", "Spite", "Spray", "Surprise", "Till", "Transition", "Weekend", "Welcome", "Yard", "Alarm", "Bend", "Bicycle", "Bite", "Blind", "Bottle", "Cable", "Candle", "Clerk", "Cloud", "Concert", "Counter", "Flower", "Grandfather", "Harm", "Knee", "Lawyer", "Leather", "Load", "Mirror", "Neck", "Pension", "Plate", "Purple", "Ruin", "Ship", "Skirt", "Slice", "Snow", "Specialist", "Stroke", "Switch", "Trash", "Tune", "Zone", "Anger", "Award", "Bid", "Bitter", "Boot", "Bug", "Camp", "Candy", "Carpet", "Cat", "Champion", "Channel", "Clock", "Comfort", "Cow", "Crack", "Engineer", "Entrance", "Fault", "Grass", "Guy", "Hell", "Highlight", "Incident", "Island", "Joke", "Jury", "Leg", "Lip", "Mate", "Motor", "Nerve", "Passage", "Pen", "Pride", "Priest", "Prize", "Promise", "Resident", "Resort", "Ring", "Roof", "Rope", "Sail", "Scheme", "Script", "Sock", "Station", "Toe", "Tower", "Truck", "Witness", "A", "You", "It", "Can", "Will", "If", "One", "Many", "Most", "Other", "Use", "Make", "Good", "Look", "Help", "Go", "Great", "Being", "Few", "Might", "Still", "Public", "Read", "Keep", "Start", "Give", "Human", "Local", "General", "She", "Specific", "Long", "Play", "Feel", "High", "Tonight", "Put", "Common", "Set", "Change", "Simple", "Past", "Big", "Possible", "Particular", "Today", "Major", "Personal", "Current", "National", "Cut", "Natural", "Physical", "Show", "Try", "Check", "Second", "Call", "Move", "Pay", "Let", "Increase", "Single", "Individual", "Turn", "Ask", "Buy", "Guard", "Hold", "Main", "Offer", "Potential", "Professional", "International", "Travel", "Cook", "Alternative", "Following", "Special", "Working", "Whole", "Dance", "Excuse", "Cold", "Commercial", "Low", "Purchase", "Deal", "Primary", "Worth", "Fall", "Necessary", "Positive", "Produce", "Search", "Present", "Spend", "Talk", "Creative", "Tell", "Cost", "Drive", "Green", "Support", "Glad", "Remove", "Return", "Run", "Complex", "Due", "Effective", "Middle", "Regular", "Reserve", "Independent", "Leave", "Original", "Reach", "Rest", "Serve", "Watch", "Beautiful", "Charge", "Active", "Break", "Negative", "Safe", "Stay", "Visit", "Visual", "Affect", "Cover", "Report", "Rise", "Walk", "White", "Beyond", "Junior", "Pick", "Unique", "Anything", "Classic", "Final", "Lift", "Mix", "Private", "Stop", "Teach", "Western", "Concern", "Familiar", "Fly", "Official", "Broad", "Comfortable", "Gain", "Maybe", "Rich", "Save", "Stand", "Young", "Fail", "Heavy", "Hello", "Lead", "Listen", "Valuable", "Worry", "Handle", "Leading", "Meet", "Release", "Sell", "Finish", "Normal", "Press", "Ride", "Secret", "Spread", "Spring", "Tough", "Wait", "Brown", "Deep", "Display", "Flow", "Hit", "Objective", "Shoot", "Touch", "Cancel", "Chemical", "Cry", "Dump", "Extreme", "Push", "Conflict", "Eat", "Fill", "Formal", "Jump", "Kick", "Opposite", "Pass", "Pitch", "Remote", "Total", "Treat", "Vast", "Abuse", "Beat", "Burn", "Deposit", "Print", "Raise", "Sleep", "Somewhere", "Advance", "Anywhere", "Consist", "Dark", "Double", "Draw", "Equal", "Fix", "Hire", "Internal", "Join", "Kill", "Sensitive", "Tap", "Win", "Attack", "Claim", "Constant", "Drag", "Drink", "Guess", "Minor", "Pull", "Raw", "Soft", "Solid", "Wear", "Weird", "Wonder", "Annual", "Count", "Dead", "Doubt", "Feed", "Forever", "Impress", "Nobody", "Repeat", "Round", "Sing", "Slide", "Strip", "Whereas", "Wish", "Combine", "Command", "Dig", "Divide", "Equivalent", "Hang", "Hunt", "Initial", "March", "Mention", "Smell", "Spiritual", "Survey", "Tie", "Adult", "Brief", "Crazy", "Escape", "Gather", "Hate", "Prior", "Repair", "Rough", "Sad", "Scratch", "Sick", "Strike", "Employ", "External", "Hurt", "Illegal", "Laugh", "Lay", "Mobile", "Nasty", "Ordinary", "Respond", "Royal", "Senior", "Split", "Strain", "Struggle", "Swim", "Train", "Upper", "Wash", "Yellow", "Convert", "Crash", "Dependent", "Fold", "Funny", "Grab", "Hide", "Miss", "Permit", "Quote", "Recover", "Resolve", "Roll", "Sink", "Slip", "Spare", "Suspect", "Sweet", "Swing", "Twist", "Upstairs", "Usual", "Abroad", "Brave", "Calm", "Concentrate", "Estimate", "Grand", "Male", "Mine", "Prompt", "Quiet", "Refuse", "Regret", "Reveal", "Rush", "Shake", "Shift", "Shine", "Steal", "Suck", "Surround", "Anybody", "Bear", "Brilliant", "Dare", "Dear", "Delay", "Drunk", "Female", "Hurry", "Inevitable", "Invite", "Kiss", "Neat", "Pop", "Punch", "Quit", "Reply", "Representative", "Resist", "Rip", "Rub", "Silly", "Smile", "Spell", "Stretch", "Stupid", "Tear", "Temporary", "Tomorrow", "Wake", "Wrap", "Yesterday", NULL }; TCL_DECLARE_MUTEX(things_mutex) static int hash_tables_initialized = 0; static int maxlen_adjective = 0; static int maxlen_noun = 0; static Tcl_HashTable things; // Map void* -> name static Tcl_HashTable names; // Map name -> void* Tcl_ThreadDataKey outbuf; static void init() { int new; Tcl_HashEntry* he = NULL; struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); Tcl_MutexLock(&things_mutex); if (hash_tables_initialized == 0) { srandom((int)ts.tv_nsec); for (adjectivesc=0; adjectives[adjectivesc]; adjectivesc++) { int len = strlen(adjectives[adjectivesc]); if (len > maxlen_adjective) maxlen_adjective = len; } for (nounsc=0; nouns[nounsc]; nounsc++) { int len = strlen(nouns[nounsc]); if (len > maxlen_noun) maxlen_noun = len; } Tcl_InitHashTable(&things, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&names, TCL_STRING_KEYS); he = Tcl_CreateHashEntry(&names, "NULL", &new); Tcl_SetHashValue(he, NULL); hash_tables_initialized = 1; } Tcl_MutexUnlock(&things_mutex); } void names_shutdown() { Tcl_MutexLock(&things_mutex); if (hash_tables_initialized) { Tcl_HashEntry* he; Tcl_HashSearch search; for (he = Tcl_FirstHashEntry(&things, &search); he; he = Tcl_NextHashEntry(&search)) { char* chosen = Tcl_GetHashValue(he); ckfree(chosen); } Tcl_DeleteHashTable(&things); Tcl_DeleteHashTable(&names); hash_tables_initialized = 0; } Tcl_MutexUnlock(&things_mutex); Tcl_MutexFinalize(&things_mutex); } const char* randwords() { const int maxlen = 41; int adj = random() % adjectivesc; int noun = random() % nounsc; char* out = Tcl_GetThreadData(&outbuf, maxlen); snprintf(out, maxlen, "%s%s", adjectives[adj], nouns[noun]); return out; } void* thing(const char *const name) { Tcl_HashEntry* he_name = NULL; if (hash_tables_initialized == 0) init(); Tcl_MutexLock(&things_mutex); he_name = Tcl_FindHashEntry(&things, name); Tcl_MutexUnlock(&things_mutex); return Tcl_GetHashValue(he_name); } const char* name(const void *const thing) { int new; Tcl_HashEntry* he_thing = NULL; Tcl_HashEntry* he_name = NULL; const char* candidate = NULL; char* chosen = NULL; int chosenlen; if (thing == NULL) return "NULL"; if (hash_tables_initialized == 0) init(); Tcl_MutexLock(&things_mutex); he_thing = Tcl_CreateHashEntry(&things, thing, &new); Tcl_MutexUnlock(&things_mutex); if (!new) return Tcl_GetHashValue(he_thing); new = 0; while (!new) { candidate = randwords(); Tcl_MutexLock(&things_mutex); he_name = Tcl_CreateHashEntry(&names, candidate, &new); Tcl_MutexUnlock(&things_mutex); } chosenlen = strlen(candidate)+1; chosen = ckalloc(chosenlen); memcpy(chosen, candidate, chosenlen); Tcl_SetHashValue(he_name, thing); Tcl_SetHashValue(he_thing, chosen); return chosen; } // vim: ts=4 shiftwidth=4 parse_args-v0.6.3/teabase/run_bench.tcl0000644000175100017510000000250715176457507017542 0ustar runnerrunner# vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 set this_script [file normalize [info script]] set seen {} while {[file type $this_script] eq "link"} { dict set seen $this_script 1 set this_script [file normalize [file join [file dirname $this_script] [file readlink $this_script]]] if {[dict exists $seen $this_script]} { error "Symlink loop detected while trying to resolve [file normalize [info script]]" } } unset seen set here [file dirname $this_script] tcl::tm::path add $here package require teabase_bench proc main {} { global here env try { puts "[string repeat - 80]\nStarting benchmarks\n" if {[llength [glob -nocomplain -type f [file join [pwd] *.bench]]]} { set benchdir [pwd] } else { set benchdir [file dirname [file normalize [info script]]] } teabase_bench::run_benchmarks $benchdir {*}$::argv } on ok {} { exit 0 } trap {BENCH BAD_RESULT} {errmsg options} { puts stderr $errmsg exit 1 } trap {BENCH BAD_CODE} {errmsg options} { puts stderr $errmsg exit 1 } trap {BENCH INVALID_ARG} {errmsg options} { puts stderr $errmsg exit 1 } trap exit code { exit $code } on error {errmsg options} { puts stderr "Unhandled error from benchmark_mode: [dict get $options -errorinfo]" exit 2 } } main # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 parse_args-v0.6.3/teabase/tip445.h0000644000175100017510000000000015176457507024052 1parse_args-v0.6.3/generic/tip445.hustar runnerrunnerparse_args-v0.6.3/teabase/teabase.m40000644000175100017510000001705515176457507016745 0ustar runnerrunnerbuiltin(include,teabase/ax_gcc_builtin.m4) builtin(include,teabase/ax_cc_for_build.m4) builtin(include,teabase/ax_check_compile_flag.m4) AC_DEFUN([TEABASE_INIT], [ # Test for -fprofile-partial-training, introduced in GCC 10 AX_CHECK_COMPILE_FLAG([-fprofile-partial-training], [AC_SUBST(PGO_BUILD,"-fprofile-use=prof -fprofile-partial-training")], [AC_SUBST(PGO_BUILD,"-fprofile-use=prof")], [-Werror]) ]) AC_DEFUN([ENABLE_DEBUG], [ #trap 'echo "val: (${enable_debug+set}), debug_ok: ($debug_ok), DEBUG: ($DEBUG)"' DEBUG AC_MSG_CHECKING([whether to support debuging]) AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[Enable debug mode (not symbols, but portions of the code that are only used in debug builds) (default: no)]), [debug_ok=$enableval], [debug_ok=no]) if test "$debug_ok" = "yes" -o "${DEBUG}" = 1; then DEBUG=1 AC_MSG_RESULT([yes]) else DEBUG=0 AC_MSG_RESULT([no]) fi AC_DEFINE_UNQUOTED([DEBUG], [$DEBUG], [Debug enabled?]) #trap '' DEBUG ]) AC_DEFUN([ENABLE_UNLOAD], [ #trap 'echo "val: (${enable_unload+set}), unload_ok: ($unload_ok), UNLOAD: ($UNLOAD)"' DEBUG AC_MSG_CHECKING([whether to support unloading]) AC_ARG_ENABLE(unload, AS_HELP_STRING([--enable-unload],[Add support for unloading this shared library (default: no)]), [unload_ok=$enableval], [unload_ok=no]) if test "$unload_ok" = "yes" -o "${UNLOAD}" = 1; then UNLOAD=1 AC_MSG_RESULT([yes]) else UNLOAD=0 AC_MSG_RESULT([no]) fi AC_DEFINE_UNQUOTED([UNLOAD], [$UNLOAD], [Unload enabled?]) #trap '' DEBUG ]) AC_DEFUN([ENABLE_TESTMODE], [ #trap 'echo "val: (${enable_testmode+set}), testmode_ok: ($testmode_ok), TESTMODE: ($TESTMODE)"' DEBUG AC_MSG_CHECKING([whether to build in test mode]) AC_ARG_ENABLE(testmode, AS_HELP_STRING([--enable-testmode],[Build with whitebox testing hooks exposed (default: no)]), [testmode_ok=$enableval], [testmode_ok=no]) if test "$testmode_ok" = "yes" -o "${TESTMODE}" = 1; then TESTMODE=1 AC_MSG_RESULT([yes]) else TESTMODE=0 AC_MSG_RESULT([no]) fi AC_DEFINE_UNQUOTED([TESTMODE], [$TESTMODE], [Test mode enabled?]) #trap '' DEBUG ]) AC_DEFUN([CHECK_TESTMODE], [ AC_MSG_CHECKING([whether to build in test mode]) AC_ARG_ENABLE(testmode, [ --enable-testmode Build in test mode (default: off)], [enable_testmode=$enableval], [enable_testmode="no"]) AC_MSG_RESULT($enable_testmode) if test "$enable_testmode" = "yes" then AC_DEFINE(TESTMODE) fi ]) AC_DEFUN([TIP445], [ AC_MSG_CHECKING([whether we need to polyfill TIP 445]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $TCL_INCLUDE_SPEC" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[Tcl_ObjInternalRep ir;]])],[have_tcl_objintrep=yes],[have_tcl_objintrep=no]) CFLAGS="$saved_CFLAGS" if test "$have_tcl_objintrep" = yes; then AC_DEFINE(TIP445_SHIM, 0, [Do we need to polyfill TIP 445?]) AC_MSG_RESULT([no]) else AC_DEFINE(TIP445_SHIM, 1, [Do we need to polyfill TIP 445?]) AC_MSG_RESULT([yes]) fi ]) AC_DEFUN([CHECK_TCL_GETBYTESFROMOBJ], [ AC_MSG_CHECKING([whether we need to polyfill Tcl_GetBytesFromObj]) saved_CFLAGS="$CFLAGS" saved_LIBS="$LIBS" CFLAGS="$CFLAGS $TCL_INCLUDE_SPEC" LIBS="$LIBS $TCL_STUB_LIB_SPEC" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[Tcl_GetBytesFromObj(NULL, NULL, NULL);]])],[have_getbytes=yes],[have_getbytes=no]) CFLAGS="$saved_CFLAGS" LIBS="$saved_LIBS" if test "$have_getbytes" = yes; then AC_DEFINE(GETBYTES_SHIM, 0, [Do we need to polyfill Tcl_GetBytesFromObj?]) AC_MSG_RESULT([no]) else AC_DEFINE(GETBYTES_SHIM, 1, [Do we need to polyfill Tcl_GetBytesFromObj?]) AC_MSG_RESULT([yes]) fi ]) # All the best stuff seems to be Linux / glibc specific :( AC_DEFUN([CHECK_GLIBC], [ AC_MSG_CHECKING([for GNU libc]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ #if ! (defined __GLIBC__ || defined __GNU_LIBRARY__) # error "Not glibc" #endif ]])],[glibc=yes],[glibc=no]) if test "$glibc" = yes then AC_DEFINE(_GNU_SOURCE, 1, [Always define _GNU_SOURCE when using glibc]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ]) # We need a modified version of TEA_ADD_SOURCES because some of those files will be # generated *after* the macro runs, so it can't test for existence: AC_DEFUN([TEABASE_ADD_SOURCES], [ vars="$@" for i in $vars; do case $i in [\$]*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" PKG_OBJECTS="$PKG_OBJECTS $i" ;; *) PKG_SOURCES="$PKG_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done AC_SUBST(PKG_SOURCES) AC_SUBST(PKG_OBJECTS) ]) AC_DEFUN([DEDUP_STUBS], [ if test "${STUBS_BUILD}" = "1"; then AC_DEFINE(USE_DEDUP_STUBS, 1, [Use Dedup Stubs]) fi ]) AC_DEFUN([REURI_STUBS], [ if test "${STUBS_BUILD}" = "1"; then AC_DEFINE(USE_REURI_STUBS, 1, [Use ReURI Stubs]) fi ]) #------------------------------------------------------------------------ # HIGHEST_C_STANDARD # # Determines the highest C standard supported by the compiler. # Tests standards in descending order: C23, C17, C11, C99, C90. # # Arguments: # None # # Results: # Sets the following variables: # C_STD_CFLAGS - Compiler flags for the highest supported standard # C_STD_VERSION - The highest supported standard (e.g., "c23", "c17") #------------------------------------------------------------------------ AC_DEFUN([HIGHEST_C_STANDARD], [ AC_MSG_CHECKING([for highest supported C standard]) # Save current CFLAGS SAVE_CFLAGS_STD="$CFLAGS" # Test standards in descending order for std in c23 c17 c11 c99 c90; do CFLAGS="$SAVE_CFLAGS_STD -std=$std" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [C_STD_VERSION="$std" C_STD_CFLAGS="-std=$std" break], []) done # Restore CFLAGS CFLAGS="$SAVE_CFLAGS_STD" if test -n "$C_STD_VERSION"; then AC_MSG_RESULT([$C_STD_VERSION]) else AC_MSG_RESULT([none, using compiler default]) C_STD_CFLAGS="" C_STD_VERSION="default" fi AC_SUBST(C_STD_CFLAGS) AC_SUBST(C_STD_VERSION) ]) #------------------------------------------------------------------------ # CHECK_C23_EMBED # # Checks if the compiler supports the C23 #embed directive. # Should be called after HIGHEST_C_STANDARD if you want to use # the detected standard for testing. # # Arguments: # None # # Results: # Defines HAVE_C23_EMBED if #embed is supported #------------------------------------------------------------------------ AC_DEFUN([CHECK_C23_EMBED], [ AC_MSG_CHECKING([if compiler supports @%:@embed directive]) # Save current CFLAGS SAVE_CFLAGS_EMBED="$CFLAGS" # Use C_STD_CFLAGS if available, otherwise try with current flags if test -n "$C_STD_CFLAGS"; then CFLAGS="$SAVE_CFLAGS_EMBED $C_STD_CFLAGS" fi # Create a temporary test file to embed echo "test" > conftest_embed.txt AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ const char embedded_data@<:@@:>@ = { @%:@embed "conftest_embed.txt" , 0 }; int main(void) { return 0; } ]])], [AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_C23_EMBED], [1], [Define if compiler supports C23 @%:@embed directive]) have_c23_embed=yes], [AC_MSG_RESULT([no]) have_c23_embed=no]) # Clean up rm -f conftest_embed.txt # Restore CFLAGS CFLAGS="$SAVE_CFLAGS_EMBED" ]) parse_args-v0.6.3/teabase/subprojects/0000755000175100017510000000000015176457507017432 5ustar runnerrunnerparse_args-v0.6.3/teabase/subprojects/re2c.wrap0000644000175100017510000000046515176457507021165 0ustar runnerrunner[wrap-file] directory = re2c-4.3 source_url = https://github.com/skvadrik/re2c/releases/download/4.3/re2c-4.3.tar.xz source_filename = re2c-4.3.tar.xz source_hash = 51e88d6d6b6ab03eb7970276aca7e0db4f8e29c958b84b561d2fdcb8351c7150 patch_directory = re2c [provide] dependency_names = re2c program_names = re2c parse_args-v0.6.3/teabase/subprojects/rl_json.wrap0000644000175100017510000000045015176457507021772 0ustar runnerrunner[wrap-file] source_url = https://github.com/RubyLane/rl_json/releases/download/v0.17.1/rl_json-v0.17.1.tar.gz source_filename = rl_json-v0.17.1.tar.gz source_hash = 6f351ba66863604e9d2424a8ef0a3e147dd9fbfbea6d312803294eeeac3d9fe5 directory = rl_json-v0.17.1 [provide] dependency_names = rl_json parse_args-v0.6.3/teabase/subprojects/dedup.wrap0000644000175100017510000000021615176457507021425 0ustar runnerrunner[wrap-git] clone-recursive = true url = https://github.com/cyanogilvie/dedup revision = v0.9.22 depth = 1 [provide] dependency_names = dedup parse_args-v0.6.3/teabase/subprojects/libtommath.wrap0000644000175100017510000000047515176457507022473 0ustar runnerrunner[wrap-file] directory = libtommath-1.3.0 source_url = https://github.com/libtom/libtommath/releases/download/v1.3.0/ltm-1.3.0.tar.xz source_filename = ltm-1.3.0.tar.xz source_hash = 296272d93435991308eb73607600c034b558807a07e829e751142e65ccfa9d08 patch_directory = libtommath [provide] dependency_names = libtommath parse_args-v0.6.3/teabase/subprojects/tcl.wrap0000644000175100017510000000041315176457507021105 0ustar runnerrunner[wrap-file] directory = tcl source_url = https://core.tcl-lang.org/tcl/tarball/core-9-0-3/tcl.tar.gz source_filename = tcl-core-9-0-3.tar.gz source_hash = 3d56fe35d1da7b229676c11131272de82cb9cae8fff3ce369e9b1cb5ce1066bd patch_directory = tcl [provide] tcl = tcl_dep parse_args-v0.6.3/teabase/subprojects/packagefiles/0000755000175100017510000000000015176457507022050 5ustar runnerrunnerparse_args-v0.6.3/teabase/subprojects/packagefiles/tcl/0000755000175100017510000000000015176457507022632 5ustar runnerrunnerparse_args-v0.6.3/teabase/subprojects/packagefiles/tcl/meson.build0000644000175100017510000003403015176457507024774 0ustar runnerrunnerproject('tcl', 'c', version: '9.0.3', default_options: ['c_std=gnu11', 'werror=false', 'warning_level=1'], ) cc = meson.get_compiler('c') is_win = host_machine.system() == 'windows' generic_inc = include_directories('generic') compat_zlib_inc = include_directories('compat/zlib', 'compat/zlib/contrib/minizip') platform_inc = include_directories(is_win ? 'win' : 'unix') override_opts = ['werror=false', 'warning_level=1'] # --- Dependencies --- zlib_dep = dependency('zlib', required: false) tommath_dep = dependency('libtommath', version: '>=1.3.0', allow_fallback: true) if not zlib_dep.found() # Use Tcl's bundled zlib sources bundled_zlib = static_library('tclzlib', 'compat/zlib/adler32.c', 'compat/zlib/compress.c', 'compat/zlib/crc32.c', 'compat/zlib/deflate.c', 'compat/zlib/infback.c', 'compat/zlib/inffast.c', 'compat/zlib/inflate.c', 'compat/zlib/inftrees.c', 'compat/zlib/trees.c', 'compat/zlib/uncompr.c', 'compat/zlib/zutil.c', include_directories: compat_zlib_inc, override_options: override_opts, ) zlib_dep = declare_dependency( link_with: bundled_zlib, include_directories: compat_zlib_inc, ) endif # --- Common compile args --- dll_name = is_win ? 'tcl90.dll' : 'libtcl9.0.so' incdir = meson.project_source_root() / 'generic' builddir = meson.current_build_dir() tcl_library = meson.project_source_root() / 'library' tcl_args = [ '-DBUILD_tcl', '-DCFG_INSTALL_BINDIR="' + builddir + '"', '-DCFG_INSTALL_DOCDIR="' + builddir + '"', '-DCFG_INSTALL_INCDIR="' + incdir + '"', '-DCFG_INSTALL_LIBDIR="' + builddir + '"', '-DCFG_INSTALL_SCRDIR="' + tcl_library + '"', '-DCFG_RUNTIME_BINDIR="' + builddir + '"', '-DCFG_RUNTIME_DLLFILE="' + dll_name + '"', '-DCFG_RUNTIME_DOCDIR="' + builddir + '"', '-DCFG_RUNTIME_INCDIR="' + incdir + '"', '-DCFG_RUNTIME_LIBDIR="' + builddir + '"', '-DCFG_RUNTIME_SCRDIR="' + tcl_library + '"', '-DMP_FIXED_CUTOFFS', '-DMP_PREC=4', '-DPACKAGE_NAME="tcl"', '-DPACKAGE_VERSION="' + meson.project_version() + '"', '-DTCL_WITH_EXTERNAL_TOMMATH', ] if is_win if cc.get_id() != 'msvc' tcl_args += '-DHAVE_NO_SEH=1' endif tcl_args += '-DUNICODE' tcl_args += '-D_UNICODE' tcl_args += '-DTCL_CFGVAL_ENCODING="utf-8"' tcl_args += '-DSTDC_HEADERS=1' tcl_args += '-DZIPFS_BUILD=1' elif not is_win if cc.has_function_attribute('visibility') tcl_args += '-DMODULE_SCOPE=extern __attribute__((__visibility__("hidden")))' tcl_args += '-DHAVE_HIDDEN=1' else tcl_args += '-DMODULE_SCOPE=extern' endif tcl_args += '-D_GNU_SOURCE' tcl_args += '-D_REENTRANT=1' tcl_args += '-D_THREAD_SAFE=1' foreach h : [ 'inttypes.h', 'langinfo.h', 'stdint.h', 'strings.h', 'sys/epoll.h', 'sys/eventfd.h', 'sys/ioctl.h', 'sys/param.h', 'sys/stat.h', 'sys/time.h', 'termios.h', 'unistd.h', ] if cc.has_header(h) tcl_args += '-DHAVE_' + h.underscorify().to_upper() + '=1' endif endforeach foreach pair : [ ['cfmakeraw', ''], ['cpuid', ''], ['freeaddrinfo', ''], ['fts', ''], ['gai_strerror', ''], ['getaddrinfo', ''], ['getcwd', ''], ['getnameinfo', ''], ['gmtime_r', ''], ['localtime_r', ''], ['mkstemp', ''], ['mkstemps', ''], ['posix_spawnp', ''], ['pselect', ''], ['vfork', ''], ['waitpid', ''], ] if cc.has_function(pair[0]) tcl_args += '-DHAVE_' + pair[0].to_upper() + '=1' endif endforeach if cc.has_header_symbol('sys/epoll.h', 'epoll_create') tcl_args += '-DNOTIFIER_EPOLL=1' endif if cc.has_function('eventfd') tcl_args += '-DHAVE_EVENTFD=1' endif if cc.has_member('struct stat', 'st_blocks', prefix: '#include ') tcl_args += '-DHAVE_STRUCT_STAT_ST_BLOCKS=1' endif if cc.has_member('struct stat', 'st_blksize', prefix: '#include ') tcl_args += '-DHAVE_STRUCT_STAT_ST_BLKSIZE=1' endif if cc.has_member('struct tm', 'tm_gmtoff', prefix: '#include ') tcl_args += '-DHAVE_TM_GMTOFF=1' endif if cc.compiles('extern int timezone;\nint main(){return timezone;}') tcl_args += '-DHAVE_TIMEZONE_VAR=1' endif if cc.has_type('intptr_t', prefix: '#include ') tcl_args += '-DHAVE_INTPTR_T=1' endif if cc.has_type('uintptr_t', prefix: '#include ') tcl_args += '-DHAVE_UINTPTR_T=1' endif if cc.sizeof('long') >= 8 tcl_args += '-DTCL_WIDE_INT_IS_LONG=1' endif net_prefix = '#include \n#include \n#include ' foreach s : ['addrinfo', 'in6_addr', 'sockaddr_in6', 'sockaddr_storage'] if cc.has_type('struct ' + s, prefix: net_prefix) tcl_args += '-DHAVE_STRUCT_' + s.to_upper() + '=1' endif endforeach if cc.has_function('pthread_attr_setstacksize', prefix: '#include ') tcl_args += '-DHAVE_PTHREAD_ATTR_SETSTACKSIZE=1' endif if cc.has_function('pthread_atfork', prefix: '#include ') tcl_args += '-DHAVE_PTHREAD_ATFORK=1' endif tcl_args += '-DHAVE_BLKCNT_T=1' tcl_args += '-DHAVE_SIGNED_CHAR=1' tcl_args += '-D_LARGEFILE64_SOURCE=1' tcl_args += '-DNO_UNION_WAIT=1' tcl_args += '-DSTDC_HEADERS=1' tcl_args += '-DTCL_CFGVAL_ENCODING="utf-8"' tcl_args += '-DTCL_LIBRARY="' + tcl_library + '"' tcl_args += '-DTCL_PACKAGE_PATH="' + tcl_library + '"' tcl_args += '-DTCL_SHLIB_EXT=".so"' tcl_args += '-DTCL_UNLOAD_DLLS=1' tcl_args += '-DZIPFS_BUILD=1' if cc.has_function('dladdr', prefix: '#define _GNU_SOURCE\n#include ') tcl_args += '-DHAVE_DLADDR=1' endif endif fs = import('fs') # --- Generated headers --- # tclUuid.h — derived from fossil manifest.uuid manifest_uuid = fs.read('manifest.uuid').strip() uuid_conf = configuration_data() uuid_conf.set('UUID', manifest_uuid) tclUuid_h = configure_file( input: 'tclUuid.h.in', output: 'tclUuid.h', configuration: uuid_conf, ) # --- Source files --- generic_sources = files( 'generic/regcomp.c', 'generic/regerror.c', 'generic/regexec.c', 'generic/regfree.c', 'generic/tclAlloc.c', 'generic/tclArithSeries.c', 'generic/tclAssembly.c', 'generic/tclAsync.c', 'generic/tclBasic.c', 'generic/tclBinary.c', 'generic/tclCkalloc.c', 'generic/tclClock.c', 'generic/tclClockFmt.c', 'generic/tclCmdAH.c', 'generic/tclCmdIL.c', 'generic/tclCmdMZ.c', 'generic/tclCompCmds.c', 'generic/tclCompCmdsGR.c', 'generic/tclCompCmdsSZ.c', 'generic/tclCompExpr.c', 'generic/tclCompile.c', 'generic/tclConfig.c', 'generic/tclDate.c', 'generic/tclDictObj.c', 'generic/tclDisassemble.c', 'generic/tclEncoding.c', 'generic/tclEnsemble.c', 'generic/tclEnv.c', 'generic/tclEvent.c', 'generic/tclExecute.c', 'generic/tclFCmd.c', 'generic/tclFileName.c', 'generic/tclGet.c', 'generic/tclHash.c', 'generic/tclHistory.c', 'generic/tclIcu.c', 'generic/tclIndexObj.c', 'generic/tclInterp.c', 'generic/tclIO.c', 'generic/tclIOCmd.c', 'generic/tclIOGT.c', 'generic/tclIORChan.c', 'generic/tclIORTrans.c', 'generic/tclIOSock.c', 'generic/tclIOUtil.c', 'generic/tclLink.c', 'generic/tclListObj.c', 'generic/tclLiteral.c', 'generic/tclLoad.c', 'generic/tclMain.c', 'generic/tclNamesp.c', 'generic/tclNotify.c', 'generic/tclObj.c', 'generic/tclOptimize.c', 'generic/tclPanic.c', 'generic/tclParse.c', 'generic/tclPathObj.c', 'generic/tclPipe.c', 'generic/tclPkg.c', 'generic/tclPkgConfig.c', 'generic/tclPosixStr.c', 'generic/tclPreserve.c', 'generic/tclProc.c', 'generic/tclProcess.c', 'generic/tclRegexp.c', 'generic/tclResolve.c', 'generic/tclResult.c', 'generic/tclScan.c', 'generic/tclStrIdxTree.c', 'generic/tclStringObj.c', 'generic/tclStrToD.c', 'generic/tclStubInit.c', 'generic/tclThreadAlloc.c', 'generic/tclThread.c', 'generic/tclThreadJoin.c', 'generic/tclThreadStorage.c', 'generic/tclTimer.c', 'generic/tclTomMathInterface.c', 'generic/tclTrace.c', 'generic/tclUtf.c', 'generic/tclUtil.c', 'generic/tclVar.c', 'generic/tclZipfs.c', 'generic/tclZlib.c', ) oo_sources = files( 'generic/tclOOBasic.c', 'generic/tclOO.c', 'generic/tclOOCall.c', 'generic/tclOODefineCmds.c', 'generic/tclOOInfo.c', 'generic/tclOOMethod.c', 'generic/tclOOProp.c', 'generic/tclOOStubInit.c', ) if is_win platform_sources = files( 'win/tclWin32Dll.c', 'win/tclWinChan.c', 'win/tclWinConsole.c', 'win/tclWinError.c', 'win/tclWinFCmd.c', 'win/tclWinFile.c', 'win/tclWinInit.c', 'win/tclWinLoad.c', 'win/tclWinNotify.c', 'win/tclWinPipe.c', 'win/tclWinSerial.c', 'win/tclWinSock.c', 'win/tclWinThrd.c', 'win/tclWinTime.c', ) # tclWinPanic.c provides Tcl_ConsolePanic — linked into both the DLL # and tclsh directly (the symbol isn't dllexport'd) platform_sources += files('win/tclWinPanic.c') tclsh_sources = files('win/tclAppInit.c', 'win/tclWinPanic.c') platform_deps = [ cc.find_library('ws2_32'), cc.find_library('netapi32'), cc.find_library('user32'), cc.find_library('userenv'), ] tclsh_link_args = cc.get_id() != 'msvc' ? ['-mconsole', '-municode'] : [] else platform_sources = files( 'unix/tclEpollNotfy.c', 'unix/tclKqueueNotfy.c', 'unix/tclLoadDl.c', 'unix/tclSelectNotfy.c', 'unix/tclUnixChan.c', 'unix/tclUnixCompat.c', 'unix/tclUnixEvent.c', 'unix/tclUnixFCmd.c', 'unix/tclUnixFile.c', 'unix/tclUnixInit.c', 'unix/tclUnixPipe.c', 'unix/tclUnixSock.c', 'unix/tclUnixThrd.c', 'unix/tclUnixTime.c', ) tclsh_sources = files('unix/tclAppInit.c') platform_deps = [ cc.find_library('dl', required: false), cc.find_library('pthread', required: false), cc.find_library('m', required: false), ] endif # --- Shared library --- build_inc = include_directories('.') tcllib = shared_library( is_win ? 'tcl90' : 'tcl9.0', generic_sources, oo_sources, platform_sources, include_directories: [generic_inc, compat_zlib_inc, platform_inc, build_inc], c_args: tcl_args, dependencies: [zlib_dep, tommath_dep] + platform_deps, override_options: override_opts, name_prefix: is_win ? '' : 'lib', gnu_symbol_visibility: is_win ? 'default' : 'hidden', ) # --- Stubs library --- stub_args = [ '-DCFG_RUNTIME_BINDIR="' + builddir + '"', '-DCFG_RUNTIME_DLLFILE="' + dll_name + '"', '-DCFG_RUNTIME_LIBDIR="' + builddir + '"', '-DMP_FIXED_CUTOFFS', '-DTCL_WITH_EXTERNAL_TOMMATH', ] if not is_win stub_args += '-DMODULE_SCOPE=extern' endif tclstub = static_library('tclstub', 'generic/tclOOStubLib.c', 'generic/tclStubCall.c', 'generic/tclStubLib.c', 'generic/tclStubLibTbl.c', 'generic/tclTomMathStubLib.c', include_directories: [generic_inc, platform_inc], dependencies: tommath_dep.partial_dependency(compile_args: true, includes: true), c_args: stub_args, override_options: override_opts, install: true, # Needed to prevent meson creating a thin archive install_tag: 'dontuse', ) # --- ZipFS: embed library scripts --- exe_suffix = is_win ? '.exe' : '' zip_prog = find_program('zip', native: true) srcroot = meson.project_source_root() outdir = meson.current_build_dir() zip_output = 'libtcl@0@.zip'.format(meson.project_version()) tcl_zip = custom_target('tcl-zipfs', output: zip_output, input: tcllib, command: [ 'sh', '-c', 'set -e && ' + 'rm -rf @0@/libtcl.vfs && '.format(outdir) + 'mkdir -p @0@/libtcl.vfs/tcl_library && '.format(outdir) + 'cp -a @0@/library/* @1@/libtcl.vfs/tcl_library/ && '.format(srcroot, outdir) + 'if [ -f @0@/libtcl.vfs/tcl_library/manifest.txt ]; then '.format(outdir) + 'mv @0@/libtcl.vfs/tcl_library/manifest.txt @0@/libtcl.vfs/tcl_library/pkgIndex.tcl; '.format(outdir) + 'fi && ' + 'cd @0@/libtcl.vfs && @1@ -rq @2@/@3@ *'.format(outdir, zip_prog.full_path(), outdir, zip_output), ], ) # --- tclsh --- tclsh_name = 'tclsh' + meson.project_version().split('.')[0] + '.' + meson.project_version().split('.')[1] tclsh_exe = executable(tclsh_name + '-base', tclsh_sources, include_directories: [generic_inc, platform_inc], c_args: tcl_args, link_args: is_win ? tclsh_link_args : [], link_with: [tcllib, tclstub], dependencies: [zlib_dep, tommath_dep] + platform_deps, override_options: override_opts, ) # Append the zipfs archive to tclsh so it can find its init scripts tclsh = custom_target('tclsh-zipfs', output: tclsh_name + exe_suffix, input: [tclsh_exe, tcl_zip], command: [ 'sh', '-c', 'cp "$1" "$3" && cat "$2" >> "$3" && chmod +x "$3"', 'sh', '@INPUT0@', '@INPUT1@', '@OUTPUT@', ], build_by_default: true, ) if host_machine.system() != 'windows' custom_target( output: 'tclsh' + exe_suffix, command: [find_program('ln', native: true), '-s', tclsh_name + exe_suffix, '@OUTPUT@'], build_by_default: true, ) endif tcl_library = meson.project_source_root() / 'library' exec_prefix = meson.current_build_dir() # Point TCL_LIBRARY at the source tree so tclsh can find init.tcl meson.add_devenv({'TCL_LIBRARY': tcl_library}) # --- Dependency for consuming projects --- tcl_dep = declare_dependency( include_directories: generic_inc, link_with: tclstub, # tclTomMath.h does `#include "tommath.h"` unless TCL_NO_TOMMATH_H is # defined, so any consumer that pulls in (e.g. for the # TclBN stubs in Tcl 9) needs libtommath's headers on the compile line. # Tcl itself is built with -DTCL_WITH_EXTERNAL_TOMMATH and links against # tommath_dep; we propagate the compile-only parts of that dep through # tcl_dep so downstream packages don't have to re-declare it themselves. dependencies: [tommath_dep.partial_dependency(compile_args: true, includes: true)], version: meson.project_version(), variables: { 'libdir': meson.current_build_dir(), 'exec_prefix': exec_prefix, 'source_root': meson.project_source_root(), 'tcl_library': tcl_library, }, ) parse_args-v0.6.3/teabase/subprojects/packagefiles/tcl/tclUuid.h.in0000644000175100017510000000004215176457507025015 0ustar runnerrunner#define TCL_VERSION_UUID \ @UUID@ parse_args-v0.6.3/teabase/subprojects/packagefiles/tcllib/0000755000175100017510000000000015176457507023321 5ustar runnerrunnerparse_args-v0.6.3/teabase/subprojects/packagefiles/tcllib/meson.build0000644000175100017510000000056415176457507025470 0ustar runnerrunnerproject('tcllib', version: '2.0', meson_version: '>=1.3.0', ) tcllib_dep = declare_dependency( variables: { 'tcl_pkg_path': meson.project_source_root() / 'modules', 'version': meson.project_version(), }, ) meson.override_dependency(meson.project_name(), tcllib_dep) # vim: foldmethod=marker foldmarker=<<<,>>> shiftwidth=2 expandtab parse_args-v0.6.3/teabase/subprojects/packagefiles/re2c/0000755000175100017510000000000015176457507022703 5ustar runnerrunnerparse_args-v0.6.3/teabase/subprojects/packagefiles/re2c/meson.build0000644000175100017510000000724315176457507025053 0ustar runnerrunner# Minimal re2c build from pre-generated bootstrap sources. # Only builds the C-language re2c executable needed for lexer generation. project( 're2c', 'cpp', version: '4.3', license: 'Unlicense', default_options: [ 'cpp_std=c++11', 'warning_level=0', ], meson_version: '>=1.3.0', ) cpp = meson.get_compiler('cpp') conf_data = configuration_data() conf_data.set_quoted('PROJECT_VERSION', meson.project_version()) defines = ['-DPACKAGE_VERSION=' + conf_data.get('PROJECT_VERSION')] foreach header : ['sys/types.h', 'sys/stat.h', 'fcntl.h', 'unistd.h', 'io.h'] name = 'HAVE_' + header.underscorify().to_upper() conf_data.set10(name, cpp.has_header(header)) defines += ['-D@0@=@1@'.format(name, conf_data.get(name))] endforeach defines += [ '-DRE2C_STDLIB_DIR=""', ] configure_file( output: 'config.h', configuration: conf_data, ) # Copy bootstrap generated files to build dir so that includes like # "src/parse/lexer.h" resolve via the build dir include path python = find_program('python3') run_command(python, '-c', 'import shutil; shutil.copytree("bootstrap/src", "src", dirs_exist_ok=True)', check: true, ) _pkg_install_dir = get_option('pkg_install_dir') re2c_exe = executable('re2c', [ 'bootstrap/src/default_syntax_c.h', 'bootstrap/src/msg/help_re2c.cc', 'bootstrap/src/msg/ver_to_vernum.cc', 'bootstrap/src/options/parse_opts.cc', 'bootstrap/src/parse/conf_lexer.cc', 'bootstrap/src/parse/conf_parser.cc', 'bootstrap/src/parse/conf_parser.h', 'bootstrap/src/parse/lexer.cc', 'bootstrap/src/parse/lexer.h', 'bootstrap/src/parse/parser.cc', 'bootstrap/src/parse/parser.h', 'src/adfa/adfa.cc', 'src/cfg/cfg.cc', 'src/cfg/compact.cc', 'src/cfg/dce.cc', 'src/cfg/freeze.cc', 'src/cfg/interfere.cc', 'src/cfg/liveanal.cc', 'src/cfg/normalize.cc', 'src/cfg/optimize.cc', 'src/cfg/rename.cc', 'src/cfg/varalloc.cc', 'src/codegen/helpers.cc', 'src/codegen/output.cc', 'src/codegen/pass1_analyze.cc', 'src/codegen/pass2_generate.cc', 'src/codegen/pass3_fixup.cc', 'src/codegen/pass4_render.cc', 'src/debug/dump_adfa.cc', 'src/debug/dump_cfg.cc', 'src/debug/dump_dfa.cc', 'src/debug/dump_dfa_tree.cc', 'src/debug/dump_interf.cc', 'src/debug/dump_nfa.cc', 'src/dfa/closure.cc', 'src/dfa/dead_rules.cc', 'src/dfa/determinization.cc', 'src/dfa/fallback_tags.cc', 'src/dfa/fillpoints.cc', 'src/dfa/find_state.cc', 'src/dfa/minimization.cc', 'src/dfa/tagver_table.cc', 'src/dfa/tcmd.cc', 'src/encoding/ebcdic.cc', 'src/encoding/enc.cc', 'src/encoding/range_suffix.cc', 'src/encoding/utf16.cc', 'src/encoding/utf8.cc', 'src/main.cc', 'src/msg/msg.cc', 'src/msg/warn.cc', 'src/nfa/re_to_nfa.cc', 'src/options/opt.cc', 'src/options/symtab.cc', 'src/parse/ast.cc', 'src/parse/input.cc', 'src/regexp/ast_to_re.cc', 'src/regexp/default_tags.cc', 'src/regexp/fixed_tags.cc', 'src/regexp/nullable.cc', 'src/regexp/regexp.cc', 'src/regexp/split_charset.cc', 'src/skeleton/control_flow.cc', 'src/skeleton/generate_code.cc', 'src/skeleton/generate_data.cc', 'src/skeleton/maxpath.cc', 'src/skeleton/skeleton.cc', 'src/util/file_utils.cc', 'src/util/range.cc', 'src/util/string_utils.cc', ], include_directories: include_directories('.'), cpp_args: defines, install: _pkg_install_dir != '', install_dir: _pkg_install_dir != '' ? _pkg_install_dir : [], ) meson.override_dependency(meson.project_name(), declare_dependency( variables: { 'prog': re2c_exe.full_path(), }, )) meson.override_find_program('re2c', re2c_exe) parse_args-v0.6.3/teabase/subprojects/packagefiles/re2c/meson.options0000644000175100017510000000021615176457507025440 0ustar runnerrunneroption('pkg_install_dir', type: 'string', value: '', description: 'Package install directory for the re2c binary (empty = do not install)') parse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/0000755000175100017510000000000015176457507024210 5ustar runnerrunnerparse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/meson_options.txt0000644000175100017510000000150015176457507027641 0ustar runnerrunneroption( 'tests', type: 'boolean', value: false, description: 'Build and run unit tests', ) option( 'benchmarks', type: 'boolean', value: false, description: 'Build and run benchmarks', ) option( 'docs', type: 'boolean', value: false, description: 'Build PDF documentation from LaTeX sources', ) option( 'tcl_alloc', type: 'boolean', value: false, description: 'Use Tcl allocator (ckalloc/ckrealloc/ckfree) via external tommath_malloc/etc. shims. The consuming project must provide the shim function implementations.', ) option( 'mp_digit_size', type: 'integer', value: 0, description: 'Target mp_digit size in bytes. When non-zero, forces the digit width to match (e.g. 4 for Tcl 8.6, 8 for Tcl 9 on 64-bit). 0 means use libtommath defaults.', ) parse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/meson.build0000644000175100017510000002541115176457507026355 0ustar runnerrunnerproject( 'libtommath', 'c', version: '1.3.0', license: 'Unlicense', default_options: [ 'c_std=c99', ], meson_version: '>=0.63.0', ) cc = meson.get_compiler('c') # Override optimization for debug builds to use -Og instead of -O0 to work # around an issue with clang not optimizing away references to some # conditionally defined functions with forward references if get_option('debug') and get_option('optimization') == '0' and cc.get_id() in [ 'clang', 'clang-cl', ] add_project_arguments( '-Og', language: 'c', ) endif if cc.get_id() in ['msvc', 'clang-cl'] add_project_arguments( '/wd4146', '/wd4127', '/wd4668', '/wd4710', '/wd4711', '/wd4820', '/wd5045', '/wd4305', '/Ox', language: 'c', ) endif if host_machine.system() == 'windows' add_project_arguments( '-D_CRT_SECURE_NO_WARNINGS', '-D_CRT_NONSTDC_NO_DEPRECATE', '-D__STDC_WANT_SECURE_LIB__=1', '-D_CRT_HAS_CXX17=0', language: 'c', ) endif add_project_arguments( cc.get_supported_arguments('-Wno-unused-but-set-variable'), language: 'c', ) # Library sources sources = files( 'bn_cutoffs.c', 'bn_deprecated.c', 'bn_mp_2expt.c', 'bn_mp_abs.c', 'bn_mp_add.c', 'bn_mp_add_d.c', 'bn_mp_addmod.c', 'bn_mp_and.c', 'bn_mp_clamp.c', 'bn_mp_clear.c', 'bn_mp_clear_multi.c', 'bn_mp_cmp.c', 'bn_mp_cmp_d.c', 'bn_mp_cmp_mag.c', 'bn_mp_cnt_lsb.c', 'bn_mp_complement.c', 'bn_mp_copy.c', 'bn_mp_count_bits.c', 'bn_mp_decr.c', 'bn_mp_div.c', 'bn_mp_div_2.c', 'bn_mp_div_2d.c', 'bn_mp_div_d.c', 'bn_mp_dr_is_modulus.c', 'bn_mp_dr_reduce.c', 'bn_mp_dr_setup.c', 'bn_mp_error_to_string.c', 'bn_mp_exch.c', 'bn_mp_expt_n.c', 'bn_mp_exptmod.c', 'bn_mp_exteuclid.c', 'bn_mp_fread.c', 'bn_mp_from_sbin.c', 'bn_mp_from_ubin.c', 'bn_mp_fwrite.c', 'bn_mp_gcd.c', 'bn_mp_get_double.c', 'bn_mp_get_i32.c', 'bn_mp_get_i64.c', 'bn_mp_get_l.c', 'bn_mp_get_mag_u32.c', 'bn_mp_get_mag_u64.c', 'bn_mp_get_mag_ul.c', 'bn_mp_grow.c', 'bn_mp_incr.c', 'bn_mp_init.c', 'bn_mp_init_copy.c', 'bn_mp_init_i32.c', 'bn_mp_init_i64.c', 'bn_mp_init_l.c', 'bn_mp_init_multi.c', 'bn_mp_init_set.c', 'bn_mp_init_size.c', 'bn_mp_init_u32.c', 'bn_mp_init_u64.c', 'bn_mp_init_ul.c', 'bn_mp_invmod.c', 'bn_mp_is_square.c', 'bn_mp_iseven.c', 'bn_mp_isodd.c', 'bn_mp_kronecker.c', 'bn_mp_lcm.c', 'bn_mp_log_n.c', 'bn_mp_lshd.c', 'bn_mp_mod.c', 'bn_mp_mod_2d.c', 'bn_mp_mod_d.c', 'bn_mp_montgomery_calc_normalization.c', 'bn_mp_montgomery_reduce.c', 'bn_mp_montgomery_setup.c', 'bn_mp_mul.c', 'bn_mp_mul_2.c', 'bn_mp_mul_2d.c', 'bn_mp_mul_d.c', 'bn_mp_mulmod.c', 'bn_mp_neg.c', 'bn_mp_or.c', 'bn_mp_pack.c', 'bn_mp_pack_count.c', 'bn_mp_prime_fermat.c', 'bn_mp_prime_frobenius_underwood.c', 'bn_mp_prime_is_prime.c', 'bn_mp_prime_miller_rabin.c', 'bn_mp_prime_next_prime.c', 'bn_mp_prime_rabin_miller_trials.c', 'bn_mp_prime_rand.c', 'bn_mp_prime_strong_lucas_selfridge.c', 'bn_mp_radix_size.c', 'bn_mp_radix_smap.c', 'bn_mp_rand.c', 'bn_mp_read_radix.c', 'bn_mp_reduce.c', 'bn_mp_reduce_2k.c', 'bn_mp_reduce_2k_l.c', 'bn_mp_reduce_2k_setup.c', 'bn_mp_reduce_2k_setup_l.c', 'bn_mp_reduce_is_2k.c', 'bn_mp_reduce_is_2k_l.c', 'bn_mp_reduce_setup.c', 'bn_mp_root_n.c', 'bn_mp_rshd.c', 'bn_mp_sbin_size.c', 'bn_mp_set.c', 'bn_mp_set_double.c', 'bn_mp_set_i32.c', 'bn_mp_set_i64.c', 'bn_mp_set_l.c', 'bn_mp_set_u32.c', 'bn_mp_set_u64.c', 'bn_mp_set_ul.c', 'bn_mp_shrink.c', 'bn_mp_signed_rsh.c', 'bn_mp_sqr.c', 'bn_mp_sqrmod.c', 'bn_mp_sqrt.c', 'bn_mp_sqrtmod_prime.c', 'bn_mp_sub.c', 'bn_mp_sub_d.c', 'bn_mp_submod.c', 'bn_mp_to_radix.c', 'bn_mp_to_sbin.c', 'bn_mp_to_ubin.c', 'bn_mp_ubin_size.c', 'bn_mp_unpack.c', 'bn_mp_xor.c', 'bn_mp_zero.c', 'bn_prime_tab.c', 'bn_s_mp_add.c', 'bn_s_mp_balance_mul.c', 'bn_s_mp_div_3.c', 'bn_s_mp_exptmod.c', 'bn_s_mp_exptmod_fast.c', 'bn_s_mp_get_bit.c', 'bn_s_mp_invmod_fast.c', 'bn_s_mp_invmod_slow.c', 'bn_s_mp_karatsuba_mul.c', 'bn_s_mp_karatsuba_sqr.c', 'bn_s_mp_log.c', 'bn_s_mp_log_2expt.c', 'bn_s_mp_log_d.c', 'bn_s_mp_montgomery_reduce_fast.c', 'bn_s_mp_mul_digs.c', 'bn_s_mp_mul_digs_fast.c', 'bn_s_mp_mul_high_digs.c', 'bn_s_mp_mul_high_digs_fast.c', 'bn_s_mp_prime_is_divisible.c', 'bn_s_mp_rand_jenkins.c', 'bn_s_mp_rand_platform.c', 'bn_s_mp_reverse.c', 'bn_s_mp_sqr.c', 'bn_s_mp_sqr_fast.c', 'bn_s_mp_sub.c', 'bn_s_mp_toom_mul.c', 'bn_s_mp_toom_sqr.c', ) inc = include_directories('.') # Add extra optimization flags to match Makefile and CMake builds # Note: Meson already adds -O3 when optimization=3 (from buildtype=release) # We only need to add the flags Meson doesn't add by default if not get_option('debug') add_project_arguments( cc.get_supported_arguments('-funroll-loops', '-fomit-frame-pointer'), language: 'c', ) endif # When tcl_alloc is enabled, define MP_MALLOC etc. so libtommath declares them # as extern functions rather than using stdlib malloc/free. The consuming Tcl # extension must provide the implementations (tommath_malloc, tommath_realloc, # tommath_calloc, tommath_free) that forward to Tcl's ckalloc/ckrealloc/ckfree. # This is necessary because Tcl frees mp_int digit arrays from bignum Tcl_Objs # with ckfree, so they must have been allocated with ckalloc. tcl_compat_args = [] if get_option('tcl_alloc') tcl_compat_args += [ '-DMP_MALLOC=tommath_malloc', '-DMP_REALLOC=tommath_realloc', '-DMP_CALLOC=tommath_calloc', '-DMP_FREE=tommath_free', ] endif # Match the mp_digit width of the target Tcl. Tcl 8.6 forces 32-bit digits # (unsigned int) while standalone libtommath 1.3.0 defaults to 64-bit on # 64-bit platforms. mp_int structs cross the boundary via Tcl_NewBignumObj, # so the digit width must agree. _mp_digit_size = get_option('mp_digit_size') if _mp_digit_size == 4 tcl_compat_args += '-DMP_32BIT' elif _mp_digit_size == 2 tcl_compat_args += '-DMP_16BIT' elif _mp_digit_size == 1 tcl_compat_args += '-DMP_8BIT' endif # 8 (or 0) → use libtommath's default 64-bit digits on 64-bit platforms libtommath = static_library( 'tommath', sources, install: false, include_directories: inc, c_args: tcl_compat_args + (cc.get_id() in ['msvc', 'clang-cl'] ? [ # MSVC defaults to IEEE754 since VS 2010, but doesn't set the macro. # Can't use add_project_arguments here because that enables tests that contain # literal division by zero, which breaks compilation. '/fp:precise', '-D__STDC_IEC_559__', ] : []), ) # Install headers #install_headers(files('tommath.h')) # Generate pkg-config file #pkg = import('pkgconfig') #pkg.generate( # libtommath, # name: meson.project_name(), # description: 'public domain library for manipulating large integer numbers', # url: 'https://www.libtom.net/LibTomMath/', #) # Create a dependency object for use by other projects # This makes the library usable as a Meson subproject libtommath_dep = declare_dependency( link_with: libtommath, include_directories: inc, ) # Make the dependency available to parent projects meson.override_dependency('libtommath', libtommath_dep) # Build and run unit tests if requested if get_option('tests') if not meson.can_run_host_binaries() error( 'Cannot run tests: cross-compilating and no host binary helper available', ) endif libtommath_for_tests = libtommath if cc.get_id() in ['msvc', 'clang-cl'] if get_option('default_library') == 'shared' error('Static library build is required to run tests with MSVC/clang-cl') endif libtommath_for_tests = libtommath.get_static_lib() endif tommath_test_exe = executable( 'tommath_test', ['demo/test.c', 'demo/shared.c'], link_with: libtommath_for_tests, include_directories: inc, build_by_default: false, ) mtest_opponent_exe = executable( 'mtest_opponent', ['demo/mtest_opponent.c', 'demo/shared.c'], link_with: libtommath_for_tests, include_directories: inc, build_by_default: false, ) # Build mtest - reference implementation for differential testing # Note: mtest.c includes mpi.c directly, so we only compile mtest.c # Have to disable optimization when building mpi.c or the test fails # due to bugs in mpi.c mtest_exe = executable( 'mtest', 'mtest/mtest.c', include_directories: include_directories('mtest'), override_options: ['optimization=0'], c_args: cc.get_id() == 'clang-cl' ? [ # For some reason the optimization=0 override doesn't work properly with clang-cl '/Od', ] : [], build_by_default: false, ) test('tommath_test', tommath_test_exe) # Differential test: mtest generates test cases, mtest_opponent validates them # Usage: mtest | mtest_opponent test( 'mtest_opponent', find_program( 'run_mtest.py', native: true, ), args: [ mtest_exe.full_path(), mtest_opponent_exe.full_path(), # Iteration count can be added using --test-args, default is 1000 ], depends: [mtest_exe, mtest_opponent_exe], timeout: 30, suite: 'differential', ) endif if get_option('benchmarks') if not meson.can_run_host_binaries() error( 'Cannot run benchmarks: cross-compilating and no host binary helper available', ) endif timing_exe = executable( 'timing', 'demo/timing.c', link_with: libtommath, c_args: ['-DTIMER'], include_directories: inc, build_by_default: false, ) # Create logs directory in build root for benchmark output (timings binary segfaults without it) python_mkdir = [ find_program( 'python3', native: true, ), '-c', 'import os, sys; os.makedirs(sys.argv[1]) if not os.path.exists(sys.argv[1]) else None', ] run_command( python_mkdir, meson.project_build_root() / 'logs', check: true, ) benchmark( 'benchmarks', timing_exe, timeout: 30, ) endif # Documentation target - build PDF manual from LaTeX sources if get_option('docs') # Find LaTeX tools (these may not be installed) latex = find_program( 'latex', required: true, ) pdflatex = find_program( 'pdflatex', required: true, ) makeindex = find_program( 'makeindex', required: true, ) custom_target( 'docs', input: 'doc/bn.tex', output: '@0@-@1@.pdf'.format(meson.project_name(), meson.project_version()), command: [ find_program( 'doc/build-manual.py', native: true, ), '@INPUT@', '@OUTDIR@', '@OUTPUT@', ], env: environment( { 'LATEX': latex.full_path(), 'PDFLATEX': pdflatex.full_path(), 'MAKEINDEX': makeindex.full_path(), }, ), console: true, install: false, install_dir: get_option('datadir') / 'doc' / 'libtommath', ) endif parse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/run_mtest.py0000644000175100017510000000132715176457507026605 0ustar runnerrunner#!/usr/bin/env python3 import sys import subprocess # Get executables from arguments mtest, mtest_opponent = sys.argv[1:3] # Get iteration count from command line (default 1000) iterations = sys.argv[3] if len(sys.argv) > 3 else '1000' # Run mtest and pipe its output to mtest_opponent mtest_proc = subprocess.Popen([mtest, iterations], stdout=subprocess.PIPE) mtest_opponent_proc = subprocess.Popen([mtest_opponent], stdin=mtest_proc.stdout) # Close mtest stdout in parent to allow proper SIGPIPE handling mtest_proc.stdout.close() # Wait for both processes to complete mtest_opponent_proc.wait() mtest_proc.wait() # Exit with mtest_opponent's exit code (standard pipe behavior) sys.exit(mtest_opponent_proc.returncode) parse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/doc/0000755000175100017510000000000015176457507024755 5ustar runnerrunnerparse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/doc/build-manual.py0000644000175100017510000000620715176457507027706 0ustar runnerrunner#!/usr/bin/env python3 """Build the libtommath PDF manual from LaTeX sources This script is called by meson with the following environment variables set: LATEX, PDFLATEX, MAKEINDEX Only requires standard Python library - no external tools beyond LaTeX itself. """ import os import sys import shutil import subprocess import re from datetime import datetime, timezone def main(): if len(sys.argv) != 4: print("Usage: build-manual.py INPUT OUTDIR OUTPUT", file=sys.stderr) sys.exit(1) input_file = sys.argv[1] outdir = sys.argv[2] output_file = sys.argv[3] # Get tools from environment latex = os.environ.get('LATEX', 'latex') pdflatex = os.environ.get('PDFLATEX', 'pdflatex') makeindex = os.environ.get('MAKEINDEX', 'makeindex') # Convert paths to absolute before changing directories input_file = os.path.abspath(input_file) output_file = os.path.abspath(output_file) # Change to output directory os.chdir(outdir) # Copy input to bn.tex shutil.copy2(input_file, 'bn.tex') # Create backup with same timestamp shutil.copy2('bn.tex', 'bn.bak') # Get modification time of bn.tex and format for PDF mtime = os.stat('bn.tex').st_mtime dt = datetime.fromtimestamp(mtime, tz=timezone.utc) # Format as PDF date string: D:YYYYMMDDHHmmSS+HH'mm' # For UTC, timezone offset is +00'00' date_str = dt.strftime("D:%Y%m%d%H%M%S+00'00'") # Write deterministic PDF header with open('bn-deterministic.tex', 'w') as f: f.write(f"\\def\\fixedpdfdate{{{date_str}}}\n") f.write("\\pdfinfo{\n") f.write(" /CreationDate (\\fixedpdfdate)\n") f.write(" /ModDate (\\fixedpdfdate)\n") f.write("}\n") # Append original content with open('bn.tex', 'r') as orig: f.write(orig.read()) # Replace bn.tex with deterministic version shutil.move('bn-deterministic.tex', 'bn.tex') # Restore original timestamp shutil.copystat('bn.bak', 'bn.tex') # Build the manual with open('bn.ind', 'w') as f: f.write('hello\n') subprocess.run([latex, 'bn'], stdout=subprocess.DEVNULL, check=True) subprocess.run([latex, 'bn'], stdout=subprocess.DEVNULL, check=True) subprocess.run([makeindex, 'bn'], check=True) subprocess.run([latex, 'bn'], stdout=subprocess.DEVNULL, check=True) subprocess.run([pdflatex, 'bn'], stdout=subprocess.DEVNULL, check=True) # Make PDF ID deterministic using Python with open('bn.pdf', 'rb') as f: pdf_data = f.read() # Replace /ID [<...> <...>] with /ID [<0> <0>] pdf_data = re.sub(rb'^/ID \[.*\]$', rb'/ID [<0> <0>]', pdf_data, flags=re.MULTILINE) with open('bn.pdf', 'wb') as f: f.write(pdf_data) # Rename to desired output name shutil.move('bn.pdf', output_file) # Cleanup shutil.move('bn.bak', 'bn.tex') cleanup_files = [ 'bn.aux', 'bn.dvi', 'bn.log', 'bn.idx', 'bn.lof', 'bn.out', 'bn.toc', 'bn.ilg', 'bn.ind', 'bn.tex' ] for f in cleanup_files: try: os.remove(f) except FileNotFoundError: pass if __name__ == '__main__': main() parse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/libtommath.def0000644000175100017510000000740315176457507027034 0ustar runnerrunnerLIBRARY tommath-1 EXPORTS fast_mp_invmod fast_mp_montgomery_reduce fast_s_mp_mul_digs fast_s_mp_mul_high_digs fast_s_mp_sqr mp_2expt mp_abs mp_add mp_add_d mp_addmod mp_and mp_balance_mul mp_clamp mp_clear mp_clear_multi mp_cmp mp_cmp_d mp_cmp_mag mp_cnt_lsb mp_complement mp_copy mp_count_bits mp_decr mp_div mp_div_2 mp_div_2d mp_div_3 mp_div_d mp_dr_is_modulus mp_dr_reduce mp_dr_setup mp_error_to_string mp_exch mp_export mp_expt_d mp_expt_d_ex mp_exptmod mp_exptmod_fast mp_expt_n mp_expt_u32 mp_exteuclid mp_fread mp_from_sbin mp_from_ubin mp_fwrite mp_gcd mp_get_bit mp_get_double mp_get_i32 mp_get_i64 mp_get_int mp_get_l mp_get_ll mp_get_long mp_get_long_long mp_get_mag_u32 mp_get_mag_u64 mp_get_mag_ul mp_get_mag_ull mp_grow mp_import mp_incr mp_init mp_init_copy mp_init_i32 mp_init_i64 mp_init_l mp_init_ll mp_init_multi mp_init_set mp_init_set_int mp_init_size mp_init_u32 mp_init_u64 mp_init_ul mp_init_ull mp_invmod mp_invmod_slow mp_iseven mp_isodd mp_is_square mp_jacobi mp_karatsuba_mul mp_karatsuba_sqr mp_kronecker mp_lcm mp_log_n mp_log_u32 mp_lshd mp_mod mp_mod_2d mp_mod_d mp_montgomery_calc_normalization mp_montgomery_reduce mp_montgomery_setup mp_mul mp_mul_2 mp_mul_2d mp_mul_d mp_mulmod mp_neg mp_n_root mp_n_root_ex mp_or mp_pack mp_pack_count mp_prime_fermat mp_prime_frobenius_underwood mp_prime_is_divisible mp_prime_is_prime mp_prime_miller_rabin mp_prime_next_prime mp_prime_rabin_miller_trials mp_prime_rand mp_prime_random_ex mp_prime_strong_lucas_selfridge mp_radix_size mp_rand mp_rand_digit mp_rand_source mp_read_radix mp_read_signed_bin mp_read_unsigned_bin mp_reduce mp_reduce_2k mp_reduce_2k_l mp_reduce_2k_setup mp_reduce_2k_setup_l mp_reduce_is_2k mp_reduce_is_2k_l mp_reduce_setup mp_root_n mp_root_u32 mp_rshd mp_sbin_size mp_set mp_set_double mp_set_i32 mp_set_i64 mp_set_int mp_set_l mp_set_ll mp_set_long mp_set_long_long mp_set_u32 mp_set_u64 mp_set_ul mp_set_ull mp_shrink mp_signed_bin_size mp_signed_rsh mp_sqr mp_sqrmod mp_sqrt mp_sqrtmod_prime mp_sub mp_sub_d mp_submod mp_tc_and mp_tc_div_2d mp_tc_or mp_tc_xor mp_toom_mul mp_toom_sqr mp_to_radix mp_toradix mp_toradix_n mp_to_sbin mp_to_signed_bin mp_to_signed_bin_n mp_to_ubin mp_to_unsigned_bin mp_to_unsigned_bin_n mp_ubin_size mp_unpack mp_unsigned_bin_size mp_xor mp_zero s_mp_add s_mp_balance_mul s_mp_div_3 s_mp_exptmod s_mp_exptmod_fast s_mp_get_bit s_mp_invmod_fast s_mp_invmod_slow s_mp_karatsuba_mul s_mp_karatsuba_sqr s_mp_log s_mp_log_2expt s_mp_log_d s_mp_montgomery_reduce_fast s_mp_mul_digs s_mp_mul_digs_fast s_mp_mul_high_digs s_mp_mul_high_digs_fast s_mp_prime_is_divisible s_mp_prime_random_ex s_mp_rand_jenkins s_mp_rand_jenkins_init s_mp_rand_platform s_mp_reverse s_mp_sqr s_mp_sqr_fast s_mp_sub s_mp_toom_mul s_mp_toom_sqr KARATSUBA_MUL_CUTOFF DATA KARATSUBA_SQR_CUTOFF DATA TOOM_MUL_CUTOFF DATA TOOM_SQR_CUTOFF DATA ltm_prime_tab DATA mp_s_rmap DATA mp_s_rmap_reverse DATA mp_s_rmap_reverse_sz DATA s_mp_prime_tab DATA s_mp_rand_source DATA parse_args-v0.6.3/teabase/subprojects/tcllib.wrap0000644000175100017510000000045415176457507021601 0ustar runnerrunner[wrap-file] source_url = https://github.com/tcltk/tcllib/archive/refs/tags/tcllib-2-0.tar.gz source_filename = tcllib-2-0.tar.gz source_hash = c239f54cedc2fc11eb9fd5a7bbf2df1e12965937cd7fd1110e17383ec8f5e632 patch_directory = tcllib directory = tcllib-tcllib-2-0 [provide] dependency_names = tcllib parse_args-v0.6.3/teabase/subprojects/hedley.wrap0000644000175100017510000000070315176457507021577 0ustar runnerrunner[wrap-file] directory = hedley-15 source_url = https://codeload.github.com/nemequ/hedley/tar.gz/v15 source_filename = hedley-15.tar.gz source_hash = e91c71b58f59d08c7b8289be8f687866863d934dfaa528e4be30b178139ae863 patch_filename = hedley_15-1_patch.zip patch_url = https://wrapdb.mesonbuild.com/v2/hedley_15-1/get_patch patch_hash = 4fe21441ad90dce22fc2e88b4c2b164ab65682c15858ec710a2b206a5bbe5272 wrapdb_version = 15-1 [provide] hedley = hedley_dep parse_args-v0.6.3/teabase/init/0000755000175100017510000000000015176457507016032 5ustar runnerrunnerparse_args-v0.6.3/teabase/init/meson.build0000644000175100017510000002405715176457507020204 0ustar runnerrunnerteabase_initialized = true if not is_variable('deps') deps = [] endif if not is_variable('tea_want_shims') tea_want_shims = [] endif # Tcl-package dependencies needed at test/benchmark time, expressed as # meson dependency() objects. teabase reads `tcl_pkg_path` (binary # packages — added to TCLLIBPATH) and `tcl_tm_path` (pure-Tcl .tm # modules — added to TCL__TM_PATH) from each dep's variables; # same names are used in .pc files and in declare_dependency(variables:) # subproject fallbacks. Any dep that exports neither is ignored. # # tea_bench_deps is conceptually additive to tea_test_deps (benchmarks # inherit the test deps). Keeping them separate lets a project add # heavyweight bench-only fixtures that aren't fetched/built when only # `meson test` runs. if not is_variable('tea_test_deps') tea_test_deps = [] endif if not is_variable('tea_bench_deps') tea_bench_deps = [] endif # Extra build targets (executables, custom_targets, shared_modules ...) # that must exist before `meson test` runs. For tools accessed via # tea_host_env's PATH (re2c, packcc, ...) and for subproject-fallback # Tcl packages whose underlying targets would otherwise not get built # (tea_test_deps holds dependency() objects, which can't appear in a # test()'s `depends:` list). # # tea_bench_extra_depends is the bench-only counterpart, also additive: # `meson test --benchmark` builds tea_extra_depends + tea_bench_extra_depends. if not is_variable('tea_extra_depends') tea_extra_depends = [] endif if not is_variable('tea_bench_extra_depends') tea_bench_extra_depends = [] endif # Live host env (used for configure-time run_command and meson.add_devenv). # Mutations to tea_host_env are mirrored into tea_host_env_ops so we can # replay the same modifications onto fresh environment objects later. # meson's environment() can't be cloned and stores a reference (not a # snapshot) when passed to test() — without an op log there's no way to # build distinct test_env / bench_env objects with overlapping content. # Each entry: {'op': 'set' | 'prepend', 'var': str, 'value': str} if not is_variable('tea_host_env') tea_host_env = environment() endif if not is_variable('tea_host_env_ops') tea_host_env_ops = [] endif if not is_variable('tea_build_env') tea_build_env = environment() endif add_project_arguments('-DHAVE_CONFIG_H=1', language: 'c') tcl_dep = dependency('tcl') if tcl_dep.type_name() == 'internal' pkg_dir = 'lib' / meson.project_name()+'-'+meson.project_version() else pkg_dir = tcl_dep.get_variable('libdir') / meson.project_name()+'-'+meson.project_version() endif # Use tcl_dep for compile args (includes) only, link against stubs library deps += tcl_dep.partial_dependency(compile_args: true, includes: true) if tcl_dep.type_name() == 'internal' # Subproject fallback: stubs library is already part of tcl_dep deps += tcl_dep.partial_dependency(links: true) else deps += cc.find_library('tclstub', dirs: [tcl_dep.get_variable('libdir')]) endif add_project_arguments('-DUSE_TCL_STUBS=1', language: 'c') add_project_arguments('-DUSE_TCL_STUBS=1', language: 'cpp') if 'hedley' in tea_want_shims hedley_dep = dependency('hedley', version: '>=15', allow_fallback: true, required: false) if hedley_dep.found() deps += hedley_dep add_project_arguments('-DHAVE_HEDLEY_H', language: 'c') add_project_arguments('-DHAVE_HEDLEY_H', language: 'cpp') endif endif teaconf = conf teaconf.set('PACKAGE_NAME', meson.project_name()) teaconf.set('PACKAGE_VERSION', meson.project_version()) conf.set_quoted('PACKAGE_NAME', meson.project_name()) conf.set_quoted('PACKAGE_VERSION', meson.project_version()) if tcl_dep.type_name() != 'internal' # Compile checks require an external dependency if 'tip445' in tea_want_shims conf.set10('TIP445_SHIM', not cc.has_function('Tcl_FetchInternalRep', prefix: '#include ', dependencies: tcl_dep)) endif if 'Tcl_GetBytesFromObj' in tea_want_shims conf.set10('GETBYTES_SHIM', not cc.has_function('Tcl_GetBytesFromObj', prefix: '#include ', dependencies: tcl_dep)) endif if not cc.compiles('#include \nTcl_Size foo=0;', dependencies: tcl_dep) conf.set('Tcl_Size', 'int') endif if not cc.has_header_symbol('tcl.h', 'TCL_SIZE_MODIFIER', dependencies: tcl_dep) conf.set('TCL_SIZE_MODIFIER', '""') endif if not cc.has_define('MODULE_SCOPE', prefix: '#include ', dependencies: tcl_dep) add_project_arguments('-DMODULE_SCOPE=extern', language: 'c') add_project_arguments('-DMODULE_SCOPE=extern "C"', language: 'cpp') endif # Detect libtommath configuration when requested by the consuming project. # Set tea_want_tommath = true before subdir('teabase/init') to enable. if is_variable('tea_want_tommath') and tea_want_tommath # tclTomMath.h may #include "tommath.h" which may not be installed # even when Tcl has internal tommath. Probe first to avoid a hard # error from has_define / sizeof. _tommath_hdr_ok = cc.compiles( '#include \n#include \nmp_digit d;', name: 'tclTomMath.h usable', dependencies: tcl_dep, ) if _tommath_hdr_ok tcl_has_internal_tommath = not cc.has_define('TCL_WITH_EXTERNAL_TOMMATH', prefix: '#include ', dependencies: tcl_dep) tcl_mp_digit_size = cc.sizeof('mp_digit', prefix: '#include \n#include ', dependencies: tcl_dep) else # Header broken or missing tommath.h — assume internal tommath tcl_has_internal_tommath = true tcl_mp_digit_size = cc.sizeof('size_t') endif endif else # Internal subproject provides Tcl 9 source — all features present if is_variable('tea_want_tommath') and tea_want_tommath tcl_has_internal_tommath = true tcl_mp_digit_size = cc.sizeof('size_t') endif if 'tip445' in tea_want_shims conf.set10('TIP445_SHIM', false) endif if 'Tcl_GetBytesFromObj' in tea_want_shims conf.set10('GETBYTES_SHIM', false) endif endif # defer.h support: set tea_want_defer = true before subdir('teabase/init') to # enable #include "teabase/defer.h". Detects either native _Defer (clang 22+, # with or without -fdefer-ts), or GCC nested-function + cleanup-attribute # polyfill. Errors if neither is available. if is_variable('tea_want_defer') and tea_want_defer _defer_native = ''' int main(void) { int x = 0; _Defer { x = 1; } return x; } ''' _defer_polyfill = ''' void cleanup(int *p) { (void)p; } int main(void) { __attribute__((__cleanup__(cleanup))) int x; auto void f(int*); inline auto void f(__attribute__((__unused__)) int *p) {} return 0; } ''' if cc.compiles(_defer_native, name: 'native _Defer') conf.set10('HAVE_NATIVE_DEFER', true) elif cc.compiles(_defer_native, args: ['-fdefer-ts'], name: 'native _Defer (-fdefer-ts)') conf.set10('HAVE_NATIVE_DEFER', true) add_project_arguments('-fdefer-ts', language: 'c') elif cc.compiles(_defer_polyfill, name: 'GCC defer polyfill support') conf.set10('HAVE_DEFER_POLYFILL', true) else error('No defer support: need _Defer (clang 22+ with -fdefer-ts) or GCC 9+ nested functions') endif endif tclver_full = tcl_dep.version() tclver_parts = tclver_full.split('.') tclver_major = tclver_parts[0] tclver_minor = tclver_parts[1] # Strip alpha/beta suffixes tclver_minor = tclver_minor.split('a')[0].split('b')[0].split('rc')[0] tclver = tclver_major + '.' + tclver_minor exe_suffix = host_machine.system() == 'windows' ? '.exe' : '' exec_prefix = tcl_dep.get_variable('exec_prefix') tclsh_search = [] foreach name : [ exec_prefix / 'bin/tclsh', exec_prefix / 'tclsh', 'tclsh', ] tclsh_search += [ name + tclver + exe_suffix, name + exe_suffix, ] endforeach tcl_is_internal = tcl_dep.type_name() == 'internal' if tcl_is_internal # Get the host tclsh directly from the subproject. For tests this # runs via the exe_wrapper in cross builds. build_tclsh (used in # run_command at configure time) can't be a compiled target, so it's # only set in native builds where the subproject's tclsh IS a native # program. tcl_subproj = subproject('tcl') tclsh = tcl_subproj.get_variable('tclsh_exe') _tcl_lib = tcl_subproj.get_variable('tcl_library') _tcl_pre = tcl_subproj.get_variable('exec_prefix') tea_host_env.set('TCL_LIBRARY', _tcl_lib) tea_host_env.prepend('PATH', _tcl_pre) tea_host_env_ops += [ {'op': 'set', 'var': 'TCL_LIBRARY', 'value': _tcl_lib}, { 'var': 'PATH', 'value': _tcl_pre}, ] build_tclsh = tclsh tea_build_env.set('TCL_LIBRARY', _tcl_lib) tea_build_env.prepend('PATH', _tcl_pre) else tclsh = find_program(tclsh_search, native: false, required: false) if tclsh.found() and meson.can_run_host_binaries() if run_command(tclsh, '../tools/check_ver.tcl', tclver, check: false, env: tea_host_env).returncode() != 0 error('Tcl version of found tclsh: '+tclsh.full_path()+' does not match the Tcl version of the Tcl dependency: ' + tclver) endif build_tclsh = tclsh endif if not is_variable('build_tclsh') # Try to find a build machine tclsh for configure-time scripts exe_suffix = build_machine.system() == 'windows' ? '.exe' : '' exec_prefix = tcl_dep.get_variable('exec_prefix') tclsh_search = [] foreach name : [ exec_prefix / 'bin/tclsh', exec_prefix / 'tclsh', 'tclsh', ] tclsh_search += [ name + tclver + exe_suffix, name + exe_suffix, ] endforeach build_tclsh = find_program(tclsh_search, native: true, required: false) if build_tclsh.found() if run_command(build_tclsh, '../tools/check_ver.tcl', tclver, check: false, env: tea_build_env).returncode() != 0 error('Tcl version of found tclsh: '+build_tclsh.full_path()+' does not match the Tcl version of the Tcl dependency: ' + tclver) endif endif endif if tclsh.found() _tclsh_dir = fs.parent(tclsh.full_path()) tea_host_env.prepend('PATH', _tclsh_dir) tea_host_env_ops += {'var': 'PATH', 'value': _tclsh_dir} endif if build_tclsh.found() tea_build_env.prepend('PATH', fs.parent(build_tclsh.full_path())) endif endif parse_args-v0.6.3/teabase/termdebug.vim.in0000644000175100017510000000021315176457507020163 0ustar runnerrunnerset number set mouse=a set foldlevel=100 packadd termdebug execute '@TERMDEBUG_ARG@ ' . $TESTFLAGS 2windo set nonumber 1windo set nonumber parse_args-v0.6.3/LICENSE0000644000175100017510000000415215176457507014472 0ustar runnerrunnerThis software is copyrighted by the Ruby Lane, and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. parse_args-v0.6.3/tclconfig/0000755000175100017510000000000015176457625015434 5ustar runnerrunnerparse_args-v0.6.3/tclconfig/license.terms0000644000175100017510000000431715176457507020136 0ustar runnerrunnerThis software is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation and other parties. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. GOVERNMENT USE: If you are acquiring this software on behalf of the U.S. government, the Government shall have only "Restricted Rights" in the software and related documentation as defined in the Federal Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are acquiring the software on behalf of the Department of Defense, the software shall be classified as "Commercial Computer Software" and the Government shall have only "Restricted Rights" as defined in Clause 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. parse_args-v0.6.3/tclconfig/README.txt0000644000175100017510000000151415176457507017132 0ustar runnerrunnerThese files comprise the basic building blocks for a Tcl Extension Architecture (TEA) extension. For more information on TEA see: https://wiki.tcl-lang.org/page/TEA This package is part of the Tcl project at SourceForge, but sources and bug/patch database are hosted on fossil here: https://core.tcl-lang.org/tclconfig This package is a freely available open source package. You can do virtually anything you like with it, such as modifying it, redistributing it, and selling it either in whole or in part. CONTENTS ======== The following is a short description of the files you will find in the sample extension. README.txt This file install-sh Program used for copying binaries and script files to their install locations. tcl.m4 Collection of Tcl autoconf macros. Included by a package's aclocal.m4 to define TEA_* macros. parse_args-v0.6.3/tclconfig/install-sh0000755000175100017510000003577615176457507017461 0ustar runnerrunner#!/bin/sh # install - install a program, script, or datafile scriptversion=2020-11-14.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Email bug reports to bug-automake@gnu.org. Automake home page: https://www.gnu.org/software/automake/ " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: parse_args-v0.6.3/tclconfig/tcl.m40000644000175100017510000040640515176457507016470 0ustar runnerrunner# tcl.m4 -- # # This file provides a set of autoconf macros to help TEA-enable # a Tcl extension. # # Copyright (c) 1999-2000 Ajuba Solutions. # Copyright (c) 2002-2005 ActiveState Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. AC_PREREQ([2.69]) # Possible values for key variables defined: # # TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem') # TEA_PLATFORM - windows unix # TEA_TK_EXTENSION - True if this is a Tk extension # #------------------------------------------------------------------------ # TEA_PATH_TCLCONFIG -- # # Locate the tclConfig.sh file and perform a sanity check on # the Tcl compile flags # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tcl=... # # Defines the following vars: # TCL_BIN_DIR Full path to the directory containing # the tclConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([TEA_PATH_TCLCONFIG], [ dnl TEA specific: Make sure we are initialized AC_REQUIRE([TEA_INIT]) # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true AC_ARG_WITH(tcl, AS_HELP_STRING([--with-tcl], [directory containing tcl configuration (tclConfig.sh)]), [with_tclconfig="${withval}"]) AC_ARG_WITH(tcl8, AS_HELP_STRING([--with-tcl8], [Compile for Tcl8 in Tcl9 environment]), [with_tcl8="${withval}"]) AC_MSG_CHECKING([for Tcl configuration]) AC_CACHE_VAL(ac_cv_c_tclconfig,[ # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/lib/tcl9.1 2>/dev/null` \ `ls -d /usr/lib/tcl9.0 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl9.1 2>/dev/null` \ `ls -d /usr/local/lib/tcl9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl9.1 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # TEA_PATH_TKCONFIG -- # # Locate the tkConfig.sh file # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tk=... # # Defines the following vars: # TK_BIN_DIR Full path to the directory containing # the tkConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([TEA_PATH_TKCONFIG], [ # # Ok, lets find the tk configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tk # if test x"${no_tk}" = x ; then # we reset no_tk in case something fails here no_tk=true AC_ARG_WITH(tk, AS_HELP_STRING([--with-tk], [directory containing tk configuration (tkConfig.sh)]), [with_tkconfig="${withval}"]) AC_MSG_CHECKING([for Tk configuration]) AC_CACHE_VAL(ac_cv_c_tkconfig,[ # First check to see if --with-tkconfig was specified. if test x"${with_tkconfig}" != x ; then case "${with_tkconfig}" in */tkConfig.sh ) if test -f "${with_tkconfig}"; then AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" fi ;; esac if test -f "${with_tkconfig}/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" else AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) fi fi # then check for a private Tk library if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ../tk \ `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tk \ `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tk \ `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ ; do if test -f "$i/Tk.framework/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib/tk9.1 2>/dev/null` \ `ls -d /usr/lib/tk9.0 2>/dev/null` \ `ls -d /usr/lib/tk8.6 2>/dev/null` \ `ls -d /usr/lib/tk8.5 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/local/lib/tk9.1 2>/dev/null` \ `ls -d /usr/local/lib/tk9.0 2>/dev/null` \ `ls -d /usr/local/lib/tk8.6 2>/dev/null` \ `ls -d /usr/local/lib/tk8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk9.1 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk8.5 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ${srcdir}/../tk \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tkconfig}" = x ; then TK_BIN_DIR="# no Tk configs found" AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) else no_tk= TK_BIN_DIR="${ac_cv_c_tkconfig}" AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # TEA_LOAD_TCLCONFIG -- # # Load the tclConfig.sh file # # Arguments: # # Requires the following vars to be set: # TCL_BIN_DIR # # Results: # # Substitutes the following vars: # TCL_BIN_DIR # TCL_SRC_DIR # TCL_LIB_FILE # TCL_ZIP_FILE # TCL_ZIPFS_SUPPORT #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_TCLCONFIG], [ AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh]) if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then AC_MSG_RESULT([loading]) . "${TCL_BIN_DIR}/tclConfig.sh" else AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh]) fi # If the TCL_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TCL_LIB_SPEC will be set to the value # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TCL_BIN_DIR}/Makefile" ; then TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tcl.framework installed in an arbitrary location. case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" break fi done fi if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" fi ;; esac fi AC_SUBST(TCL_VERSION) AC_SUBST(TCL_PATCH_LEVEL) AC_SUBST(TCL_BIN_DIR) AC_SUBST(TCL_SRC_DIR) AC_SUBST(TCL_LIB_FILE) AC_SUBST(TCL_LIB_FLAG) AC_SUBST(TCL_LIB_SPEC) AC_SUBST(TCL_STUB_LIB_FILE) AC_SUBST(TCL_STUB_LIB_FLAG) AC_SUBST(TCL_STUB_LIB_SPEC) AC_MSG_CHECKING([platform]) hold_cc=$CC; CC="$TCL_CC" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ #ifdef _WIN32 #error win32 #endif ]])],[ # first test we've already retrieved platform (cross-compile), fallback to unix otherwise: TEA_PLATFORM="${TEA_PLATFORM-unix}" CYGPATH=echo ],[ TEA_PLATFORM="windows" AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo) ]) CC=$hold_cc AC_MSG_RESULT($TEA_PLATFORM) # The BUILD_$pkg is to define the correct extern storage class # handling when making this package # To be able to sefely use the package name in a #define, it must not # contain anything other than alphanumeric characters and underscores SAFE_PKG_NAME=patsubst(AC_PACKAGE_NAME, [[^A-Za-z0-9_]], [_]) AC_DEFINE_UNQUOTED(BUILD_${SAFE_PKG_NAME}, [], [Building extension source?]) # Do this here as we have fully defined TEA_PLATFORM now if test "${TEA_PLATFORM}" = "windows" ; then EXEEXT=".exe" CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" fi # TEA specific: AC_SUBST(CLEANFILES) AC_SUBST(TCL_LIBS) AC_SUBST(TCL_DEFS) AC_SUBST(TCL_EXTRA_CFLAGS) AC_SUBST(TCL_LD_FLAGS) AC_SUBST(TCL_SHLIB_LD_LIBS) ]) #------------------------------------------------------------------------ # TEA_LOAD_TKCONFIG -- # # Load the tkConfig.sh file # # Arguments: # # Requires the following vars to be set: # TK_BIN_DIR # # Results: # # Sets the following vars that should be in tkConfig.sh: # TK_BIN_DIR #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_TKCONFIG], [ AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then AC_MSG_RESULT([loading]) . "${TK_BIN_DIR}/tkConfig.sh" else AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) fi # If the TK_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TK_LIB_SPEC will be set to the value # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC # instead of TK_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TK_BIN_DIR}/Makefile" ; then TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tk was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tk.framework installed in an arbitrary location. case ${TK_DEFS} in *TK_FRAMEWORK*) if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then for i in "`cd "${TK_BIN_DIR}"; pwd`" \ "`cd "${TK_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" break fi done fi if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" fi ;; esac fi # TEA specific: Ensure windowingsystem is defined if test "${TEA_PLATFORM}" = "unix" ; then case ${TK_DEFS} in *MAC_OSX_TK*) AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?]) TEA_WINDOWINGSYSTEM="aqua" ;; *) TEA_WINDOWINGSYSTEM="x11" ;; esac elif test "${TEA_PLATFORM}" = "windows" ; then TEA_WINDOWINGSYSTEM="win32" fi AC_SUBST(TK_VERSION) AC_SUBST(TK_BIN_DIR) AC_SUBST(TK_SRC_DIR) AC_SUBST(TK_LIB_FILE) AC_SUBST(TK_LIB_FLAG) AC_SUBST(TK_LIB_SPEC) AC_SUBST(TK_STUB_LIB_FILE) AC_SUBST(TK_STUB_LIB_FLAG) AC_SUBST(TK_STUB_LIB_SPEC) # TEA specific: AC_SUBST(TK_LIBS) AC_SUBST(TK_XINCLUDES) ]) #------------------------------------------------------------------------ # TEA_PROG_TCLSH # Determine the fully qualified path name of the tclsh executable # in the Tcl build directory or the tclsh installed in a bin # directory. This macro will correctly determine the name # of the tclsh executable even if tclsh has not yet been # built in the build directory. The tclsh found is always # associated with a tclConfig.sh file. This tclsh should be used # only for running extension test cases. It should never be # or generation of files (like pkgIndex.tcl) at build time. # # Arguments: # none # # Results: # Substitutes the following vars: # TCLSH_PROG #------------------------------------------------------------------------ AC_DEFUN([TEA_PROG_TCLSH], [ AC_MSG_CHECKING([for tclsh]) if test -f "${TCL_BIN_DIR}/Makefile" ; then # tclConfig.sh is in Tcl build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" fi else TCLSH_PROG="${TCL_BIN_DIR}/tclsh" fi else # tclConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" else TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" fi list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${TCLSH_PROG}" ; then REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" break fi done TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" fi AC_MSG_RESULT([${TCLSH_PROG}]) AC_SUBST(TCLSH_PROG) ]) #------------------------------------------------------------------------ # TEA_PROG_WISH # Determine the fully qualified path name of the wish executable # in the Tk build directory or the wish installed in a bin # directory. This macro will correctly determine the name # of the wish executable even if wish has not yet been # built in the build directory. The wish found is always # associated with a tkConfig.sh file. This wish should be used # only for running extension test cases. It should never be # or generation of files (like pkgIndex.tcl) at build time. # # Arguments: # none # # Results: # Substitutes the following vars: # WISH_PROG #------------------------------------------------------------------------ AC_DEFUN([TEA_PROG_WISH], [ AC_MSG_CHECKING([for wish]) if test -f "${TK_BIN_DIR}/Makefile" ; then # tkConfig.sh is in Tk build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}" elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}s${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}$s{EXEEXT}" elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}t${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}t${EXEEXT}" elif test -f "${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}st${EXEEXT}" ; then WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}st${EXEEXT}" fi else WISH_PROG="${TK_BIN_DIR}/wish" fi else # tkConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${EXEEXT}" else WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}" fi list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TK_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${WISH_PROG}" ; then REAL_TK_BIN_DIR="`cd "$i"; pwd`/" break fi done WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}" fi AC_MSG_RESULT([${WISH_PROG}]) AC_SUBST(WISH_PROG) ]) #------------------------------------------------------------------------ # TEA_ENABLE_SHARED -- # # Allows the building of shared libraries # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-shared=yes|no # --enable-stubs=yes|no # # Defines the following vars: # STATIC_BUILD Used for building import/export libraries # on Windows. # # Sets the following vars: # SHARED_BUILD Value of 1 or 0 # STUBS_BUILD Value if 1 or 0 # USE_TCL_STUBS Value true: if SHARED_BUILD or --enable-stubs # USE_TCLOO_STUBS Value true: if SHARED_BUILD or --enable-stubs # USE_TK_STUBS Value true: if SHARED_BUILD or --enable-stubs # AND TEA_WINDOWING_SYSTEM != "" #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_SHARED], [ AC_MSG_CHECKING([how to build libraries]) AC_ARG_ENABLE(shared, AS_HELP_STRING([--enable-shared], [build and link with shared libraries (default: on)]), [shared_ok=$enableval], [shared_ok=yes]) if test "${enable_shared+set}" = set; then enableval="$enable_shared" shared_ok=$enableval else shared_ok=yes fi AC_ARG_ENABLE(stubs, AS_HELP_STRING([--enable-stubs], [build and link with stub libraries. Always true for shared builds (default: on)]), [stubs_ok=$enableval], [stubs_ok=yes]) if test "${enable_stubs+set}" = set; then enableval="$enable_stubs" stubs_ok=$enableval else stubs_ok=yes fi # Stubs are always enabled for shared builds if test "$shared_ok" = "yes" ; then AC_MSG_RESULT([shared]) SHARED_BUILD=1 STUBS_BUILD=1 else AC_MSG_RESULT([static]) SHARED_BUILD=0 AC_DEFINE(STATIC_BUILD, 1, [This a static build]) if test "$stubs_ok" = "yes" ; then STUBS_BUILD=1 else STUBS_BUILD=0 fi fi if test "${STUBS_BUILD}" = "1" ; then AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) AC_DEFINE(USE_TCLOO_STUBS, 1, [Use TclOO stubs]) if test "${TEA_WINDOWINGSYSTEM}" != ""; then AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) fi fi AC_SUBST(SHARED_BUILD) AC_SUBST(STUBS_BUILD) ]) #------------------------------------------------------------------------ # TEA_ENABLE_THREADS -- # # Specify if thread support should be enabled. If "yes" is specified # as an arg (optional), threads are enabled by default, "no" means # threads are disabled. "yes" is the default. # # TCL_THREADS is checked so that if you are compiling an extension # against a threaded core, your extension must be compiled threaded # as well. # # Note that it is legal to have a thread enabled extension run in a # threaded or non-threaded Tcl core, but a non-threaded extension may # only run in a non-threaded Tcl core. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-threads # # Sets the following vars: # THREADS_LIBS Thread library(s) # # Defines the following vars: # TCL_THREADS # _REENTRANT # _THREAD_SAFE #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_THREADS], [ AC_ARG_ENABLE(threads, AS_HELP_STRING([--enable-threads], [build with threads (default: on)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "${enable_threads+set}" = set; then enableval="$enable_threads" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then TCL_THREADS=1 if test "${TEA_PLATFORM}" != "windows" ; then # We are always OK on Windows, so check what this platform wants: # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention AC_DEFINE(USE_THREAD_ALLOC, 1, [Do we want to use the threaded memory allocator?]) AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) if test "`uname -s`" = "SunOS" ; then AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) fi AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?]) AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no) if test "$tcl_ok" = "no"; then # Check a little harder for __pthread_mutex_init in the same # library, as some systems hide it there until pthread.h is # defined. We could alternatively do an AC_TRY_COMPILE with # pthread.h, but that will work with libpthread really doesn't # exist, like AIX 4.2. [Bug: 4359] AC_CHECK_LIB(pthread, __pthread_mutex_init, tcl_ok=yes, tcl_ok=no) fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else AC_CHECK_LIB(pthreads, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else AC_CHECK_LIB(c, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "no"; then AC_CHECK_LIB(c_r, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -pthread" else TCL_THREADS=0 AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled]) fi fi fi fi fi else TCL_THREADS=0 fi # Do checking message here to not mess up interleaved configure output AC_MSG_CHECKING([for building with threads]) if test "${TCL_THREADS}" = 1; then AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?]) AC_MSG_RESULT([yes (default)]) else AC_MSG_RESULT([no]) fi # TCL_THREADS sanity checking. See if our request for building with # threads is the same as the way Tcl was built. If not, warn the user. case ${TCL_DEFS} in *THREADS=1*) if test "${TCL_THREADS}" = "0"; then AC_MSG_WARN([ Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads.]) fi ;; esac AC_SUBST(TCL_THREADS) ]) #------------------------------------------------------------------------ # TEA_ENABLE_SYMBOLS -- # # Specify if debugging symbols should be used. # Memory (TCL_MEM_DEBUG) debugging can also be enabled. # # Arguments: # none # # TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives # the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted. # Requires the following vars to be set in the Makefile: # CFLAGS_DEFAULT # LDFLAGS_DEFAULT # # Results: # # Adds the following arguments to configure: # --enable-symbols # # Defines the following vars: # CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true # Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false # LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true # Sets to $(LDFLAGS_OPTIMIZE) if false #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_SYMBOLS], [ dnl TEA specific: Make sure we are initialized AC_REQUIRE([TEA_CONFIG_CFLAGS]) AC_MSG_CHECKING([for build with symbols]) AC_ARG_ENABLE(symbols, AS_HELP_STRING([--enable-symbols], [build with debugging symbols (default: off)]), [tcl_ok=$enableval], [tcl_ok=no]) if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" AC_MSG_RESULT([no]) AC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?]) else CFLAGS_DEFAULT="${CFLAGS_DEBUG}" LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" if test "$tcl_ok" = "yes"; then AC_MSG_RESULT([yes (standard debugging)]) fi fi AC_SUBST(CFLAGS_DEFAULT) AC_SUBST(LDFLAGS_DEFAULT) if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?]) fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then AC_MSG_RESULT([enabled symbols mem debugging]) else AC_MSG_RESULT([enabled $tcl_ok debugging]) fi fi ]) #------------------------------------------------------------------------ # TEA_ENABLE_LANGINFO -- # # Allows use of modern nl_langinfo check for better l10n. # This is only relevant for Unix. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-langinfo=yes|no (default is yes) # # Defines the following vars: # HAVE_LANGINFO Triggers use of nl_langinfo if defined. #------------------------------------------------------------------------ AC_DEFUN([TEA_ENABLE_LANGINFO], [ AC_ARG_ENABLE(langinfo, AS_HELP_STRING([--enable-langinfo], [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]), [langinfo_ok=$enableval], [langinfo_ok=yes]) HAVE_LANGINFO=0 if test "$langinfo_ok" = "yes"; then AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no]) fi AC_MSG_CHECKING([whether to use nl_langinfo]) if test "$langinfo_ok" = "yes"; then AC_CACHE_VAL(tcl_cv_langinfo_h, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[nl_langinfo(CODESET);]])], [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])]) AC_MSG_RESULT([$tcl_cv_langinfo_h]) if test $tcl_cv_langinfo_h = yes; then AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?]) fi else AC_MSG_RESULT([$langinfo_ok]) fi ]) #-------------------------------------------------------------------- # TEA_CONFIG_SYSTEM # # Determine what the system is (some things cannot be easily checked # on a feature-driven basis, alas). This can usually be done via the # "uname" command. # # Arguments: # none # # Results: # Defines the following var: # # system - System/platform/version identification code. # #-------------------------------------------------------------------- AC_DEFUN([TEA_CONFIG_SYSTEM], [ AC_CACHE_CHECK([system version], tcl_cv_sys_version, [ # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then AC_MSG_WARN([can't find uname command]) tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi ]) system=$tcl_cv_sys_version ]) #-------------------------------------------------------------------- # TEA_CONFIG_CFLAGS # # Try to determine the proper flags to pass to the compiler # for building shared libraries and other such nonsense. # # Arguments: # none # # Results: # # Defines and substitutes the following vars: # # DL_OBJS, DL_LIBS - removed for TEA, only needed by core. # LDFLAGS - Flags to pass to the compiler when linking object # files into an executable application binary such # as tclsh. # LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib", # that tell the run-time dynamic linker where to look # for shared libraries such as libtcl.so. Depends on # the variable LIB_RUNTIME_DIR in the Makefile. Could # be the same as CC_SEARCH_FLAGS if ${CC} is used to link. # CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib", # that tell the run-time dynamic linker where to look # for shared libraries such as libtcl.so. Depends on # the variable LIB_RUNTIME_DIR in the Makefile. # SHLIB_CFLAGS - Flags to pass to cc when compiling the components # of a shared library (may request position-independent # code, among other things). # SHLIB_LD - Base command to use for combining object files # into a shared library. # SHLIB_LD_LIBS - Dependent libraries for the linker to scan when # creating shared libraries. This symbol typically # goes at the end of the "ld" commands that build # shared libraries. The value of the symbol defaults to # "${LIBS}" if all of the dependent libraries should # be specified when creating a shared library. If # dependent libraries should not be specified (as on # SunOS 4.x, where they cause the link to fail, or in # general if Tcl and Tk aren't themselves shared # libraries), then this symbol has an empty string # as its value. # SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable # extensions. An empty string means we don't know how # to use shared libraries on this platform. # LIB_SUFFIX - Specifies everything that comes after the "libfoo" # in a static or shared library name, using the $PACKAGE_VERSION variable # to put the version in the right place. This is used # by platforms that need non-standard library names. # Examples: ${PACKAGE_VERSION}.so.1.1 on NetBSD, since it needs # to have a version after the .so, and ${PACKAGE_VERSION}.a # on AIX, since a shared library needs to have # a .a extension whereas shared objects for loadable # extensions have a .so extension. Defaults to # ${PACKAGE_VERSION}${SHLIB_SUFFIX}. # CFLAGS_DEBUG - # Flags used when running the compiler in debug mode # CFLAGS_OPTIMIZE - # Flags used when running the compiler in optimize mode # CFLAGS - Additional CFLAGS added as necessary (usually 64-bit) #-------------------------------------------------------------------- AC_DEFUN([TEA_CONFIG_CFLAGS], [ dnl TEA specific: Make sure we are initialized AC_REQUIRE([TEA_INIT]) # Step 0.a: Enable 64 bit support? AC_MSG_CHECKING([if 64bit support is requested]) AC_ARG_ENABLE(64bit, AS_HELP_STRING([--enable-64bit], [enable 64bit support (default: off)]), [do64bit=$enableval], [do64bit=no]) AC_MSG_RESULT([$do64bit]) # Step 0.b: Enable Solaris 64 bit VIS support? AC_MSG_CHECKING([if 64bit Sparc VIS support is requested]) AC_ARG_ENABLE(64bit-vis, AS_HELP_STRING([--enable-64bit-vis], [enable 64bit Sparc VIS support (default: off)]), [do64bitVIS=$enableval], [do64bitVIS=no]) AC_MSG_RESULT([$do64bitVIS]) # Force 64bit on with VIS AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes]) # Step 0.c: Check if visibility support is available. Do this here so # that platform specific alternatives can be used below if this fails. AC_CACHE_CHECK([if compiler supports visibility "hidden"], tcl_cv_cc_visibility_hidden, [ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ extern __attribute__((__visibility__("hidden"))) void f(void); void f(void) {}]], [[f();]])],[tcl_cv_cc_visibility_hidden=yes], [tcl_cv_cc_visibility_hidden=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [ AC_DEFINE(MODULE_SCOPE, [extern __attribute__((__visibility__("hidden")))], [Compiler support for module scope symbols]) AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols]) ]) # Step 0.d: Disable -rpath support? AC_MSG_CHECKING([if rpath support is requested]) AC_ARG_ENABLE(rpath, AS_HELP_STRING([--disable-rpath], [disable rpath support (default: on)]), [doRpath=$enableval], [doRpath=yes]) AC_MSG_RESULT([$doRpath]) # Set the variable "system" to hold the name and version number # for the system. TEA_CONFIG_SYSTEM # Require ranlib early so we can override it in special cases below. AC_REQUIRE([AC_PROG_RANLIB]) # Set configuration options based on system name and version. # This is similar to Tcl's unix/tcl.m4 except that we've added a # "windows" case and removed some core-only vars. do64bit_ok=no # default to '{$LIBS}' and set to "" on per-platform necessary basis SHLIB_LD_LIBS='${LIBS}' # When ld needs options to work in 64-bit mode, put them in # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] # is disabled by the user. [Bug 1016796] LDFLAGS_ARCH="" UNSHARED_LIB_SUFFIX="" # TEA specific: use PACKAGE_VERSION instead of VERSION TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g AS_IF([test "$GCC" = yes], [ CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall" ], [ CFLAGS_OPTIMIZE=-O CFLAGS_WARNING="" ]) AC_CHECK_TOOL(AR, ar) STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION=""],[SHLIB_VERSION=".$SHLIB_VERSION"]) case $system in # TEA specific: windows) MACHINE="X86" if test "$do64bit" != "no" ; then case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # default to AMD64 64-bit build ;; arm64|aarch64) MACHINE="ARM64" ;; ia64) MACHINE="IA64" ;; esac do64bit_ok=yes fi if test "$GCC" != "yes" ; then if test "${SHARED_BUILD}" = "0" ; then runtime=-MT else runtime=-MD fi case "x`echo \${VisualStudioVersion}`" in x1[[4-9]]*) lflags="${lflags} -nodefaultlib:ucrt.lib" TEA_ADD_LIBS([ucrt.lib]) ;; *) ;; esac if test "$do64bit" != "no" ; then CC="cl.exe" RC="rc.exe" lflags="${lflags} -nologo -MACHINE:${MACHINE} " LINKBIN="link.exe" CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" # Avoid 'unresolved external symbol __security_cookie' # errors, c.f. http://support.microsoft.com/?id=894573 TEA_ADD_LIBS([bufferoverflowU.lib]) else RC="rc" lflags="${lflags} -nologo" LINKBIN="link" CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" fi fi if test "$GCC" = "yes"; then # mingw gcc mode AC_CHECK_TOOL(RC, windres) CFLAGS_DEBUG="-g" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" SHLIB_LD='${CC} -shared' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" AC_CACHE_CHECK(for cross-compile version of gcc, ac_cv_cross, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #ifdef _WIN32 #error cross-compiler #endif ]], [[]])], [ac_cv_cross=yes], [ac_cv_cross=no]) ) if test "$ac_cv_cross" = "yes"; then case "$do64bit" in amd64|x64|yes) CC="x86_64-w64-mingw32-${CC}" LD="x86_64-w64-mingw32-ld" AR="x86_64-w64-mingw32-ar" RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; arm64|aarch64) CC="aarch64-w64-mingw32-clang" LD="aarch64-w64-mingw32-ld" AR="aarch64-w64-mingw32-ar" RANLIB="aarch64-w64-mingw32-ranlib" RC="aarch64-w64-mingw32-windres" ;; *) CC="i686-w64-mingw32-${CC}" LD="i686-w64-mingw32-ld" AR="i686-w64-mingw32-ar" RANLIB="i686-w64-mingw32-ranlib" RC="i686-w64-mingw32-windres" ;; esac fi else SHLIB_LD="${LINKBIN} -dll ${lflags}" # link -lib only works when -lib is the first arg STLIB_LD="${LINKBIN} -lib ${lflags}" UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' PATHTYPE=-w # For information on what debugtype is most useful, see: # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp # and also # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx # This essentially turns it all on. LDFLAGS_DEBUG="-debug -debugtype:cv" LDFLAGS_OPTIMIZE="-release" LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" fi SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots ;; AIX-*) AS_IF([test "$GCC" != "yes"], [ # AIX requires the _r compiler when gcc isn't being used case "${CC}" in *_r|*_r\ *) # ok ... ;; *) # Make sure only first arg gets _r CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'` ;; esac AC_MSG_RESULT([Using $CC for compiling with threads]) ]) LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_SUFFIX=".so" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ AS_IF([test "$GCC" = yes], [ AC_MSG_WARN([64bit mode not supported with GCC on $system]) ], [ do64bit_ok=yes CFLAGS="$CFLAGS -q64" LDFLAGS_ARCH="-q64" RANLIB="${RANLIB} -X64" AR="${AR} -X64" SHLIB_LD_FLAGS="-b64" ]) ]) AS_IF([test "`uname -m`" = ia64], [ # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC SHLIB_LD="/usr/ccs/bin/ld -G -z text" AS_IF([test "$GCC" = yes], [ CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' ], [ CC_SEARCH_FLAGS='"-R${LIB_RUNTIME_DIR}"' ]) LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' ], [ AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared -Wl,-bexpall' ], [ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" LDFLAGS="$LDFLAGS -brtl" ]) SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" CC_SEARCH_FLAGS='"-L${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ]) ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -nostart' SHLIB_SUFFIX=".so" #----------------------------------------------------------- # Check for inet_ntoa in -lbind, for BeOS (which also needs # -lsocket, even if the network functions are in -lnet which # is always linked to, for compatibility. #----------------------------------------------------------- AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"]) ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" if test "${TEA_PLATFORM}" = "unix" -a "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$(patsubst cyg%.dll,lib%.dll,\$[@]).a" else SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$[@].a" fi EXEEXT=".exe" do64bit_ok=yes CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; Haiku*) LDFLAGS="$LDFLAGS -Wl,--export-dynamic" SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"]) ;; HP-UX-*.11.*) # Use updated header definitions where possible AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) # TEA specific: Needed by Tcl, but not most extensions #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) #LIBS="$LIBS -lxnet" # Use the XOPEN network library AS_IF([test "`uname -m`" = ia64], [ SHLIB_SUFFIX=".so" ], [ SHLIB_SUFFIX=".sl" ]) AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) AS_IF([test "$tcl_ok" = yes], [ SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" ]) AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ], [ CFLAGS="$CFLAGS -z" ]) # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = "yes"], [ AS_IF([test "$GCC" = yes], [ case `${CC} -dumpmachine` in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD='${CC} -shared' AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) AC_MSG_WARN([64bit mode not supported with GCC on $system]) ;; esac ], [ do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" ]) ]) ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) AS_IF([test "$tcl_ok" = yes], [ SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" ]) ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_SUFFIX=".so" AC_LIBOBJ(mkstemp) AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"']) ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"']) AS_IF([test "$GCC" = yes], [ CFLAGS="$CFLAGS -mabi=n32" LDFLAGS="$LDFLAGS -mabi=n32" ], [ case $system in IRIX-6.3) # Use to build 6.2 compatible binaries on 6.3. CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ;; *) CFLAGS="$CFLAGS -n32" ;; esac LDFLAGS="$LDFLAGS -n32" ]) ;; IRIX64-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"']) # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ AS_IF([test "$GCC" = yes], [ AC_MSG_WARN([64bit mode not supported by gcc]) ], [ do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" ]) ]) ;; Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" # TEA specific: CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS_DEFAULT} -shared' LDFLAGS="$LDFLAGS -Wl,--export-dynamic" case $system in DragonFly-*|FreeBSD-*) AS_IF([test "${TCL_THREADS}" = "1"], [ # The -pthread needs to go in the LDFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) ;; esac AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) AS_IF([test $do64bit = yes], [ AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -m64" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_m64=yes],[tcl_cv_cc_m64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_m64 = yes], [ CFLAGS="$CFLAGS -m64" do64bit_ok=yes ]) ]) # The combo of gcc + glibc has a bug related to inlining of # functions like strtod(). The -fno-builtin flag should address # this problem but it does not work. The -fno-inline flag is kind # of overkill but it works. Disable inlining only when one of the # files in compat/*.c is being linked in. AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"]) ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD='${CC} -shared' LD_FLAGS="-Wl,--export-dynamic" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) ;; OpenBSD-*) arch=`arch -s` case "$arch" in alpha|sparc64) SHLIB_CFLAGS="-fPIC" ;; *) SHLIB_CFLAGS="-fpic" ;; esac SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' LDFLAGS="$LDFLAGS -Wl,-export-dynamic" CFLAGS_OPTIMIZE="-O2" # On OpenBSD: Compile with -pthread # Don't link with -lpthread LIBS=`echo $LIBS | sed s/-lpthread//` CFLAGS="$CFLAGS -pthread" # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; NetBSD-*) # NetBSD has ELF and can use 'cc -shared' to build shared libs SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # The -pthread needs to go in the CFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" # To avoid discrepancies between what headers configure sees during # preprocessing tests and compiling tests, move any -isysroot and # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`" CFLAGS="`echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`" AS_IF([test $do64bit = yes], [ case `arch` in ppc) AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag], tcl_cv_cc_arch_ppc64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_arch_ppc64=yes],[tcl_cv_cc_arch_ppc64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" do64bit_ok=yes ]);; i386) AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag], tcl_cv_cc_arch_x86_64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch x86_64" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_arch_x86_64=yes],[tcl_cv_cc_arch_x86_64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [ CFLAGS="$CFLAGS -arch x86_64" do64bit_ok=yes ]);; *) AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);; esac ], [ # Check for combined 32-bit and 64-bit fat build AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [ fat_32_64=yes]) ]) # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' # TEA specific: link shlib with current and compatibility version flags vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" SHLIB_SUFFIX=".dylib" LDFLAGS="$LDFLAGS -headerpad_max_install_names" AC_CACHE_CHECK([if ld accepts -search_paths_first flag], tcl_cv_ld_search_paths_first, [ hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])], [tcl_cv_ld_search_paths_first=yes],[tcl_cv_ld_search_paths_first=no]) LDFLAGS=$hold_ldflags]) AS_IF([test $tcl_cv_ld_search_paths_first = yes], [ LDFLAGS="$LDFLAGS -Wl,-search_paths_first" ]) AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ AC_DEFINE(MODULE_SCOPE, [__private_extern__], [Compiler support for module scope symbols]) tcl_cv_cc_visibility_hidden=yes ]) CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for combined 32 & 64 bit fat builds of Tk # extensions, verify that 64-bit build is possible. AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [ AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [ AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [ for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[XrmInitialize();]])], [tcl_cv_lib_x11_64=yes],[tcl_cv_lib_x11_64=no]) for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done]) ]) AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [ AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [ for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[Tk_InitStubs(NULL, "", 0);]])], [tcl_cv_lib_tk_64=yes],[tcl_cv_lib_tk_64=no]) for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done]) ]) # remove 64-bit arch flags from CFLAGS et al. if configuration # does not support 64-bit. AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [ AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags]) for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' done]) ]) ;; OS/390-*) CFLAGS_OPTIMIZE="" # Optimizer is buggy AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h [Should OS/390 do the right thing with sockets?]) ;; OSF1-V*) # Digital OSF/1 SHLIB_CFLAGS="" AS_IF([test "$SHARED_BUILD" = 1], [ SHLIB_LD='ld -shared -expect_unresolved "*"' ], [ SHLIB_LD='ld -non_shared -expect_unresolved "*"' ]) SHLIB_SUFFIX=".so" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"]) # see pthread_intro(3) for pthread support on osf1, k.furukawa CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" LIBS=`echo $LIBS | sed s/-lpthreads//` AS_IF([test "$GCC" = yes], [ LIBS="$LIBS -lpthread -lmach -lexc" ], [ CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ]) ;; QNX-6*) # QNX RTP # This may work for all QNX, but it was only reported for v6. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) AS_IF([test "$GCC" = yes], [ SHLIB_CFLAGS="-fPIC -melf" LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" ], [ SHLIB_CFLAGS="-Kpic -belf" LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" ]) SHLIB_LD="ld -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-5.[[0-6]]) # Careful to not let 5.10+ fall into this case # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) SHLIB_CFLAGS="-KPIC" SHLIB_SUFFIX=".so" AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ], [ SHLIB_LD="/usr/ccs/bin/ld -G -z text" CC_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ]) ;; SunOS-5*) # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) SHLIB_CFLAGS="-KPIC" # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ arch=`isainfo` AS_IF([test "$arch" = "sparcv9 sparc"], [ AS_IF([test "$GCC" = yes], [ AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [ AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) ], [ do64bit_ok=yes CFLAGS="$CFLAGS -m64 -mcpu=v9" LDFLAGS="$LDFLAGS -m64 -mcpu=v9" SHLIB_CFLAGS="-fPIC" ]) ], [ do64bit_ok=yes AS_IF([test "$do64bitVIS" = yes], [ CFLAGS="$CFLAGS -xarch=v9a" LDFLAGS_ARCH="-xarch=v9a" ], [ CFLAGS="$CFLAGS -xarch=v9" LDFLAGS_ARCH="-xarch=v9" ]) # Solaris 64 uses this as well #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" ]) ], [AS_IF([test "$arch" = "amd64 i386"], [ AS_IF([test "$GCC" = yes], [ case $system in SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) do64bit_ok=yes CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) AC_MSG_WARN([64bit mode not supported with GCC on $system]);; esac ], [ do64bit_ok=yes case $system in SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64";; esac ]) ], [AC_MSG_WARN([64bit mode not supported for $arch])])]) ]) SHLIB_SUFFIX=".so" AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} AS_IF([test "$do64bit_ok" = yes], [ AS_IF([test "$arch" = "sparcv9 sparc"], [ # We need to specify -static-libgcc or we need to # add the path to the sparv9 libgcc. # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" # for finding sparcv9 libgcc, get the regular libgcc # path, remove so name and append 'sparcv9' #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" ], [AS_IF([test "$arch" = "amd64 i386"], [ # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" ])]) ]) ], [ case $system in SunOS-5.[[1-9]][[0-9]]*) # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; *) SHLIB_LD='/usr/ccs/bin/ld -G -z text';; esac CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' ]) ;; UNIX_SV* | UnixWare-5*) SHLIB_CFLAGS="-KPIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [ hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])], [tcl_cv_ld_Bexport=yes],[tcl_cv_ld_Bexport=no]) LDFLAGS=$hold_ldflags]) AS_IF([test $tcl_cv_ld_Bexport = yes], [ LDFLAGS="$LDFLAGS -Wl,-Bexport" ]) CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; esac AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [ AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) ]) dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so dnl # until the end of configure, as configure's compile and link tests use dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's dnl # preprocessing tests use only CPPFLAGS. AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""]) # Add in the arch flags late to ensure it wasn't removed. # Not necessary in TEA, but this is aligned with core LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" # If we're running gcc, then change the C flags for compiling shared # libraries to the right flags for gcc, instead of those for the # standard manufacturer compiler. AS_IF([test "$GCC" = yes], [ case $system in AIX-*) ;; BSD/OS*) ;; CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) ;; IRIX*) ;; NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac]) AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ AC_DEFINE(MODULE_SCOPE, [extern], [No Compiler support for module scope symbols]) ]) AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [ # TEA specific: use PACKAGE_VERSION instead of VERSION SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}']) AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [ # TEA specific: use PACKAGE_VERSION instead of VERSION UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a']) if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then AC_CACHE_CHECK(for SEH support in compiler, tcl_cv_seh, AC_RUN_IFELSE([AC_LANG_SOURCE([[ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main(int argc, char** argv) { int a, b = 0; __try { a = 666 / b; } __except (EXCEPTION_EXECUTE_HANDLER) { return 0; } return 1; } ]])], [tcl_cv_seh=yes], [tcl_cv_seh=no], [tcl_cv_seh=no]) ) if test "$tcl_cv_seh" = "no" ; then AC_DEFINE(HAVE_NO_SEH, 1, [Defined when mingw does not support SEH]) fi # # Check to see if the excpt.h include file provided contains the # definition for EXCEPTION_DISPOSITION; if not, which is the case # with Cygwin's version as of 2002-04-10, define it to be int, # sufficient for getting the current code to work. # AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files, tcl_cv_eh_disposition, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ # define WIN32_LEAN_AND_MEAN # include # undef WIN32_LEAN_AND_MEAN ]], [[ EXCEPTION_DISPOSITION x; ]])], [tcl_cv_eh_disposition=yes], [tcl_cv_eh_disposition=no]) ) if test "$tcl_cv_eh_disposition" = "no" ; then AC_DEFINE(EXCEPTION_DISPOSITION, int, [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION]) fi # Check to see if winnt.h defines CHAR, SHORT, and LONG # even if VOID has already been #defined. The win32api # used by mingw and cygwin is known to do this. AC_CACHE_CHECK(for winnt.h that ignores VOID define, tcl_cv_winnt_ignore_void, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #define VOID void #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN ]], [[ CHAR c; SHORT s; LONG l; ]])], [tcl_cv_winnt_ignore_void=yes], [tcl_cv_winnt_ignore_void=no]) ) if test "$tcl_cv_winnt_ignore_void" = "yes" ; then AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1, [Defined when cygwin/mingw ignores VOID define in winnt.h]) fi fi # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. AC_CACHE_CHECK(for cast to union support, tcl_cv_cast_to_union, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ union foo { int i; double d; }; union foo f = (union foo) (int) 0; ]])], [tcl_cv_cast_to_union=yes], [tcl_cv_cast_to_union=no]) ) if test "$tcl_cv_cast_to_union" = "yes"; then AC_DEFINE(HAVE_CAST_TO_UNION, 1, [Defined when compiler supports casting to union type.]) fi AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have ?])],) AC_SUBST(CFLAGS_DEBUG) AC_SUBST(CFLAGS_OPTIMIZE) AC_SUBST(CFLAGS_WARNING) AC_SUBST(LDFLAGS_DEBUG) AC_SUBST(LDFLAGS_OPTIMIZE) AC_SUBST(STLIB_LD) AC_SUBST(SHLIB_LD) AC_SUBST(SHLIB_LD_LIBS) AC_SUBST(SHLIB_CFLAGS) AC_SUBST(LD_LIBRARY_PATH_VAR) # These must be called after we do the basic CFLAGS checks and # verify any possible 64-bit or similar switches are necessary TEA_TCL_EARLY_FLAGS TEA_TCL_64BIT_FLAGS ]) #-------------------------------------------------------------------- # TEA_SERIAL_PORT # # Determine which interface to use to talk to the serial port. # Note that #include lines must begin in leftmost column for # some compilers to recognize them as preprocessor directives, # and some build environments have stdin not pointing at a # pseudo-terminal (usually /dev/null instead.) # # Arguments: # none # # Results: # # Defines only one of the following vars: # HAVE_SYS_MODEM_H # USE_TERMIOS # USE_TERMIO # USE_SGTTY #-------------------------------------------------------------------- AC_DEFUN([TEA_SERIAL_PORT], [ AC_CHECK_HEADERS(sys/modem.h) AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() { struct termios t; if (tcgetattr(0, &t) == 0) { cfsetospeed(&t, 0); t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termios],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) if test $tcl_cv_api_serial = no ; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() { struct termio t; if (ioctl(0, TCGETA, &t) == 0) { t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termio],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no ; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include int main() { struct sgttyb t; if (ioctl(0, TIOCGETP, &t) == 0) { t.sg_ospeed = 0; t.sg_flags |= ODDP | EVENP | RAW; return 0; } return 1; }]])],[tcl_cv_api_serial=sgtty],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no ; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main() { struct termios t; if (tcgetattr(0, &t) == 0 || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { cfsetospeed(&t, 0); t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termios],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main() { struct termio t; if (ioctl(0, TCGETA, &t) == 0 || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB; return 0; } return 1; }]])],[tcl_cv_api_serial=termio],[tcl_cv_api_serial=no],[tcl_cv_api_serial=no]) fi if test $tcl_cv_api_serial = no; then AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main() { struct sgttyb t; if (ioctl(0, TIOCGETP, &t) == 0 || errno == ENOTTY || errno == ENXIO || errno == EINVAL) { t.sg_ospeed = 0; t.sg_flags |= ODDP | EVENP | RAW; return 0; } return 1; }]])],[tcl_cv_api_serial=sgtty],[tcl_cv_api_serial=none],[tcl_cv_api_serial=none]) fi]) case $tcl_cv_api_serial in termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);; termio) AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);; sgtty) AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);; esac ]) #-------------------------------------------------------------------- # TEA_PATH_X # # Locate the X11 header files and the X11 library archive. Try # the ac_path_x macro first, but if it doesn't find the X stuff # (e.g. because there's no xmkmf program) then check through # a list of possible directories. Under some conditions the # autoconf macro will return an include directory that contains # no include files, so double-check its result just to be safe. # # This should be called after TEA_CONFIG_CFLAGS as setting the # LIBS line can confuse some configure macro magic. # # Arguments: # none # # Results: # # Sets the following vars: # XINCLUDES # XLIBSW # PKG_LIBS (appends to) #-------------------------------------------------------------------- AC_DEFUN([TEA_PATH_X], [ if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then TEA_PATH_UNIX_X fi ]) AC_DEFUN([TEA_PATH_UNIX_X], [ AC_PATH_X not_really_there="" if test "$no_x" = ""; then if test "$x_includes" = ""; then AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[],[not_really_there="yes"]) else if test ! -r $x_includes/X11/Xlib.h; then not_really_there="yes" fi fi fi if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then AC_MSG_CHECKING([for X11 header files]) found_xincludes="no" AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[found_xincludes="yes"],[found_xincludes="no"]) if test "$found_xincludes" = "no"; then dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" for i in $dirs ; do if test -r $i/X11/Xlib.h; then AC_MSG_RESULT([$i]) XINCLUDES=" -I$i" found_xincludes="yes" break fi done fi else if test "$x_includes" != ""; then XINCLUDES="-I$x_includes" found_xincludes="yes" fi fi if test "$found_xincludes" = "no"; then AC_MSG_RESULT([couldn't find any!]) fi if test "$no_x" = yes; then AC_MSG_CHECKING([for X11 libraries]) XLIBSW=nope dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" for i in $dirs ; do if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then AC_MSG_RESULT([$i]) XLIBSW="-L$i -lX11" x_libraries="$i" break fi done else if test "$x_libraries" = ""; then XLIBSW=-lX11 else XLIBSW="-L$x_libraries -lX11" fi fi if test "$XLIBSW" = nope ; then AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow) fi if test "$XLIBSW" = nope ; then AC_MSG_RESULT([could not find any! Using -lX11.]) XLIBSW=-lX11 fi # TEA specific: if test x"${XLIBSW}" != x ; then PKG_LIBS="${PKG_LIBS} ${XLIBSW}" fi ]) #-------------------------------------------------------------------- # TEA_BLOCKING_STYLE # # The statements below check for systems where POSIX-style # non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. # On these systems (mostly older ones), use the old BSD-style # FIONBIO approach instead. # # Arguments: # none # # Results: # # Defines some of the following vars: # HAVE_SYS_IOCTL_H # HAVE_SYS_FILIO_H # USE_FIONBIO # O_NONBLOCK #-------------------------------------------------------------------- AC_DEFUN([TEA_BLOCKING_STYLE], [ AC_CHECK_HEADERS(sys/ioctl.h) AC_CHECK_HEADERS(sys/filio.h) TEA_CONFIG_SYSTEM AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O]) case $system in OSF*) AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) AC_MSG_RESULT([FIONBIO]) ;; *) AC_MSG_RESULT([O_NONBLOCK]) ;; esac ]) #-------------------------------------------------------------------- # TEA_TIME_HANDLER # # Checks how the system deals with time.h, what time structures # are used on the system, and what fields the structures have. # # Arguments: # none # # Results: # # Defines some of the following vars: # USE_DELTA_FOR_TZ # HAVE_TM_GMTOFF # HAVE_TM_TZADJ # HAVE_TIMEZONE_VAR # #-------------------------------------------------------------------- AC_DEFUN([TEA_TIME_HANDLER], [ AC_CHECK_HEADERS(sys/time.h) AC_HEADER_TIME AC_STRUCT_TIMEZONE AC_CHECK_FUNCS(gmtime_r localtime_r mktime) AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct tm tm; (void)tm.tm_tzadj;]])], [tcl_cv_member_tm_tzadj=yes], [tcl_cv_member_tm_tzadj=no])]) if test $tcl_cv_member_tm_tzadj = yes ; then AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?]) fi AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct tm tm; (void)tm.tm_gmtoff;]])], [tcl_cv_member_tm_gmtoff=yes], [tcl_cv_member_tm_gmtoff=no])]) if test $tcl_cv_member_tm_gmtoff = yes ; then AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?]) fi # # Its important to include time.h in this check, as some systems # (like convex) have timezone functions, etc. # AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[extern long timezone; timezone += 1; exit (0);]])], [tcl_cv_timezone_long=yes], [tcl_cv_timezone_long=no])]) if test $tcl_cv_timezone_long = yes ; then AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) else # # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. # AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[extern time_t timezone; timezone += 1; exit (0);]])], [tcl_cv_timezone_time=yes], [tcl_cv_timezone_time=no])]) if test $tcl_cv_timezone_time = yes ; then AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) fi fi ]) #-------------------------------------------------------------------- # TEA_BUGGY_STRTOD # # Under Solaris 2.4, strtod returns the wrong value for the # terminating character under some conditions. Check for this # and if the problem exists use a substitute procedure # "fixstrtod" (provided by Tcl) that corrects the error. # Also, on Compaq's Tru64 Unix 5.0, # strtod(" ") returns 0.0 instead of a failure to convert. # # Arguments: # none # # Results: # # Might defines some of the following vars: # strtod (=fixstrtod) #-------------------------------------------------------------------- AC_DEFUN([TEA_BUGGY_STRTOD], [ AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0) if test "$tcl_strtod" = 1; then AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[ AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include extern double strtod(); int main() { char *infString="Inf", *nanString="NaN", *spaceString=" "; char *term; double value; value = strtod(infString, &term); if ((term != infString) && (term[-1] == 0)) { exit(1); } value = strtod(nanString, &term); if ((term != nanString) && (term[-1] == 0)) { exit(1); } value = strtod(spaceString, &term); if (term == (spaceString+1)) { exit(1); } exit(0); }]])], [tcl_cv_strtod_buggy=ok], [tcl_cv_strtod_buggy=buggy], [tcl_cv_strtod_buggy=buggy])]) if test "$tcl_cv_strtod_buggy" = buggy; then AC_LIBOBJ([fixstrtod]) USE_COMPAT=1 AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?]) fi fi ]) #-------------------------------------------------------------------- # TEA_TCL_LINK_LIBS # # Search for the libraries needed to link the Tcl shell. # Things like the math library (-lm), socket stuff (-lsocket vs. # -lnsl), zlib (-lz) and libtommath (-ltommath) are dealt with here. # # Arguments: # None. # # Results: # # Might append to the following vars: # LIBS # MATH_LIBS # # Might define the following vars: # HAVE_NET_ERRNO_H # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_LINK_LIBS], [ #-------------------------------------------------------------------- # On a few very rare systems, all of the libm.a stuff is # already in libc.a. Set compiler flags accordingly. #-------------------------------------------------------------------- AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") #-------------------------------------------------------------------- # Interactive UNIX requires -linet instead of -lsocket, plus it # needs net/errno.h to define the socket-related error codes. #-------------------------------------------------------------------- AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) AC_CHECK_HEADER(net/errno.h, [ AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have ?])]) #-------------------------------------------------------------------- # Check for the existence of the -lsocket and -lnsl libraries. # The order here is important, so that they end up in the right # order in the command line generated by make. Here are some # special considerations: # 1. Use "connect" and "accept" to check for -lsocket, and # "gethostbyname" to check for -lnsl. # 2. Use each function name only once: can't redo a check because # autoconf caches the results of the last check and won't redo it. # 3. Use -lnsl and -lsocket only if they supply procedures that # aren't already present in the normal libraries. This is because # IRIX 5.2 has libraries, but they aren't needed and they're # bogus: they goof up name resolution if used. # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. # To get around this problem, check for both libraries together # if -lsocket doesn't work by itself. #-------------------------------------------------------------------- tcl_checkBoth=0 AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) if test "$tcl_checkSocket" = 1; then AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt, LIBS="$LIBS -lsocket", tcl_checkBoth=1)]) fi if test "$tcl_checkBoth" = 1; then tk_oldLibs=$LIBS LIBS="$LIBS -lsocket -lnsl" AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) fi AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname, [LIBS="$LIBS -lnsl"])]) AC_CHECK_FUNC(mp_log_u32, , [AC_CHECK_LIB(tommath, mp_log_u32, [LIBS="$LIBS -ltommath"])]) AC_CHECK_FUNC(deflateSetHeader, , [AC_CHECK_LIB(z, deflateSetHeader, [LIBS="$LIBS -lz"])]) ]) #-------------------------------------------------------------------- # TEA_TCL_EARLY_FLAGS # # Check for what flags are needed to be passed so the correct OS # features are available. # # Arguments: # None # # Results: # # Might define the following vars: # _ISOC99_SOURCE # _FILE_OFFSET_BITS # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_EARLY_FLAG],[ AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]), AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$2]], [[$3]])], [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[[#define ]$1[ ]m4_default([$4],[1])[ ]$2]], [[$3]])], [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)])) if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then AC_DEFINE($1, m4_default([$4],[1]), [Add the ]$1[ flag when building]) tcl_flags="$tcl_flags $1" fi ]) AC_DEFUN([TEA_TCL_EARLY_FLAGS],[ AC_MSG_CHECKING([for required early compiler flags]) tcl_flags="" TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include ], [char *p = (char *)strtoll; char *q = (char *)strtoull;]) if test "${TCL_MAJOR_VERSION}" -ne 8 ; then TEA_TCL_EARLY_FLAG(_FILE_OFFSET_BITS,[#include ], [switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; }],64) fi if test "x${tcl_flags}" = "x" ; then AC_MSG_RESULT([none]) else AC_MSG_RESULT([${tcl_flags}]) fi ]) #-------------------------------------------------------------------- # TEA_TCL_64BIT_FLAGS # # Check for what is defined in the way of 64-bit features. # # Arguments: # None # # Results: # # Might define the following vars: # TCL_WIDE_INT_IS_LONG # TCL_WIDE_INT_TYPE # HAVE_STRUCT_DIRENT64, HAVE_DIR64 # HAVE_STRUCT_STAT64 # HAVE_TYPE_OFF64_T # _TIME_BITS # #-------------------------------------------------------------------- AC_DEFUN([TEA_TCL_64BIT_FLAGS], [ AC_MSG_CHECKING([for 64-bit integer type]) AC_CACHE_VAL(tcl_cv_type_64bit,[ tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[__int64 value = (__int64) 0;]])], [tcl_type_64bit=__int64],[tcl_type_64bit="long long"]) # See if we could use long anyway Note that we substitute in the # type that is our current guess for a 64-bit type inside this check # program, so it should be modified only carefully... AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; }]])],[tcl_cv_type_64bit=${tcl_type_64bit}],[])]) if test "${tcl_cv_type_64bit}" = none ; then AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Do 'long' and 'long long' have the same size (64-bit)?]) AC_MSG_RESULT([yes]) elif test "${tcl_cv_type_64bit}" = "__int64" \ -a "${TEA_PLATFORM}" = "windows" ; then # TEA specific: We actually want to use the default tcl.h checks in # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* AC_MSG_RESULT([using Tcl header defaults]) else AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit}, [What type should be used to define wide integers?]) AC_MSG_RESULT([${tcl_cv_type_64bit}]) # Now check for auxiliary declarations if test "${TCL_MAJOR_VERSION}" -ne 8 ; then AC_CACHE_CHECK([for 64-bit time_t], tcl_cv_time_t_64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])], [tcl_cv_time_t_64=yes],[tcl_cv_time_t_64=no])]) if test "x${tcl_cv_time_t_64}" = "xno" ; then # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64 # which SC_TCL_EARLY_FLAGS has defined if necessary. AC_CACHE_CHECK([if _TIME_BITS=64 enables 64-bit time_t], tcl_cv__time_bits,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#define _TIME_BITS 64 #include ]], [[switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;}]])], [tcl_cv__time_bits=yes],[tcl_cv__time_bits=no])]) if test "x${tcl_cv__time_bits}" = "xyes" ; then AC_DEFINE(_TIME_BITS, 64, [_TIME_BITS=64 enables 64-bit time_t.]) fi fi fi AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[struct dirent64 p;]])], [tcl_cv_struct_dirent64=yes],[tcl_cv_struct_dirent64=no])]) if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in ?]) fi AC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[struct dirent64 *p; DIR64 d = opendir64("."); p = readdir64(d); rewinddir64(d); closedir64(d);]])], [tcl_cv_DIR64=yes], [tcl_cv_DIR64=no])]) if test "x${tcl_cv_DIR64}" = "xyes" ; then AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in ?]) fi AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct stat64 p; ]])], [tcl_cv_struct_stat64=yes], [tcl_cv_struct_stat64=no])]) if test "x${tcl_cv_struct_stat64}" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in ?]) fi AC_CHECK_FUNCS(open64 lseek64) AC_MSG_CHECKING([for off64_t]) AC_CACHE_VAL(tcl_cv_type_off64_t,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[off64_t offset; ]])], [tcl_cv_type_off64_t=yes], [tcl_cv_type_off64_t=no])]) dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the dnl functions lseek64 and open64 are defined. if test "x${tcl_cv_type_off64_t}" = "xyes" && \ test "x${ac_cv_func_lseek64}" = "xyes" && \ test "x${ac_cv_func_open64}" = "xyes" ; then AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in ?]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi fi ]) ## ## Here ends the standard Tcl configuration bits and starts the ## TEA specific functions ## #------------------------------------------------------------------------ # TEA_INIT -- # # Init various Tcl Extension Architecture (TEA) variables. # This should be the first called TEA_* macro. # # Arguments: # none # # Results: # # Defines and substs the following vars: # CYGPATH # EXEEXT # Defines only: # TEA_VERSION # TEA_INITED # TEA_PLATFORM (windows or unix) # # "cygpath" is used on windows to generate native path names for include # files. These variables should only be used with the compiler and linker # since they generate native path names. # # EXEEXT # Select the executable extension based on the host type. This # is a lightweight replacement for AC_EXEEXT that doesn't require # a compiler. #------------------------------------------------------------------------ AC_DEFUN([TEA_INIT], [ TEA_VERSION="3.13" AC_MSG_CHECKING([TEA configuration]) if test x"${PACKAGE_NAME}" = x ; then AC_MSG_ERROR([ The PACKAGE_NAME variable must be defined by your TEA configure.ac]) fi AC_MSG_RESULT([ok (TEA ${TEA_VERSION})]) # If the user did not set CFLAGS, set it now to keep macros # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi case "`uname -s`" in *win32*|*WIN32*|*MINGW32_*|*MINGW64_*|*MSYS_*) AC_CHECK_PROG(CYGPATH, cygpath, cygpath -m, echo) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *CYGWIN_*) EXEEXT=".exe" # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG ;; *) CYGPATH=echo # Maybe we are cross-compiling.... case ${host_alias} in *mingw32*) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) EXEEXT="" TEA_PLATFORM="unix" ;; esac ;; esac # Check if exec_prefix is set. If not use fall back to prefix. # Note when adjusted, so that TEA_PREFIX can correct for this. # This is needed for recursive configures, since autoconf propagates # $prefix, but not $exec_prefix (doh!). if test x$exec_prefix = xNONE ; then exec_prefix_default=yes exec_prefix=$prefix fi AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}]) AC_SUBST(EXEEXT) AC_SUBST(CYGPATH) # This package name must be replaced statically for AC_SUBST to work AC_SUBST(PKG_LIB_FILE) AC_SUBST(PKG_LIB_FILE8) AC_SUBST(PKG_LIB_FILE9) # We AC_SUBST these here to ensure they are subst'ed, # in case the user doesn't call TEA_ADD_... AC_SUBST(PKG_STUB_SOURCES) AC_SUBST(PKG_STUB_OBJECTS) AC_SUBST(PKG_TCL_SOURCES) AC_SUBST(PKG_HEADERS) AC_SUBST(PKG_INCLUDES) AC_SUBST(PKG_LIBS) AC_SUBST(PKG_CFLAGS) # Configure the installer. TEA_INSTALLER ]) #------------------------------------------------------------------------ # TEA_ADD_SOURCES -- # # Specify one or more source files. Users should check for # the right platform before adding to their list. # It is not important to specify the directory, as long as it is # in the generic, win or unix subdirectory of $(srcdir). # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_SOURCES # PKG_OBJECTS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_SOURCES], [ vars="$@" for i in $vars; do case $i in [\$]*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" PKG_OBJECTS="$PKG_OBJECTS $i" ;; *) # check for existence - allows for generic/win/unix VPATH # To add more dirs here (like 'src'), you have to update VPATH # in Makefile.in as well if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then AC_MSG_ERROR([could not find source file '$i']) fi PKG_SOURCES="$PKG_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done AC_SUBST(PKG_SOURCES) AC_SUBST(PKG_OBJECTS) ]) #------------------------------------------------------------------------ # TEA_ADD_STUB_SOURCES -- # # Specify one or more source files. Users should check for # the right platform before adding to their list. # It is not important to specify the directory, as long as it is # in the generic, win or unix subdirectory of $(srcdir). # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_STUB_SOURCES # PKG_STUB_OBJECTS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_STUB_SOURCES], [ vars="$@" for i in $vars; do # check for existence - allows for generic/win/unix VPATH if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then AC_MSG_ERROR([could not find stub source file '$i']) fi PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}" fi PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" done AC_SUBST(PKG_STUB_SOURCES) AC_SUBST(PKG_STUB_OBJECTS) ]) #------------------------------------------------------------------------ # TEA_ADD_TCL_SOURCES -- # # Specify one or more Tcl source files. These should be platform # independent runtime files. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_TCL_SOURCES #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_TCL_SOURCES], [ vars="$@" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i']) fi PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" done AC_SUBST(PKG_TCL_SOURCES) ]) #------------------------------------------------------------------------ # TEA_ADD_HEADERS -- # # Specify one or more source headers. Users should check for # the right platform before adding to their list. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_HEADERS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_HEADERS], [ vars="$@" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then AC_MSG_ERROR([could not find header file '${srcdir}/$i']) fi PKG_HEADERS="$PKG_HEADERS $i" done AC_SUBST(PKG_HEADERS) ]) #------------------------------------------------------------------------ # TEA_ADD_INCLUDES -- # # Specify one or more include dirs. Users should check for # the right platform before adding to their list. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_INCLUDES], [ vars="$@" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $i" done AC_SUBST(PKG_INCLUDES) ]) #------------------------------------------------------------------------ # TEA_ADD_LIBS -- # # Specify one or more libraries. Users should check for # the right platform before adding to their list. For Windows, # libraries provided in "foo.lib" format will be converted to # "-lfoo" when using GCC (mingw). # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_LIBS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_LIBS], [ vars="$@" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.[[lL]][[iI]][[bB]][$]/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done AC_SUBST(PKG_LIBS) ]) #------------------------------------------------------------------------ # TEA_ADD_CFLAGS -- # # Specify one or more CFLAGS. Users should check for # the right platform before adding to their list. # # Arguments: # one or more file names # # Results: # # Defines and substs the following vars: # PKG_CFLAGS #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_CFLAGS], [ PKG_CFLAGS="$PKG_CFLAGS $@" AC_SUBST(PKG_CFLAGS) ]) #------------------------------------------------------------------------ # TEA_ADD_CLEANFILES -- # # Specify one or more CLEANFILES. # # Arguments: # one or more file names to clean target # # Results: # # Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG #------------------------------------------------------------------------ AC_DEFUN([TEA_ADD_CLEANFILES], [ CLEANFILES="$CLEANFILES $@" ]) #------------------------------------------------------------------------ # TEA_PREFIX -- # # Handle the --prefix=... option by defaulting to what Tcl gave # # Arguments: # none # # Results: # # If --prefix or --exec-prefix was not specified, $prefix and # $exec_prefix will be set to the values given to Tcl when it was # configured. #------------------------------------------------------------------------ AC_DEFUN([TEA_PREFIX], [ if test "${prefix}" = "NONE"; then prefix_default=yes if test x"${TCL_PREFIX}" != x; then AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}]) prefix=${TCL_PREFIX} else AC_MSG_NOTICE([--prefix defaulting to /usr/local]) prefix=/usr/local fi fi if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ -o x"${exec_prefix_default}" = x"yes" ; then if test x"${TCL_EXEC_PREFIX}" != x; then AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}]) exec_prefix=${TCL_EXEC_PREFIX} else AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}]) exec_prefix=$prefix fi fi ]) #------------------------------------------------------------------------ # TEA_SETUP_COMPILER_CC -- # # Do compiler checks the way we want. This is just a replacement # for AC_PROG_CC in TEA configure.ac files to make them cleaner. # # Arguments: # none # # Results: # # Sets up CC var and other standard bits we need to make executables. #------------------------------------------------------------------------ AC_DEFUN([TEA_SETUP_COMPILER_CC], [ # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) # in this macro, they need to go into TEA_SETUP_COMPILER instead. AC_PROG_CC AC_PROG_CPP #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- AC_PROG_MAKE_SET #-------------------------------------------------------------------- # Find ranlib #-------------------------------------------------------------------- AC_CHECK_TOOL(RANLIB, ranlib) #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- AC_OBJEXT AC_EXEEXT ]) #------------------------------------------------------------------------ # TEA_SETUP_COMPILER -- # # Do compiler checks that use the compiler. This must go after # TEA_SETUP_COMPILER_CC, which does the actual compiler check. # # Arguments: # none # # Results: # # Sets up CC var and other standard bits we need to make executables. #------------------------------------------------------------------------ AC_DEFUN([TEA_SETUP_COMPILER], [ # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. AC_REQUIRE([TEA_SETUP_COMPILER_CC]) #------------------------------------------------------------------------ # If we're using GCC, see if the compiler understands -pipe. If so, use it. # It makes compiling go faster. (This is only a performance feature.) #------------------------------------------------------------------------ if test -z "$no_pipe" -a -n "$GCC"; then AC_CACHE_CHECK([if the compiler understands -pipe], tcl_cv_cc_pipe, [ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_cc_pipe=yes],[tcl_cv_cc_pipe=no]) CFLAGS=$hold_cflags]) if test $tcl_cv_cc_pipe = yes; then CFLAGS="$CFLAGS -pipe" fi fi if test "${TCL_MAJOR_VERSION}" -lt 9 -a "${TCL_MINOR_VERSION}" -lt 7; then AC_DEFINE(Tcl_Size, int, [Is 'Tcl_Size' in ?]) fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- AC_C_BIGENDIAN(,,,[#]) ]) #------------------------------------------------------------------------ # TEA_MAKE_LIB -- # # Generate a line that can be used to build a shared/unshared library # in a platform independent manner. # # Arguments: # none # # Requires: # # Results: # # Defines the following vars: # CFLAGS - Done late here to note disturb other AC macros # MAKE_LIB - Command to execute to build the Tcl library; # differs depending on whether or not Tcl is being # compiled as a shared library. # MAKE_SHARED_LIB Makefile rule for building a shared library # MAKE_STATIC_LIB Makefile rule for building a static library # MAKE_STUB_LIB Makefile rule for building a stub library # VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL # VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE #------------------------------------------------------------------------ AC_DEFUN([TEA_MAKE_LIB], [ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" AC_EGREP_CPP([manifest needed], [ #if defined(_MSC_VER) && _MSC_VER >= 1400 print("manifest needed") #endif ], [ # Could do a CHECK_PROG for mt, but should always be with MSVC8+ VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi" VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi" MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" TEA_ADD_CLEANFILES([*.manifest]) ]) MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@ \$(PKG_STUB_OBJECTS)" else MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)" fi if test "${SHARED_BUILD}" = "1" ; then MAKE_LIB="${MAKE_SHARED_LIB} " else MAKE_LIB="${MAKE_STATIC_LIB} " fi #-------------------------------------------------------------------- # Shared libraries and static libraries have different names. # Use the double eval to make sure any variables in the suffix is # substituted. (@@@ Might not be necessary anymore) #-------------------------------------------------------------------- if test "$TEA_PLATFORM" = "unix"; then PACKAGE_LIB_PREFIX8="lib" if test "$EXEEXT" = ".exe" -a "$SHARED_BUILD" != "0"; then PACKAGE_LIB_PREFIX9="cygtcl9" else PACKAGE_LIB_PREFIX9="libtcl9" fi else PACKAGE_LIB_PREFIX8="" PACKAGE_LIB_PREFIX9="tcl9" fi if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX9}" else PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX8}" AC_DEFINE(TCL_MAJOR_VERSION, 8, [Compile for Tcl8?]) AC_DEFINE(TK_MAJOR_VERSION, 8, [Compile for Tk8?]) fi if test "${TEA_PLATFORM}" = "windows" ; then if test "${SHARED_BUILD}" = "1" ; then # We force the unresolved linking of symbols that are really in # the private libraries of Tcl and Tk. if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test "$GCC" = "yes"; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" fi AC_CACHE_CHECK([if the linker understands --disable-high-entropy-va], tcl_cv_ld_high_entropy, [ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Wl,--disable-high-entropy-va" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[tcl_cv_ld_high_entropy=yes],[tcl_cv_ld_high_entropy=no]) CFLAGS=$hold_cflags]) if test $tcl_cv_ld_high_entropy = yes; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--disable-high-entropy-va" fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else if test "$GCC" = "yes"; then PACKAGE_LIB_PREFIX=lib${PACKAGE_LIB_PREFIX} fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi if test "$GCC" = "yes"; then PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} fi # These aren't needed on Windows (either MSVC or gcc) RANLIB=: RANLIB_STUB=: else RANLIB_STUB="${RANLIB}" if test "${SHARED_BUILD}" = "1" ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi fi # These are escaped so that only CFLAGS is picked up at configure time. # The other values will be substituted at make time. CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" if test "${SHARED_BUILD}" = "1" ; then CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" fi AC_SUBST(MAKE_LIB) AC_SUBST(MAKE_SHARED_LIB) AC_SUBST(MAKE_STATIC_LIB) AC_SUBST(MAKE_STUB_LIB) # Substitute STUB_LIB_FILE in case package creates a stub library too. AC_SUBST(PKG_STUB_LIB_FILE) AC_SUBST(RANLIB_STUB) AC_SUBST(VC_MANIFEST_EMBED_DLL) AC_SUBST(VC_MANIFEST_EMBED_EXE) ]) #------------------------------------------------------------------------ # TEA_LIB_SPEC -- # # Compute the name of an existing object library located in libdir # from the given base name and produce the appropriate linker flags. # # Arguments: # basename The base name of the library without version # numbers, extensions, or "lib" prefixes. # extra_dir Extra directory in which to search for the # library. This location is used first, then # $prefix/$exec-prefix, then some defaults. # # Requires: # TEA_INIT and TEA_PREFIX must be called first. # # Results: # # Defines the following vars: # ${basename}_LIB_NAME The computed library name. # ${basename}_LIB_SPEC The computed linker flags. #------------------------------------------------------------------------ AC_DEFUN([TEA_LIB_SPEC], [ AC_MSG_CHECKING([for $1 library]) # Look in exec-prefix for the library (defined by TEA_PREFIX). tea_lib_name_dir="${exec_prefix}/lib" # Or in a user-specified location. if test x"$2" != x ; then tea_extra_lib_dir=$2 else tea_extra_lib_dir=NONE fi for i in \ `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \ `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \ `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do if test -f "$i" ; then tea_lib_name_dir=`dirname $i` $1_LIB_NAME=`basename $i` $1_LIB_PATH_NAME=$i break fi done if test "${TEA_PLATFORM}" = "windows"; then $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\" else # Strip off the leading "lib" and trailing ".a" or ".so" tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'` $1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}" fi if test "x${$1_LIB_NAME}" = x ; then AC_MSG_ERROR([not found]) else AC_MSG_RESULT([${$1_LIB_SPEC}]) fi ]) #------------------------------------------------------------------------ # TEA_PRIVATE_TCL_HEADERS -- # # Locate the private Tcl include files # # Arguments: # # Requires: # TCL_SRC_DIR Assumes that TEA_LOAD_TCLCONFIG has # already been called. # # Results: # # Substitutes the following vars: # TCL_TOP_DIR_NATIVE # TCL_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [ # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh} AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS]) AC_MSG_CHECKING([for Tcl private include files]) TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" # Check to see if tclPort.h isn't already with the public headers # Don't look for tclInt.h because that resides with tcl.h in the core # sources, but the Port headers are in a different directory if test "${TEA_PLATFORM}" = "windows" -a \ -f "${ac_cv_c_tclh}/tclWinPort.h"; then result="private headers found with public headers" elif test "${TEA_PLATFORM}" = "unix" -a \ -f "${ac_cv_c_tclh}/tclUnixPort.h"; then result="private headers found with public headers" else TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" if test "${TEA_PLATFORM}" = "windows"; then TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" else TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" fi # Overwrite the previous TCL_INCLUDES as this should capture both # public and private headers in the same set. # We want to ensure these are substituted so as not to require # any *_NATIVE vars be defined in the Makefile TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers and PrivateHeaders directories case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -d "${TCL_BIN_DIR}/Headers" -a \ -d "${TCL_BIN_DIR}/PrivateHeaders"; then TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}" else TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" fi ;; esac result="Using ${TCL_INCLUDES}" else if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}]) fi result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" fi fi AC_SUBST(TCL_TOP_DIR_NATIVE) AC_SUBST(TCL_INCLUDES) AC_MSG_RESULT([${result}]) ]) #------------------------------------------------------------------------ # TEA_PUBLIC_TCL_HEADERS -- # # Locate the installed public Tcl header files # # Arguments: # None. # # Requires: # CYGPATH must be set # # Results: # # Adds a --with-tclinclude switch to configure. # Result is cached. # # Substitutes the following vars: # TCL_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [ AC_MSG_CHECKING([for Tcl public headers]) AC_ARG_WITH(tclinclude, [ --with-tclinclude directory containing the public Tcl header files], with_tclinclude=${withval}) AC_CACHE_VAL(ac_cv_c_tclh, [ # Use the value from --with-tclinclude, if it was given if test x"${with_tclinclude}" != x ; then if test -f "${with_tclinclude}/tcl.h" ; then ac_cv_c_tclh=${with_tclinclude} else AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h]) fi else list="" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers directory case ${TCL_DEFS} in *TCL_FRAMEWORK*) list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" ;; esac fi # Look in the source dir only if Tcl is not installed, # and in that situation, look there before installed locations. if test -f "${TCL_BIN_DIR}/Makefile" ; then list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" fi # Check order: pkg --prefix location, Tcl's --prefix location, # relative to directory of tclConfig.sh. eval "temp_includedir=${includedir}" list="$list \ `ls -d ${temp_includedir} 2>/dev/null` \ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then list="$list /usr/local/include /usr/include" if test x"${TCL_INCLUDE_SPEC}" != x ; then d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` list="$list `ls -d ${d} 2>/dev/null`" fi fi for i in $list ; do if test -f "$i/tcl.h" ; then ac_cv_c_tclh=$i break fi done fi ]) # Print a message based on how we determined the include path if test x"${ac_cv_c_tclh}" = x ; then AC_MSG_ERROR([tcl.h not found. Please specify its location with --with-tclinclude]) else AC_MSG_RESULT([${ac_cv_c_tclh}]) fi # Convert to a native path and substitute into the output files. INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" AC_SUBST(TCL_INCLUDES) ]) #------------------------------------------------------------------------ # TEA_PRIVATE_TK_HEADERS -- # # Locate the private Tk include files # # Arguments: # # Requires: # TK_SRC_DIR Assumes that TEA_LOAD_TKCONFIG has # already been called. # # Results: # # Substitutes the following vars: # TK_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [ # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh} AC_REQUIRE([TEA_PUBLIC_TK_HEADERS]) AC_MSG_CHECKING([for Tk private include files]) TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}` TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\" # Check to see if tkPort.h isn't already with the public headers # Don't look for tkInt.h because that resides with tk.h in the core # sources, but the Port headers are in a different directory if test "${TEA_PLATFORM}" = "windows" -a \ -f "${ac_cv_c_tkh}/tkWinPort.h"; then result="private headers found with public headers" elif test "${TEA_PLATFORM}" = "unix" -a \ -f "${ac_cv_c_tkh}/tkUnixPort.h"; then result="private headers found with public headers" else TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\" TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\" if test "${TEA_PLATFORM}" = "windows"; then TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\" else TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\" fi # Overwrite the previous TK_INCLUDES as this should capture both # public and private headers in the same set. # We want to ensure these are substituted so as not to require # any *_NATIVE vars be defined in the Makefile TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}" # Detect and add ttk subdir if test -d "${TK_SRC_DIR}/generic/ttk"; then TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\"" fi if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\"" fi if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\"" fi if test "`uname -s`" = "Darwin"; then # If Tk was built as a framework, attempt to use # the framework's Headers and PrivateHeaders directories case ${TK_DEFS} in *TK_FRAMEWORK*) if test -d "${TK_BIN_DIR}/Headers" -a \ -d "${TK_BIN_DIR}/PrivateHeaders"; then TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}" else TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" fi ;; esac result="Using ${TK_INCLUDES}" else if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}]) fi result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}" fi fi AC_SUBST(TK_TOP_DIR_NATIVE) AC_SUBST(TK_XLIB_DIR_NATIVE) AC_SUBST(TK_INCLUDES) AC_MSG_RESULT([${result}]) ]) #------------------------------------------------------------------------ # TEA_PUBLIC_TK_HEADERS -- # # Locate the installed public Tk header files # # Arguments: # None. # # Requires: # CYGPATH must be set # # Results: # # Adds a --with-tkinclude switch to configure. # Result is cached. # # Substitutes the following vars: # TK_INCLUDES #------------------------------------------------------------------------ AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [ AC_MSG_CHECKING([for Tk public headers]) AC_ARG_WITH(tkinclude, [ --with-tkinclude directory containing the public Tk header files], with_tkinclude=${withval}) AC_CACHE_VAL(ac_cv_c_tkh, [ # Use the value from --with-tkinclude, if it was given if test x"${with_tkinclude}" != x ; then if test -f "${with_tkinclude}/tk.h" ; then ac_cv_c_tkh=${with_tkinclude} else AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h]) fi else list="" if test "`uname -s`" = "Darwin"; then # If Tk was built as a framework, attempt to use # the framework's Headers directory. case ${TK_DEFS} in *TK_FRAMEWORK*) list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`" ;; esac fi # Look in the source dir only if Tk is not installed, # and in that situation, look there before installed locations. if test -f "${TK_BIN_DIR}/Makefile" ; then list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`" fi # Check order: pkg --prefix location, Tk's --prefix location, # relative to directory of tkConfig.sh, Tcl's --prefix location, # relative to directory of tclConfig.sh. eval "temp_includedir=${includedir}" list="$list \ `ls -d ${temp_includedir} 2>/dev/null` \ `ls -d ${TK_PREFIX}/include 2>/dev/null` \ `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then list="$list /usr/local/include /usr/include" if test x"${TK_INCLUDE_SPEC}" != x ; then d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'` list="$list `ls -d ${d} 2>/dev/null`" fi fi for i in $list ; do if test -f "$i/tk.h" ; then ac_cv_c_tkh=$i break fi done fi ]) # Print a message based on how we determined the include path if test x"${ac_cv_c_tkh}" = x ; then AC_MSG_ERROR([tk.h not found. Please specify its location with --with-tkinclude]) else AC_MSG_RESULT([${ac_cv_c_tkh}]) fi # Convert to a native path and substitute into the output files. INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}` TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" AC_SUBST(TK_INCLUDES) if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then # On Windows and Aqua, we need the X compat headers AC_MSG_CHECKING([for X11 header files]) if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`" TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" AC_SUBST(TK_XINCLUDES) fi AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}]) fi ]) #------------------------------------------------------------------------ # TEA_PATH_CONFIG -- # # Locate the ${1}Config.sh file and perform a sanity check on # the ${1} compile flags. These are used by packages like # [incr Tk] that load *Config.sh files from more than Tcl and Tk. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-$1=... # # Defines the following vars: # $1_BIN_DIR Full path to the directory containing # the $1Config.sh file #------------------------------------------------------------------------ AC_DEFUN([TEA_PATH_CONFIG], [ # # Ok, lets find the $1 configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-$1 # if test x"${no_$1}" = x ; then # we reset no_$1 in case something fails here no_$1=true AC_ARG_WITH($1, [ --with-$1 directory containing $1 configuration ($1Config.sh)], with_$1config=${withval}) AC_MSG_CHECKING([for $1 configuration]) AC_CACHE_VAL(ac_cv_c_$1config,[ # First check to see if --with-$1 was specified. if test x"${with_$1config}" != x ; then case ${with_$1config} in */$1Config.sh ) if test -f ${with_$1config}; then AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself]) with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'` fi;; esac if test -f "${with_$1config}/$1Config.sh" ; then ac_cv_c_$1config=`(cd ${with_$1config}; pwd)` else AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh]) fi fi # then check for a private $1 installation if test x"${ac_cv_c_$1config}" = x ; then for i in \ ../$1 \ `ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ../../$1 \ `ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ../../../$1 \ `ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ${srcdir}/../$1 \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \ ; do if test -f "$i/$1Config.sh" ; then ac_cv_c_$1config=`(cd $i; pwd)` break fi if test -f "$i/unix/$1Config.sh" ; then ac_cv_c_$1config=`(cd $i/unix; pwd)` break fi done fi # check in a few common install locations if test x"${ac_cv_c_$1config}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ ; do if test -f "$i/$1Config.sh" ; then ac_cv_c_$1config=`(cd $i; pwd)` break fi done fi ]) if test x"${ac_cv_c_$1config}" = x ; then $1_BIN_DIR="# no $1 configs found" AC_MSG_WARN([Cannot find $1 configuration definitions]) exit 0 else no_$1= $1_BIN_DIR=${ac_cv_c_$1config} AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh]) fi fi ]) #------------------------------------------------------------------------ # TEA_LOAD_CONFIG -- # # Load the $1Config.sh file # # Arguments: # # Requires the following vars to be set: # $1_BIN_DIR # # Results: # # Substitutes the following vars: # $1_SRC_DIR # $1_LIB_FILE # $1_LIB_SPEC #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_CONFIG], [ AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh]) if test -f "${$1_BIN_DIR}/$1Config.sh" ; then AC_MSG_RESULT([loading]) . "${$1_BIN_DIR}/$1Config.sh" else AC_MSG_RESULT([file not found]) fi # # If the $1_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable $1_LIB_SPEC will be set to the value # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC # instead of $1_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. # if test -f "${$1_BIN_DIR}/Makefile" ; then AC_MSG_WARN([Found Makefile - using build library specs for $1]) $1_LIB_SPEC=${$1_BUILD_LIB_SPEC} $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC} $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH} $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC} $1_LIBRARY_PATH=${$1_LIBRARY_PATH} fi AC_SUBST($1_VERSION) AC_SUBST($1_BIN_DIR) AC_SUBST($1_SRC_DIR) AC_SUBST($1_LIB_FILE) AC_SUBST($1_LIB_SPEC) AC_SUBST($1_STUB_LIB_FILE) AC_SUBST($1_STUB_LIB_SPEC) AC_SUBST($1_STUB_LIB_PATH) # Allow the caller to prevent this auto-check by specifying any 2nd arg AS_IF([test "x$2" = x], [ # Check both upper and lower-case variants # If a dev wanted non-stubs libs, this function could take an option # to not use _STUB in the paths below AS_IF([test "x${$1_STUB_LIB_SPEC}" = x], [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)], [TEA_LOAD_CONFIG_LIB($1_STUB)]) ]) ]) #------------------------------------------------------------------------ # TEA_LOAD_CONFIG_LIB -- # # Helper function to load correct library from another extension's # ${PACKAGE}Config.sh. # # Results: # Adds to LIBS the appropriate extension library #------------------------------------------------------------------------ AC_DEFUN([TEA_LOAD_CONFIG_LIB], [ AC_MSG_CHECKING([For $1 library for LIBS]) # This simplifies the use of stub libraries by automatically adding # the stub lib to your path. Normally this would add to SHLIB_LD_LIBS, # but this is called before CONFIG_CFLAGS. More importantly, this adds # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD. if test "x${$1_LIB_SPEC}" != "x" ; then if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"]) AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}]) else TEA_ADD_LIBS([${$1_LIB_SPEC}]) AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}]) fi else AC_MSG_RESULT([file not found]) fi ]) #------------------------------------------------------------------------ # TEA_EXPORT_CONFIG -- # # Define the data to insert into the ${PACKAGE}Config.sh file # # Arguments: # # Requires the following vars to be set: # $1 # # Results: # Substitutes the following vars: #------------------------------------------------------------------------ AC_DEFUN([TEA_EXPORT_CONFIG], [ #-------------------------------------------------------------------- # These are for $1Config.sh #-------------------------------------------------------------------- # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib) eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}" if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}" eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}" else eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`" eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`" fi if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval $1_STUB_LIB_FLAG="-l$1stub" fi $1_BUILD_LIB_SPEC="-L`$CYGPATH $(pwd)` ${$1_LIB_FLAG}" $1_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` ${$1_LIB_FLAG}" $1_BUILD_STUB_LIB_SPEC="-L`$CYGPATH $(pwd)` [$]{$1_STUB_LIB_FLAG}" $1_STUB_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` [$]{$1_STUB_LIB_FLAG}" $1_BUILD_STUB_LIB_PATH="`$CYGPATH $(pwd)`/[$]{PKG_STUB_LIB_FILE}" $1_STUB_LIB_PATH="`$CYGPATH ${pkglibdir}`/[$]{PKG_STUB_LIB_FILE}" AC_SUBST($1_BUILD_LIB_SPEC) AC_SUBST($1_LIB_SPEC) AC_SUBST($1_BUILD_STUB_LIB_SPEC) AC_SUBST($1_STUB_LIB_SPEC) AC_SUBST($1_BUILD_STUB_LIB_PATH) AC_SUBST($1_STUB_LIB_PATH) AC_SUBST(MAJOR_VERSION) AC_SUBST(MINOR_VERSION) AC_SUBST(PATCHLEVEL) ]) #------------------------------------------------------------------------ # TEA_INSTALLER -- # # Configure the installer. # # Arguments: # none # # Results: # Substitutes the following vars: # INSTALL # INSTALL_DATA_DIR # INSTALL_DATA # INSTALL_PROGRAM # INSTALL_SCRIPT # INSTALL_LIBRARY #------------------------------------------------------------------------ AC_DEFUN([TEA_INSTALLER], [ INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c' INSTALL_DATA_DIR='${INSTALL} -d -m 755' INSTALL_DATA='${INSTALL} -m 644' INSTALL_PROGRAM='${INSTALL} -m 755' INSTALL_SCRIPT='${INSTALL} -m 755' TEA_CONFIG_SYSTEM case $system in HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;; *) INSTALL_LIBRARY='${INSTALL} -m 644' ;; esac AC_SUBST(INSTALL) AC_SUBST(INSTALL_DATA_DIR) AC_SUBST(INSTALL_DATA) AC_SUBST(INSTALL_PROGRAM) AC_SUBST(INSTALL_SCRIPT) AC_SUBST(INSTALL_LIBRARY) ]) ### # Tip 430 - ZipFS Modifications ### #------------------------------------------------------------------------ # TEA_ZIPFS_SUPPORT # Locate a zip encoder installed on the system path, or none. # # Arguments: # none # # Results: # Substitutes the following vars: # MACHER_PROG # ZIP_PROG # ZIP_PROG_OPTIONS # ZIP_PROG_VFSSEARCH # ZIP_INSTALL_OBJS #------------------------------------------------------------------------ AC_DEFUN([TEA_ZIPFS_SUPPORT], [ MACHER_PROG="" ZIP_PROG="" ZIP_PROG_OPTIONS="" ZIP_PROG_VFSSEARCH="" ZIP_INSTALL_OBJS="" AC_MSG_CHECKING([for macher]) AC_CACHE_VAL(ac_cv_path_macher, [ search_path=`echo ${PATH} | sed -e 's/:/ /g'` for dir in $search_path ; do for j in `ls -r $dir/macher 2> /dev/null` \ `ls -r $dir/macher 2> /dev/null` ; do if test x"$ac_cv_path_macher" = x ; then if test -f "$j" ; then ac_cv_path_macher=$j break fi fi done done ]) if test -f "$ac_cv_path_macher" ; then MACHER_PROG="$ac_cv_path_macher" AC_MSG_RESULT([$MACHER_PROG]) AC_MSG_RESULT([Found macher in environment]) fi AC_MSG_CHECKING([for zip]) AC_CACHE_VAL(ac_cv_path_zip, [ search_path=`echo ${PATH} | sed -e 's/:/ /g'` for dir in $search_path ; do for j in `ls -r $dir/zip 2> /dev/null` \ `ls -r $dir/zip 2> /dev/null` ; do if test x"$ac_cv_path_zip" = x ; then if test -f "$j" ; then ac_cv_path_zip=$j break fi fi done done ]) if test -f "$ac_cv_path_zip" ; then ZIP_PROG="$ac_cv_path_zip" AC_MSG_RESULT([$ZIP_PROG]) ZIP_PROG_OPTIONS="-rq" ZIP_PROG_VFSSEARCH="*" AC_MSG_RESULT([Found INFO Zip in environment]) # Use standard arguments for zip else # It is not an error if an installed version of Zip can't be located. # We can use the locally distributed minizip instead ZIP_PROG="./minizip${EXEEXT_FOR_BUILD}" ZIP_PROG_OPTIONS="-o -r" ZIP_PROG_VFSSEARCH="*" ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}" AC_MSG_RESULT([No zip found on PATH. Building minizip]) fi AC_SUBST(MACHER_PROG) AC_SUBST(ZIP_PROG) AC_SUBST(ZIP_PROG_OPTIONS) AC_SUBST(ZIP_PROG_VFSSEARCH) AC_SUBST(ZIP_INSTALL_OBJS) ]) # Local Variables: # mode: autoconf # End: parse_args-v0.6.3/tclconfig/ChangeLog0000644000175100017510000011005515176457507017207 0ustar runnerrunner2016-03-11 Sean Woods *tcl.m4 Fixed the search for Tcl and Wish shells under MinGW. Static builds and threaded builds get an "s" or "t" added to the name. 2015-08-28 Jan Nijtmans * tcl.m4: Rfe [00189c4afc]: Allow semi-static UCRT build on Windows with VC 14.0 2013-10-08 Jan Nijtmans * tcl.m4: Bug [172223e008]: Wrong filename in --disable-shared compile on MinGW 2013-10-04 Jan Nijtmans * tcl.m4: stub library is no longer linked with msvcrt??.dll. 2013-10-01 Jan Nijtmans * tcl.m4: Workaround for MinGW bug #2065: "gcc --shared" links with libgcc_s_dw2-1.dll when using 64-bit division in C 2013-07-04 Jan Nijtmans * tcl.m4: Bug [3324676]: AC_PROG_INSTALL incompat, Bug [3606445]: Unneeded -DHAVE_NO_SEH=1 when not building on Windows 2013-07-02 Jan Nijtmans * tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4 (thanks to Brian Griffin) 2013-06-20 Jan Nijtmans * tcl.m4: Use X11/Xlib.h for checking where X11 can be found in stead of X11/XIntrinsic.h. Suggested by Pietro Cerutti. 2013-06-04 Jan Nijtmans * tcl.m4: Eliminate NO_VIZ macro as current zlib uses HAVE_HIDDEN in stead. One more last-moment fix for FreeBSD by Pietro Cerutti 2013-05-19 Jan Nijtmans * tcl.m4: Fix for FreeBSD, and remove support for old FreeBSD versions. Patch by Pietro Cerutti 2013-03-12 Jan Nijtmans * tcl.m4: Patch by Andrew Shadura, providing better support for * three architectures they have in Debian. 2012-08-07 Stuart Cassoff * tcl.m4: Added "-DNDEBUG" to CFLAGS_DEFAULT when building with --disable-symbols. 2012-08-07 Stuart Cassoff * tcl.m4: [Bug 3555058]: Checkin [30736d63f0] broke CFLAGS_DEFAULT, LDFLAGS_DEFAULT 2012-08-07 Stuart Cassoff * tcl.m4: [Bug 3511806]: Checkin [30736d63f0] broke CFLAGS 2012-08-07 Jan Nijtmans * tcl.m4: [Bug 3511806]: Checkin [30736d63f0] broke CFLAGS 2012-07-25 Jan Nijtmans * tcl.m4: My previous commit (2012-04-03) broke the ActiveTcl build for AMD64, because of the quotes in "C://AMD64/cl.exe". It turns out that the AC_TRY_COMPILE macro cannot handle that. 2012-07-22 Stuart Cassoff * tcl.m4: Tidy: consistency, spelling, phrasing, whitespace. No functional change. 2012-04-03 Jan Nijtmans * tcl.m4: [Bug 3511806] Compiler checks too early This change allows to build the cygwin and mingw32 ports of Tcl/Tk extensions to build out-of-the-box using a native or cross-compiler, e.g. on Cygwin, Linux or Darwin. 2011-04-02 Jan Nijtmans * install-sh: Fix issue with library stripping in install-sh (backported from kevin_walzer's patch from Tcl 8.6 trunk) 2011-04-05 Andreas Kupries * tcl.m4: Applied patch by Jeff Lawson. Nicer error message when tclConfig.sh was not found. 2010-12-15 Stuart Cassoff * install-sh: Upgrade to newer install-sh and use it. * tcl.m4: 2010-12-14 Stuart Cassoff * tcl.m4: Better building on OpenBSD. 2010-12-14 Jan Nijtmans * tcl.m4: when using gcc, don't try to determine Win64 SDK 2010-12-12 Jan Nijtmans * tcl.m4: Determine correctly a cross-compiler-windres 2010-11-23 Jan Nijtmans * tcl.m4: add some cross-compile support, borrowed from Tcl 8.6 2010-09-16 Jeff Hobbs * tcl.m4: correct HP-UX LDFLAGS (only used when building big shell) 2010-09-14 Jeff Hobbs * tcl.m4: add extra if check for .manifest file generation Add notice about package name and version being built. 2010-09-09 Jan Nijtmans * tcl.m4: [FREQ #3058486] TEA_LOAD_CONFIG doesn't set all BUILD_ vars Slightly related: defining BUILD_$1 on all platforms - not only win - allows the -fvisibility feature to be used in extensions as well, at least if you compile against tcl >= 8.5. 2010-08-26 Jeff Hobbs * tcl.m4: ensure safe quoting for autoheader usage 2010-08-19 Jeff Hobbs * tcl.m4: add TEA_ADD_CLEANFILES macro to make adding cleanfiles easier, and add *.exp to CLEANFILES Windows default. (TEA_MAKE_LIB): Enhanced to check for MSVC that requires manifests and auto-embed it into proj DLL via MAKE_SHARED_LIB. Also define VC_MANIFEST_EMBED_DLL and VC_MANIFEST_EMBED_EXE that do the same magic in case it is needed for extended TEA projects. 2010-08-16 Jeff Hobbs *** Bump to TEA_VERSION 3.9 *** If upgrading from TEA_VERSION 3.8, copy over tcl.m4, change TEA_INIT to use 3.9 and reconfigure (ac-2.59+). BUILD_${PACKAGE_NAME} will be auto-defined on Windows for correct setting of TCL_STORAGE_CLASS. TEA_LOAD_CONFIG users should remove the SHLIB_LD_LIBS setting done in configure.in (LIBS will be automagically populated by TEA_LOAD_CONFIG). TEA_EXPORT_CONFIG has been added for ${pkg}Config.sh creators SHLIB_LD_FLAGS was deprecated a while ago, remove it if it is still in your Makefile.in. * tcl.m4: add /usr/lib64 to set of auto-search dirs. [Bug 1230554] Auto-define BUILD_$PACKAGE_NAME so users don't need to. This needs to correspond with $pkg.h define magic for TCL_STORAGE_CLASS. Auto-define CLEANFILES. Users can expand it. (SHLIB_LD_LIBS): define to '${LIBS}' default and change it only if necessary. Platforms not using this may simply not work or have very funky linkers. (TEA_LOAD_CONFIG): When loading config for another extension, auto-add stub libraries found with TEA_ADD_LIBS. Eases configure.in for modules like itk and img::*. (TEA_EXPORT_CONFIG): Add standardized function for exporting a ${pkg}Config.sh. See use by img::* and itcl. 2010-08-12 Jeff Hobbs *** Bump to TEA_VERSION 3.8 *** If upgrading from TEA_VERSION 3.7, copy over tcl.m4, change TEA_INIT to use 3.8 and reconfigure (ac-2.59+). No other changes should be necessary. * tcl.m4: remove more vestigial bits from removed platforms. Add back SCO_SV-3.2*. Remove use of DL_LIBS and DL_OBJS and related baggage - these are only needed by the core to support 'load'. Allow for macosx in TEA_ADD_SOURCES. Correct check for found_xincludes=no in TEA_PATH_UNIX_X. 2010-08-11 Jeff Hobbs * tcl.m4: remove the following old platform configurations: UNIX_SV*|UnixWare-5*, SunOS-4.*, SINIX*5.4*, SCO_SV-3.2*, OSF1-1.*, NEXTSTEP-*, NetBSD-1.*|FreeBSD-[[1-2]].*, MP-RAS-*, IRIX-5.*, HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*, dgux*, BSD/OS-2.1*|BSD/OS-3* (AIX): drop AIX-pre4 support and use of ldAix, use -bexpall/-brtl 2010-07-05 Jan Nijtmans * tcl.m4: [Patch #1055668] removal of exported internals from tclInt.h (EXTERN macro) 2010-04-14 Jan Nijtmans * tcl.m4 - Backport a lot of quoting fixes from tcl8.6/unix/tcl.m4 - Fix determination of CYGPATH for CYGWIN With those fixes, itcl and tdbc compile fine with CYGWIN 2010-04-06 Jan Nijtmans * install-sh [Bug 2982540] configure and install* script files should always have LF 2010-02-19 Stuart Cassoff * tcl.m4: Correct compiler/linker flags for threaded builds on OpenBSD. 2010-01-19 Jan Nijtmans * tcl.m4: Detect CYGWIN variant: win32 or unix 2010-01-03 Donal K. Fellows * unix/tcl.m4 (TEA_CONFIG_CFLAGS): [Tcl Bug 1636685]: Use the configuration for modern FreeBSD suggested by the FreeBSD porter. 2009-10-22 Jan Nijtmans * tcl.m4: [Tcl Patch #2883533] tcl.m4 support for Haiku OS 2009-04-27 Jeff Hobbs * tcl.m4 (TEA_CONFIG_CFLAGS): harden the check to add _r to CC on AIX with threads. 2009-04-10 Daniel Steffen * tcl.m4 (Darwin): check for 64-bit TkAqua. 2009-03-26 Jan Nijtmans * tclconfig/tcl.m4: Adapt LDFLAGS and LD_SEARCH_FLAGS together with SHLIB_LD definition to unbreak building on HPUX. 2009-03-20 Andreas Kupries * tclconfig/tcl.m4: Changed SHLIB_LD definition to unbreak building on HPUX. 2009-03-16 Joe English * tcl.m4(TEA_PUBLIC_TK_HEADERS): Look at ${TK_INCLUDE_SPEC} (found in tkConfig.sh) when trying to guess where tk.h might be [Patch 1960628]. 2009-03-11 Joe English * tcl.m4: Allow ${SHLIB_SUFFIX} to be overridden at configure-time [Patch 1960628]. Also fix some comment typos, and an uninitialized variable bug-waiting-to-happen. 2008-12-21 Jan Nijtmans * tcl.m4: [Bug 2073255] Tcl_GetString(NULL) doesn't crash on HP-UX (this bug report was for Tcl, but holds for TEA as well.) 2008-12-20 Daniel Steffen * tcl.m4: sync with tdbc tcl.m4 changes (SunOS-5.11): Sun cc SHLIB_LD: use LDFLAGS_DEFAULT instead of LDFLAGS 2008-12-02 Jeff Hobbs *** Bump to TEA_VERSION 3.7 *** * tcl.m4: in private header check, check for Port.h instead of Int.h to ensure all private headers are available. 2008-11-04 Daniel Steffen * tcl.m4 (Darwin): sync TEA_PRIVATE_TK_HEADERS handling of Tk.framework PrivateHeaders with TEA_PRIVATE_TCL_HEADERS. 2008-11-04 Jeff Hobbs * tcl.m4 (TEA_PATH_TCLCONFIG, TEA_PATH_TKCONFIG): exit with error when tclConfig.sh cannot be found. [Bug #1997760] (TEA_PRIVATE_TCL_HEADERS, TEA_PRIVATE_TK_HEADERS): allow for finding the headers installed in the public areas, e.g. a result of make install-private-headers. [Bug #1631922] 2008-08-12 Daniel Steffen * tcl.m4 (Darwin): link shlib with current and compatiblity version flags; look for libX11.dylib when searching for X11 libraries. 2008-06-12 Daniel Steffen * tcl.m4 (SunOS-5.11): fix 64bit amd64 support with gcc & Sun cc. 2008-03-27 Daniel Steffen * tcl.m4 (SunOS-5.1x): fix 64bit support for Sun cc. [Bug 1921166] 2008-02-01 Donal K. Fellows * tcl.m4 (TEA_CONFIG_CFLAGS): Updated to work at least in part with more modern VC versions. Currently just made the linker flags more flexible; more work may be needed. 2007-10-26 Daniel Steffen * tcl.m4 (Darwin): add support for 64-bit X11. 2007-10-23 Jeff Hobbs *** Tagged tea-3-branch to start TEA 4 development on HEAD *** 2007-09-17 Joe English * tcl.m4: use '${CC} -shared' instead of 'ld -Bshareable' to build shared libraries on current NetBSDs [Bug 1749251]. 2007-09-15 Daniel Steffen * tcl.m4: replace all direct references to compiler by ${CC} to enable CC overriding at configure & make time. (SunOS-5.1x): replace direct use of '/usr/ccs/bin/ld' in SHLIB_LD by 'cc' compiler driver. 2007-08-08 Jeff Hobbs * tcl.m4: check Ttk dir for Tk private headers (8.5). Add some comments to other bits. 2007-06-25 Jeff Hobbs * tcl.m4 (TEA_PROG_TCLSH, TEA_PROG_WISH): move where / is added. 2007-06-13 Jeff Hobbs * tcl.m4: fix --with-tkinclude alignment. [Bug 1506111] 2007-06-06 Daniel Steffen * tcl.m4 (Darwin): fix 64bit arch removal in fat 32&64bit builds. 2007-05-18 Donal K. Fellows * tcl.m4: Added quoting so that paths with spaces cause fewer problems. 2007-03-07 Daniel Steffen * tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in -mmacosx-version-min check. 2007-02-15 Jeff Hobbs * tcl.m4: correct private header check to search in generic subdir 2007-02-09 Jeff Hobbs *** Bump to TEA_VERSION 3.6 *** * tcl.m4: correct -d to -f (TEA_CONFIG_CFLAGS): SHLIB_SUFFIX is .so on HP ia64 [Bug 1615058] 2007-02-08 Jeff Hobbs * tcl.m4 (TEA_PRIVATE_TCL_HEADERS, TEA_PRIVATE_TK_HEADERS): check that the dirs actually have private headers. [Bug 1631922] 2007-02-04 Daniel Steffen * tcl.m4: add caching to -pipe check. 2007-01-25 Daniel Steffen * tcl.m4: integrate CPPFLAGS into CFLAGS as late as possible and move (rather than duplicate) -isysroot flags from CFLAGS to CPPFLAGS to avoid errors about multiple -isysroot flags from some older gcc builds. 2006-01-19 Daniel Steffen * tcl.m4: ensure CPPFLAGS env var is used when set. [Bug 1586861] (Darwin): add -isysroot and -mmacosx-version-min flags to CPPFLAGS when present in CFLAGS to avoid discrepancies between what headers configure sees during preprocessing tests and compiling tests. 2006-12-19 Daniel Steffen * tcl.m4 (Darwin): --enable-64bit: verify linking with 64bit -arch flag succeeds before enabling 64bit build. 2006-12-16 Daniel Steffen * tcl.m4 (Linux): fix previous change to use makefile variable LDFLAGS_DEFAULT instead of LDFLAGS in SHLIB_LD, to ensure linker flags in sampleextension Makefile are picked up. 2006-11-26 Daniel Steffen * tcl.m4 (Linux): --enable-64bit support. [Patch 1597389], [Bug 1230558] 2006-08-18 Daniel Steffen * tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for universal builds including x86_64 and for use of -mmacosx-version-min instead of MACOSX_DEPLOYMENT_TARGET. For Tk extensions, remove 64-bit arch flags from CFLAGS like in the Tk configure, as neither TkAqua nor TkX11 can be built for 64-bit at present. 2006-03-28 Jeff Hobbs * tcl.m4: []-quote AC_DEFUN functions. (TEA_PATH_TKCONFIG): Fixed Windows-specific check for tkConfig.sh. (TEA_MAKE_LIB): Prepend 'lib' for Windows-gcc configs. 2006-03-07 Joe English * tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD, as per the other *BSD variants [Bug 1334613]. 2006-01-25 Jeff Hobbs *** Bump to TEA version 3.5 *** * tcl.m4: keep LD_SEARCH_FLAGS and CC_SEARCH_FLAGS synchronous with core tcl.m4 meaning. 2006-01-24 Daniel Steffen * tcl.m4 (Darwin): use makefile variable LDFLAGS_DEFAULT instead of LDFLAGS in SHLIB_LD, to ensure linker flags in sampleextension Makefile are picked up. [Bug 1403343] 2006-01-23 Jeff Hobbs * tcl.m4: add C:/Tcl/lib and C:/Progra~1/Tcl/lib dirs to check for *Config.sh on Windows. [Bug 1407544] 2006-01-23 Daniel Steffen * tcl.m4 (Darwin): for Tk extensions, remove -arch ppc64 from CFLAGS like in the Tk configure, as neither TkAqua nor TkX11 can be built for 64bit at present (no 64bit GUI libraries). 2006-01-22 Jeff Hobbs * tcl.m4: restore system=windows on Windows. Remove error if 'ar' isn't found (it may not be on Windows). Do not add -lxnet or define _XOPEN_SOURCE on HP-UX by default. Ensure the C|LDFLAGS_DEFAULT gets the fully sub'd value at configure time. 2006-01-10 Daniel Steffen * tcl.m4: add caching, use AC_CACHE_CHECK instead of AC_CACHE_VAL where possible, consistent message quoting, sync relevant tcl/unix/tcl.m4 HEAD changes and gratuitous formatting differences (notably sunc removal of support for for ancient BSD's, IRIX 4, RISCos and Ultrix by kennykb), Darwin improvements to TEA_LOAD_*CONFIG to make linking work against Tcl/Tk frameworks installed in arbitrary location, change TEA_PROG_* search order (look in *_BIN_DIR parents before *_PREFIX). 2006-01-05 Jeff Hobbs * tcl.m4: add dkf's system config refactor 2006-01-04 Jeff Hobbs * tcl.m4: remove extraneous ' that causes bash 3.1 to choke 2005-12-19 Joe English * tcl.m4 (TEA_PATH_TCLCONFIG &c): Look for tclConfig.sh &c in ${libdir}, where they are installed by default [Patch #1377407]. 2005-12-05 Don Porter * tcl.m4 (TEA_PUBLIC_*_HEADERS): Better support for finding header files for uninstalled Tcl and Tk. 2005-12-02 Jeff Hobbs * tcl.m4: correctly bump TEA_VERSION var to 3.4 2005-12-01 Daniel Steffen * unix/tcl.m4 (Darwin): fixed error when MACOSX_DEPLOYMENT_TARGET unset 2005-11-29 Jeff Hobbs * tcl.m4: *** Bump to TEA version 3.4 *** Add Windows x64 build support. Remove TEA_PATH_NOSPACE and handle the problem with ""s where necessary - the macro relied on TCLSH_PROG which didn't work for cross-compiles. 2005-11-27 Daniel Steffen * tcl.m4 (Darwin): add 64bit support, add CFLAGS to SHLIB_LD to support passing -isysroot in env(CFLAGS) to configure (flag can't be present twice, so can't be in both CFLAGS and LDFLAGS during configure), don't use -prebind when deploying on 10.4. (TEA_ENABLE_LANGINFO, TEA_TIME_HANDLER): add/fix caching. 2005-10-30 Daniel Steffen * tcl.m4: fixed two tests for TEA_WINDOWINGSYSTEM = "aqua" that should have been for `uname -s` = "Darwin" instead; added some missing quoting. (TEA_PROG_TCLSH, TEA_PROG_WISH): fix incorrect assumption that install location of tclConfig.sh/tkConfig.sh allows to determine the tclsh/wish install dir via ../bin. Indeed tcl/tk can be configured with arbitrary --libdir and --bindir (independent of prefix) and such a configuration is in fact standard with Darwin framework builds. At least now also check ${TCL_PREFIX}/bin resp. ${TK_PREFIX}/bin for presence of tclsh resp. wish (if tcl/tk have been configured with arbitrary --bindir, this will still not find them, for a general solution *Config.sh would need to contain the values of bindir/libdir/includedir passed to configure). 2005-10-07 Jeff Hobbs * tcl.m4: Fix Solaris 5.10 check and Solaris AMD64 64-bit builds. 2005-10-04 Jeff Hobbs * tcl.m4 (TEA_PRIVATE_TCL_HEADERS): add / to finish sed macro (TEA_ENABLE_THREADS): don't check for pthread_attr_setstacksize func 2005-09-13 Jeff Hobbs * tcl.m4: *** Update to TEA version 3.3 *** define TEA_WINDOWINGSYSTEM in TEA_LOAD_TKCONFIG. Make --enable-threads the default (users can --disable-threads). Improve AIX ${CC}_r fix to better check existing ${CC} value. Do the appropriate evals to not require the *TOP_DIR_NATIVE vars be set for extensions that use private headers. Make aqua check for Xlib compat headers the same as win32. 2005-07-26 Mo DeJong * tcl.m4 (TEA_PROG_TCLSH, TEA_BUILD_TCLSH, TEA_PROG_WISH, TEA_BUILD_WISH): Remove TEA_BUILD_TCLSH and TEA_BUILD_WISH because of complaints that it broke the build when only an installed version of Tcl was available at extension build time. The TEA_PROG_TCLSH and TEA_PROG_WISH macros will no longer search the path at all. The build tclsh or installed tclsh shell will now be found by TEA_PROG_TCLSH. 2005-07-24 Mo DeJong * tcl.m4 (TEA_PROG_TCLSH, TEA_BUILD_TCLSH, TEA_PROG_WISH, TEA_BUILD_WISH): Split confused search for tclsh on PATH and build and install locations into two macros. TEA_PROG_TCLSH and TEA_PROG_WISH search the system PATH for an installed tclsh or wish. The TEA_BUILD_TCLSH and TEA_BUILD_WISH macros determine the name of tclsh or wish in the Tcl or Tk build directory even if tclsh or wish has not yet been built. [Tcl bug 1160114] [Tcl patch 1244153] 2005-06-23 Daniel Steffen * tcl.m4 (TEA_PRIVATE_TK_HEADERS): add ${TK_SRC_DIR}/macosx to TK_INCLUDES when building against TkAqua. * tcl.m4 (TEA_PATH_X): fixed missing comma in AC_DEFINE * tcl.m4: changes to better support framework builds of Tcl and Tk out of the box: search framework install locations for *Config.sh, and if in presence of a framework build, use the framework's Headers and PrivateHeaders directories for public and private includes. [FR 947735] 2005-06-18 Daniel Steffen * tcl.m4 (Darwin): add -headerpad_max_install_names to LDFLAGS to ensure we can always relocate binaries with install_name_tool. 2005-06-04 Daniel Steffen * tcl.m4 (TEA_PATH_X): for TEA_WINDOWINGSYSTEM == aqua, check if xlib compat headers are available in tkheaders location, otherwise add xlib sourcedir to TK_XINCLUDES. 2005-04-25 Daniel Steffen * tcl.m4: added AC_DEFINE* descriptions (from core tcl.m4) to allow use with autoheader. (Darwin): added configure checks for recently added linker flags -single_module and -search_paths_first to allow building with older tools (and on Mac OS X 10.1), use -single_module in SHLIB_LD. (TEA_MISSING_POSIX_HEADERS): added caching of dirent.h check. (TEA_BUGGY_STRTOD): added caching (sync with core tcl.m4). 2005-03-24 Jeff Hobbs * tcl.m4 (TEA_TCL_64BIT_FLAGS): use Tcl header defaults for wide int type only on Windows when __int64 is detected as valid. 2005-03-24 Don Porter * README.txt: Update reference to "SC_* macros" to "TEA_* macros". * tcl.m4: Incorporated recent improvements in SC_PATH_TCLCONFIG and SC_PATH_TKCONFIG into TEA_PATH_TCLCONFIG and TEA_PATH_TKCONFIG. Corrected search path in TEA_PATH_CONFIG and added AC_SUBST($1_BIN_DIR) to TEA_LOAD_CONFIG so that packages that load the configuration of another package can know where they loaded it from. 2005-03-18 Jeff Hobbs * tcl.m4 (TEA_CONFIG_CFLAGS): correct 2005-03-17 change to have variant LD_SEARCH_FLAGS for gcc and cc builds. * tcl.m4 (TEA_PROG_TCLSH, TEA_PROG_WISH): correct x-compile check. 2005-03-17 Jeff Hobbs * tcl.m4: Correct gcc build and HP-UX-11. 2005-02-08 Jeff Hobbs * tcl.m4 (TEA_ADD_LIBS): don't touch lib args starting with -. (TEA_CONFIG_CFLAGS): only define _DLL for CE in shared build. (TEA_MAKE_LIB): set RANLIB* to : on Windows (it's not needed). 2005-02-01 Jeff Hobbs * tcl.m4: redo of 2005-01-27 changes to correctly handle paths with spaces. Win/CE and Win/64 builds now require a prebuilt tclsh to handle conversion to short pathnames. This is done in the new TEA_PATH_NOSPACE macro. For Win/CE|64, make CC just the compiler and move the necessary includes to CFLAGS. (TEA_CONFIG_CFLAGS): Add Solaris 64-bit gcc build support. (TEA_PROG_TCLSH, TEA_PROG_WISH): Allow TCLSH_PROG and WISH_PROG to be set in the env and prevent resetting. (TEA_ADD_LIBS): On Windows using GCC (mingw), convert foo.lib args to -lfoo, for use with mingw. *** POTENTIAL INCOMPATABILITY *** (TEA_CONFIG_CFLAGS): Fix AIX gcc builds to work out-of-box. Bumped TEA to 3.2. 2005-01-27 Jeff Hobbs * tcl.m4: remove cygpath calls to support msys. Update base CE build assumption to "420,ARMV4,ARM,Pocket PC 2003". Make STLIB_LD use $LINKBIN -lib. 2005-01-25 Daniel Steffen * tcl.m4 (Darwin): fixed bug with static build linking to dynamic library in /usr/lib etc instead of linking to static library earlier in search path. [Tcl Bug 956908] Removed obsolete references to Rhapsody. 2004-12-29 Jeff Hobbs * tcl.m4: Updates for VC7 compatibility, fixing CFLAGS and LDFLAGS options, using better default -O levels. [Bug 1092952, 1091967] 2004-12-29 Joe English * tcl.m4: Do not use ${DBGX} suffix when building shared libraries [patch #1081595, TIP #34] 2004-09-07 Jeff Hobbs * tcl.m4 (TEA_CONFIG_CFLAGS): support eVC4 Win/CE builds 2004-08-10 Jeff Hobbs * tcl.m4 (TEA_INIT, TEA_PREFIX): update handling of exec_prefix to work around subdir configures since autoconf only propagates the prefix (not exec_prefix). 2004-07-23 Daniel Steffen * tcl.m4 (TEA_CONFIG_CFLAGS): Darwin section: brought inline with Tcl 8.5 HEAD config, removed core specific & obsolete settings. 2004-07-22 Jeff Hobbs * tcl.m4 (TEA_PATH_X): check in TK_DEFS for MAC_OSX_TK to see if we are compiling on Aqua. Add TEA_WINDOWINGSYSTEM var that reflects 'tk windowingsystem' value. 2004-07-16 Jeff Hobbs * tcl.m4 (TEA_ENABLE_THREADS): force a threaded build when building against a threaded core. (CFLAGS_WARNING): Remove -Wconversion for gcc builds (TEA_CONFIG_CFLAGS): Reorder configure.in for better 64-bit build configuration, replacing EXTRA_CFLAGS with CFLAGS. [Bug #874058] Update to latest Tcl 8.5 head config settings. Call this TEA version 3.1. 2004-04-29 Jeff Hobbs * tcl.m4 (TEA_TCL_64BIT_FLAGS): replace AC_TRY_RUN test with AC_TRY_COMPILE for the long vs. long long check. (kenny) 2004-04-26 Jeff Hobbs * tcl.m4 (TEA_TCL_64BIT_FLAGS): update against core tcl.m4 to define TCL_WIDE_INT_IS_LONG if 'using long'. 2004-03-19 Jeff Hobbs * tcl.m4: correct Windows builds getting LDFLAGS info in MAKE_LIB 2004-02-11 Jeff Hobbs * tcl.m4: correct TCL_INCLUDES for private headers on Windows - it doesn't need the eval. 2004-02-10 Jeff Hobbs * tcl.m4: don't require TK_INCLUDES and TCL_INCLUDES to have the DIR_NATIVE vars defined when using private headers on unix. Allow $... to TEA_ADD_SOURCES for constructs like TEA_ADD_SOURCES([\$(WIN_OBJECTS)]), that allow the developer to place more in the Makefile.in. tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and CHECK on limits.h 2003-12-10 Jeff Hobbs * Makefile.in: added TEA_ADD_LIBS, TEA_ADD_INCLUDES and * configure: TEA_ADD_CFLAGS to configurable parameters with * configure.in: PKG_* equivs in the Makefile. This allows the * tclconfig/tcl.m4: user to worry less about actual magic VAR names. Corrected Makefile.in to note that TEA_ADD_TCL_SOURCES requires exact file names. 2003-12-09 Jeff Hobbs * tcl.m4: updated OpenBSD support based on [Patch #775246] (cassoff) 2003-12-05 Jeff Hobbs * configure: * configure.in: * Makefile.in (VPATH): readd $(srcdir) to front of VPATH as the first part of VPATH can get chopped off. Change .c.$(OBJEXT) rule to .c.@OBJEXT@ to support more makes. * tclconfig/tcl.m4: add TEA_ADD_STUB_SOURCES to support libstub generation and TEA_ADD_TCL_SOURCES to replace RUNTIME_SOURCES as the way the user specifies library files. 2003-12-03 Jeff Hobbs * configure: Update of TEA spec to (hopefully) simplify * configure.in: some aspects of TEA by making use of more * Makefile.in: AC 2.5x features. Use PACKAGE_NAME (instead * generic/tclsample.c: of PACKAGE) and PACKAGE_VERSION (instead of * tclconfig/tcl.m4: VERSION) arguments to AC_INIT as the TEA package name and version. Provide a version argument to TEA_INIT - starting with 3.0. Drop all use of interior shell substs that older makefiles didn't like. Use PKG_* naming convention instead. Move specification of source files and public headers into configure.in with TEA_ADD_SOURCES and TEA_ADD_HEADERS. These will be munged during ./configure into the right obj file names (no $(SOURCES:.c=.obj) needed). There is almost nothing that should be touched in Makefile.in now for the developer. May want to add a TEA_ADD_TCL_SOURCES for the RUNTIME_SOURCES that remains. Use SHLID_LD_FLAGS (instead of SHLID_LDFLAGS) as Tcl does. Only specify the user requested LDFLAGS/CFLAGS in the Makefile, don't mention the _OPTIMIZE/_DEBUG variants. 2003-10-15 Jeff Hobbs * tcl.m4: create a TEA_SETUP_COMPILER_CC the precedes the TEA_SETUP_COMPILER macro. They are split so the check for CC occurs before any use of CC. Also add AC_PROG_CPP to the compiler checks. 2003-10-06 Jeff Hobbs * tcl.m4: Updated for autoconf 2.5x prereq. Where TCL_WIDE_INT_TYPE would be __int64, defer to the code checks in tcl.h, which also handles TCL_LL_MODIFIER* properly. 2003-04-22 Jeff Hobbs * tcl.m4: correct default setting of ARCH for WinCE builds. Correct \ escaping for CE sed macros. 2003-04-10 Jeff Hobbs * tcl.m4: replace $(syscal) construct with older `syscall` for systems where sh != bash. 2003-04-09 Jeff Hobbs * tcl.m4 (TEA_WITH_CELIB): add --enable-wince and --with-celib options for Windows/CE compilation support. Requires the Microsoft eMbedded SDK and Keuchel's celib emulation layer. 2003-02-18 Jeff Hobbs * tcl.m4 (TEA_ENABLE_THREADS): Make sure -lpthread gets passed on the link line when checking for the pthread_attr_setstacksize symbol. (dejong) * tcl.m4 (TEA_SETUP_COMPILER): added default calls to TEA_TCL_EARLY_FLAGS, TEA_TCL_64BIT_FLAGS, TEA_MISSING_POSIX_HEADERS and TEA_BUGGY_STRTOD. 2003-02-14 Jeff Hobbs * tcl.m4: correct HP-UX ia64 --enable-64bit build flags 2003-01-29 Jeff Hobbs * tcl.m4: check $prefix/lib as well as $exec_prefix/lib when looking for tcl|tkConfig.sh, as this check is done before we would set exec_prefix when the user does not define it. 2003-01-21 Mo DeJong * tcl.m4 (TEA_CONFIG_CFLAGS): Fix build support for mingw, the previous implementation would use VC++ when compiling with mingw gcc. Don't pass -fPIC since gcc always compiles pic code under win32. Change some hard coded cases of gcc to ${CC}. 2002-10-15 Jeff Hobbs * tcl.m4: move the CFLAGS definition from TEA_ENABLE_SHARED to TEA_MAKE_LIB because setting too early confuses other AC_* macros. Correct the HP-11 SHLIB_LD_LIBS setting. * tcl.m4: add the CFLAGS definition into TEA_ENABLE_SHARED and make it pick up the env CFLAGS at configure time. 2002-10-09 Jeff Hobbs * tcl.m4: add --enable-symbols=mem option to enable TCL_MEM_DEBUG. Improved AIX 64-bit build support, allow it on AIX-4 as well. Enable 64-bit HP-11 compilation with gcc. Enable 64-bit IRIX64-6 cc build support. Correct FreeBSD thread library linkage. Add OSF1 static build support. Improve SunOS-5 shared build SHLIB_LD macro. 2002-07-20 Zoran Vasiljevic * tcl.m4: Added MINGW32 to list of systems checked for Windows build. Also, fixes some indentation issues with "--with-XXX" options. 2002-04-23 Jeff Hobbs * tcl.m4 (TEA_ENABLE_THREADS): added USE_THREAD_ALLOC define to use new threaded allocatory by default on Unix for Tcl 8.4. (TEA_CONFIG_CFLAGS): corrected LD_SEARCH_FLAGS for FreeBSD-3+. 2002-04-22 Jeff Hobbs * tcl.m4 (TEA_SETUP_COMPILER): removed call to AC_CYGWIN so that we can use autoconf 2.5x as well as 2.13. This prevents us from being able to warn against the use of cygwin gcc at configure time, but allows autoconf 2.5x, which is what is shipped with most newer systems. 2002-04-11 Jeff Hobbs * tcl.m4: Enabled COFF as well as CV style debug info with --enable-symbols to allow Dr. Watson users to see function info. More info on debugging levels can be obtained at: http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp 2002-04-03 Jeff Hobbs * tcl.m4: change all SC_* macros to TEA_*. The SC_ was for Scriptics, which is no more. TEA represents a better, independent prefix that won't need changing. Added preliminary mingw gcc support. [Patch #538772] Added TEA_PREFIX macro that handles defaulting the prefix and exec_prefix vars to those used by Tcl if none were specified. Added TEA_SETUP_COMPILER macro that encompasses the AC_PROG_CC check and several other basic AC_PROG checks needed for making executables. This greatly simplifies user's configure.in files. Collapsed AIX-5 defines into AIX-* with extra checks for doing the ELF stuff on AIX-5-ia64. Updated TEA_ENABLE_THREADS to take an optional arg to allow switching it on by default (for Thread) and add sanity checking to warn the user if configuring threads incompatibly. 2002-03-29 Jeff Hobbs * tcl.m4: made sure that SHLIB_LDFLAGS was set to LDFLAGS_DEFAULT. Removed --enable-64bit support for AIX-4 because it wasn't correct. Added -MT or -MD Windows linker switches to properly support symbols-enabled builds. 2002-03-28 Jeff Hobbs * tcl.m4: called AC_MSG_ERROR when SC_TEA_INIT wasn't called first instead of calling it as that inlines it each time in shell code. Changed Windows CFLAGS_OPTIMIZE to use -O2 instead of -Oti. Noted TCL_LIB_VERSIONS_OK=nodots for Windows builds. A few changes to support itcl (and perhaps others): Added support for making your own stub libraries to SC_MAKE_LIB. New SC_PATH_CONFIG and SC_LOAD_CONFIG that take a package name arg and find that ${pkg}Config.sh file. itk uses this for itcl. 2002-03-27 Jeff Hobbs * tcl.m4: made SC_LOAD_TKCONFIG recognize when working with a Tk build dir setup. Added EXTRA_CFLAGS and SHLIB_LD_LIBS substs to SC_CONFIG_CFLAGS. Added XLIBSW onto LIBS when it is defined. Remove TCL_LIBS from MAKE_LIB and correctly use SHLIB_LD_LIBS instead to not rely as much on tclConfig.sh cached info. Add TK_BIN_DIR to paths to find wish in SC_PROG_WISH. These move towards making TEA much more independent of *Config.sh. 2002-03-19 Jeff Hobbs * tcl.m4: corrected forgotten (UN)SHARED_LIB_SUFFIX and SHLIB_SUFFIX defines for Win. (SC_PATH_X): made this only do the check on unix platforms. 2002-03-12 Jeff Hobbs * README.txt: updated to reflect fewer files 2002-03-06 Jeff Hobbs * config.guess (removed): * config.sub (removed): removed unnecessary files * installFile.tcl (removed): * mkinstalldirs (removed): these aren't really necessary for making TEA work * tcl.m4 (SC_PUBLIC_TCL_HEADERS, SC_PUBLIC_TK_HEADERS): don't check /usr(/local)/include for includes on Windows when not using gcc 2002-03-05 Jeff Hobbs * tcl.m4: added warnings on Windows, removed RELPATH define and added TCL_LIBS to MAKE_LIB macro. This import represents 2.0.0, or a new start at attempting to make TEA much easier for C extension developers. **** moved from tclpro project to core tcl project, **** **** renamed to 'tclconfig' **** 2001-03-15 Karl Lehenbauer * installFile.tcl: Added updating of the modification time of the target file whether we overwrote it or decided that it hadn't changed. This was necessary for us to be able to determine whether or not a module install touched the file. 2001-03-08 Karl Lehenbauer * installFile.tcl: Added support for converting new-style (1.1+) Cygnus drive paths to Tcl-style. 2001-01-15 * tcl.m4: Added FreeBSD clause. 2001-01-03 * tcl.m4: Fixed typo in SC_LIB_SPEC where it is checking for exec-prefix. 2000-12-01 * tcl.m4: Concatenated most of the Ajuba acsite.m4 file so we don't need to modify the autoconf installation. * config.guess: * config.sub: * installFile.tcl: Added files from the itcl config subdirectory, which should go away. 2000-7-29 * Fixed the use of TCL_SRC_DIR and TK_SRC_DIR within TCL_PRIVATE_INCLUDES and TK_PRIVATE_INCLUDES to match their recent change from $(srcdir) to $(srcdir)/.. parse_args-v0.6.3/meson.build0000644000175100017510000000365515176457507015636 0ustar runnerrunnerproject('parse_args', 'c', version: '0.6.3', default_options: ['c_std=c11', 'warning_level=3', 'werror=true'], meson_version: '>=1.3.0', ) cc = meson.get_compiler('c') fs = import('fs') add_project_arguments('-D_DEFAULT_SOURCE', language: 'c') if get_option('debug') add_project_arguments(cc.get_supported_arguments(['-ggdb3']), language: 'c') endif add_project_arguments('-Wno-missing-field-initializers', language: 'c') conf = configuration_data() tea_want_shims = ['tip445'] add_project_arguments('-DHAVE_CONFIG_H', language: 'c') deps = [] inc = [include_directories('generic')] pkg_sources = files( 'generic/parse_args.c', ) subdir('teabase') # pkg-config metadata so downstream meson / shell consumers can locate # this install uniformly via `pkg-config --variable=tcl_pkg_path parse_args` # or `dependency('parse_args').get_variable('tcl_pkg_path')`. # tcl_dep is set by teabase/init. pc_conf = configuration_data() pc_conf.set('PACKAGE_NAME', meson.project_name()) pc_conf.set('PACKAGE_VERSION', meson.project_version()) pc_conf.set('PKG_DIR_BASENAME', meson.project_name() + '-' + meson.project_version()) configure_file( input: meson.project_name() + '.pc.in', output: meson.project_name() + '.pc', configuration: pc_conf, install: true, install_dir: tcl_dep.get_variable('libdir') / 'pkgconfig', install_tag: meson.is_subproject() ? 'deps' : 'runtime', ) # Override-dependency for meson subproject consumers. Mirrors the # tcl_pkg_path variable in the .pc file so downstream # `dependency('parse_args', fallback: ['parse_args', 'parse_args_dep']).get_variable('tcl_pkg_path')` # returns the right directory regardless of resolution path. parse_args_dep = declare_dependency( variables: { 'tcl_pkg_path': fs.parent(pkg_so.full_path()), 'version': meson.project_version(), }, ) meson.override_dependency(meson.project_name(), parse_args_dep) subdir('doc') parse_args-v0.6.3/win/0000755000175100017510000000000015176457507014260 5ustar runnerrunnerparse_args-v0.6.3/win/rules-ext.vc0000644000175100017510000000712615176457507016550 0ustar runnerrunner# This file should only be included in makefiles for Tcl extensions, # NOT in the makefile for Tcl itself. !ifndef _RULES_EXT_VC # We need to run from the directory the parent makefile is located in. # nmake does not tell us what makefile was used to invoke it so parent # makefile has to set the MAKEFILEVC macro or we just make a guess and # warn if we think that is not the case. !if "$(MAKEFILEVC)" == "" !if exist("$(PROJECT).vc") MAKEFILEVC = $(PROJECT).vc !elseif exist("makefile.vc") MAKEFILEVC = makefile.vc !endif !endif # "$(MAKEFILEVC)" == "" !if !exist("$(MAKEFILEVC)") MSG = ^ You must run nmake from the directory containing the project makefile.^ If you are doing that and getting this message, set the MAKEFILEVC^ macro to the name of the project makefile. !message WARNING: $(MSG) !endif !if "$(PROJECT)" == "tcl" !error The rules-ext.vc file is not intended for Tcl itself. !endif # We extract version numbers using the nmakehlp program. For now use # the local copy of nmakehlp. Once we locate Tcl, we will use that # one if it is newer. !if [$(CC) -nologo "nmakehlp.c" -link -subsystem:console > nul] !endif # First locate the Tcl directory that we are working with. !if "$(TCLDIR)" != "" _RULESDIR = $(TCLDIR:/=\) !else # If an installation path is specified, that is also the Tcl directory. # Also Tk never builds against an installed Tcl, it needs Tcl sources !if defined(INSTALLDIR) && "$(PROJECT)" != "tk" _RULESDIR=$(INSTALLDIR:/=\) !else # Locate Tcl sources !if [echo _RULESDIR = \> nmakehlp.out] \ || [nmakehlp -L generic\tcl.h >> nmakehlp.out] _RULESDIR = ..\..\tcl !else !include nmakehlp.out !endif !endif # defined(INSTALLDIR).... !endif # ifndef TCLDIR # Now look for the targets.vc file under the Tcl root. Note we check this # file and not rules.vc because the latter also exists on older systems. !if exist("$(_RULESDIR)\lib\nmake\targets.vc") # Building against installed Tcl _RULESDIR = $(_RULESDIR)\lib\nmake !elseif exist("$(_RULESDIR)\win\targets.vc") # Building against Tcl sources _RULESDIR = $(_RULESDIR)\win !else # If we have not located Tcl's targets file, most likely we are compiling # against an older version of Tcl and so must use our own support files. _RULESDIR = . !endif !if "$(_RULESDIR)" != "." # Potentially using Tcl's support files. If this extension has its own # nmake support files, need to compare the versions and pick newer. !if exist("rules.vc") # The extension has its own copy !if [echo TCL_RULES_MAJOR = \> versions.vc] \ && [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MAJOR >> versions.vc] !endif !if [echo TCL_RULES_MINOR = \>> versions.vc] \ && [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MINOR >> versions.vc] !endif !if [echo OUR_RULES_MAJOR = \>> versions.vc] \ && [nmakehlp -V "rules.vc" RULES_VERSION_MAJOR >> versions.vc] !endif !if [echo OUR_RULES_MINOR = \>> versions.vc] \ && [nmakehlp -V "rules.vc" RULES_VERSION_MINOR >> versions.vc] !endif !include versions.vc # We have a newer version of the support files, use them !if ($(TCL_RULES_MAJOR) != $(OUR_RULES_MAJOR)) || ($(TCL_RULES_MINOR) < $(OUR_RULES_MINOR)) _RULESDIR = . !endif !endif # if exist("rules.vc") !endif # if $(_RULESDIR) != "." # Let rules.vc know what copy of nmakehlp.c to use. NMAKEHLPC = $(_RULESDIR)\nmakehlp.c # Get rid of our internal defines before calling rules.vc !undef TCL_RULES_MAJOR !undef TCL_RULES_MINOR !undef OUR_RULES_MAJOR !undef OUR_RULES_MINOR !if exist("$(_RULESDIR)\rules.vc") !message *** Using $(_RULESDIR)\rules.vc !include "$(_RULESDIR)\rules.vc" !else !error *** Could not locate rules.vc in $(_RULESDIR) !endif !endif # _RULES_EXT_VCparse_args-v0.6.3/win/makefile.vc0000644000175100017510000000143415176457507016371 0ustar runnerrunner#------------------------------------------------------------- -*- makefile -*- # # Makefile for building parse_args # # Basic build, test and install # nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\tcl # nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\tcl test # nmake /s /nologo /f makefile.vc INSTALLDIR=c:\path\to\tcl install # # For other build options (debug, static etc.) # See TIP 477 (https://core.tcl.tk/tips/doc/trunk/tip/477.md) for # detailed documentation. # #------------------------------------------------------------------------------ # The name of the package PROJECT = parse_args !include "rules-ext.vc" PRJ_OBJS = $(TMP_DIR)\parse_args.obj # PRJ_DEFINES = -D_CRT_SECURE_NO_WARNINGS !include "$(_RULESDIR)\targets.vc" pkgindex: default-pkgindex-tea parse_args-v0.6.3/aclocal.m40000644000175100017510000000027115176457507015323 0ustar runnerrunner# # Include the TEA standard macro set # builtin(include,tclconfig/tcl.m4) # # Add here whatever m4 macros you want to define for your package # builtin(include,teabase/teabase.m4) parse_args-v0.6.3/.gitignore0000644000175100017510000000044415176457507015455 0ustar runnerrunner*.swp *.o *.so pkgIndex.tcl Makefile core vgcore.* /configure /autom4te.cache /config.log /config.status /config.h doc/parse_args.n last prof tags *~ *.gcda *.gcno /build /buildwin /subprojects/.wraplock /subprojects/packagecache /subprojects/tcl /subprojects/libtommath-* /doc/parse_args.md parse_args-v0.6.3/config.h.in0000644000175100017510000001012115176457507015501 0ustar runnerrunner/* config.h.in. Generated from configure.ac by autoheader. */ /* Defined when cygwin/mingw does not support EXCEPTION DISPOSITION */ #undef EXCEPTION_DISPOSITION /* Defined when compiler supports casting to union type. */ #undef HAVE_CAST_TO_UNION /* Is 'DIR64' in ? */ #undef HAVE_DIR64 /* Compiler support for module scope symbols */ #undef HAVE_HIDDEN /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `lseek64' function. */ #undef HAVE_LSEEK64 /* Defined when mingw does not support SEH */ #undef HAVE_NO_SEH /* Define to 1 if you have the `open64' function. */ #undef HAVE_OPEN64 /* Do we have ? */ #undef HAVE_STDBOOL_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Is 'struct dirent64' in ? */ #undef HAVE_STRUCT_DIRENT64 /* Is 'struct stat64' in ? */ #undef HAVE_STRUCT_STAT64 /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Is off64_t in ? */ #undef HAVE_TYPE_OFF64_T /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Defined when cygwin/mingw ignores VOID define in winnt.h */ #undef HAVE_WINNT_IGNORE_VOID /* No Compiler support for module scope symbols */ #undef MODULE_SCOPE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* This a static build */ #undef STATIC_BUILD /* Define to 1 if all of the C90 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* Is this an optimized build? */ #undef TCL_CFG_OPTIMIZED /* Compile for Tcl8? */ #undef TCL_MAJOR_VERSION /* Is memory debugging enabled? */ #undef TCL_MEM_DEBUG /* Are we building with threads enabled? */ #undef TCL_THREADS /* Do 'long' and 'long long' have the same size (64-bit)? */ #undef TCL_WIDE_INT_IS_LONG /* What type should be used to define wide integers? */ #undef TCL_WIDE_INT_TYPE /* Do we need to polyfill TIP 445? */ #undef TIP445_SHIM /* Compile for Tk8? */ #undef TK_MAJOR_VERSION /* Is 'Tcl_Size' in ? */ #undef Tcl_Size /* Use TclOO stubs */ #undef USE_TCLOO_STUBS /* Use Tcl stubs */ #undef USE_TCL_STUBS /* Do we want to use the threaded memory allocator? */ #undef USE_THREAD_ALLOC /* Use Tk stubs */ #undef USE_TK_STUBS /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Add the _FILE_OFFSET_BITS flag when building */ #undef _FILE_OFFSET_BITS /* Add the _ISOC99_SOURCE flag when building */ #undef _ISOC99_SOURCE /* # needed in sys/socket.h Should OS/390 do the right thing with sockets? */ #undef _OE_SOCKETS /* Do we really want to follow the standard? Yes we do! */ #undef _POSIX_PTHREAD_SEMANTICS /* Do we want the reentrant OS API? */ #undef _REENTRANT /* Do we want the thread-safe OS API? */ #undef _THREAD_SAFE /* _TIME_BITS=64 enables 64-bit time_t. */ #undef _TIME_BITS /* Do we want to use the XOPEN network library? */ #undef _XOPEN_SOURCE_EXTENDED parse_args-v0.6.3/configure.ac0000644000175100017510000001661015176457507015755 0ustar runnerrunner#!/bin/bash -norc dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tcl installation dnl to configure the system for the local environment. #----------------------------------------------------------------------- # Sample configure.ac for Tcl Extensions. The only places you should # need to modify this file are marked by the string __CHANGE__ #----------------------------------------------------------------------- #----------------------------------------------------------------------- # __CHANGE__ # Set your package name and version numbers here. # # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION # set as provided. These will also be added as -D defs in your Makefile # so you can encode the package version directly into the source files. # This will also define a special symbol for Windows (BUILD_ # so that we create the export library with the dll. #----------------------------------------------------------------------- AC_INIT([parse_args], [0.6]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_INIT() AC_CONFIG_AUX_DIR(tclconfig) #-------------------------------------------------------------------- # Load the tclConfig.sh file #-------------------------------------------------------------------- TEA_PATH_TCLCONFIG TEA_LOAD_TCLCONFIG #-------------------------------------------------------------------- # Load the tkConfig.sh file if necessary (Tk extension) #-------------------------------------------------------------------- #TEA_PATH_TKCONFIG #TEA_LOAD_TKCONFIG #----------------------------------------------------------------------- # Handle the --prefix=... option by defaulting to what Tcl gave. # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. #----------------------------------------------------------------------- TEA_PREFIX #----------------------------------------------------------------------- # Standard compiler checks. # This sets up CC by using the CC env var, or looks for gcc otherwise. # This also calls AC_PROG_CC and a few others to create the basic setup # necessary to compile executables. #----------------------------------------------------------------------- TEA_SETUP_COMPILER #----------------------------------------------------------------------- # __CHANGE__ # Specify the C source files to compile in TEA_ADD_SOURCES, # public headers that need to be installed in TEA_ADD_HEADERS, # stub library C source files to compile in TEA_ADD_STUB_SOURCES, # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- TEA_ADD_SOURCES([parse_args.c]) TEA_ADD_HEADERS([]) TEA_ADD_INCLUDES([]) TEA_ADD_LIBS([]) TEA_ADD_CFLAGS([]) TEA_ADD_STUB_SOURCES([]) TEA_ADD_TCL_SOURCES([]) #-------------------------------------------------------------------- # __CHANGE__ # # You can add more files to clean if your extension creates any extra # files by extending CLEANFILES. # Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure # and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. # # A few miscellaneous platform-specific items: # TEA_ADD_* any platform specific compiler/build info here. #-------------------------------------------------------------------- #CLEANFILES="$CLEANFILES pkgIndex.tcl" if test "${TEA_PLATFORM}" = "windows" ; then # Ensure no empty if clauses : #TEA_ADD_SOURCES([win/winFile.c]) #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) else # Ensure no empty else clauses : #TEA_ADD_SOURCES([unix/unixFile.c]) #TEA_ADD_LIBS([-lsuperfly]) fi #-------------------------------------------------------------------- # __CHANGE__ # Choose which headers you need. Extension authors should try very # hard to only rely on the Tcl public header files. Internal headers # contain private data structures and are subject to change without # notice. # This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG #-------------------------------------------------------------------- TEA_PUBLIC_TCL_HEADERS #TEA_PRIVATE_TCL_HEADERS #TEA_PUBLIC_TK_HEADERS #TEA_PRIVATE_TK_HEADERS #TEA_PATH_X #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. # This auto-enables if Tcl was compiled threaded. #-------------------------------------------------------------------- TEA_ENABLE_THREADS #-------------------------------------------------------------------- # The statement below defines a collection of symbols related to # building as a shared library instead of a static library. #-------------------------------------------------------------------- TEA_ENABLE_SHARED #-------------------------------------------------------------------- # This macro figures out what flags to use with the compiler/linker # when building shared/static debug/optimized objects. This information # can be taken from the tclConfig.sh file, but this figures it all out. #-------------------------------------------------------------------- TEA_CONFIG_CFLAGS # Check for required polyfill TIP445 TEABASE_INIT() #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols option. #-------------------------------------------------------------------- TEA_ENABLE_SYMBOLS #-------------------------------------------------------------------- # Everyone should be linking against the Tcl stub library. If you # can't for some reason, remove this definition. If you aren't using # stubs, you also need to modify the SHLIB_LD_LIBS setting below to # link against the non-stubbed Tcl library. Add Tk too if necessary. #-------------------------------------------------------------------- AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) #AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) #-------------------------------------------------------------------- # This macro generates a line to use when building a library. It # depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, # and TEA_LOAD_TCLCONFIG macros above. #-------------------------------------------------------------------- TEA_MAKE_LIB #-------------------------------------------------------------------- # Determine the name of the tclsh and/or wish executables in the # Tcl and Tk build directories or the location they were installed # into. These paths are used to support running test cases only, # the Makefile should not be making use of these paths to generate # a pkgIndex.tcl file or anything else at extension build time. #-------------------------------------------------------------------- TEA_PROG_TCLSH #TEA_PROG_WISH AC_CONFIG_FILES([Makefile pkgIndex.tcl doc/parse_args.md]) #AC_CONFIG_FILES([sampleConfig.sh]) AC_CONFIG_HEADERS([config.h]) #-------------------------------------------------------------------- # Finally, substitute all of the various values into the files # specified with AC_CONFIG_FILES. #-------------------------------------------------------------------- AC_OUTPUT parse_args-v0.6.3/doc/0000755000175100017510000000000015176457507014230 5ustar runnerrunnerparse_args-v0.6.3/doc/.vimrc0000644000175100017510000000001615176457507015346 0ustar runnerrunnerset expandtab parse_args-v0.6.3/doc/parse_args.md.in0000644000175100017510000002456015176457507017314 0ustar runnerrunner% parse_args(3) @PACKAGE_VERSION@ | Advanced argument parsing for Tcl % Cyan Ogilvie % @PACKAGE_VERSION@ # NAME parse\_args - Core-style argument parsing for scripts # SYNOPSIS **package require parse_args** ?@PACKAGE_VERSION@? **parse_args::parse_args** *args* *argspec* ?*varname*? # DESCRIPTION The commands provided by the Tcl core follow a pattern of optional, named arguments (named with a leading "-" to indicate an option) in addition to positional arguments. They strongly prefer named arguments when the number of arguments and particularly optional arguments grows beyond about 3. Tcl scripts however have no access to standard argument parsing facilities to implement this pattern and have to build their named argument parsing machinery from scratch. This is slow to do in script, error prone, and creates noise in the code that distracts from the core task of the command implementation. This means that script-defined commands generally present half-baked argument handling APIs and tend to over-use positional arguments. This package aims to address this weakness by providing a robust argument parsing mechanism to script code that can implement the full set of patterns established by the core Tcl commands, is terse and readable to specify the arguments, and is fast enough to use in any situation. # COMMANDS **parse_args::parse_args** *args* *argspec* : Parse the arguments supplied in *args* against the specification given in *argspec*, setting variables in the current scope as defined in the *argspec*. If the optional *varname* argument is supplied, it names a variable that will have a dictionary written to it containing the parsed arguments and no variables will be created for the arguments. See **ARGUMENT SPECIFICATION** below for the format of *argspec*. # ARGUMENT SPECIFICATION The syntax of the argument specification (given in the *argspec* argument to the **parse_args** command) is a dictionary, with the keys corresponding to the names by which the arguments will be available to the caller, either as variables created by the **parse_args** command or keys in the dictionary written to *varname* if that was specified. If the first character of the key is a "-" character it defines a named option, otherwise a positional parameter. Like in proc argument definitions the name `args` is special, and will consume all remaining arguments. The values of the dictionary contain the definition of the corresponding argument, such as `-required`, which marks that argument as being required (whether a named or positional argument). The options that are available to define the argument are: **-default** *val* : Provides a default value for the argument if it wasn't supplied. Without this an argument that wasn't supplied won't have its corresponding variable (or dictionary key) set. *val* is permitted to be a value that is outside of the range of possible values that would be accepted from the caller, by design. **-required** : If this boolean option is given, the argument is flagged as required. Failing to supply the arg causes the **parse_args** to throw an exception similar to what would happen if a required positional argument to a proc was not provided. **-validate** *cmdprefix* : Append the value supplied for this argument to the *cmdprefix* and run it. The value is rejected if an exception is thrown or the value returned isn't a Tcl boolean true value. **-name** *newname* : Change the name of the variable / dictionary key that will receive the value for this argument to *newname*. By default the name will be the argspec key (without the leading "-" for named arguments). **-boolean** : Flag this argument as a boolean, similar to **-nocase** to `regexp`. The variable will always be defined and be a boolean, true if the argument was supplied and false if it wasn't. **-args** *count* : By default named arguments consume a single following argument as the value for that argument. This setting changes that to *count*, which will cause the following *count* arguments to be gathered into the variable holding this argument. If *count* is the special value "all", then all remaining arguments are gathered into a list as the value of this argument. **-enum** *possible_values* : Restrict the values that will be accepted for this argument to those in the *possible_values* list. Similar to using a validator that checks for inclusion in that list but with additional internal performance optimizations. **-#** *free_form_text* : Embed a comment for this argument. The supplied *free_form_text* is ignored by **parse_args** and serves only to document the argument to programmers reading the code. In some future version this text may be incorporated into a usage error message that is generated when argument parsing fails. **-multi** : Group a set of defined arguments together, so they act like mutually exclusive flags. Used to implement patterns like the arguments `-ascii`, `-dictionary`, `-integer` and `-real` arguments to the core **lsort** command. *name* will be the name of the variable that holds the value of the flag that was supplied. A **-default** setting on any of the linked **-multi** arguments (those that share a *name*) will supply a default value in *name* if none were passed. A **-required** setting on any of the linked **-multi** arguments will require that the caller supply at least one of them. If multiple different flags were given, the one last in the argument list applies, unless **-all** was specified (on any linked option), in which case all instances are grouped as a list in *name*, in the order they were specified. **-alias** : Treat the value supplied for this argument as a variable name and bind the resulting variable for this argument to the variable of that name in the call frame above this one (upvar 1). **-all** : Collect all the instances of this argument as a list, rather than the default behaviour of using the last instance as the value. **-end** : Treat the remaining arguments as if **\-\-** directly followed this option - that is: all words in *args* after those consumed by the current option are treated as positional arguments. # EXAMPLES Mimic the argument handling of the core `glob` command: ~~~tcl proc glob args { parse_args::parse_args $args { -directory {} -join {-boolean} -nocomplain {-boolean} -path {} -tails {-boolean} -types {-default {}} args {-name patterns} } if {$join} { set patterns [list [file join {*}$patterns]] } if {[llength $patterns] == 0 && $nocomplain} return foreach pattern $patterns { if {[info exists directory]} { ... } } ... } ~~~ Mimic `regex`: ~~~tcl proc regexp args { parse_args::parse_args $args { -about {-boolean} -expanded {-boolean} -indices {-boolean} -line {-boolean} -linestop {-boolean} -lineanchor {-boolean} -nocase {-boolean} -all {-boolean} -inline {-boolean} -start {-default 0} exp {-required} string {-required} matchvar {} args {-name submatchvars} } ... } ~~~ `lsort`: ~~~tcl proc lsort args { parse_args::parse_args $args { -ascii {-name compare_as -multi -default ascii} -dictionary {-name compare_as -multi} -integer {-name compare_as -multi} -real {-name compare_as -multi} -command {} -increasing {-name order -multi -default increasing} -decreasing {-name order -multi} -indices {-boolean} -index {} -stride {-default 1} -nocase {-boolean} -unique {-boolean} list {-required} } if {![info exists command]} { switch -- $compare_as { ascii { set command {string compare} if {$nocase} { lappend command -nocase } } dictionary { ... } integer - real { set command tcl::mathop::- } } } } ~~~ `lsearch`: ~~~tcl proc lsearch args { parse_args::parse_args $args { -exact {-name matchtype -multi} -glob {-name matchtype -multi -default glob} -regexp {-name matchtype -multi} -sorted {-boolean} -all {-boolean} -inline {-boolean} -not {-boolean} -start {-default 0} -ascii {-name compare_as -multi -default ascii} -dictionary {-name compare_as -multi} -integer {-name compare_as -multi} -real {-name compare_as -multi} -nocase {-boolean} -decreasing {-name order -multi} -increasing {-name order -multi -default increasing} -bisect {-boolean} -index {} -subindices {-boolean} } if {$sorted && $matchtype in {glob regexp}} { error "-sorted is mutually exclusive with -glob and -regexp" } } ~~~ A Tk widget - `entry`: ~~~tcl proc entry {widget args} { parse_args::parse_args $args { -disabledbackground {-default {}} -disabledforeground {-default {}} -invalidcommand {-default {}} -readonlybackground {-default {}} -show {} -state {-default normal -enum { normal disabled readonly }} -validate {-default none -enum { none focus focusin focusout key all }} -validatecommand {-default {}} -width {-default 0} -textvariable {} } } ~~~ # SEE ALSO The paper presented at the 2016 Tcl Conference which discusses the approach and design choices made in this package in much greater depth: https://www.tcl-lang.org/community/tcl2016/assets/talk33/parse_args-paper.pdf # BUGS Please open an issue on the github tracker for the project if you encounter any problems: https://github.com/RubyLane/parse_args/issues # LICENSE This package is Copyright 2015-2026 Cyan Ogilvie, and is made available under the same license terms as the Tcl Core parse_args-v0.6.3/doc/meson.build0000644000175100017510000000237115176457507016375 0ustar runnerrunnerpandoc = find_program('pandoc', native: true, required: false) if pandoc.found() doc_md = configure_file( input: 'parse_args.md.in', output: '@BASENAME@', configuration: teaconf, ) doc_targets = [] doc_targets += custom_target('htmldoc', input: doc_md, output: 'parse_args.html', command: [pandoc, '--standalone', '--metadata', 'title=parse_args', '--from', 'markdown', '--to', 'html', '@INPUT@', '--output', '@OUTPUT@'], install: true, install_dir: get_option('datadir') / 'doc', build_by_default: true, ) doc_targets += custom_target('manpage', input: doc_md, output: 'parse_args.n', command: [pandoc, '--standalone', '--from', 'markdown', '--to', 'man', '@INPUT@', '--output', '@OUTPUT@'], install: true, install_dir: get_option('mandir'), build_by_default: true, ) doc_targets += custom_target('readme', input: doc_md, output: 'README.md', command: [pandoc, '--from', 'markdown', '--to', 'gfm', '@INPUT@', '--output', '@OUTPUT@'], install_dir: meson.project_source_root(), install_tag: 'source', build_by_default: false, ) alias_target('doc', doc_targets) endif parse_args-v0.6.3/bench/0000755000175100017510000000000015176457507014542 5ustar runnerrunnerparse_args-v0.6.3/bench/parse_args.bench0000644000175100017510000003720615176457507017701 0ustar runnerrunnerif {"bench" ni [info commands bench]} { package require bench namespace import bench::* } package require parse_args namespace import ::parse_args::* bench parse_args-1.1 {Parsing options} -batch 1000 -setup { #<<< set args { -title "Do the terms vintage and antique have the same meaning?" -category {"Shop Owners" "Item Listing Information"} -wiki {Most authorities consider the term ''''antique'''' to mean an age of at least '''100 years'''. If an item is not definitively datable to 100 or more years in age, it should not be directly referred to as an antique. The term ''''vintage'''' is applicable to a wider variety of objects, including items that may or may not be antique. As a general rule, vintage should not be used in reference to an object less than '''20 years''' old, and the object should be somewhat representational and recognizable as belonging to the era in which it was made.} } proc parse_args_tcl_uncached {arglist spec {dictvar {}}} { #<<< if {$dictvar ne ""} { upvar 1 $dictvar d } set seen {} set positional_names {} set settings [dict map {k v} $spec { set s {} if {[string index $k 0] eq "-"} { for {set j 0} {$j < [llength $v]} {incr j} { switch -- [lindex $v $j] { -default - -validate - -name - -args { if {$j >= [llength $v]-1} { error "[lindex $v $j] requires an argument" } dict set s [string range [lindex $v $j] 1 end] [lindex $v [incr j]] } -boolean { dict set s boolean 1 } -required { dict set s required 1 } default { error "Invalid arg spec option \"[lindex $v $j]\"" } } } if {![dict exists $s boolean]} { dict set s boolean 0 } if {![dict exists $s required]} { dict set s required 0 } if {![dict exists $s name]} { dict set s name [string range $k 1 end] } } else { for {set j 0} {$j < [llength $v]} {incr j} { switch -- [lindex $v $j] { -default - -validate - -name - -required { dict set s required 1 } default { error "Invalid arg spec option \"[lindex $v $j]\"" } } } if {![dict exists $s boolean]} { dict set s boolean 0 } if {![dict exists $s required]} { dict set s required 0 } if {![dict exists $s name]} { dict set s name $k } lappend positional_names $k } set s }] set p_i 0 set check_options 1 for {set i 0} {$i < [llength $arglist]} {incr i} { set arg [lindex $arglist $i] if {$check_options} { if {$arg eq "--"} { set check_options 0 continue } if {[string index $arglist 0] eq "-"} { if {![dict exists $spec $arg]} { error "Invalid option: \"$arg\"" } set s [dict get $settings $arg] if {[dict get $s boolean] && [dict exists $s args] && [dict get $s args] != 0} { error "-boolean options cannot have -args greater than 0" } if {[dict get $s boolean]} { set v 1 } else { if {![dict exists $s args]} { dict set s args 1 } if {[llength $arglist] - $i - 1 < [dict get $s args]} { error "option $arg requires [dict get $s args], but [expr {[llength $argslist] - $i - 1}] remain" } switch -- [dict get $s args] { 0 {set v 1} 1 {set v [lindex $arglist [incr i]]} default { set v [lrange $arglist $i+1 [expr { $i + [dict get $s args] - 1 }] incr i [dict get $s args] } } } # TODO: validate dict set d [dict get $s name] $v dict set seen $arg 1 continue } else { set check_options 0 } } if {$p_i >= [llength $positional_names]} { error "Too many arguments for positional params: [join $positional_names {, }]" } set pname [lindex $positional_names $p_i] set s [dict get $settings $pname] if {$p_i == [llength $positional_names]-1 && $pname eq "args"} { dict set d [dict get $s name] [lrange $arglist $i+1 end] set i [expr {[llength $arglist] - 1}] } else { # TODO: validate dict set d [dict get $s name] $arg } incr p_i } # Check -required and set -default for options that weren't specified dict for {k v} $spec { if {[string index $k 0] ne "-"} continue if {[dict exists $seen $k]} continue if {[dict get $settings $k default]} { dict set d [dict get $settings $k name] [dict get $settings $k default] } elseif {[dict get $settings $k required]} { error "option \"$k\" is required" } } # Set default values for positional params that need them foreach pname [lrange $positional_names $p_i end] { set s [dict get $settings $pname] if {[dict exists $s default]} { dict set d [dict get $s name] [dict get $s default] } else { error "argument $pname is required" } } if {$dictvar eq ""} { dict for {k v} $d { uplevel 1 [list set $k $v] } } } #>>> proc get_parsed_spec spec { #<<< global __spec_cache if {![info exists __spec_cache] || ![dict exists $__spec_cache $spec]} { set positional_names {} set settings [dict map {k v} $spec { set s {} if {[string index $k 0] eq "-"} { for {set j 0} {$j < [llength $v]} {incr j} { switch -- [lindex $v $j] { -default - -validate - -name - -args { if {$j >= [llength $v]-1} { error "[lindex $v $j] requires an argument" } dict set s [string range [lindex $v $j] 1 end] [lindex $v [incr j]] } -boolean { dict set s boolean 1 } -required { dict set s required 1 } default { error "Invalid arg spec option \"[lindex $v $j]\"" } } } if {![dict exists $s boolean]} { dict set s boolean 0 } if {![dict exists $s required]} { dict set s required 0 } if {![dict exists $s name]} { dict set s name [string range $k 1 end] } } else { for {set j 0} {$j < [llength $v]} {incr j} { switch -- [lindex $v $j] { -default - -validate - -name - -required { dict set s required 1 } default { error "Invalid arg spec option \"[lindex $v $j]\"" } } } if {![dict exists $s boolean]} { dict set s boolean 0 } if {![dict exists $s required]} { dict set s required 0 } if {![dict exists $s name]} { dict set s name $k } lappend positional_names $k } set s }] dict set __spec_cache $spec [list $settings $positional_names] } dict get $__spec_cache $spec } #>>> proc parse_args_tcl {arglist spec {dictvar {}}} { #<<< if {$dictvar ne ""} { upvar 1 $dictvar d } set seen {} lassign [get_parsed_spec $spec] settings positional_names set p_i 0 set check_options 1 for {set i 0} {$i < [llength $arglist]} {incr i} { set arg [lindex $arglist $i] if {$check_options} { if {$arg eq "--"} { set check_options 0 continue } if {[string index $arglist 0] eq "-"} { if {![dict exists $spec $arg]} { error "Invalid option: \"$arg\"" } set s [dict get $settings $arg] if {[dict get $s boolean] && [dict exists $s args] && [dict get $s args] != 0} { error "-boolean options cannot have -args greater than 0" } if {[dict get $s boolean]} { set v 1 } else { if {![dict exists $s args]} { dict set s args 1 } if {[llength $arglist] - $i - 1 < [dict get $s args]} { error "option $arg requires [dict get $s args], but [expr {[llength $argslist] - $i - 1}] remain" } switch -- [dict get $s args] { 0 {set v 1} 1 {set v [lindex $arglist [incr i]]} default { set v [lrange $arglist $i+1 [expr { $i + [dict get $s args] - 1 }] incr i [dict get $s args] } } } # TODO: validate dict set d [dict get $s name] $v dict set seen $arg 1 continue } else { set check_options 0 } } if {$p_i >= [llength $positional_names]} { error "Too many arguments for positional params: [join $positional_names {, }]" } set pname [lindex $positional_names $p_i] set s [dict get $settings $pname] if {$p_i == [llength $positional_names]-1 && $pname eq "args"} { dict set d [dict get $s name] [lrange $arglist $i+1 end] set i [expr {[llength $arglist] - 1}] } else { # TODO: validate dict set d [dict get $s name] $arg } incr p_i } # Check -required and set -default for options that weren't specified dict for {k v} $spec { if {[string index $k 0] ne "-"} continue if {[dict exists $seen $k]} continue if {[dict get $settings $k default]} { dict set d [dict get $settings $k name] [dict get $settings $k default] } elseif {[dict get $settings $k required]} { error "option \"$k\" is required" } } # Set default values for positional params that need them foreach pname [lrange $positional_names $p_i end] { set s [dict get $settings $pname] if {[dict exists $s default]} { dict set d [dict get $s name] [dict get $s default] } else { error "argument $pname is required" } } if {$dictvar eq ""} { dict for {k v} $d { uplevel 1 [list set $k $v] } } } #>>> proc tcl_vars args { parse_args_tcl $args { -title {-required} -category {-default {}} -wiki {-required} -rating {-default 1.0 -validate {string is double -strict}} } list $title $category $wiki $rating } proc tcl_dict args { parse_args_tcl $args { -title {-required} -category {-default {}} -wiki {-required} -rating {-default 1.0 -validate {string is double -strict}} } d list [dict get $d title] [dict get $d category] [dict get $d wiki] [dict get $d rating] } proc tcl_dict_with args { parse_args_tcl $args { -title {-required} -category {-default {}} -wiki {-required} -rating {-default 1.0 -validate {string is double -strict}} } d dict with d {} list $title $category $wiki $rating } proc native {t_a title c_a category w_a wiki {r_a rating} {rating 1.0}} { list $title $category $wiki $rating } proc c_vars args { parse_args $args { -title {-required} -category {-default {}} -wiki {-required} -rating {-default 1.0 -validate {string is double -strict}} } list $title $category $wiki $rating } proc c_dict args { parse_args $args { -title {-required} -category {-default {}} -wiki {-required} -rating {-default 1.0 -validate {string is double -strict}} } d list [dict get $d title] [dict get $d category] [dict get $d wiki] [dict get $d rating] } proc c_dict_with args { parse_args $args { -title {-required} -category {-default {}} -wiki {-required} -rating {-default 1.0 -validate {string is double -strict}} } d dict with d {} list $title $category $wiki $rating } } -compare { tcl_vars { tcl_vars {*}$args } tcl_dict { tcl_dict {*}$args } tcl_dict_with { tcl_dict_with {*}$args } native { native {*}$args } c_vars { c_vars {*}$args } c_dict { c_dict {*}$args } c_dict_with { c_dict_with {*}$args } } -cleanup { foreach p {parse_args_tcl_uncached get_parsed_spec tcl_vars tcl_dict tcl_dict_with native c_vars c_dict c_dict_with} { rename $p {} } unset -nocomplain args d title category wiki rating __spec_cache } -result {{Do the terms vintage and antique have the same meaning?} {"Shop Owners" "Item Listing Information"} {Most authorities consider the term ''''antique'''' to mean an age of at least '''100 years'''. If an item is not definitively datable to 100 or more years in age, it should not be directly referred to as an antique. The term ''''vintage'''' is applicable to a wider variety of objects, including items that may or may not be antique. As a general rule, vintage should not be used in reference to an object less than '''20 years''' old, and the object should be somewhat representational and recognizable as belonging to the era in which it was made.} 1.0} #>>> bench enum-1.1 {enum validate} -batch 1000 -setup { #<<< proc tcl {state validate} { if {$state ni {normal disabled readonly}} { throw [list TCL LOOKUP INDEX state $state] "bad state \"$state\": must be normal, disabled, or readonly" } if {$validate ni {none focus focusin focusout key all}} { throw [list TCL LOOKUP INDEX validate $validate] "bad validate \"$validate\": must be none, focus, focusin, focusout, key, or all" } list $state $validate } proc p args { parse_args $args { state {-enum {normal disabled readonly}} validate {-enum {none focus focusin focusout key all}} } list $state $validate } set state readonly set validate focusout } -compare { tcl { tcl $state $validate} parse_args { p $state $validate } } -cleanup { foreach p {tcl p} {rename $p {}} unset -nocomplain p state validate } -result {readonly focusout} #>>> bench overhead-1.1 {nop overhead} -batch 1000 -setup { #<<< proc tcl args { set args ;# Prevent Tcl from optimizing out the call entirely } proc p args { parse_args $args { } set args } } -compare { tcl tcl parse_args p } -cleanup { foreach p {tcl p} {rename $p {}} unset -nocomplain p } -result {} #>>> bench validate-1.1 {validation, succeeds} -batch 1000 -setup { #<<< proc tcl rating { list [catch { if {![string is double -strict $rating]} { error "Validation failed for \"rating\": 0" } set rating } r o] $r } proc p args { list [catch { parse_args $args { rating {-validate {string is double -strict}} } set rating } r o] $r } } -compare { tcl { tcl 1.2 } parse_args { p 1.2 } } -cleanup { foreach p {tcl p} {rename $p {}} unset -nocomplain p } -result [list 0 1.2] #>>> bench validate-1.2 {validation, fails} -batch 1000 -setup { #<<< proc tcl rating { list [catch { if {![string is double -strict $rating]} { error "Validation failed for \"rating\": 0" } set rating } r o] $r } proc p args { list [catch { parse_args $args { rating {-validate {string is double -strict}} } set rating } r o] $r } } -compare { tcl { tcl x1.2 } parse_args { p x1.2 } } -cleanup { foreach p {tcl p} {rename $p {}} unset -nocomplain p } -result [list 1 "Validation failed for \"rating\": 0"] #>>> bench multi-1.1 {multi} -batch 1000 -setup { #<<< proc tcl args { foreach arg $args { switch -- $arg { -ascii - -dictionary - -integer - -real { set compare_as [string range $arg 1 end] } } } if {![info exists compare_as]} { set compare_as ascii } set compare_as } proc p args { parse_args $args { -ascii {-multi -name compare_as -default ascii} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} -real {-multi -name compare_as} } set compare_as } } -compare { tcl {tcl -dictionary} parse_args {p -dictionary} } -cleanup { foreach p {tcl p} {rename $p {}} unset -nocomplain p } -result dictionary #>>> bench multi-1.2 {multi, default} -batch 1000 -setup { #<<< proc tcl args { foreach arg $args { switch -- $arg { -ascii - -dictionary - -integer - -real { set compare_as [string range $arg 1 end] } } } if {![info exists compare_as]} { set compare_as ascii } set compare_as } proc p args { parse_args $args { -ascii {-multi -name compare_as -default ascii} -dictionary {-multi -name compare_as} -integer {-multi -name compare_as} -real {-multi -name compare_as} } set compare_as } } -compare { tcl tcl parse_args p } -cleanup { foreach p {tcl p} {rename $p {}} unset -nocomplain p } -result ascii #>>> # vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 parse_args-v0.6.3/bench/run.tcl0000644000175100017510000000000015176457507025070 1parse_args-v0.6.3/teabase/run_bench.tclustar runnerrunnerparse_args-v0.6.3/subprojects/0000755000175100017510000000000015176457625016027 5ustar runnerrunnerparse_args-v0.6.3/subprojects/libtommath.wrap0000644000175100017510000000000015176457507033026 1parse_args-v0.6.3/teabase/subprojects/libtommath.wrapustar runnerrunnerparse_args-v0.6.3/subprojects/tcl.wrap0000644000175100017510000000000015176457507030072 1parse_args-v0.6.3/teabase/subprojects/tcl.wrapustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/0000755000175100017510000000000015176457507020444 5ustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/tcl/0000755000175100017510000000000015176457507021226 5ustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/tcl/meson.build0000644000175100017510000000000015176457507037644 1parse_args-v0.6.3/teabase/subprojects/packagefiles/tcl/meson.buildustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/tcl/tclUuid.h.in0000644000175100017510000000000015176457507037716 1parse_args-v0.6.3/teabase/subprojects/packagefiles/tcl/tclUuid.h.inustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/libtommath/0000755000175100017510000000000015176457507022604 5ustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/libtommath/meson_options.txt0000644000175100017510000000000015176457507045366 1parse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/meson_options.txtustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/libtommath/meson.build0000644000175100017510000000000015176457507042600 1parse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/meson.buildustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/libtommath/run_mtest.py0000644000175100017510000000000015176457507043260 1parse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/run_mtest.pyustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/libtommath/doc/0000755000175100017510000000000015176457507023351 5ustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/libtommath/doc/build-manual.py0000644000175100017510000000000015176457507045456 1parse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/doc/build-manual.pyustar runnerrunnerparse_args-v0.6.3/subprojects/packagefiles/libtommath/libtommath.def0000644000175100017510000000000015176457507043734 1parse_args-v0.6.3/teabase/subprojects/packagefiles/libtommath/libtommath.defustar runnerrunnerparse_args-v0.6.3/parse_args.pc.in0000644000175100017510000000045015176457507016541 0ustar runnerrunnerpkg_dir=${pcfiledir}/../@PKG_DIR_BASENAME@ # tcl_pkg_path: directory a Tcl interpreter should add to auto_path # for `package require @PACKAGE_NAME@` to resolve to this install. tcl_pkg_path=${pkg_dir} Name: @PACKAGE_NAME@ Description: Argument parser for Tcl scripts Version: @PACKAGE_VERSION@ parse_args-v0.6.3/.gitmodules0000644000175100017510000000027415176457507015643 0ustar runnerrunner[submodule "tclconfig"] path = tclconfig url = https://github.com/tcltk/tclconfig.git shallow = true [submodule "teabase"] path = teabase url = https://github.com/cyanogilvie/teabase