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 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <fset.h>
include <chars.h>
# Debug the ENVIRON environment list package. The following definitions are
# from the header of "environ.x" and are used by envdebug to examine the
# environment list data structures; these should be compared to the defs in
# environ.x to make sure they agree. Use of a header file is not warranted
# since we really do not want the environ.x data structures known outside
# the package.
task get = t_get,
put = t_put,
list = t_list,
mark = t_mark,
free = t_free,
debug = t_debug,
spawn = t_spawn,
edit = t_edit,
tty = t_tty,
urlget = t_urlget
# Strings may optionally be quoted in SET stmts with either ' or ".
define IS_QUOTE ($1 == '\'' || $1 == '"')
# Size limiting definitions.
define NTHREADS 100 # number of hash threads
define HASH_FACTOR 1637 # divisor for hash function
define NHASHCHARS 6 # no. chars used for hashing
define LEN_ENVBUF 1500 # storage for environment list
define INC_ENVBUF 500 # increment if overflow occurs
define MAX_SZKEY 32 # max chars in a key
define MAX_SZVALUE 80 # max chars in value string
define MAX_LENLISTELEM (3+(MAX_SZKEY+1+MAX_SZVALUE+1+SZ_SHORT-1)/SZ_SHORT)
define SZ_BUF 8192 # http response buffer
# List element structure, stored in ENVBUF, which is allocated as an array of
# type SHORT integer. Each list element is aligned on a short integer boundary
# within the array. E_NEXT points to the next element in a thread, whereas
# E_LASTELEM points to the last element in the envbuf (which is a stack).
define E_NEXT Mems[$1] # next element in thread (list)
define E_LASTELEM Mems[$1+1] # next element in envbuf
define E_REDEF Mems[$1+2] # set if element is redefined
define E_SETP P2C($1+3) # char pointer to name field
define E_SET Memc[E_SETP($1)] # "name=value" string
define E_SETOFFSET 3
# GET -- Lookup the definition of an environment variable.
procedure t_get()
char name[SZ_FNAME]
char value[SZ_LINE]
int envgets()
begin
call clgstr ("name", name, SZ_FNAME)
if (envgets (name, value, SZ_LINE) <= 0) {
call printf ("%s not found\n")
call pargstr (name)
} else {
call printf ("%s = %s\n")
call pargstr (name)
call pargstr (value)
}
end
# PUT -- Enter a new environment variable or list of variables into the
# environment list. Enter "stmt: set name=value" to enter a single variable,
# or "stmt: set @filename" to process set statements from a file.
procedure t_put()
char stmt[SZ_LINE]
int envscan()
begin
call clgstr ("statement", stmt, SZ_LINE)
call printf ("%d set statements processed\n")
call pargi (envscan (stmt))
end
# LIST -- Print the environment list.
procedure t_list()
bool clgetb()
int btoi()
begin
call envlist (STDOUT, " ", btoi (clgetb ("show_redefs")))
end
# MARK -- Mark the end of the environment list for later restoration by
# the FREE task.
procedure t_mark()
int top
common /xxx/ top
begin
call envmark (top)
call printf ("top = %d\n")
call pargi (top)
end
# FREE -- Free the environment list back to the last position marked.
procedure t_free()
int top
int envfree()
common /xxx/ top
begin
call printf ("free uncovers %d redefs\n")
call pargi (envfree (top, 0))
end
# DEBUG -- Print the internal data structures (the hash table) of the
# environment list package.
procedure t_debug()
begin
call envdebug (STDOUT)
end
# ENVDEBUG -- Print the contents of the environment list data structures for
# debugging the code.
procedure envdebug (fd)
int fd # output file
int i, t, head
pointer el, ep
include "environ.com"
begin
call fprintf (fd, "envbuf at %d, len %d, last=%d, top=%d, %d%% full\n")
call pargi (envbuf)
call pargi (len_envbuf)
call pargi (last)
call pargi (top)
call pargr (real(top) / real(len_envbuf) * 100.0)
for (t=1; t <= NTHREADS; t=t+1) {
call fprintf (fd, "%6d"); call pargi (t)
head = threads[t]
if (head != NULL)
for (i=head; i != NULL; i=E_NEXT(el)) {
el = envbuf + i
call putci (fd, ' ')
for (ep=E_SETP(el); Memc[ep] != '='; ep=ep+1)
call putc (fd, Memc[ep])
}
call putci (fd, '\n')
}
end
# SPAWN -- Spawn a connected subprocess. Used to test process control and
# interprocess communication.
procedure t_spawn()
char process[SZ_FNAME]
char lbuf[SZ_LINE]
int in, out, pid
int prgetline(), propen(), prclose(), strmatch()
define done_ 91
begin
call clgstr ("process", process, SZ_FNAME)
pid = propen (process, in, out)
call putline (STDERR, "-> ")
call flush (STDERR)
while (prgetline (STDIN, lbuf) != EOF) {
if (strmatch (lbuf, "^bye") > 0)
break
else {
call putline (out, lbuf)
call flush (out)
}
while (prgetline (in, lbuf) != EOF) {
call putline (STDERR, lbuf)
if (strmatch (lbuf, "^bye") > 0)
break
else {
call putline (STDERR, ">> ")
call flush (STDERR)
if (prgetline (STDIN, lbuf) == EOF)
goto done_
call putline (out, lbuf)
}
call flush (STDERR)
call flush (out)
}
call putline (STDERR, "------------\n")
call putline (STDERR, "-> ")
call flush (STDERR)
}
done_
call putline (STDERR, "\n")
call eprintf ("termination code %d\n")
call pargi (prclose (pid))
end
# EDIT -- Test raw mode to a terminal.
procedure t_edit()
char lbuf[SZ_LINE], temp[SZ_LINE], ch
int i, stdline
char getchar()
int envgets(), ttygeti()
pointer tty, ttyodes()
define accum_ 91
define done_ 92
begin
# Set terminal to raw mode.
call fseti (STDIN, F_RAW, YES)
# Open termcap for terminal.
if (envgets ("terminal", lbuf, SZ_LINE) <= 0)
call strcpy ("vt100", lbuf, SZ_LINE)
tty = ttyodes (lbuf)
stdline = ttygeti (tty, "li")
# Edit loop. The variable I is the character position within the
# line. Start out in insert mode, with line displayed at bottom
# of terminal screen.
lbuf[1] = EOS
i = 1
call ttygoto (STDOUT, tty, 1, stdline)
call flush (STDOUT)
goto accum_
while (getchar (ch) != EOF) {
switch (ch) {
case 'h':
# Move left one column.
if (i <= 1)
call putci (STDOUT, BEL)
else {
call putci (STDOUT, BS)
i = i - 1
}
case 'l':
# Move right one column.
if (lbuf[i+1] == EOS)
call putci (STDOUT, BEL)
else {
call putc (STDOUT, lbuf[i])
i = i + 1
}
case 'x':
# Delete a character.
call strcpy (lbuf[i+1], lbuf[i], SZ_LINE-i+1)
call putline (STDOUT, lbuf[i])
call putci (STDOUT, BLANK)
call ttygoto (STDOUT, tty, i, STDLINE)
if (i > 1 && lbuf[i] == EOS) {
call putci (STDOUT, BS)
i = i - 1
}
case 'i':
# Insert a character.
accum_
while (getchar (ch) != ESC) {
call putc (STDOUT, ch)
if (ch == '\r')
goto done_
# Insert char in line buffer.
call strcpy (lbuf[i], temp, SZ_LINE)
lbuf[i] = ch
i = i + 1
call strcpy (temp, lbuf[i], SZ_LINE-i+1)
# Redraw right portion of line.
call putline (STDOUT, lbuf[i])
call ttygoto (STDOUT, tty, i, STDLINE)
call flush (STDOUT)
}
if (i > 1) {
call putci (STDOUT, BS)
i = i - 1
}
case '\f':
# Redraw line.
call printf ("\r%s")
call pargstr (lbuf)
call ttygoto (STDOUT, tty, i, STDLINE)
case '\r':
break
default:
call putci (STDOUT, BEL)
}
call flush (STDOUT)
}
done_
call fseti (STDIN, F_RAW, NO)
call putci (STDOUT, '\n')
call ttycdes (tty)
end
# TTY -- Test direct terminal i/o.
procedure t_tty()
int in, out, ch
int ttopen(), getci()
bool clgetb()
begin
if (clgetb ("dualstreams")) {
in = ttopen ("dev$tty", READ_ONLY)
out = ttopen ("dev$tty", WRITE_ONLY)
} else {
in = ttopen ("dev$tty", READ_WRITE) # NOT SUPPORTED
out = in
}
call fseti (in, F_RAW, YES)
while (getci (in, ch) > 0) {
call fprintf (out, "%c\r\n")
call pargi (ch)
call flush (out)
if (ch == EOFCHAR)
break
}
if (in == out)
call close (in)
else {
call close (out)
call close (in)
}
end
# URL_GET -- Do an HTTP GET of a URL
procedure t_urlget ()
pointer reply
char url[SZ_LINE], fname[SZ_FNAME]
bool hdr
int nread
int url_get()
begin
call clgstr ("url", url, SZ_LINE) # get the parameters
call clgstr ("fname", fname, SZ_FNAME)
hdr = clgetb ("hdr")
call calloc (reply, SZ_BUF, TY_CHAR)
nread = url_get (url, fname, reply)
call eprintf ("File '%s', downloaded %d bytes.\n")
call pargstr (fname)
call pargi (nread)
if (hdr)
call eprintf (Memc[reply])
call mfree (reply, TY_CHAR)
end
|