diff --git a/README.md b/README.md index 75a9169..10b6099 100644 --- a/README.md +++ b/README.md @@ -377,3 +377,38 @@ License ------- Copyright 2015-2023 Ruby Lane. Licensed under the same terms as the Tcl core. + +Building under Windows msys2 +------- + +* Install msys2: `choco.exe install -y msys2` +* Start Terminal: `C:\tools\msys64\mingw64.exe` +* Install tools: +```bash + pacman --noconfirm -S --needed autoconf \ + base-devel\ + development\ + cmake\ + mingw-w64-x86_64-toolchain\ + mingw-w64-cross-binutils\ + gcc\ + rsync\ + unzip\ + git\ + vim +``` +* Make sure tcl is installed +* git clone +* cd +* build: +```bash + INSTALLDIR="${INSTALLDIR:-build/x64}" + SHAREDIR=${INSTALLDIR}/share + VERSION="0.15.2" + BUILD_OPTS="${CONFIG:- --prefix=$(pwd)/${INSTALLDIR} --mandir=$(pwd)/${SHAREDIR}}" + + autoconf + ./configure ${BUILD_OPTS} + make -j8 + make install +``` diff --git a/bench/old.tcl b/bench/old.tcl old mode 100644 new mode 100755 diff --git a/bench/run.tcl b/bench/run.tcl deleted file mode 120000 index 4ae89d9..0000000 --- a/bench/run.tcl +++ /dev/null @@ -1 +0,0 @@ -../teabase/run_bench.tcl \ No newline at end of file diff --git a/bench/run.tcl b/bench/run.tcl new file mode 100644 index 0000000..f90bd1f --- /dev/null +++ b/bench/run.tcl @@ -0,0 +1,47 @@ +# vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4 + +set big [string repeat a [expr {int(1e8)}]] ;# Allocate 100MB to pre-expand the zippy pool +unset big + +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 + try { + puts "[string repeat - 80]\nStarting benchmarks\n" + teabase_bench::run_benchmarks [file dirname [file normalize [info script]]] {*}$::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 diff --git a/configure.ac b/configure.ac old mode 100644 new mode 100755 index 3779f44..cb758cf --- a/configure.ac +++ b/configure.ac @@ -103,6 +103,9 @@ if test "${TEA_PLATFORM}" = "windows" ; then : #TEA_ADD_SOURCES([win/winFile.c]) #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) + dnl start PRS changes + TEA_ADD_LIBS([ws2_32.lib]) + dnl end PRS changes else # Ensure no empty else clauses : diff --git a/generic/cbor.c b/generic/cbor.c index d7dfe90..e92b331 100644 --- a/generic/cbor.c +++ b/generic/cbor.c @@ -1,10 +1,14 @@ #include "rl_jsonInt.h" +/* + * Renamed enum values, see: + * https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/hresult-values + */ enum svalue_types { - S_FALSE = 20, - S_TRUE = 21, - S_NULL = 22, - S_UNDEF = 23 + CBOR_FALSE = 20, + CBOR_TRUE = 21, + CBOR_NULL = 22, + CBOR_UNDEF = 23 }; enum indexmode { @@ -51,7 +55,7 @@ static float decode_float(const uint8_t* p) { //{{{ //}}} static double decode_double(const uint8_t* p) { //{{{ double val; - uint64_t uval = be64toh(*(uint64_t*)p); + uint64_t uval = be64Itoh(*(uint64_t*)p); memcpy(&val, &uval, sizeof(double)); return val; } @@ -109,7 +113,7 @@ static int well_formed(Tcl_Interp* interp, const uint8_t** pPtr, const uint8_t* case 24: TEST_OK_LABEL(finally, code, take(interp, pPtr, e, 1, &part)); val = *(uint8_t*)part; break; case 25: TEST_OK_LABEL(finally, code, take(interp, pPtr, e, 2, &part)); val = be16toh(*(uint16_t*)part); break; case 26: TEST_OK_LABEL(finally, code, take(interp, pPtr, e, 4, &part)); val = be32toh(*(uint32_t*)part); break; - case 27: TEST_OK_LABEL(finally, code, take(interp, pPtr, e, 8, &part)); val = be64toh(*(uint64_t*)part); break; + case 27: TEST_OK_LABEL(finally, code, take(interp, pPtr, e, 8, &part)); val = be64Itoh(*(uint64_t*)part); break; case 28: case 29: case 30: CBOR_INVALID(finally, code, "reserved additional info value: %d", ai); case 31: return well_formed_indefinite(interp, pPtr, e, breakable, mtPtr, mt); } @@ -365,7 +369,7 @@ static int cbor_get_obj(Tcl_Interp* interp, const uint8_t** pPtr, const uint8_t* case 24: TAKE(1); val = *(uint8_t*)valPtr; break; case 25: TAKE(2); val = be16toh(*(uint16_t*)valPtr); break; case 26: TAKE(4); val = be32toh(*(uint32_t*)valPtr); break; - case 27: TAKE(8); val = be64toh(*(uint64_t*)valPtr); break; + case 27: TAKE(8); val = be64Itoh(*(uint64_t*)valPtr); break; case 28: case 29: case 30: CBOR_INVALID(finally, code, "reserved additional info value: %d", ai); } @@ -413,11 +417,17 @@ static int cbor_get_obj(Tcl_Interp* interp, const uint8_t** pPtr, const uint8_t* uint64_t chunk_val; switch (chunk_ai) { - case 0 ... 23: chunk_val = chunk_ai; break; + //case 0 ... 23: + case 0: case 1: case 2: case 3: case 4: + case 5: case 6: case 7: case 8: case 9: + case 10: case 11: case 12: case 13: case 14: + case 15: case 16: case 17: case 18: case 19: + case 20: case 21: case 22: case 23: + chunk_val = chunk_ai; break; case 24: TAKE(1); chunk_val = *(uint8_t*)valPtr; break; case 25: TAKE(2); chunk_val = be16toh(*(uint16_t*)valPtr); break; case 26: TAKE(4); chunk_val = be32toh(*(uint32_t*)valPtr); break; - case 27: TAKE(8); chunk_val = be64toh(*(uint64_t*)valPtr); break; + case 27: TAKE(8); chunk_val = be64Itoh(*(uint64_t*)valPtr); break; default: CBOR_INVALID(finally, code, "invalid chunk additional info: %d", chunk_ai); } TAKE(chunk_val); @@ -479,16 +489,29 @@ static int cbor_get_obj(Tcl_Interp* interp, const uint8_t** pPtr, const uint8_t* case M_REAL: { switch (ai) { - case 0 ... 19: replace_tclobj(&res, Tcl_ObjPrintf("simple(%" PRIu64 ")", val)); break; - case S_FALSE: replace_tclobj(&res, l->cbor_false); break; - case S_TRUE: replace_tclobj(&res, l->cbor_true); break; - case S_NULL: replace_tclobj(&res, l->cbor_null); break; - case S_UNDEF: replace_tclobj(&res, l->cbor_undefined); break; + //case 0 ... 19: + case 0: case 1: case 2: case 3: case 4: + case 5: case 6: case 7: case 8: case 9: + case 10: case 11: case 12: case 13: case 14: + case 15: case 16: case 17: case 18: case 19: + replace_tclobj(&res, Tcl_ObjPrintf("simple(%" PRIu64 ")", val)); break; + case CBOR_FALSE: replace_tclobj(&res, l->cbor_false); break; + case CBOR_TRUE: replace_tclobj(&res, l->cbor_true); break; + case CBOR_NULL: replace_tclobj(&res, l->cbor_null); break; + case CBOR_UNDEF: replace_tclobj(&res, l->cbor_undefined); break; case 24: +#if 1 + if (val >= 32 && val <= 255) { + replace_tclobj(&res, Tcl_ObjPrintf("simple(%" PRIu64 ")", val)); + } else { + CBOR_INVALID(finally, code, "invalid simple value: %" PRIu64, val); + } +#else switch (val) { case 32 ... 255: replace_tclobj(&res, Tcl_ObjPrintf("simple(%" PRIu64 ")", val)); break; - default: CBOR_INVALID(finally, code, "invalid simple value: %" PRIu64, val); + default: CBOR_INVALID(finally, code, "invalid simple value: %" PRIu64, val); } +#endif break; case 25: replace_tclobj(&res, Tcl_NewDoubleObj( decode_half(valPtr) )); break; case 26: replace_tclobj(&res, Tcl_NewDoubleObj( decode_float(valPtr) )); break; @@ -674,7 +697,7 @@ static int cbor_matches(Tcl_Interp* interp, const uint8_t** pPtr, const uint8_t* case 24: TAKE(1); val = *(uint8_t*)valPtr; break; case 25: TAKE(2); val = be16toh(*(uint16_t*)valPtr); break; case 26: TAKE(4); val = be32toh(*(uint32_t*)valPtr); break; - case 27: TAKE(8); val = be64toh(*(uint64_t*)valPtr); break; + case 27: TAKE(8); val = be64Itoh(*(uint64_t*)valPtr); break; case 28: case 29: case 30: CBOR_INVALID(finally, code, "reserved additional info value: %d", ai); } //}}} @@ -730,7 +753,7 @@ static int cbor_matches(Tcl_Interp* interp, const uint8_t** pPtr, const uint8_t* case 24: TAKE(1); chunk_val = *(uint8_t*)valPtr; break; case 25: TAKE(2); chunk_val = be16toh(*(uint16_t*)valPtr); break; case 26: TAKE(4); chunk_val = be32toh(*(uint32_t*)valPtr); break; - case 27: TAKE(8); chunk_val = be64toh(*(uint64_t*)valPtr); break; + case 27: TAKE(8); chunk_val = be64Itoh(*(uint64_t*)valPtr); break; case 28: case 29: case 30: CBOR_INVALID(finally, code, "reserved additional info value: %d", chunk_ai); case 31: CBOR_INVALID(finally, code, "cannot nest indefinite length chunks"); } @@ -789,7 +812,7 @@ static int cbor_matches(Tcl_Interp* interp, const uint8_t** pPtr, const uint8_t* case 24: TAKE(1); chunk_val = *(uint8_t*)valPtr; break; case 25: TAKE(2); chunk_val = be16toh(*(uint16_t*)valPtr); break; case 26: TAKE(4); chunk_val = be32toh(*(uint32_t*)valPtr); break; - case 27: TAKE(8); chunk_val = be64toh(*(uint64_t*)valPtr); break; + case 27: TAKE(8); chunk_val = be64Itoh(*(uint64_t*)valPtr); break; case 28: case 29: case 30: CBOR_INVALID(finally, code, "reserved additional info value: %d", chunk_ai); case 31: CBOR_INVALID(finally, code, "cannot nest indefinite length chunks"); } @@ -1005,7 +1028,7 @@ int CBOR_GetDataItemFromPath(Tcl_Interp* interp, Tcl_Obj* cborObj, Tcl_Obj* path case 24: TAKE(1); val = *(uint8_t*)valPtr; break; case 25: TAKE(2); val = be16toh(*(uint16_t*)valPtr); break; case 26: TAKE(4); val = be32toh(*(uint32_t*)valPtr); break; - case 27: TAKE(8); val = be64toh(*(uint64_t*)valPtr); break; + case 27: TAKE(8); val = be64Itoh(*(uint64_t*)valPtr); break; case 28: case 29: case 30: CBOR_INVALID(finally, code, "reserved additional info value: %d", ai); } diff --git a/generic/names.c b/generic/names.c deleted file mode 120000 index b8c7303..0000000 --- a/generic/names.c +++ /dev/null @@ -1 +0,0 @@ -../teabase/names.c \ No newline at end of file diff --git a/generic/names.c b/generic/names.c new file mode 100644 index 0000000..ad1c59d --- /dev/null +++ b/generic/names.c @@ -0,0 +1,440 @@ +#if DEBUG +#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; +} + +#endif +// vim: ts=4 shiftwidth=4 diff --git a/generic/names.h b/generic/names.h deleted file mode 120000 index 1204667..0000000 --- a/generic/names.h +++ /dev/null @@ -1 +0,0 @@ -../teabase/names.h \ No newline at end of file diff --git a/generic/names.h b/generic/names.h new file mode 100644 index 0000000..f188cd8 --- /dev/null +++ b/generic/names.h @@ -0,0 +1,10 @@ +#ifndef _NAMES_H +#define _NAMES_H +#if DEBUG + +const char* name(const void *const thing); // name given thing +void* thing(const char *const name); // thing given name +void names_shutdown(); + +#endif +#endif diff --git a/generic/rl_json.c b/generic/rl_json.c index 904647d..f600f14 100644 --- a/generic/rl_json.c +++ b/generic/rl_json.c @@ -23,6 +23,10 @@ static Tcl_Config cfg[] = { #if defined(_WIN32) #define snprintf _snprintf +/* start PRS changes */ +# define _Pragma(x) +# define mkstemp(x) mktemp(x) +/* end PRS changes */ #endif static const char* dyn_prefix[] = { @@ -3254,7 +3258,9 @@ static int jsonValid(ClientData cdata, Tcl_Interp* interp, int objc, Tcl_Obj *co { struct interp_cx* l = (struct interp_cx*)cdata; int i, valid, retval=TCL_OK; - struct parse_error details = {}; + /* start PRS changes */ + struct parse_error details = {0}; + /* end PRS changes */ Tcl_Obj* detailsvar = NULL; // ref is borrowed from variable Tcl_Obj* details_obj = NULL; Tcl_Obj* k = NULL; @@ -3824,7 +3830,7 @@ static int checkmem(ClientData cdata, Tcl_Interp* interp, int objc, Tcl_Obj *con memcpy(temp, TEMP_TEMPLATE, sizeof(TEMP_TEMPLATE)); - fd = mkstemp(temp); + fd = (int)mkstemp(temp); h_before = fdopen(fd, "r"); #if DEDUP @@ -3842,7 +3848,7 @@ static int checkmem(ClientData cdata, Tcl_Interp* interp, int objc, Tcl_Obj *con free_cache(l); #endif memcpy(temp, TEMP_TEMPLATE, sizeof(TEMP_TEMPLATE)); - fd = mkstemp(temp); + fd = (int)mkstemp(temp); h_after = fdopen(fd, "r"); Tcl_DumpActiveMemory(temp); if (unlink(temp) != 0) { diff --git a/generic/rl_jsonInt.h b/generic/rl_jsonInt.h index 5093edd..60d017e 100644 --- a/generic/rl_jsonInt.h +++ b/generic/rl_jsonInt.h @@ -13,7 +13,94 @@ #ifdef HAVE_UNISTD_H #include #endif -#include +/* start PRS changes */ +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) +# define __WINDOWS__ +#endif + +#if defined(__APPLE__) +/* + * Compatibility header for endian.h. + * A simple compatibility shim to convert + * BSD/Linux endian macros to the Mac OS X equivalents. + * */ +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) + + + +#elif defined(__WINDOWS__) +# include +# include +# if defined(_WIN32) +# define ssize_t int +# elif defined(_WIN64) +# define ssize_t __int64 +# endif +# if BYTE_ORDER == LITTLE_ENDIAN + +// implement missing +inline uint64_t be64Itoh(uint64_t value) { + if (htonl(1) != 1) { + uint32_t high_part = ntohl((uint32_t)(value >> 32)); + uint32_t low_part = ntohl((uint32_t)(value & 0xFFFFFFFFLL)); + return ((uint64_t)low_part << 32) | high_part; + } else { + return value; + } +} + +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) +# define htobe32(x) htonl(x) +# define htole32(x) (x) +# define be32toh(x) ntohl(x) +# define le32toh(x) (x) +# define htobe64(x) htonll(x) +# define htole64(x) (x) +// # define be64Itoh(x) ntohll(x) +# define le64toh(x) (x) +# elif BYTE_ORDER == BIG_ENDIAN + /* that would be xbox 360 */ +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) +# else +# error byte order not supported +# endif +//# define __BYTE_ORDER BYTE_ORDER +//# define __BIG_ENDIAN BIG_ENDIAN +//# define __LITTLE_ENDIAN LITTLE_ENDIAN +//# define __PDP_ENDIAN PDP_ENDIAN + +#else +# include +# define be64Itoh(x) be64toh(x) +#endif +/* end PRS changes */ #include #include "tip445.h" #include "names.h" @@ -155,6 +242,13 @@ struct kc_entry { /* _BitScanForward64 numbers bits starting with 0, ffsll starts with 1 */ # define FFS(x) (_BitScanForward64(&ix, x) ? ix+1 : 0) # define FREEMAP_TYPE long long +/* start PRS changes */ +#elif defined(_WIN32) +/* _BitScanForward numbers bits starting with 0, ffsll starts with 1 */ +# define FFS_TMP_STORAGE unsigned long ix; +# define FFS(x) (_BitScanForward(&ix, x) ? ix+1 : 0) +# define FREEMAP_TYPE long +/* end PRS changes */ #else # define FFS_TMP_STORAGE /* nothing to declare */ # define FFS ffs diff --git a/generic/tclstuff.h b/generic/tclstuff.h deleted file mode 120000 index ade55f1..0000000 --- a/generic/tclstuff.h +++ /dev/null @@ -1 +0,0 @@ -../teabase/tclstuff.h \ No newline at end of file diff --git a/generic/tclstuff.h b/generic/tclstuff.h new file mode 100644 index 0000000..a9e2bfd --- /dev/null +++ b/generic/tclstuff.h @@ -0,0 +1,159 @@ +// 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( ... ) \ + { \ + Tcl_AppendResult(interp, ##__VA_ARGS__, NULL); \ + return TCL_ERROR; \ + } + +#define THROW_PRINTF( fmtstr, ... ) \ + { \ + Tcl_SetObjResult(interp, Tcl_ObjPrintf((fmtstr), ##__VA_ARGS__)); \ + return TCL_ERROR; \ + } + +#define THROW_ERROR_LABEL( label, var, ... ) \ + { \ + Tcl_AppendResult(interp, ##__VA_ARGS__, NULL); \ + var = TCL_ERROR; \ + goto label; \ + } + +#define THROW_PRINTF_LABEL( label, var, fmtstr, ... ) \ + { \ + Tcl_SetObjResult(interp, Tcl_ObjPrintf((fmtstr), ##__VA_ARGS__)); \ + var = TCL_ERROR; \ + goto label; \ + } + +#define THROW_POSIX_LABEL(label, code, msg) do { \ + int err = Tcl_GetErrno(); \ + const char* errstr = Tcl_ErrnoId(); \ + 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(expected, msg) \ + if (objc != expected + 1) { \ + Tcl_WrongNumArgs(interp, 1, objv, msg); \ + return TCL_ERROR; \ + } + +#define CHECK_ARGS_LABEL(label, rc, msg) \ + do { \ + if (objc != A_objc) { \ + Tcl_WrongNumArgs(interp, A_cmd+1, objv, msg); \ + rc = TCL_ERROR; \ + goto label; \ + } \ + } while(0); + +#define CHECK_MIN_ARGS_LABEL(label, rc, msg) \ + do { \ + if (objc < A_args) { \ + Tcl_WrongNumArgs(interp, A_cmd+1, objv, msg); \ + rc = TCL_ERROR; \ + goto label; \ + } \ + } while(0); + +#define CHECK_RANGE_ARGS_LABEL(label, rc, msg) \ + do { \ + if (objc < A_args || objc > A_objc) { \ + Tcl_WrongNumArgs(interp, A_cmd+1, objv, msg); \ + 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) \ +{ \ + release_tclobj(&target); \ + if (replacement) Tcl_IncrRefCount(target = replacement); \ +} +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: %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 diff --git a/generic/tip445.h b/generic/tip445.h deleted file mode 120000 index a53b808..0000000 --- a/generic/tip445.h +++ /dev/null @@ -1 +0,0 @@ -../teabase/tip445.h \ No newline at end of file diff --git a/generic/tip445.h b/generic/tip445.h new file mode 100644 index 0000000..cc68a04 --- /dev/null +++ b/generic/tip445.h @@ -0,0 +1,108 @@ +#ifndef _TIP445_H +#define _TIP445_H + +#if TIP445_SHIM +#include +#include +#include + +/* Just enough of TIP445 to build on Tcl 8.6 */ + +#ifndef Tcl_ObjInternalRep +# ifdef Tcl_ObjIntRep +typedef Tcl_ObjIntRep Tcl_ObjInternalRep +# else +typedef union Tcl_ObjInternalRep { + struct { + void* ptr1; + void* ptr2; + } twoPtrValue; + struct { + void* ptr; + unsigned long value; + } ptrAndLongRep; +} Tcl_ObjInternalRep; +# endif +#endif + +#ifndef Tcl_FetchInternalRep +# ifdef Tcl_FetchIntRep +# define Tcl_FetchInternalRep(obj, type) (Tcl_ObjInternalRep*)Tcl_FetchIntRep(obj, type) +# else +# define Tcl_FetchInternalRep(obj, type) (Tcl_ObjInternalRep*)(((obj)->typePtr == (type)) ? &(obj)->internalRep : NULL) +# endif +#endif + +#ifndef Tcl_FreeInternalRep +# ifdef Tcl_FreeIntRep +# define Tcl_FreeInternalRep Tcl_FreeIntRep +# else +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 +#endif + +#ifndef Tcl_StoreInternalRep +# ifdef Tcl_StoreIntRep +# define Tcl_StoreInternalRep(obj, type, ir) Tcl_StoreIntRep(obj, type, (Tcl_ObjIntRep*)ir) +# else +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 +#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 + +#endif // TIP445_SHIM + +#endif // _TI445_H