/usr/share/epic5/script/data_struct is in epic5 1.1.11-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 | if (word(2 $loadinfo()) != [pf]) { load -pf $word(1 $loadinfo()); return; };
#
# Struct/Assign manipulation functions.
#
# The distinction between the two is that the assign functions operate on
# the entire alias space whereas the struct functions operate only on sub
# structures. The assign functions are typically slower per call, but since
# they do all the work in one call, they can be faster than the recursive
# struct functions.
#
# For each assign.* alias, a corresponding alias.*, but some of them have
# implicit bugs from the fact that arg lists can't yet be retrieved for stored
# aliases.
#
#
# Assign functions.
#
# Make two aliases for every alias. One for assign handling, one for alias
# handling, then make two more for forward and reverse modes.
#
stack push alias alias.ttt;
stack push alias alias.tt;
alias alias.ttt (args) {
alias $args;
@ sar(gr/assign/alias/args);
alias $args;
};
alias alias.tt (args) {
alias.ttt $args;
@ sar(gr/assign./assign.r/args);
@ sar(gr/pmatch/rpmatch/args);
@ sar(gr/;@ :list = revw($list);/;/args);
alias.ttt $args;
};
#
# Check the consistency of the internal structures. The only
# reason to use these is if an epic bug is suspected.
#
alias.ttt assign.check {
@ :oxd = xdebug(dword);
xdebug dword;
@ :omr = aliasctl(maxret 0);
@ :last = [];
@ :list = aliasctl(assign pmatch "\\[$*\\]");
fe ($list) foo {
if (uniq($last $foo)!=sort($last $foo)) {
echo assign consistancy failure: $last >= $foo;
@ last = foo;
};
};
@ aliasctl(maxret $omr);
echo Checked $#list assigns matching $*;
xdebug $oxd;
};
#
# Faster version. Tells you whether there's an error, not where it is.
#
alias.ttt assign.qcheck {
@ :oxd = xdebug(dword);
xdebug dword;
@ :omr = aliasctl(maxret 0);
@ :list = aliasctl(assign pmatch "\\[$*\\]");
@ :status = uniq($list) == sort($list) ? [passed] : [failed];
@ aliasctl(maxret $omr);
echo Checked $#list assigns matching $*: $status;
xdebug $oxd;
};
#
# Dump all assigns with name matching the given masks.
#
alias.tt assign.dump {
@ :oxd = xdebug(dword);
xdebug dword;
@ :list = aliasctl(assign pmatch "\\[$*\\]");
fe ($list) e {
echo [$aliasctl(assign getpackage $e)] $e$chr(9)$aliasctl(assign get $e);
};
@ list = #list;
xdebug $oxd;
if (functioncall()) {
return $list;
} else {
echo Dumped $list matching $*;
};
};
#
# Dump all assigns with name matching the first arg and
# contents matching the rest.
#
alias.tt assign.grep (args) {
@ :oxd = xdebug(dword);
xdebug dword;
@ :list = aliasctl(assign pmatch "\\[$shift(args)\\]");
fe ($list) e {
if (aliasctl(assign get $e) =~ args) {
echo [$aliasctl(assign getpackage $e)] $e$chr(9)$aliasctl(assign get $e);
};
};
@ list = #list;
xdebug $oxd;
if (functioncall()) {
return $list;
} else {
echo Dumped $list matching $*;
};
};
#
# Delete and reassign all matching vars. Theoretically, this is a no-op,
# however, alias.pack will destroy the arg lists of the alias.
#
alias.tt assign.pack {
@ :oxd = xdebug(dword);
xdebug dword;
do {
@ :list = aliasctl(assign $start pmatch "\\[$*\\]");
fe ($list) foo {
@ :baz = aliasctl(assign getpackage $foo);
@ aliasctl(assign set $foo $aliasctl(assign get $foo));
@ aliasctl(assign setpackage $foo $baz);
};
@ list = #list;
if (functioncall()) {
return $list;
} elsif (isdisplaying()) {
echo Packed $list matching $*;
};
} while (list && (:start += aliasctl(maxret)));
xdebug $oxd;
};
#
# Delete all matching vars.
#
alias.tt assign.purge {
if (functioncall()) {
@ :list = aliasctl(assign pmatch "\\[$*\\]");
@ :list = revw($list);
fe ($list) bar {^assign -$bar};
return $#list;
} else {
@ :oxd = xdebug(dword);
xdebug dword;
do {
@ :list = assign.purge($*);
if (isdisplaying()) {
echo Purged $list matching $*;
};
} while (list && list == aliasctl(maxret));
xdebug $oxd;
};
};
#
# Write matching assigns to a file which can then be /load'ed. Any arg lists
# in the original definition won't be saved by alias.save.
#
alias.tt assign.save {
@ :pkg = rand(0);
@ :fh = open($0 W);
@ :start = [];
@ :oxd = xdebug(dword);
xdebug dword;
do {
@ :list = aliasctl(assign $start pmatch "\\[$1-\\]");
fe list foo {
if (pkg != aliasctl(assign getpackage $foo)) {
@ write($fh PACKAGE ${pkg=aliasctl(assign getpackage $foo)});
};
@ write($fh assign $foo $sar(g/\{/\\\{/$sar(g/\}/\\\}/$aliasctl(assign get $foo))));
@ foo = 0;
};
if (functioncall()) {
break;
} elsif (isdisplaying()) {
echo Wrote $#list matching $1-;
};
@ :start += aliasctl(maxret);
} while (#list && start);
@ close($fh);
xdebug $oxd;
return $#list;
};
#
# As for .save, but write a $decode() encoded file which won't be
# damaged by certain variable contents.
#
alias.tt assign.esave {
@ :pkg = rand(0);
@ :fh = open($0 W);
@ :start = [];
@ :oxd = xdebug(dword);
xdebug dword;
do {
@ :list = aliasctl(assign $start pmatch "\\[$1-\\]");
fe list foo {
if (pkg != aliasctl(assign getpackage $foo)) {
@ write($fh PACKAGE ${pkg=aliasctl(assign getpackage $foo)});
};
@ write($fh @aliasctl\(assign set $foo \$decode\($encode($aliasctl(assign get $foo))\)\));
@ foo = 0;
};
if (functioncall()) {
break;
} elsif (isdisplaying()) {
echo Wrote $#list matching $1-;
};
@ :start += aliasctl(maxret);
} while (#list && start);
@ close($fh);
xdebug $oxd;
return $#list;
};
#
# Save the data, then delete it. Repeat until no more data exists.
# The reason the procedure is repeated is because of the aforementioned
# potential bug that .check checks for.
#
alias.tt assign.flush {
do {
@ :bar = assign.save($*);
@ :bar = assign.purge($1-);
echo Flushed $bar matching $1-;
} while (foo != (:foo = bar) || (foo && foo == aliasctl(maxret)));
};
#
# As above but use .esave.
#
alias.tt assign.eflush {
do {
@ :bar = assign.esave($*);
@ :bar = assign.purge($1-);
echo Flushed $bar matching $1-;
} while (foo != (:foo = bar) || (foo && foo == aliasctl(maxret)));
};
#
# End of /assign.* functions.
#
stack pop alias alias.tt;
stack pop alias alias.ttt;
#
# struct functions.
#
#
# Recursively erase a structure.
#
alias struct.purge {
fe ($*) foo {
^assign -$foo;
};
return ${struct.purgesub($*)+#};
};
#
# Continued.
# The third sub-loop does what the first does and should never be entered.
# It's there for company.
#
alias struct.purgesub {
fe ($*) foo {
@ :bar = aliasctl(assign match ${foo}.);
@ :bar = revw($bar);
@ :hit += #bar;
fe ($bar) baz {
^assign -$baz;
};
foreach $foo bar {
@ hit += struct.purgesub(${foo}.${bar});
};
foreach $foo bar {
^assign -${foo}.${bar};
};
};
return ${0+hit};
};
#
# Save a structure, like array.save.
#
alias struct.savefn {
@ :fd = open($0 w);
@ :hit = struct.savefd($fd $1-);
@ close($fd);
return $hit;
};
#
# Continued. Save to an FD.
#
alias struct.savefd {
@:fd=[$0];
fe ($1-) foo {
if (strlen($($foo))) {
@ write($fd assign $foo $sar(g/\{/\\\{/$sar(g/\}/\\\}/$aliasctl(assign get $foo))));
@ :hit = 1;
} else {
@ :hit = 0;
};
foreach $foo bar {
@ hit += struct.savefd($fd ${foo}.${bar});
};
};
return $hit;
};
#
# Some basic /assign handling functions.
#
# /assign.uniq won't work without the functions and data_array scripts. You need to load those manually.
#
alias assign.add (var,val) {assign $var $uniq($($var) $val);};
alias assign.addn (var,val) {assign $var $revw($uniq($revw($($var) $val)));};
alias assign.ifnul {if ([]==[$($0)]){assign $*};};
alias assign.filter {fe ($uniq($aliasctl(assign pmatch "\\[$split(, $0)\\]"))) foo {assign $foo $filter("\\[$1-\\]" $($foo))};};
alias assign.uniq (args) {
bless;
@ :num = isnumber(b10 $args) ? shift(args) : 1;
@ delarray(assign.uniq);
fe ($args) var {
@ :vars = replace(\$varx x $jot(1 $num));
fe ($($var)) $replace(varx x $jot(1 $num)) {
eval setuniqitem assign.uniq $vars;
};
assign $var $getandmitems(assign.uniq *);
};
};
|