home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume23 / abc / part07 < prev    next >
Text File  |  1991-01-08  |  55KB  |  1,819 lines

  1. Subject:  v23i086:  ABC interactive programming environment, Part07/25
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: d3fb3d1f f1ec7d0d bf88903f f25840a8
  5.  
  6. Submitted-by: Steven Pemberton <steven@cwi.nl>
  7. Posting-number: Volume 23, Issue 86
  8. Archive-name: abc/part07
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  abc/abc.hlp abc/bint2/i2gen.c abc/bint3/i3bws.c
  17. #   abc/ex/try/position.abc
  18. # Wrapped by rsalz@litchi.bbn.com on Mon Dec 17 13:27:57 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. echo If this archive is complete, you will see the following message:
  21. echo '          "shar: End of archive 7 (of 25)."'
  22. if test -f 'abc/abc.hlp' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'abc/abc.hlp'\"
  24. else
  25.   echo shar: Extracting \"'abc/abc.hlp'\" \(20503 characters\)
  26.   sed "s/^X//" >'abc/abc.hlp' <<'END_OF_FILE'
  27. XSUMMARY OF SPECIAL ACTIONS
  28. X
  29. X  :name   Visit how-to called 'name'
  30. X  :       Visit last how-to refered to
  31. X  ::      Display headings of how-to's in this workspace
  32. X
  33. X  =name   Visit contents of location
  34. X  =       Visit last location visited
  35. X  ==      Display names of permament locations in this workspace
  36. X
  37. X  >name   Visit workspace 'name'
  38. X  >       Visit last workspace visited
  39. X  >>      Display list of workspace names
  40. X
  41. X  QUIT    Leave ABC
  42. X
  43. XSUMMARY OF EDITING OPERATIONS
  44. X
  45. X  Name      Default Keys*    Short description
  46. X
  47. X  Accept    [TAB]            Accept suggestion, focus to hole or end of line
  48. X  Return    [RETURN]         Add line or decrease indentation
  49. X
  50. X  Widen     f1, [ESC] w      Widen focus
  51. X  Extend    f2, [ESC] e      Extend focus (usually to the right)
  52. X  First     f3, [ESC] f      Move focus to first contained item
  53. X  Last      f4, [ESC] l      Move focus to last contained item
  54. X
  55. X  Previous  f5, [ESC] p      Move focus to previous item
  56. X  Next      f6, [ESC] n      Move focus to next item
  57. X  Upline    f7, [ESC] u      Move focus to whole line above
  58. X  Downline  f8, [ESC] d      Move focus to whole line below
  59. X
  60. X  Up        ^, [ESC] U       Make new hole, move up
  61. X  Down      v, [ESC] D       Make new hole, move down
  62. X  Left      <-, [ESC] ,      Make new hole, move left
  63. X  Right     ->, [ESC] .      Make new hole, move right
  64. X
  65. X  Goto      [ctrl-G], mouseclick  New focus at cursor position
  66. X
  67. X  Undo      [BACKSPACE]      Undo effect of last key pressed (may be repeated)
  68. X  Redo      [ctrl-U]         Redo last UNDOne key (may be repeated)
  69. X
  70. X  Copy      f9, [ctrl-C], [ESC]c  Copy buffer to hole, or focus to buffer
  71. X  Delete    [ctrl-D]         Delete contents of focus (to buffer if empty)
  72. X
  73. X  Record    [ctrl-R]         Start/stop recording keystrokes
  74. X  Play      [ctrl-P]         Play back recorded keystrokes
  75. X
  76. X  Look      [ctrl-L]         Redisplay screen
  77. X  Help      f10, [ESC]?      Print summary of editing operations
  78. X
  79. X  Exit      [ctrl-X]         Finish changes or execute command
  80. X  Interrupt (as set by 'stty')Interrupt command execution
  81. X  Suspend (as set by 'stty') Suspend ABC (only for shell with job control)
  82. X
  83. X  * Notes:
  84. X
  85. X  [Ctrl-D] means: hold the [CTRL] (or [CONTROL]) key down while pressing d.
  86. X  [ESC] w means: press the [ESC] key first, then w.
  87. X
  88. XABC QUICK REFERENCE
  89. X
  90. X  COMMANDS
  91. X
  92. X  WRITE expr                    Write to screen;
  93. X                                / before or after expr gives new line
  94. X  READ address EG expr          Read expression from terminal to address;
  95. X                                expr is example
  96. X  READ address RAW              Read line of text
  97. X  PUT expr IN address           Put value of expr in address
  98. X  SET RANDOM expr               Start random sequence for random and choice
  99. X  REMOVE expr FROM list         Remove one element from list
  100. X  INSERT expr IN list           Insert in right place
  101. X  DELETE address                Delete permanent location or table entry
  102. X  PASS                          Do nothing
  103. X  KEYWORD expr KEYWORD ...      Execute user-defined command
  104. X  KEYWORD                       Execute refined command
  105. X
  106. X  CHECK test                    Check test and stop if it fails
  107. X  IF test:                      If test succeeds, execute commands;
  108. X     commands                       no ELSE allowed
  109. X  SELECT:                       Select one alternative:
  110. X      test: commands                 try each test in order
  111. X      ...                            (one must succeed;
  112. X      test: commands                 the last test may be ELSE)
  113. X  WHILE test:                   As long as test succeeds
  114. X     commands                       execute commands
  115. X  FOR name,... IN train:        Take each element of train in turn
  116. X     commands
  117. X
  118. X  HOW-TO's
  119. X
  120. X  HOW TO KEYWORD ...:           Define new command KEYWORD ...
  121. X     commands
  122. X  HOW TO RETURN f:              Define new function f with no arguments
  123. X     commands                      (returns a value)
  124. X  HOW TO RETURN f x:            Define new function f with one argument
  125. X     commands
  126. X  HOW TO RETURN x f y:          Define new function f with two arguments
  127. X     commands
  128. X  HOW TO REPORT pr:             Define new predicate pr with no arguments
  129. X     commands                      (succeeds/fails)
  130. X  HOW TO REPORT pr x:           Define new predicate pr with one argument
  131. X     commands
  132. X  HOW TO REPORT x pr y:         Define new predicate pr with two arguments
  133. X     commands
  134. X
  135. X  SHARE name,...                Share permanent locations
  136. X                                (before commands of how-to)
  137. X
  138. X  Refinements (after the commands of a how-to)
  139. X
  140. X  KEYWORD : commands            Define command refinement
  141. X  name: commands                Define expression- or test-refinement
  142. X
  143. X  Terminating commands
  144. X
  145. X  QUIT                          Leave command how-to or command refinement,
  146. X                                or leave ABC
  147. X  RETURN expr                   Leave function how-to or expression refinement,
  148. X                                return value of expr
  149. X  REPORT test                   Leave predicate how-to or test-refinement,
  150. X                                report outcome of test
  151. X  SUCCEED                       The same, report success
  152. X  FAIL                          The same, report failure
  153. X
  154. X  EXPRESSIONS AND ADDRESSES
  155. X
  156. X  666, 3.14, 3.14e-9            Exact constants
  157. X
  158. X  expr,expr,...                 Compound
  159. X  name,name,...                 Naming (may also be used as address)
  160. X
  161. X  text@p                        "ABCD"@2 = "BCD" (also address)
  162. X  text|q                        "ABCD"|3 = "ABC" (also address)
  163. X  text@p|q                      "ABCD"@2|1 = "BCD"|1 = "B"
  164. X
  165. X  table[expr]                   Table selection (also address)
  166. X
  167. X  "Jan", 'Feb', 'Won''t!'       Textual displays (empty: "" or '')
  168. X  "value = `expr`;"             Conversion of expr to text
  169. X
  170. X  {1; 2; 2; ...}                List display (empty: {})
  171. X  {1..9; ...}, {"a".."z"; ...}  List of consecutive values
  172. X
  173. X  {["Jan"]: 1; ["Feb"]: 2; ...} Table display (empty: {})
  174. X
  175. X  f, f x, x f y                 Result of function f (no permanent effects)
  176. X  name                          Result of refinement (no permanent effects)
  177. X
  178. X  TESTS
  179. X
  180. X  x < y, x <= y, x >= y, x > y  Order tests
  181. X  x = y, x <> y                      (<> means 'not equals')
  182. X  0 <= d < 10
  183. X
  184. X  pr, pr x, x pr y              Outcome of predicate pr (no permanent effects)
  185. X  name                          Outcome of refinement (no permanent effects)
  186. X
  187. X  test AND test AND ...         Fails as soon as one of the tests fails
  188. X  test OR test OR ...           Succeeds as soon as one of the tests succeeds
  189. X  NOT test
  190. X
  191. X  SOME name,... IN train HAS test
  192. X                                Sets name, ... on success
  193. X  EACH name,... IN train HAS test
  194. X                                Sets name, ... on failure
  195. X  NO   name,... IN train HAS test
  196. X                                Sets name, ... on failure
  197. X
  198. X  PREDEFINED FUNCTIONS AND PREDICATES
  199. X
  200. X  Functions and predicates on numbers
  201. X
  202. X  ~x                            Approximate value of x
  203. X  exactly x                     Exact value of x
  204. X  exact x                       Test if x is exact
  205. X  +x, x+y, x-y, -x, x*y, x/y    Plain arithmetic
  206. X  x**y                          x raised to the power y
  207. X  root x, n root x              Square root, n-th root
  208. X  abs x, sign x                 Absolute value, sign (= -1, 0, or +1)
  209. X  round x, floor x, ceiling x   Rounded to whole number
  210. X  n round x                     x rounded to n digits after decimal point
  211. X  a mod n                       Remainder of a on division by n
  212. X  */x                           Numerator of exact number x
  213. X  /*x                           Denominator
  214. X  random                        Random approximate number r, 0 <= r < 1
  215. X  e, exp x                      Base of natural logarithm, exponential function
  216. X  log x, b log x                Natural logarithm, logarithm to the base b
  217. X  pi, sin x, cos x, tan x, arctan x
  218. X                                Trigonometric functions, with x in radians
  219. X  angle (x, y), radius (x, y)   Angle of and radius to point (x, y)
  220. X  c sin x, c cos x, c tan x     Similar, with the circle divided into c parts
  221. X  c arctan x, c angle (x, y)        (e.g. 360 for degrees)
  222. X  now                           e.g. (1999, 12, 31, 23, 59, 59.999)
  223. X
  224. X  Functions on texts
  225. X
  226. X  t^u                           t and u joined into one text
  227. X  t^^n                          t repeated n times
  228. X  lower t                       lower "aBc" = "abc"
  229. X  upper t                       upper "aBc" = "ABC"
  230. X  stripped t                    Strip leading and trailing spaces from t
  231. X  split t                       Split text t into words
  232. X
  233. X  Function on tables
  234. X
  235. X  keys table                    List of all keys in table
  236. X
  237. X  Functions and predicates on trains
  238. X
  239. X  #train                        Number of elements in train
  240. X  e#train                       Number of elements equal to e
  241. X  e in train, e not.in train    Test for presence or absence
  242. X  min train                     Smallest element of train
  243. X  e min train                   Smallest element larger than e
  244. X  max train, e max train        Largest element
  245. X  train item n                  n-th element
  246. X  choice train                  Random element
  247. X
  248. X  Functions on all types
  249. X
  250. X  x<<n                          x converted to text, aligned left in width n
  251. X  x><n                          The same, centred
  252. X  x>>n                          The same, aligned right
  253. X
  254. X  THE CHARACTERS
  255. X
  256. X   !"#$%&'()*+,-./              This is the order of all characters
  257. X  0123456789:;<=>?              that may occur in a text.
  258. X  @ABCDEFGHIJKLMNO              (The first is a space.)
  259. X  PQRSTUVWXYZ[\]^_
  260. X  `abcdefghijklmno
  261. X  pqrstuvwxyz{|}~
  262. XABC MANUAL
  263. X
  264. XNAME
  265. X  abc - ABC interpreter & environment
  266. X  abckeys - change key bindings for 'abc'
  267. X
  268. XSYNOPSIS
  269. X  abc    [workspace and editor options]  [file ...]
  270. X  abc    [workspace and task options]
  271. X  abckeys
  272. X
  273. XDESCRIPTION
  274. X  Without options or files, the ABC interpreter is started, using the ABC
  275. X  editor, in the last workspace used or in workspace 'first' if this is
  276. X  your first abc session.  A workspace is kept as a group of files in a
  277. X  directory, with separate files for each how-to and location.  The
  278. X  workspace directories themselves are kept by default in the directory
  279. X  $HOME/abc.  On non-Unix machines, $HOME is the disk you are working on.
  280. X
  281. X  Workspace Options:
  282. X
  283. X  -W dir        use group of workspaces in 'dir' instead of $HOME/abc.
  284. X
  285. X  -w name       start in workspace 'name' instead of last workspace used.
  286. X
  287. X  -w path       use 'path' as workspace (no -W option allowed).
  288. X
  289. X  Editor option:
  290. X
  291. X  -e            Use $EDITOR as editor to edit definitions, instead of ABC
  292. X                editor (Unix only).
  293. X
  294. X  file ...      Read commands from file(s) instead of from standard input;
  295. X                input for READ commands is taken from standard input.  If a
  296. X                file is called '-' and standard input is the keyboard, the
  297. X                ABC system is started up interactively for that entry.
  298. X
  299. X  Special tasks:
  300. X
  301. X  -i tab        Fill table 'tab' with text lines from standard input
  302. X
  303. X  -o tab        Write text lines from table 'tab' to standard output
  304. X
  305. X  -l            List the how-to's in workspace on standard output
  306. X
  307. X  -r            Recover a workspace when its index is lost: useful after a
  308. X                machine crash if the ABC internal administration files
  309. X                didn't get written out.
  310. X
  311. X  -R            Recover the index of a group of workspaces
  312. X
  313. XUSAGE
  314. X  (This is necessarily a very brief description; see 'The ABC Programmer's
  315. X  Handbook' for full details.)
  316. X
  317. X  Use 'QUIT' to finish an ABC session.
  318. X
  319. X  When ABC starts up interactively, it displays a prompt and awaits input.
  320. X
  321. X  TYPING AND SUGGESTIONS: as you type, the system tries to suggest a
  322. X  possible continuation for what you have typed; to accept the suggestion,
  323. X  press [accept] (by default this is bound to the [TAB] key; type '?' to
  324. X  find out the bindings for the keyboard you are using).  If you don't want
  325. X  to accept the suggestion, just carry on typing (you can always type
  326. X  character for character, ignoring the suggestions).  Usually the system
  327. X  knows where a letter must be capital and where not, and you usually don't
  328. X  have to use the shift key; however, in the few places where both a
  329. X  lower-case and an upper-case letter would be legal (for instance for
  330. X  AND), you have to type the letter upper-case.
  331. X
  332. X  When you type a control command, like WHILE, the system provides
  333. X  indentation automatically for the body of the command; to reduce the
  334. X  indentation one level, type [return].
  335. X
  336. X  CORRECTING AND EDITING: the [undo] key (by default bound to backspace)
  337. X  undoes the last key you typed.  Repeatedly typing it undoes more and
  338. X  more, up to a certain maximum number of keypresses.
  339. X
  340. X  To correct other parts, you must put the 'focus' onto the part you want
  341. X  to change.  The focus is displayed by underlining or reverse video.
  342. X  [Widen] and [extend] make the focus larger, [first] and [last] make it
  343. X  smaller.
  344. X
  345. X  [Delete] deletes the contents of the focus.
  346. X
  347. X  [Copy] copies the contents of the focus to a buffer, or if the focus is
  348. X  not focussed on anything, copies the contents of the buffer back to where
  349. X  you are positioned.
  350. X
  351. X  MOVING THE FOCUS: [Upline] and [downline] focus on one line above or
  352. X  below.  [Previous] and [next] move the focus left and right.  [Up],
  353. X  [down], [left], and [right] move an empty focus around.  [Goto] widens
  354. X  the focus to the largest thing at the current position.
  355. X
  356. X  OTHER OPERATIONS: [Look] redraws the screen; [record] records all
  357. X  keystrokes until the next time you press [record] - [play] replays them.
  358. X  [Redo] redoes the last key(s) undone; [interrupt] interrupts a running
  359. X  command.
  360. X
  361. X  WORKSPACES: To create a new workspace, or go to an existing workspace,
  362. X  type '>name'.  To go to the last workspace you were in, type a single
  363. X  '>'.  To get a list of workspace names, type '>>'.
  364. X
  365. X  HOW-TO's: To create a new how-to, just type the first line of the how-to.
  366. X  This creates the new how-to, and allows you to type the body.  Use [exit]
  367. X  to finish it (by default [ESC][ESC]).
  368. X
  369. X  To visit a how-to, type a colon, followed by the name of the how-to.
  370. X  Again, use [exit] to exit.  To visit the last how-to again, or the last
  371. X  how-to you got an error message for, type a single ':'.  To get a list of
  372. X  the how-to's in this workspace, type '::'.
  373. X
  374. X  To edit a location, type a '=' followed by the name of the location.  To
  375. X  re-edit it, type a single '='.  To get a list of the locations in the
  376. X  workspace, type '=='.
  377. X
  378. XKEY BINDINGS
  379. X  The binding of editing operations like [accept] to keys may be different
  380. X  for your keyboard; type a '?' at the prompt to find out what the bindings
  381. X  are for your keyboard.
  382. X  To redefine the keys used for editor operations, run 'abckeys'.  This
  383. X  produces a private key definitions file.  You will be given instructions
  384. X  on how to use it.
  385. X  Keys labeled f1...f8 are function keys. On Unix, the way to type these is
  386. X  terminal-dependent.  The codes they send must be defined by the termcap
  387. X  entry for your terminal.
  388. X  If a terminal has arrow keys which transmit codes to the computer, these
  389. X  should be used for Up, Down, Left and Right.  Again, the termcap entry
  390. X  must define the codes.
  391. X  The Goto operation is of most use if the cursor can be moved locally at
  392. X  the terminal, or if the terminal has a mouse; the Goto operation will
  393. X  sense the terminal for the cursor or mouse position.  On Unix, we use two
  394. X  extra non-standard termcap capabilities for this: 'sp' which gives the
  395. X  string that must be sent to the terminal to sense the cursor position,
  396. X  and 'cp' which defines the format of the reply (in the same format as
  397. X  other cursor-addressing strings in termcap).  If your terminal's mouse-
  398. X  click sends the position of the click automatically, just set 'sp' to the
  399. X  empty string.  See termcap(5) for more details.
  400. X
  401. XFILES
  402. X  $HOME/copybuf.abc        copy buffer between sessions
  403. X  $HOME/abc/wsgroup.abc    table mapping workspace names to directory names
  404. X  $HOME/abc/abckeys_$TERM  private key definitions file (Unix only)
  405. X  $HOME/abc/abc.key        private key definitions file (non-Unix)
  406. X  position.abc             focus position of edited how-to's in workspace
  407. X  perm.abc                 table mapping object names to file names
  408. X  suggest.abc              suggestion list for user-defined commands
  409. X  types.abc                table with codes for typechecking between how-to's
  410. X  *.cmd                    command how-to's in this workspace
  411. X  *.zfd, *.mfd, *.dfd      function how-to's in this workspace
  412. X  *.zpd, *.mpd, *.dpd      predicate how-to's in this workspace
  413. X  *.cts                    permanent locations in this workspace
  414. X  abc.msg                  messages file, used for errors (not on Macintosh)
  415. X  abc.hlp                  helpfile with this text (MacABC.help on Macintosh)
  416. X
  417. X  The latter two are searched for first in your startup directory, then in
  418. X  $HOME/abc, and finally, on Unix, in a directory determined by the
  419. X  installer of ABC.  On the IBM PC and Atari ST the directories in your
  420. X  $PATH are used in the last stage (if you have a hard disk place these
  421. X  files in the workspaces directory abc).
  422. X
  423. XATARI ST IMPLEMENTATION
  424. X  There are four files supplied: the program abc.tos itself, abckeys.tos
  425. X  for changing your key bindings, the help file abc.hlp, and the error
  426. X  messages file abc.msg.  (See FILES above.)
  427. X  If you start ABC up from the desktop, and you want to use the options
  428. X  given above, like -w, you should rename abc.tos to abc.ttp.  There is an
  429. X  additional facility for redirecting input and output: the parameter
  430. X  >outfile redirects all output from ABC to the file called outfile, and
  431. X  similarly <infile takes its input from the file called infile.
  432. X
  433. XIBM PC IMPLEMENTATION
  434. X  There are four files for running ABC, the program abc.exe itself,
  435. X  abckeys.exe for changing your key bindings, the help file abc.hlp, and
  436. X  the error messages file abc.msg.  (See FILES above.)
  437. X  If your screen size is non-standard, or your machine is not 100% BIOS
  438. X  compatible (which is unusal these days), you can specify the screen-size,
  439. X  and whether to use the BIOS or ANSI.SYS for output, by typing after the
  440. X  A> prompt, before you start ABC up, one of the following:
  441. X       SET SCREEN=ANSI lines cols
  442. X       SET SCREEN=BIOS lines cols
  443. X  If you are going to use ANSI.SYS, be sure you have the line
  444. X       DEVICE=ANSI.SYS
  445. X  in your CONFIG.SYS file.  Consult the DOS manual for further details.
  446. X
  447. XAPPLE MACINTOSH IMPLEMENTATION
  448. X  There are three files supplied: MacABC, the application itself,
  449. X  MacABC.help, the help file, and MacABC.doc, a MacWrite document
  450. X  containing a variant of this text.  The help file should be in the same
  451. X  folder as MacABC, or in your System Folder.
  452. X  MacABC runs in a single window.  You'll notice that most operations are
  453. X  menu entries, as well as being possible from the keyboard.  You can start
  454. X  ABC up by double-clicking the MacABC icon in which case you start up in
  455. X  the last workspace used, or by double-clicking on any icon in a
  456. X  workspace, in which case you start in that workspace.  In this latter
  457. X  case, if the filename of the icon you clicked on ends in .cmd, that how-
  458. X  to is executed, but the how-to may not have any parameters.
  459. X  Instead of the special option flags mentioned above, most of the tasks,
  460. X  like recovering a workspace, can be done from the File menu.
  461. X  * Notes for Macintosh guru's:
  462. X  The messages are STR# resources in MacABC; you must use a resource editor
  463. X  to change them.
  464. X  MacABC uses Monaco 9 for the screen, and Courier 10 for printing.  You
  465. X  can change them with ResEdit, by editing the resource with type Conf and
  466. X  ID 0.  The horizontal and vertical window-size and the window-title can
  467. X  also be adapted there.  To facilitate this, first Paste the TMPL resource
  468. X  with ID 5189 named Conf from MacABC to (a copy of) ResEdit.  But beware,
  469. X  MacABC only works properly with Fixed-width Fonts like Monaco and
  470. X  Courier.
  471. X
  472. XSEE ALSO
  473. X  Leo Geurts, Lambert Meertens and Steven Pemberton, The ABC Programmer's
  474. X       Handbook, Prentice-Hall, Englewood Cliffs, New Jersey, 1989,
  475. X       ISBN 0-13-000027-2.
  476. X  Steven Pemberton, An Alternative Simple Language and Environment for PCs,
  477. X       IEEE Software, Vol. 4, No. 1, January 1987, pp. 56-64.
  478. X  The ABC Newsletter. Available free from CWI.
  479. X
  480. XAUTHORS
  481. X  Frank van Dijk, Leo Geurts, Timo Krijnen, Lambert Meertens, Steven
  482. X  Pemberton, Guido van Rossum.
  483. X
  484. XADDRESS
  485. X  ABC Distribution, CWI/AA, Postbox 4079, 1009 AB Amsterdam, The
  486. X  Netherlands.
  487. X  E-mail: 'abc@cwi.nl'.
  488. X
  489. END_OF_FILE
  490.   if test 20503 -ne `wc -c <'abc/abc.hlp'`; then
  491.     echo shar: \"'abc/abc.hlp'\" unpacked with wrong size!
  492.   fi
  493.   # end of 'abc/abc.hlp'
  494. fi
  495. if test -f 'abc/bint2/i2gen.c' -a "${1}" != "-c" ; then 
  496.   echo shar: Will not clobber existing file \"'abc/bint2/i2gen.c'\"
  497. else
  498.   echo shar: Extracting \"'abc/bint2/i2gen.c'\" \(19819 characters\)
  499.   sed "s/^X//" >'abc/bint2/i2gen.c' <<'END_OF_FILE'
  500. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
  501. X
  502. X/* Code generation */
  503. X
  504. X#include "b.h"
  505. X#include "bint.h"
  506. X#include "feat.h"
  507. X#include "bobj.h"
  508. X#include "i0err.h"
  509. X#include "i2nod.h"
  510. X#include "i2gen.h" /* Must be after i2nod.h */
  511. X#include "i2par.h"
  512. X#include "i3env.h"
  513. X#include "i3int.h"
  514. X#include "i3sou.h"
  515. X
  516. XVisible Procedure fix_nodes(pt, code) parsetree *pt; parsetree *code; {
  517. X    context c; value *setup(), *su;
  518. X    sv_context(&c);
  519. X    curline= *pt; curlino= one;
  520. X    su= setup(*pt);
  521. X    if (su != Pnil) analyze(*pt, su);
  522. X    if (still_ok) no_mysteries();
  523. X    curline= *pt; curlino= one;
  524. X    inithreads();
  525. X    fix(pt, su ? 'x' : 'v');
  526. X    endthreads(code);
  527. X    cleanup();
  528. X#ifdef TYPE_CHECK
  529. X    if (cntxt != In_wsgroup && cntxt != In_prmnv)
  530. X        type_check(*pt);
  531. X#endif
  532. X    set_context(&c);
  533. X}
  534. X
  535. XHidden Procedure no_mysteries() {
  536. X    value names= keys(mysteries);
  537. X    int i, n= length(names);
  538. X    for (i= 1; i <= n; ++i) {
  539. X        value name= thof(i, names);
  540. X        value f;
  541. X        if (!is_zerfun(name, &f)) {
  542. X            value *aa= envassoc(mysteries, name);
  543. X            if (locals != Vnil)
  544. X                e_replace(*aa, &locals, name);
  545. X            else
  546. X                e_replace(zero, &globals, name);
  547. X        }
  548. X    }
  549. X    release(names);
  550. X}
  551. X
  552. X/* ******************************************************************** */
  553. X
  554. X/* Utilities used by threading. */
  555. X
  556. X/* A 'threaded tree' is, in our case, a fixed(*) parse tree with extra links
  557. X   that are used by the interpreter to determine the execution order.
  558. X   __________
  559. X   (*) 'Fixed' means: processed by 'fix_nodes', which removes UNPARSED
  560. X       nodes and distinguishes TAG nodes into local, global tags etc.
  561. X       fix_nodes also creates the threads, but this is accidental, not
  562. X       essential.  For UNPARSED nodes, the threads are actually laid
  563. X       in a second pass through the subtree that was UNPARSED.
  564. X   __________
  565. X
  566. X   A small example: the parse tree for the expression  'a+b*c'  looks like
  567. X
  568. X    (DYOP,
  569. X        (TAGlocal, "a"),
  570. X        "+",
  571. X        (DYOP,
  572. X            (TAGlocal, "b"),
  573. X            "*",
  574. X            (TAGlocal, "c"))).
  575. X
  576. X   The required execution order is here:
  577. X
  578. X    1) (TAGlocal, "a")
  579. X    2) (TAGlocal, "b")
  580. X    3) (TAGlocal, "c")
  581. X    4) (DYOP, ..., "*", ...)
  582. X    5) (DYOP, ..., "+", ...)
  583. X
  584. X   Of course, the result of each operation (if it has a result) is pushed
  585. X   on a stack, and the operands are popped from this same stack.  Think of
  586. X   reversed polish notation (well-known by owners of HP pocket calculators).
  587. X
  588. X   The 'threads' are explicit links from each node to its successor in this
  589. X   execution order.  Conditional operations like IF and AND have two threads,
  590. X   one for success and one for failure.  Loops can be made by having the
  591. X   thread from the last node of the loop body point to the head of the loop.
  592. X
  593. X   Threading expressions, locations and simple-commands is easy: recursively
  594. X   thread each of the subtrees, then lay a thread from the last threaded
  595. X   to the current node.  Nodes occurring in a 'location' context are
  596. X   marked, so that the interpreter knows when to push a 'location' on
  597. X   the stack.
  598. X
  599. X   Tests and looping commands cause most of the complexity of the threading
  600. X   utilities.  The basic technique is 'backpatching'.
  601. X   Nodes that need a conditional forward jump are chained together in a
  602. X   linked list, and when their destination is reached, all nodes in the
  603. X   chain get its 'address' patched into their secondary thread.  There is
  604. X   one such chain, called 'bpchain', which at all times contains those nodes
  605. X   whose secondary destination would be the next generated instruction.
  606. X   This is used by IF, WHILE, test-suites, AND and OR.
  607. X
  608. X   To generate a loop, both this chain and the last normal instruction
  609. X   (if any) are diverted to the node where the loop continues.
  610. X
  611. X   For test-suites, we also need to be capable of jumping unconditionally
  612. X   forward (over the remainder of the SELECT-command).  This is done by
  613. X   saving both the backpatch chain and the last node visited, and restoring
  614. X   them after the remainder has been processed.
  615. X*/
  616. X
  617. X/* Implementation tricks: in order not to show circular lists to 'release',
  618. X   parse tree nodes are generated as compounds where there is room for two
  619. X   more fields than their length indicates.
  620. X*/
  621. X
  622. X#define Flag (MkSmallInt(1))
  623. X    /* Flag used to indicate Location or TestRefinement node */
  624. X
  625. XHidden parsetree start; /* First instruction.  Picked up by endthreads() */
  626. X
  627. XHidden parsetree last; /* Last visited node */
  628. X
  629. XHidden parsetree bpchain; /* Backpatch chain for conditional goto's */
  630. XHidden parsetree *wanthere; /* Chain of requests to return next tree */
  631. X
  632. X#ifdef MSDOS
  633. X#ifdef M_I86LM
  634. X
  635. X/* Patch for MSC 3.0 large model bugs... */
  636. XVisible parsetree *_thread(p) parsetree p; {
  637. X    return &_Thread(p);
  638. X}
  639. X
  640. XVisible parsetree *_thread2(p) parsetree p; {
  641. X    return &_Thread2(p);
  642. X}
  643. X
  644. X#endif /* M_I86LM */
  645. X#endif /* MSDOS */
  646. X
  647. X/* Start threading */
  648. X
  649. XHidden Procedure inithreads() {
  650. X    bpchain= NilTree;
  651. X    wanthere= 0;
  652. X    last= NilTree;
  653. X    here(&start);
  654. X}
  655. X
  656. X/* Finish threading */
  657. X
  658. XHidden Procedure endthreads(code) parsetree *code; {
  659. X    jumpto(Stop);
  660. X    if (!still_ok) start= NilTree;
  661. X    *code= start;
  662. X}
  663. X
  664. X
  665. X/* Fill 't' as secondary thread for all nodes in the backpatch chain,
  666. X   leaving the chain empty. */
  667. X
  668. XHidden Procedure backpatch(t) parsetree t; {
  669. X    parsetree u;
  670. X    while (bpchain != NilTree) {
  671. X        u= Thread2(bpchain);
  672. X        Thread2(bpchain)= t;
  673. X        bpchain= u;
  674. X    }
  675. X}
  676. X
  677. XVisible Procedure jumpto(t) parsetree t; {
  678. X    parsetree u;
  679. X    if (!still_ok) return;
  680. X    while (wanthere != 0) {
  681. X        u= *wanthere;
  682. X        *wanthere= t;
  683. X        wanthere= (parsetree*)u;
  684. X    }
  685. X    while (last != NilTree) {
  686. X        u= Thread(last);
  687. X        Thread(last)= t;
  688. X        last= u;
  689. X    }
  690. X    backpatch(t);
  691. X}
  692. X
  693. XHidden parsetree seterr(n) int n; {
  694. X    return (parsetree)MkSmallInt(n);
  695. X}
  696. X
  697. X/* Visit node 't', and set its secondary thread to 't2'. */
  698. X
  699. XHidden Procedure visit2(t, t2) parsetree t, t2; {
  700. X    if (!still_ok) return;
  701. X    jumpto(t);
  702. X    Thread2(t)= t2;
  703. X    Thread(t)= NilTree;
  704. X    last= t;
  705. X}
  706. X
  707. X/* Visit node 't' */
  708. X
  709. XHidden Procedure visit(t) parsetree t; {
  710. X    visit2(t, NilTree);
  711. X}
  712. X
  713. X/* Visit node 't' and flag it as a location (or test-refinement). */
  714. X
  715. XHidden Procedure lvisit(t) parsetree t; {
  716. X    visit2(t, Flag);
  717. X}
  718. X
  719. X#ifdef NOT_USED
  720. XHidden Procedure jumphere(t) parsetree t; {
  721. X    Thread(t)= last;
  722. X    last= t;
  723. X}
  724. X#endif
  725. X
  726. X/* Add node 't' to the backpatch chain. */
  727. X
  728. XHidden Procedure jump2here(t) parsetree t; {
  729. X    if (!still_ok) return;
  730. X    Thread2(t)= bpchain;
  731. X    bpchain= t;
  732. X}
  733. X
  734. XHidden Procedure here(pl) parsetree *pl; {
  735. X    if (!still_ok) return;
  736. X    *pl= (parsetree) wanthere;
  737. X    wanthere= pl;
  738. X}
  739. X
  740. XVisible Procedure hold(pl) struct state *pl; {
  741. X    if (!still_ok) return;
  742. X    pl->h_last= last; pl->h_bpchain= bpchain; pl->h_wanthere= wanthere;
  743. X    last= bpchain= NilTree; wanthere= 0;
  744. X}
  745. X
  746. XVisible Procedure let_go(pl) struct state *pl; {
  747. X    parsetree p, *w;
  748. X    if (!still_ok) return;
  749. X    if (last != NilTree) {
  750. X        for (p= last; Thread(p) != NilTree; p= Thread(p))
  751. X            ;
  752. X        Thread(p)= pl->h_last;
  753. X    }
  754. X    else last= pl->h_last;
  755. X    if (bpchain != NilTree) {
  756. X        for (p= bpchain; Thread2(p) != NilTree; p= Thread2(p))
  757. X            ;
  758. X        Thread2(p)= pl->h_bpchain;
  759. X    }
  760. X    else bpchain= pl->h_bpchain;
  761. X    if (wanthere) {
  762. X        for (w= wanthere; *w != 0; w= (parsetree*) *w)
  763. X            ;
  764. X        *w= (parsetree) pl->h_wanthere;
  765. X    }
  766. X    else wanthere= pl->h_wanthere;
  767. X}
  768. X
  769. XHidden bool reachable() {
  770. X    return last != NilTree || bpchain != NilTree || wanthere != 0;
  771. X}
  772. X
  773. X
  774. X/* ******************************************************************** */
  775. X/* *********************** code generation **************************** */
  776. X/* ******************************************************************** */
  777. X
  778. XForward bool is_variable();
  779. XForward bool is_cmd_ref();
  780. XForward value copydef();
  781. X
  782. XVisible Procedure fix(pt, flag) parsetree *pt; char flag; {
  783. X    struct state st; value v, function;
  784. X    parsetree t, l1= NilTree, w;
  785. X    typenode nt, nt1; string s; char c; int n, k, len;
  786. X
  787. X    t= *pt;
  788. X    if (!Is_node(t) || !still_ok) return;
  789. X    nt= Nodetype(t);
  790. X    if (nt < 0 || nt >= NTYPES) syserr(MESS(2200, "fix bad tree"));
  791. X    s= gentab[nt];
  792. X    if (s == NULL) return;
  793. X    n= First_fieldnr;
  794. X    if (flag == 'x') curline= t;
  795. X    while ((c= *s++) != '\0' && still_ok) {
  796. X        switch (c) {
  797. X        case '0':
  798. X        case '1':
  799. X        case '2':
  800. X        case '3':
  801. X        case '4':
  802. X        case '5':
  803. X        case '6':
  804. X        case '7':
  805. X        case '8':
  806. X        case '9':
  807. X            n= (c - '0') + First_fieldnr;
  808. X            break;
  809. X        case 'c':
  810. X            v= *Branch(t, n);
  811. X            if (v != Vnil) {
  812. X                len= Nfields(v);
  813. X                for (k= 0; k < len; ++k)
  814. X                    fix(Field(v, k), flag);
  815. X            }
  816. X            ++n;
  817. X            break;
  818. X        case '#':
  819. X            curlino= *Branch(t, n);
  820. X            ++n;
  821. X            break;
  822. X        case 'g':
  823. X        case 'h':
  824. X            ++n;
  825. X            break;
  826. X        case 'a':
  827. X        case 'l':
  828. X            if (flag == 'v' || flag == 't')
  829. X                c= flag;
  830. X            /* Fall through */
  831. X        case 'b':
  832. X        case 't':
  833. X        case 'u':    
  834. X        case 'v':
  835. X        case 'x':
  836. X            fix(Branch(t, n), c);
  837. X            ++n;
  838. X            break;
  839. X        case 'f':
  840. X            f_fpr_formals(*Branch(t, n));
  841. X            ++n;
  842. X            break;
  843. X
  844. X        case ':':    /* code for WHILE loop */
  845. X            curlino= *Branch(t, WHL_LINO);
  846. X            here(&l1);
  847. X            visit(t);
  848. X            fix(Branch(t, WHL_TEST), 't');
  849. X            v= *Branch(t, WHL_SUITE);
  850. X            if (nodetype((parsetree) v) != COLON_NODE)
  851. X                syserr(BAD_WHILE);
  852. X            visit(v);
  853. X            fix(Branch(v, COLON_SUITE), 'x');
  854. X            jumpto(l1);
  855. X            jump2here(v);
  856. X            break;
  857. X            
  858. X        case ';':    /* code for TEST_SUITE */
  859. X            if (*Branch(t, TSUI_TEST) == NilTree) {
  860. X                sk_tsuite_comment(t, &w);
  861. X                if (w != NilTree)
  862. X                    fix(&w, 'x');
  863. X                break;
  864. X            }
  865. X            curlino= *Branch(t, TSUI_LINO);
  866. X            visit(t);
  867. X            curline= *Branch(t, TSUI_TEST);
  868. X            fix(Branch(t, TSUI_TEST), 't');
  869. X            v= *Branch(t, TSUI_SUITE);
  870. X            if (nodetype((parsetree) v) != COLON_NODE)
  871. X                syserr(BAD_TESTSUITE);
  872. X            visit2(v, seterr(1));
  873. X            fix(Branch(v, COLON_SUITE), 'x');
  874. X            hold(&st);
  875. X            sk_tsuite_comment(t, &w);
  876. X            if (w != NilTree) {
  877. X                jump2here(v);
  878. X                fix(&w, 'x');
  879. X            }
  880. X            let_go(&st);
  881. X            break;
  882. X            
  883. X        case '?':
  884. X            if (flag == 'v')
  885. X                f_eunparsed(pt);
  886. X            else if (flag == 't')
  887. X                f_cunparsed(pt);
  888. X            else
  889. X              syserr(MESS(2201, "fix unparsed with bad flag"));
  890. X            fix(pt, flag);
  891. X            break;
  892. X        case '@':
  893. X            f_trim_target(t, '@');
  894. X            break;
  895. X        case '|':
  896. X            f_trim_target(t, '|');
  897. X            break;
  898. X        case 'C':
  899. X            v= *Branch(t, REL_LEFT);
  900. X            nt1= nodetype((parsetree) v);
  901. X            if (Comparison(nt1))
  902. X                jump2here(v);
  903. X            break;
  904. X        case 'D':
  905. X            v= (value)*Branch(t, DYA_NAME);
  906. X            if (!is_dyafun(v, &function))
  907. X                fixerrV(NO_DEFINITION, v);
  908. X            else
  909. X                *Branch(t, DYA_FCT)= copydef(function);
  910. X            break;
  911. X        case 'E':
  912. X            v= (value)*Branch(t, DYA_NAME);
  913. X            if (!is_dyaprd(v, &function))
  914. X                fixerrV(NO_DEFINITION, v);
  915. X            else
  916. X                *Branch(t, DYA_FCT)= copydef(function);
  917. X            break;
  918. X        case 'F':
  919. X            if (*Branch(t, NUM_VALUE) == Vnil) {
  920. X                *Branch(t, NUM_VALUE)=
  921. X                numconst(*Branch(t, NUM_TEXT));
  922. X            }
  923. X            break;
  924. X        case 'G':
  925. X            jumpto(l1);
  926. X            break;
  927. X        case 'H':
  928. X            here(&l1);
  929. X            break;
  930. X        case 'I':
  931. X            if (*Branch(t, n) == NilTree)
  932. X                break;
  933. X            /* Else fall through */
  934. X        case 'J':
  935. X            jump2here(t);
  936. X            break;
  937. X        case 'K':
  938. X            hold(&st);
  939. X            break;
  940. X        case 'L':
  941. X            let_go(&st);
  942. X            break;
  943. X        case 'M':
  944. X            v= (value)*Branch(t, MON_NAME);
  945. X            if (is_variable(v) || !is_monfun(v, &function))
  946. X                fixerrV(NO_DEFINITION, v);
  947. X            else
  948. X                *Branch(t, MON_FCT)= copydef(function);
  949. X            break;
  950. X        case 'N':
  951. X            v= (value)*Branch(t, MON_NAME);
  952. X            if (is_variable(v) || !is_monprd(v, &function))
  953. X                fixerrV(NO_DEFINITION, v);
  954. X            else
  955. X                *Branch(t, MON_FCT)= copydef(function);
  956. X            break;
  957. X        case 'Q':    /* don't visit comment SUITE nodes */
  958. X            if (*Branch(t, n) != NilTree)
  959. X                visit(t);
  960. X            break;
  961. X#ifdef REACH
  962. X        case 'R':
  963. X            if (*Branch(t, n) != NilTree && !reachable())
  964. X                fixerr(MESS(2202, "command cannot be reached"));
  965. X            break;
  966. X#endif
  967. X        case 'S':
  968. X            jumpto(Stop);
  969. X            break;
  970. X        case 'T':
  971. X            if (flag == 't')
  972. X                f_ctag(pt);
  973. X            else if (flag == 'v' || flag == 'x')
  974. X                f_etag(pt);
  975. X            else
  976. X                f_ttag(pt);
  977. X            break;
  978. X        case 'U':
  979. X            f_ucommand(pt);
  980. X            break;
  981. X        case 'V':
  982. X            visit(t);
  983. X            break;
  984. X        case 'X':
  985. X            if (flag == 'a' || flag == 'l' || flag == 'b')
  986. X                lvisit(t);
  987. X            else
  988. X                visit(t);
  989. X            break;
  990. X        case 'W':
  991. X/*!*/            visit2(t, seterr(1));
  992. X            break;
  993. X        case 'Y':
  994. X            if (still_ok && reachable()) {
  995. X              if (nt == YIELD)
  996. X                fixerr(YIELD_NO_RETURN);
  997. X              else
  998. X                fixerr(TEST_NO_REPORT);
  999. X            }
  1000. X            break;
  1001. X        case 'Z':
  1002. X            if (!is_cmd_ref(t) && still_ok && reachable())
  1003. X  fixerr(MESS(2203, "refinement returns no value or reports no outcome"));
  1004. X              *Branch(t, REF_START)= copy(l1);
  1005. X            break;
  1006. X        }
  1007. X    }
  1008. X}
  1009. X
  1010. X/* skip test-suite comment nodes */
  1011. X
  1012. XHidden Procedure sk_tsuite_comment(v, w) parsetree v, *w; {
  1013. X    while ((*w= *Branch(v, TSUI_NEXT)) != NilTree &&
  1014. X                    Nodetype(*w) == TEST_SUITE &&
  1015. X            *Branch(*w, TSUI_TEST) == NilTree)
  1016. X        v= *w;
  1017. X}
  1018. X
  1019. X/* ******************************************************************** */
  1020. X
  1021. XHidden bool is_cmd_ref(t) parsetree t; { /* HACK */
  1022. X    value name= *Branch(t, REF_NAME);
  1023. X    string s;
  1024. X    
  1025. X    if (!Valid(name))
  1026. X        return No;
  1027. X    s= strval(name);
  1028. X    /* return isupper(*s); */
  1029. X    return *s <= 'Z' && *s >= 'A';
  1030. X}
  1031. X
  1032. XVisible bool is_name(v) value v; {
  1033. X    if (!Valid(v) || !Is_text(v))
  1034. X        return No;
  1035. X    else {
  1036. X        string s= strval(v);
  1037. X        /* return islower(*s); */
  1038. X        return *s <= 'z' && *s >= 'a';
  1039. X    }
  1040. X}
  1041. X
  1042. XVisible value copydef(f) value f; {
  1043. X    if (f == Vnil || Funprd(f)->pre == Use) return Vnil;
  1044. X    return copy(f);
  1045. X}
  1046. X
  1047. XHidden bool is_basic_target(v) value v; {
  1048. X    if (!Valid(v))
  1049. X        return No;
  1050. X    return    locals != Vnil && envassoc(locals, v) != Pnil ||
  1051. X        envassoc(globals, v) != Pnil;
  1052. X}
  1053. X
  1054. XHidden bool is_variable(v) value v; {
  1055. X    value f;
  1056. X    if (!Valid(v))
  1057. X        return No;
  1058. X    return is_basic_target(v) ||
  1059. X        envassoc(refinements, v) != Pnil ||
  1060. X        is_zerfun(v, &f);
  1061. X}
  1062. X
  1063. XHidden bool is_target(p) parsetree *p; {
  1064. X    value v;
  1065. X    int k, len;
  1066. X    parsetree w, *left, *right;
  1067. X    typenode trimtype;
  1068. X    typenode nt= nodetype(*p);
  1069. X
  1070. X    switch (nt) {
  1071. X
  1072. X    case TAG:
  1073. X        v= *Branch(*p, First_fieldnr);
  1074. X        return is_basic_target(v);
  1075. X
  1076. X    case SELECTION:
  1077. X    case BEHEAD:
  1078. X    case CURTAIL:
  1079. X    case COMPOUND:
  1080. X        return is_target(Branch(*p, First_fieldnr));
  1081. X
  1082. X    case COLLATERAL:
  1083. X        v= *Branch(*p, First_fieldnr);
  1084. X        len= Nfields(v);
  1085. X        k_Overfields {
  1086. X            if (!is_target(Field(v, k))) return No;
  1087. X        }
  1088. X        return Yes;
  1089. X    case DYAF:
  1090. X        if (trim_opr(*Branch(*p, DYA_NAME), &trimtype)) {
  1091. X            left= Branch(*p, DYA_LEFT);
  1092. X            if (is_target(left)) {
  1093. X                right= Branch(*p, DYA_RIGHT);
  1094. X                w= node3(trimtype, copy(*left), copy(*right));
  1095. X                release(*p);
  1096. X                *p= w;
  1097. X                return Yes;
  1098. X            }
  1099. X        }
  1100. X        return No;
  1101. X
  1102. X    default:
  1103. X        return No;
  1104. X
  1105. X    }
  1106. X}
  1107. X
  1108. XHidden bool trim_opr(name, type) value name; typenode *type; {
  1109. X    value v;
  1110. X
  1111. X    if (!Valid(name))
  1112. X        return No;
  1113. X    if (compare(name, v= mk_text(S_BEHEAD)) == 0) {
  1114. X        release(v);
  1115. X        *type= BEHEAD;
  1116. X        return Yes;
  1117. X    }
  1118. X    release(v);
  1119. X    if (compare(name, v= mk_text(S_CURTAIL)) == 0) {
  1120. X        release(v);
  1121. X        *type= CURTAIL;
  1122. X        return Yes;
  1123. X    }
  1124. X    release(v);
  1125. X    return No;
  1126. X}
  1127. X    
  1128. X/* ******************************************************************** */
  1129. X
  1130. X#define WRONG_KEYWORD    MESS(2204, "wrong keyword %s")
  1131. X#define NO_ACTUAL    MESS(2205, "missing actual parameter after %s")
  1132. X#define EXP_KEYWORD    MESS(2206, "can't find expected %s")
  1133. X#define ILL_ACTUAL    MESS(2207, "unexpected actual parameter after %s")
  1134. X#define ILL_KEYWORD    MESS(2208, "unexpected keyword %s")
  1135. X
  1136. XHidden Procedure f_actuals(formals, actuals) parsetree formals, actuals; {
  1137. X    /* name, actual, next */
  1138. X    parsetree act, form, next_a, next_f, kw, *pact;
  1139. X    
  1140. X    do {
  1141. X        kw= *Branch(actuals, ACT_KEYW);
  1142. X        pact= Branch(actuals, ACT_EXPR); act= *pact;
  1143. X        form= *Branch(formals, FML_TAG);
  1144. X        next_a= *Branch(actuals, ACT_NEXT);
  1145. X        next_f= *Branch(formals, FML_NEXT);
  1146. X    
  1147. X        if (compare(*Branch(formals, FML_KEYW), kw) != 0)
  1148. X            fixerrV(WRONG_KEYWORD, kw);
  1149. X        else if (act == NilTree && form != NilTree)
  1150. X            fixerrV(NO_ACTUAL, kw);
  1151. X        else if (next_a == NilTree && next_f != NilTree)
  1152. X            fixerrV(EXP_KEYWORD, *Branch(next_f, FML_KEYW));
  1153. X        else if (act != NilTree && form == NilTree)
  1154. X            fixerrV(ILL_ACTUAL, kw);
  1155. X        else if (next_a != NilTree && next_f == NilTree)
  1156. X            fixerrV(ILL_KEYWORD, *Branch(next_a, ACT_KEYW));
  1157. X        else if (act != NilTree)
  1158. X            act_expr_gen(pact, form);
  1159. X        actuals= next_a;
  1160. X        formals= next_f;
  1161. X    }
  1162. X    while (still_ok && actuals != NilTree);
  1163. X}
  1164. X
  1165. X/* Fix and generate code for an actual parameter.
  1166. X   This generates 'locate' code if it looks like a target,
  1167. X   or 'evaluate' code if the parameter looks like an expression.
  1168. X   The formal parameter's form is also taken into account:
  1169. X   if it is a compound, and the actual is also a compound,
  1170. X   the number of fields must match and the decision between 'locate'
  1171. X   and 'evaluate' code is made recursively for each field.
  1172. X   (If the formal is a compound but the actual isn't,
  1173. X   that's OK, since it might be an expression or simple location
  1174. X   of type compound.
  1175. X   The reverse is also acceptable: then the formal parameter has
  1176. X   a compound type.) */
  1177. X
  1178. XHidden Procedure act_expr_gen(pact, form) parsetree *pact; parsetree form; {
  1179. X    while (Nodetype(form) == COMPOUND)
  1180. X        form= *Branch(form, COMP_FIELD);
  1181. X    while (Nodetype(*pact) == COMPOUND)
  1182. X        pact= Branch(*pact, COMP_FIELD);
  1183. X    if (Nodetype(form) == COLLATERAL && Nodetype(*pact) == COLLATERAL) {
  1184. X        value vact= *Branch(*pact, COLL_SEQ);
  1185. X        value vform= *Branch(form, COLL_SEQ);
  1186. X        int n= Nfields(vact);
  1187. X        if (n != Nfields(vform))
  1188. X            fixerr(MESS(2209, "compound parameter has wrong length"));
  1189. X        else {
  1190. X            int k;
  1191. X            for (k= 0; k < n; ++k)
  1192. X                act_expr_gen(Field(vact, k), *Field(vform, k));
  1193. X            visit(*pact);
  1194. X        }
  1195. X    }
  1196. X    else {
  1197. X        if (is_target(pact))
  1198. X            f_targ(pact);
  1199. X        else
  1200. X            f_expr(pact);
  1201. X    }
  1202. X}
  1203. X
  1204. XHidden Procedure f_ucommand(pt) parsetree *pt; {
  1205. X    value t= *pt, *aa;
  1206. X    parsetree u, f1= *Branch(t, UCMD_NAME), f2= *Branch(t, UCMD_ACTUALS);
  1207. X    release(*Branch(t, UCMD_DEF));
  1208. X    *Branch(t, UCMD_DEF)= Vnil;
  1209. X    if ((aa= envassoc(refinements, f1)) != Pnil) {
  1210. X        if (*Branch(f2, ACT_EXPR) != Vnil
  1211. X                || *Branch(f2, ACT_NEXT) != Vnil)
  1212. X            fixerr(MESS(2210, "refinement with parameters"));
  1213. X        else *Branch(t, UCMD_DEF)= copy(*aa);
  1214. X    }
  1215. X    else if (is_unit(f1, Cmd, &aa)) {
  1216. X        u= How_to(*aa)->unit;
  1217. X        f_actuals(*Branch(u, HOW_FORMALS), f2);
  1218. X    }
  1219. X    else fixerrV(MESS(2211, "you haven't told me HOW TO %s"), f1);
  1220. X}
  1221. X
  1222. XHidden Procedure f_fpr_formals(t) parsetree t; {
  1223. X    typenode nt= nodetype(t);
  1224. X
  1225. X    switch (nt) {
  1226. X    case TAG:
  1227. X        break;
  1228. X    case MONF: case MONPRD:
  1229. X        f_targ(Branch(t, MON_RIGHT));
  1230. X        break;
  1231. X    case DYAF: case DYAPRD:
  1232. X        f_targ(Branch(t, DYA_LEFT));
  1233. X        f_targ(Branch(t, DYA_RIGHT));
  1234. X        break;
  1235. X    default:
  1236. X        syserr(MESS(2212, "f_fpr_formals"));
  1237. X    }
  1238. X}
  1239. X
  1240. XVisible bool modify_tag(name, tag) parsetree *tag; value name; {
  1241. X    value *aa, function;
  1242. X    *tag= NilTree;
  1243. X    if (!Valid(name))
  1244. X        return No;
  1245. X    else if (locals != Vnil && (aa= envassoc(locals, name)) != Pnil)
  1246. X        *tag= node3(TAGlocal, name, copy(*aa));
  1247. X    else if ((aa= envassoc(globals, name)) != Pnil)
  1248. X        *tag= node2(TAGglobal, name);
  1249. X    else if ((aa= envassoc(refinements, name)) != Pnil)
  1250. X        *tag= node3(TAGrefinement, name, copy(*aa));
  1251. X    else if (is_zerfun(name, &function))
  1252. X        *tag= node3(TAGzerfun, name, copydef(function));
  1253. X    else if (is_zerprd(name, &function))
  1254. X        *tag= node3(TAGzerprd, name, copydef(function));
  1255. X    else return No;
  1256. X    return Yes;
  1257. X}
  1258. X
  1259. XHidden Procedure f_etag(pt) parsetree *pt; {
  1260. X    parsetree t= *pt; value name= copy(*Branch(t, TAG_NAME));
  1261. X    if (modify_tag(name, &t)) {
  1262. X        release(*pt);
  1263. X        *pt= t;
  1264. X        if (Nodetype(t) == TAGzerprd)
  1265. X            fixerrV(MESS(2213, "%s cannot be used in an expression"), name);
  1266. X        else
  1267. X            visit(t);
  1268. X    } else {
  1269. X        fixerrV(NO_INIT_OR_DEF, name);
  1270. X        release(name);
  1271. X    }
  1272. X}
  1273. X
  1274. XHidden Procedure f_ttag(pt) parsetree *pt; {
  1275. X    parsetree t= *pt; value name= copy(*Branch(t, TAG_NAME));
  1276. X    if (modify_tag(name, &t)) {
  1277. X        release(*pt);
  1278. X        *pt= t;
  1279. X        switch (Nodetype(t)) {
  1280. X        case TAGrefinement:
  1281. X            fixerr(REF_NO_TARGET);
  1282. X            break;
  1283. X        case TAGzerfun:
  1284. X        case TAGzerprd:
  1285. X            fixerrV(NO_INIT_OR_DEF, name);
  1286. X            break;
  1287. X        default:
  1288. X            lvisit(t);
  1289. X            break;
  1290. X        }
  1291. X    } else {
  1292. X        fixerrV(NO_INIT_OR_DEF, name);
  1293. X        release(name);
  1294. X    }
  1295. X}
  1296. X
  1297. X#define NO_REF_OR_ZER    MESS(2214, "%s is neither a refined test nor a zeroadic predicate")
  1298. X
  1299. XHidden Procedure f_ctag(pt) parsetree *pt; {
  1300. X    parsetree t= *pt; value name= copy(*Branch(t, TAG_NAME));
  1301. X    if (modify_tag(name, &t)) {
  1302. X        release(*pt);
  1303. X        *pt= t;
  1304. X        switch (Nodetype(t)) {
  1305. X        case TAGrefinement:
  1306. X            lvisit(t); /* 'Loc' flag here means 'Test' */
  1307. X            break;
  1308. X        case TAGzerprd:
  1309. X            visit(t);
  1310. X            break;
  1311. X        default:
  1312. X            fixerrV(NO_REF_OR_ZER, name);
  1313. X            break;
  1314. X        }
  1315. X    } else {
  1316. X        fixerrV(NO_REF_OR_ZER, name);
  1317. X        release(name);
  1318. X    }
  1319. X}
  1320. END_OF_FILE
  1321.   if test 19819 -ne `wc -c <'abc/bint2/i2gen.c'`; then
  1322.     echo shar: \"'abc/bint2/i2gen.c'\" unpacked with wrong size!
  1323.   fi
  1324.   # end of 'abc/bint2/i2gen.c'
  1325. fi
  1326. if test -f 'abc/bint3/i3bws.c' -a "${1}" != "-c" ; then 
  1327.   echo shar: Will not clobber existing file \"'abc/bint3/i3bws.c'\"
  1328. else
  1329.   echo shar: Extracting \"'abc/bint3/i3bws.c'\" \(10277 characters\)
  1330.   sed "s/^X//" >'abc/bint3/i3bws.c' <<'END_OF_FILE'
  1331. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1988. */
  1332. X
  1333. X#include "b.h"
  1334. X#include "bint.h"
  1335. X#include "bfil.h"
  1336. X#include "bmem.h"
  1337. X#include "bobj.h"
  1338. X#include "args.h"
  1339. X#include "feat.h"
  1340. X#include "i2par.h"
  1341. X#include "i3bws.h"
  1342. X#include "i3env.h"
  1343. X#include "i3sou.h"
  1344. X
  1345. X/* ******************************************************************** */
  1346. X/*        workspace routines                    */
  1347. X/* ******************************************************************** */
  1348. X
  1349. XVisible char *bwsdir= (char *) NULL;    /* group name workspaces */
  1350. X
  1351. XVisible value ws_group= Vnil;        /* index workspaces */
  1352. XVisible bool groupchanges= No;        /* if Yes index is changed */
  1353. X
  1354. XVisible value curwskey= Vnil;        /* special index key for cur_ws */
  1355. XVisible value lastwskey= Vnil;        /* special index key for last_ws */
  1356. X
  1357. XVisible value cur_ws= Vnil;        /* the current workspace */
  1358. X                    /* only visible for m1bio.c */
  1359. XHidden value last_ws= Vnil;        /* the last visited workspace */
  1360. X
  1361. XHidden bool path_workspace= No;        /* if Yes no workspace change allowed */
  1362. X
  1363. X#define gr_exists(name, aa) (in_env(ws_group, name, aa))
  1364. X#define def_group(name, f)  (e_replace(f, &ws_group, name), groupchanges= Yes)
  1365. X#define free_group(name)    (e_delete(&ws_group, name), groupchanges= Yes)
  1366. X
  1367. X#ifndef DIRMODE
  1368. X#define DIRMODE 0777
  1369. X#endif
  1370. X
  1371. X/* ******************************************************************** */
  1372. X
  1373. X#define DEFAULT_WS    "first"
  1374. X
  1375. X#define CURWSKEY    ">"
  1376. X#define LASTWSKEY    ">>"
  1377. X
  1378. XHidden Procedure initgroup() {
  1379. X    wsgroupfile= (string) makepath(bwsdir, WSGROUPFILE);
  1380. X    curwskey= mk_text(CURWSKEY);
  1381. X    lastwskey= mk_text(LASTWSKEY);
  1382. X    if (F_exists(wsgroupfile)) {
  1383. X        value fname= mk_text(wsgroupfile);
  1384. X        ws_group= getval(fname, In_wsgroup);
  1385. X        release(fname);
  1386. X        if (!still_ok) {
  1387. X            still_ok= Yes;
  1388. X            rec_wsgroup();
  1389. X        }
  1390. X        
  1391. X    }
  1392. X    else ws_group= mk_elt();
  1393. X    groupchanges= No;
  1394. X}
  1395. X
  1396. XHidden Procedure endgroup() {
  1397. X    save_curlast(curwskey, cur_ws);
  1398. X    save_curlast(lastwskey, last_ws);
  1399. X    only_default();
  1400. X    put_wsgroup();
  1401. X}
  1402. X
  1403. XHidden Procedure save_curlast(wskey, ws) value wskey, ws; {
  1404. X    value *aa;
  1405. X    
  1406. X    if (Valid(ws) && (!gr_exists(wskey, &aa) || (compare(ws, *aa) != 0)))
  1407. X        def_group(wskey, ws);
  1408. X}
  1409. X
  1410. X/*
  1411. X * removes the default entry if it is the only one;
  1412. X * the default is [CURWSKEY]: DEFAULT_WS;
  1413. X * this has to be done to create the possibility of removing an empty
  1414. X * wsgroupfile and bwsdefault directory;
  1415. X * still this will hardly happen (see comments in endbws() )
  1416. X */
  1417. X
  1418. XHidden Procedure only_default() {
  1419. X    value *aa;
  1420. X
  1421. X    if (length(ws_group) == 1 &&
  1422. X        Valid(curwskey) && gr_exists(curwskey, &aa) 
  1423. X       ) {
  1424. X           value defws= mk_text(DEFAULT_WS);
  1425. X           if (compare(defws, *aa) == 0)
  1426. X               free_group(curwskey);
  1427. X           release(defws);
  1428. X    }
  1429. X}
  1430. X
  1431. XHidden Procedure put_wsgroup() {
  1432. X    value fn;
  1433. X    intlet len;
  1434. X    
  1435. X    if (!groupchanges || !Valid(ws_group))
  1436. X        return;
  1437. X    fn= mk_text(wsgroupfile);
  1438. X    /* Remove the file if empty */
  1439. X    len= length(ws_group);
  1440. X    if (len == 0)
  1441. X        f_delete(fn);
  1442. X    else
  1443. X        putval(fn, ws_group, Yes, In_wsgroup);
  1444. X    release(fn);
  1445. X    groupchanges= No;
  1446. X}
  1447. X
  1448. X/* ******************************************************************** */
  1449. X
  1450. XHidden bool wschange(ws) value ws; {
  1451. X    value name, *aa;
  1452. X    bool new= No, changed;
  1453. X    char *path;
  1454. X
  1455. X    if (gr_exists(ws, &aa))
  1456. X        name= copy(*aa);
  1457. X    else {
  1458. X        name= new_fname(ws, Wsp);
  1459. X        if (!Valid(name))
  1460. X            return No;
  1461. X        new= Yes;
  1462. X    }
  1463. X    path= makepath(bwsdir, strval(name));
  1464. X    VOID Mkdir(path);
  1465. X    changed= chdir(path) == 0 ? Yes : No;
  1466. X    if (changed && new)
  1467. X        def_group(ws, name);
  1468. X    freepath(path);
  1469. X    release(name);
  1470. X    return changed;
  1471. X}
  1472. X
  1473. XHidden Procedure wsempty(ws) value ws; {
  1474. X    char *path, *permpath;
  1475. X    value *aa;
  1476. X    
  1477. X    if (!gr_exists(ws, &aa))
  1478. X        return;
  1479. X    path= makepath(bwsdir, strval(*aa));
  1480. X    permpath= makepath(path, permfile);
  1481. X    if (F_exists(permpath));
  1482. X    else if (strcmp(startdir, path) == 0);
  1483. X    else if (rmdir(path) != 0);
  1484. X    else free_group(ws);
  1485. X    freepath(path);
  1486. X    freepath(permpath);
  1487. X}
  1488. X
  1489. X/* ******************************************************************** */
  1490. X
  1491. XVisible Procedure goto_ws() {
  1492. X    value ws= Vnil;
  1493. X    bool prname; /* print workspace name */
  1494. X
  1495. X    if (path_workspace) {
  1496. X        parerr(MESS(2900, "change of workspace not allowed"));
  1497. X        return;
  1498. X    }
  1499. X    if (Ceol(tx)) {
  1500. X        if (Valid(last_ws))
  1501. X            ws= copy(last_ws);
  1502. X        else
  1503. X            parerr(MESS(2901, "no previous workspace"));
  1504. X        prname= Yes;
  1505. X    }
  1506. X    else if (is_tag(&ws))
  1507. X        prname= No;
  1508. X    else
  1509. X        parerr(MESS(2902, "I find no workspace name here"));
  1510. X    
  1511. X    if (still_ok && (compare(ws, cur_ws) != 0)) {
  1512. X        can_interrupt= No;
  1513. X        endworkspace();
  1514. X        
  1515. X        if (wschange(ws)) {
  1516. X            release(last_ws); last_ws= copy(cur_ws);
  1517. X            release(cur_ws); cur_ws= copy(ws);
  1518. X        }
  1519. X        else {
  1520. X            parerrV(MESS(2903, "I can't goto/create workspace %s"), ws);
  1521. X            still_ok= Yes;
  1522. X            prname= No;
  1523. X        }
  1524. X        
  1525. X        init_workspace(prname);
  1526. X        wsempty(last_ws);
  1527. X        can_interrupt= Yes;
  1528. X    }
  1529. X    release(ws);
  1530. X}
  1531. X
  1532. XVisible Procedure lst_wss() {
  1533. X    value wslist, ws;
  1534. X    value k, len, m;
  1535. X    
  1536. X    if (path_workspace) {
  1537. X        print_wsname();
  1538. X        return;
  1539. X    }
  1540. X    wslist= keys(ws_group);
  1541. X    
  1542. X    if (!in(cur_ws, wslist))
  1543. X        insert(cur_ws, &wslist);
  1544. X    
  1545. X    k= one; len= size(wslist);
  1546. X    while (numcomp(k, len) <= 0) {
  1547. X        ws= item(wslist, k);
  1548. X        if (compare(ws, curwskey) == 0);
  1549. X        else if (compare(ws, lastwskey) == 0);
  1550. X        else if (compare(ws, cur_ws) == 0)
  1551. X            putSstr(stdout, ">%s ", strval(ws));
  1552. X        else
  1553. X            putSstr(stdout, "%s ", strval(ws));
  1554. X        release(ws);
  1555. X        k= sum(m= k, one);
  1556. X        release(m);
  1557. X    }
  1558. X    if (numcomp(len, zero) > 0)
  1559. X        putnewline(stdout);
  1560. X    fflush(stdout);
  1561. X    release(k); release(len);
  1562. X    release(wslist);
  1563. X}
  1564. X
  1565. X/************************************************************************/
  1566. X
  1567. X#define NO_PARENT    MESS(2905, "*** I cannot find parent directory\n")
  1568. X#define NO_WORKSPACE    MESS(2906, "*** I cannot find workspace\n")
  1569. X#define NO_DEFAULT    MESS(2907, "*** I cannot find your home directory\n")
  1570. X#define USE_CURRENT    MESS(2908, "*** I shall use the current directory as your single workspace\n")
  1571. X#define NO_ABCNAME    MESS(2909, "*** %s isn't an ABC name\n")
  1572. X#define TRY_DEFAULT    MESS(2910, "*** I shall try the default workspace\n")
  1573. X
  1574. XHidden Procedure wserr(m, use_cur) int m; bool use_cur; {
  1575. X    putmess(errfile, m);
  1576. X    if (use_cur)
  1577. X        wscurrent();
  1578. X}
  1579. X
  1580. XHidden Procedure wserrV(m, v, use_cur) int m; value v; bool use_cur; {
  1581. X    putSmess(errfile, m, strval(v));
  1582. X    if (use_cur)
  1583. X        wscurrent();
  1584. X}
  1585. X
  1586. XHidden Procedure wscurrent() {
  1587. X    putmess(errfile, USE_CURRENT);
  1588. X    path_workspace= Yes;
  1589. X}
  1590. X
  1591. X/* ******************************************************************** */
  1592. X
  1593. XHidden bool wsinit() {
  1594. X    value *aa;
  1595. X    
  1596. X    initgroup();
  1597. X    cur_ws= Vnil;
  1598. X    last_ws= Vnil;
  1599. X    if (wsp_arg) {
  1600. X        /* wsp_arg is a single name here, not a pathname */
  1601. X#ifdef WSP_DIRNAME
  1602. X        /* on the mac wsp_arg is a mac foldername, not an ABC wsname */
  1603. X        cur_ws= abc_wsname(wsp_arg);
  1604. X        if (!Valid(cur_ws))
  1605. X            return No;
  1606. X#else
  1607. X        /* wsp_arg is here an ABC workspace name, not a path */
  1608. X        cur_ws= mk_text(wsp_arg);
  1609. X#endif
  1610. X        if (!is_abcname(cur_ws)) {
  1611. X            wserrV(NO_ABCNAME, cur_ws, No);
  1612. X            wserr(TRY_DEFAULT, No);
  1613. X            release(cur_ws); cur_ws= Vnil;
  1614. X        }
  1615. X    }
  1616. X    if (gr_exists(curwskey, &aa)) {
  1617. X        if (!Valid(cur_ws))
  1618. X            cur_ws= copy(*aa);
  1619. X        else if (compare(cur_ws, *aa) != 0)
  1620. X            last_ws= copy(*aa);
  1621. X        if (!Valid(last_ws) && gr_exists(lastwskey, &aa))
  1622. X            last_ws= copy(*aa);
  1623. X    }
  1624. X    if (!Valid(cur_ws))
  1625. X        cur_ws= mk_text(DEFAULT_WS);
  1626. X    if (!is_abcname(cur_ws))
  1627. X        wserrV(NO_ABCNAME, cur_ws, Yes);
  1628. X    else if (wschange(cur_ws)) {
  1629. X        path_workspace= No;
  1630. X        return Yes;
  1631. X    }
  1632. X    else wserr(NO_WORKSPACE, Yes);
  1633. X    return No;
  1634. X}
  1635. X
  1636. XVisible Procedure initbws() {
  1637. X    if (is_gr_reccall) { /* recover index of group workspaces */
  1638. X        if (!setbwsdir() || !D_exists(bwsdir)) {
  1639. X            wserr(NO_PARENT, No);
  1640. X            immexit(1);
  1641. X        }
  1642. X        initgroup();
  1643. X        return;
  1644. X    }
  1645. X    if (is_path(wsp_arg)) {
  1646. X        /* !bws_arg already assured in main.c */
  1647. X        if (chdir(wsp_arg) != 0)
  1648. X            wserr(NO_WORKSPACE, Yes);
  1649. X        else 
  1650. X            path_workspace= Yes;
  1651. X    }
  1652. X    else if (setbwsdir()) {
  1653. X        if (!D_exists(bwsdir))
  1654. X            wserr(NO_PARENT, Yes);
  1655. X        else if (!wsinit())
  1656. X            wsrelease();
  1657. X    }
  1658. X    else wserr(NO_DEFAULT, Yes);
  1659. X    if (path_workspace) {
  1660. X        release(cur_ws);
  1661. X        cur_ws= mk_text(curdir());
  1662. X    }
  1663. X    init_workspace(Yes);
  1664. X}
  1665. X
  1666. XVisible Procedure endbws() {
  1667. X    if (!is_gr_reccall) {
  1668. X        endworkspace();
  1669. X        VOID chdir(startdir);
  1670. X        if (path_workspace) {
  1671. X            release(cur_ws);
  1672. X            cur_ws= Vnil;
  1673. X            return;
  1674. X        }
  1675. X        else wsempty(cur_ws);
  1676. X    }
  1677. X    /* else: only index of group workspaces recovered */
  1678. X
  1679. X    endgroup();
  1680. X    /* 
  1681. X     * if the bwsdefault directory is used and empty, remove it;
  1682. X     * because of the savings of the last two visited workspaces
  1683. X     * in the file `bwsdefault`/`wsgroupfile` this will hardly happen;
  1684. X     * only if you stays for ever in the default workspace.
  1685. X     */
  1686. X    if (!bws_arg && bwsdefault)
  1687. X        VOID rmdir(bwsdefault); /* fails if not empty */
  1688. X    wsrelease();
  1689. X}
  1690. X
  1691. XVisible bool is_path(path) char *path; {
  1692. X    if (path == (char *) NULL)
  1693. X        return No;
  1694. X    if (strcmp(path, CURDIR) == 0 || strcmp(path, PARENTDIR) == 0)
  1695. X        return Yes;
  1696. X    for (; *path; path++) {
  1697. X        if (Isanysep(*path)) return Yes;
  1698. X    }
  1699. X    return No;
  1700. X}
  1701. X
  1702. XHidden bool setbwsdir() {
  1703. X    if (bws_arg || bwsdefault) {
  1704. X        if (!bws_arg) {
  1705. X            bwsdir= savepath(bwsdefault); /* full path name */
  1706. X            VOID Mkdir(bwsdir);
  1707. X        }
  1708. X        else if (!Isabspath(bws_arg))
  1709. X            bwsdir= makepath(startdir, bws_arg);
  1710. X        else
  1711. X            bwsdir= savepath(bws_arg);
  1712. X        return Yes;
  1713. X    }
  1714. X    return No;
  1715. X}
  1716. X
  1717. XHidden Procedure wsrelease() {
  1718. X    release(last_ws); last_ws= Vnil;
  1719. X    release(cur_ws); cur_ws= Vnil;
  1720. X    release(lastwskey); lastwskey= Vnil;
  1721. X    release(curwskey); curwskey= Vnil;
  1722. X    release(ws_group); ws_group= Vnil;
  1723. X    freepath(wsgroupfile); wsgroupfile= (string) NULL;
  1724. X    freepath(bwsdir); bwsdir= (char *) NULL;
  1725. X}
  1726. X
  1727. X/************************************************************************/
  1728. X
  1729. XHidden Procedure init_workspace(prname) bool prname; {
  1730. X    if (interactive && prname)
  1731. X        print_wsname();
  1732. X    initworkspace();
  1733. X    if (!still_ok) {
  1734. X        still_ok= Yes;
  1735. X        rec_workspace();
  1736. X    }
  1737. X}
  1738. X
  1739. XVisible Procedure initworkspace() {
  1740. X    initsou();
  1741. X    initfpr();
  1742. X    initenv();
  1743. X#ifdef USERSUGG
  1744. X    initsugg();
  1745. X#endif
  1746. X#ifdef SAVEPOS
  1747. X    initpos();
  1748. X#endif
  1749. X#ifdef TYPE_CHECK
  1750. X    initstc();
  1751. X#endif
  1752. X    setprmnv();
  1753. X    initperm();
  1754. X}
  1755. X
  1756. XVisible Procedure endworkspace() {
  1757. X    endperm();
  1758. X    endsou();
  1759. X    endenv();
  1760. X#ifdef USERSUGG
  1761. X    endsugg();
  1762. X#endif
  1763. X#ifdef SAVEPOS
  1764. X    endpos();
  1765. X#endif
  1766. X#ifdef TYPE_CHECK
  1767. X    endstc();
  1768. X#endif
  1769. X    enderro();
  1770. X}
  1771. X
  1772. X/************************************************************************/
  1773. X
  1774. XVisible bool wsp_writable() {
  1775. X    return F_writable(CURDIR) ? Yes : No;
  1776. X}
  1777. X
  1778. XHidden Procedure print_wsname() {
  1779. X    putSstr(errfile, ">%s\n", strval(cur_ws));
  1780. X    fflush(errfile);
  1781. X}
  1782. X
  1783. X/************************************************************************/
  1784. END_OF_FILE
  1785.   if test 10277 -ne `wc -c <'abc/bint3/i3bws.c'`; then
  1786.     echo shar: \"'abc/bint3/i3bws.c'\" unpacked with wrong size!
  1787.   fi
  1788.   # end of 'abc/bint3/i3bws.c'
  1789. fi
  1790. if test -f 'abc/ex/try/position.abc' -a "${1}" != "-c" ; then 
  1791.   echo shar: Will not clobber existing file \"'abc/ex/try/position.abc'\"
  1792. else
  1793.   echo shar: Extracting \"'abc/ex/try/position.abc'\" \(12 characters\)
  1794.   sed "s/^X//" >'abc/ex/try/position.abc' <<'END_OF_FILE'
  1795. Xstart.cmd    4
  1796. END_OF_FILE
  1797.   if test 12 -ne `wc -c <'abc/ex/try/position.abc'`; then
  1798.     echo shar: \"'abc/ex/try/position.abc'\" unpacked with wrong size!
  1799.   fi
  1800.   # end of 'abc/ex/try/position.abc'
  1801. fi
  1802. echo shar: End of archive 7 \(of 25\).
  1803. cp /dev/null ark7isdone
  1804. MISSING=""
  1805. for I in 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 ; do
  1806.     if test ! -f ark${I}isdone ; then
  1807.     MISSING="${MISSING} ${I}"
  1808.     fi
  1809. done
  1810. if test "${MISSING}" = "" ; then
  1811.     echo You have unpacked all 25 archives.
  1812.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1813. else
  1814.     echo You still must unpack the following archives:
  1815.     echo "        " ${MISSING}
  1816. fi
  1817. exit 0 # Just in case...
  1818.