rsalz@bbn.com (Rich Salz) (12/18/90)
Submitted-by: Steven Pemberton <steven@cwi.nl> Posting-number: Volume 23, Issue 86 Archive-name: abc/part07 #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: abc/abc.hlp abc/bint2/i2gen.c abc/bint3/i3bws.c # abc/ex/try/position.abc # Wrapped by rsalz@litchi.bbn.com on Mon Dec 17 13:27:57 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive 7 (of 25)."' if test -f 'abc/abc.hlp' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'abc/abc.hlp'\" else echo shar: Extracting \"'abc/abc.hlp'\" \(20503 characters\) sed "s/^X//" >'abc/abc.hlp' <<'END_OF_FILE' XSUMMARY OF SPECIAL ACTIONS X X :name Visit how-to called 'name' X : Visit last how-to refered to X :: Display headings of how-to's in this workspace X X =name Visit contents of location X = Visit last location visited X == Display names of permament locations in this workspace X X >name Visit workspace 'name' X > Visit last workspace visited X >> Display list of workspace names X X QUIT Leave ABC X XSUMMARY OF EDITING OPERATIONS X X Name Default Keys* Short description X X Accept [TAB] Accept suggestion, focus to hole or end of line X Return [RETURN] Add line or decrease indentation X X Widen f1, [ESC] w Widen focus X Extend f2, [ESC] e Extend focus (usually to the right) X First f3, [ESC] f Move focus to first contained item X Last f4, [ESC] l Move focus to last contained item X X Previous f5, [ESC] p Move focus to previous item X Next f6, [ESC] n Move focus to next item X Upline f7, [ESC] u Move focus to whole line above X Downline f8, [ESC] d Move focus to whole line below X X Up ^, [ESC] U Make new hole, move up X Down v, [ESC] D Make new hole, move down X Left <-, [ESC] , Make new hole, move left X Right ->, [ESC] . Make new hole, move right X X Goto [ctrl-G], mouseclick New focus at cursor position X X Undo [BACKSPACE] Undo effect of last key pressed (may be repeated) X Redo [ctrl-U] Redo last UNDOne key (may be repeated) X X Copy f9, [ctrl-C], [ESC]c Copy buffer to hole, or focus to buffer X Delete [ctrl-D] Delete contents of focus (to buffer if empty) X X Record [ctrl-R] Start/stop recording keystrokes X Play [ctrl-P] Play back recorded keystrokes X X Look [ctrl-L] Redisplay screen X Help f10, [ESC]? Print summary of editing operations X X Exit [ctrl-X] Finish changes or execute command X Interrupt (as set by 'stty')Interrupt command execution X Suspend (as set by 'stty') Suspend ABC (only for shell with job control) X X * Notes: X X [Ctrl-D] means: hold the [CTRL] (or [CONTROL]) key down while pressing d. X [ESC] w means: press the [ESC] key first, then w. X XABC QUICK REFERENCE X X COMMANDS X X WRITE expr Write to screen; X / before or after expr gives new line X READ address EG expr Read expression from terminal to address; X expr is example X READ address RAW Read line of text X PUT expr IN address Put value of expr in address X SET RANDOM expr Start random sequence for random and choice X REMOVE expr FROM list Remove one element from list X INSERT expr IN list Insert in right place X DELETE address Delete permanent location or table entry X PASS Do nothing X KEYWORD expr KEYWORD ... Execute user-defined command X KEYWORD Execute refined command X X CHECK test Check test and stop if it fails X IF test: If test succeeds, execute commands; X commands no ELSE allowed X SELECT: Select one alternative: X test: commands try each test in order X ... (one must succeed; X test: commands the last test may be ELSE) X WHILE test: As long as test succeeds X commands execute commands X FOR name,... IN train: Take each element of train in turn X commands X X HOW-TO's X X HOW TO KEYWORD ...: Define new command KEYWORD ... X commands X HOW TO RETURN f: Define new function f with no arguments X commands (returns a value) X HOW TO RETURN f x: Define new function f with one argument X commands X HOW TO RETURN x f y: Define new function f with two arguments X commands X HOW TO REPORT pr: Define new predicate pr with no arguments X commands (succeeds/fails) X HOW TO REPORT pr x: Define new predicate pr with one argument X commands X HOW TO REPORT x pr y: Define new predicate pr with two arguments X commands X X SHARE name,... Share permanent locations X (before commands of how-to) X X Refinements (after the commands of a how-to) X X KEYWORD : commands Define command refinement X name: commands Define expression- or test-refinement X X Terminating commands X X QUIT Leave command how-to or command refinement, X or leave ABC X RETURN expr Leave function how-to or expression refinement, X return value of expr X REPORT test Leave predicate how-to or test-refinement, X report outcome of test X SUCCEED The same, report success X FAIL The same, report failure X X EXPRESSIONS AND ADDRESSES X X 666, 3.14, 3.14e-9 Exact constants X X expr,expr,... Compound X name,name,... Naming (may also be used as address) X X text@p "ABCD"@2 = "BCD" (also address) X text|q "ABCD"|3 = "ABC" (also address) X text@p|q "ABCD"@2|1 = "BCD"|1 = "B" X X table[expr] Table selection (also address) X X "Jan", 'Feb', 'Won''t!' Textual displays (empty: "" or '') X "value = `expr`;" Conversion of expr to text X X {1; 2; 2; ...} List display (empty: {}) X {1..9; ...}, {"a".."z"; ...} List of consecutive values X X {["Jan"]: 1; ["Feb"]: 2; ...} Table display (empty: {}) X X f, f x, x f y Result of function f (no permanent effects) X name Result of refinement (no permanent effects) X X TESTS X X x < y, x <= y, x >= y, x > y Order tests X x = y, x <> y (<> means 'not equals') X 0 <= d < 10 X X pr, pr x, x pr y Outcome of predicate pr (no permanent effects) X name Outcome of refinement (no permanent effects) X X test AND test AND ... Fails as soon as one of the tests fails X test OR test OR ... Succeeds as soon as one of the tests succeeds X NOT test X X SOME name,... IN train HAS test X Sets name, ... on success X EACH name,... IN train HAS test X Sets name, ... on failure X NO name,... IN train HAS test X Sets name, ... on failure X X PREDEFINED FUNCTIONS AND PREDICATES X X Functions and predicates on numbers X X ~x Approximate value of x X exactly x Exact value of x X exact x Test if x is exact X +x, x+y, x-y, -x, x*y, x/y Plain arithmetic X x**y x raised to the power y X root x, n root x Square root, n-th root X abs x, sign x Absolute value, sign (= -1, 0, or +1) X round x, floor x, ceiling x Rounded to whole number X n round x x rounded to n digits after decimal point X a mod n Remainder of a on division by n X */x Numerator of exact number x X /*x Denominator X random Random approximate number r, 0 <= r < 1 X e, exp x Base of natural logarithm, exponential function X log x, b log x Natural logarithm, logarithm to the base b X pi, sin x, cos x, tan x, arctan x X Trigonometric functions, with x in radians X angle (x, y), radius (x, y) Angle of and radius to point (x, y) X c sin x, c cos x, c tan x Similar, with the circle divided into c parts X c arctan x, c angle (x, y) (e.g. 360 for degrees) X now e.g. (1999, 12, 31, 23, 59, 59.999) X X Functions on texts X X t^u t and u joined into one text X t^^n t repeated n times X lower t lower "aBc" = "abc" X upper t upper "aBc" = "ABC" X stripped t Strip leading and trailing spaces from t X split t Split text t into words X X Function on tables X X keys table List of all keys in table X X Functions and predicates on trains X X #train Number of elements in train X e#train Number of elements equal to e X e in train, e not.in train Test for presence or absence X min train Smallest element of train X e min train Smallest element larger than e X max train, e max train Largest element X train item n n-th element X choice train Random element X X Functions on all types X X x<<n x converted to text, aligned left in width n X x><n The same, centred X x>>n The same, aligned right X X THE CHARACTERS X X !"#$%&'()*+,-./ This is the order of all characters X 0123456789:;<=>? that may occur in a text. X @ABCDEFGHIJKLMNO (The first is a space.) X PQRSTUVWXYZ[\]^_ X `abcdefghijklmno X pqrstuvwxyz{|}~ X XABC MANUAL X XNAME X abc - ABC interpreter & environment X abckeys - change key bindings for 'abc' X XSYNOPSIS X abc [workspace and editor options] [file ...] X abc [workspace and task options] X abckeys X XDESCRIPTION X Without options or files, the ABC interpreter is started, using the ABC X editor, in the last workspace used or in workspace 'first' if this is X your first abc session. A workspace is kept as a group of files in a X directory, with separate files for each how-to and location. The X workspace directories themselves are kept by default in the directory X $HOME/abc. On non-Unix machines, $HOME is the disk you are working on. X X Workspace Options: X X -W dir use group of workspaces in 'dir' instead of $HOME/abc. X X -w name start in workspace 'name' instead of last workspace used. X X -w path use 'path' as workspace (no -W option allowed). X X Editor option: X X -e Use $EDITOR as editor to edit definitions, instead of ABC X editor (Unix only). X X file ... Read commands from file(s) instead of from standard input; X input for READ commands is taken from standard input. If a X file is called '-' and standard input is the keyboard, the X ABC system is started up interactively for that entry. X X Special tasks: X X -i tab Fill table 'tab' with text lines from standard input X X -o tab Write text lines from table 'tab' to standard output X X -l List the how-to's in workspace on standard output X X -r Recover a workspace when its index is lost: useful after a X machine crash if the ABC internal administration files X didn't get written out. X X -R Recover the index of a group of workspaces X XUSAGE X (This is necessarily a very brief description; see 'The ABC Programmer's X Handbook' for full details.) X X Use 'QUIT' to finish an ABC session. X X When ABC starts up interactively, it displays a prompt and awaits input. X X TYPING AND SUGGESTIONS: as you type, the system tries to suggest a X possible continuation for what you have typed; to accept the suggestion, X press [accept] (by default this is bound to the [TAB] key; type '?' to X find out the bindings for the keyboard you are using). If you don't want X to accept the suggestion, just carry on typing (you can always type X character for character, ignoring the suggestions). Usually the system X knows where a letter must be capital and where not, and you usually don't X have to use the shift key; however, in the few places where both a X lower-case and an upper-case letter would be legal (for instance for X AND), you have to type the letter upper-case. X X When you type a control command, like WHILE, the system provides X indentation automatically for the body of the command; to reduce the X indentation one level, type [return]. X X CORRECTING AND EDITING: the [undo] key (by default bound to backspace) X undoes the last key you typed. Repeatedly typing it undoes more and X more, up to a certain maximum number of keypresses. X X To correct other parts, you must put the 'focus' onto the part you want X to change. The focus is displayed by underlining or reverse video. X [Widen] and [extend] make the focus larger, [first] and [last] make it X smaller. X X [Delete] deletes the contents of the focus. X X [Copy] copies the contents of the focus to a buffer, or if the focus is X not focussed on anything, copies the contents of the buffer back to where X you are positioned. X X MOVING THE FOCUS: [Upline] and [downline] focus on one line above or X below. [Previous] and [next] move the focus left and right. [Up], X [down], [left], and [right] move an empty focus around. [Goto] widens X the focus to the largest thing at the current position. X X OTHER OPERATIONS: [Look] redraws the screen; [record] records all X keystrokes until the next time you press [record] - [play] replays them. X [Redo] redoes the last key(s) undone; [interrupt] interrupts a running X command. X X WORKSPACES: To create a new workspace, or go to an existing workspace, X type '>name'. To go to the last workspace you were in, type a single X '>'. To get a list of workspace names, type '>>'. X X HOW-TO's: To create a new how-to, just type the first line of the how-to. X This creates the new how-to, and allows you to type the body. Use [exit] X to finish it (by default [ESC][ESC]). X X To visit a how-to, type a colon, followed by the name of the how-to. X Again, use [exit] to exit. To visit the last how-to again, or the last X how-to you got an error message for, type a single ':'. To get a list of X the how-to's in this workspace, type '::'. X X To edit a location, type a '=' followed by the name of the location. To X re-edit it, type a single '='. To get a list of the locations in the X workspace, type '=='. X XKEY BINDINGS X The binding of editing operations like [accept] to keys may be different X for your keyboard; type a '?' at the prompt to find out what the bindings X are for your keyboard. X To redefine the keys used for editor operations, run 'abckeys'. This X produces a private key definitions file. You will be given instructions X on how to use it. X Keys labeled f1...f8 are function keys. On Unix, the way to type these is X terminal-dependent. The codes they send must be defined by the termcap X entry for your terminal. X If a terminal has arrow keys which transmit codes to the computer, these X should be used for Up, Down, Left and Right. Again, the termcap entry X must define the codes. X The Goto operation is of most use if the cursor can be moved locally at X the terminal, or if the terminal has a mouse; the Goto operation will X sense the terminal for the cursor or mouse position. On Unix, we use two X extra non-standard termcap capabilities for this: 'sp' which gives the X string that must be sent to the terminal to sense the cursor position, X and 'cp' which defines the format of the reply (in the same format as X other cursor-addressing strings in termcap). If your terminal's mouse- X click sends the position of the click automatically, just set 'sp' to the X empty string. See termcap(5) for more details. X XFILES X $HOME/copybuf.abc copy buffer between sessions X $HOME/abc/wsgroup.abc table mapping workspace names to directory names X $HOME/abc/abckeys_$TERM private key definitions file (Unix only) X $HOME/abc/abc.key private key definitions file (non-Unix) X position.abc focus position of edited how-to's in workspace X perm.abc table mapping object names to file names X suggest.abc suggestion list for user-defined commands X types.abc table with codes for typechecking between how-to's X *.cmd command how-to's in this workspace X *.zfd, *.mfd, *.dfd function how-to's in this workspace X *.zpd, *.mpd, *.dpd predicate how-to's in this workspace X *.cts permanent locations in this workspace X abc.msg messages file, used for errors (not on Macintosh) X abc.hlp helpfile with this text (MacABC.help on Macintosh) X X The latter two are searched for first in your startup directory, then in X $HOME/abc, and finally, on Unix, in a directory determined by the X installer of ABC. On the IBM PC and Atari ST the directories in your X $PATH are used in the last stage (if you have a hard disk place these X files in the workspaces directory abc). X XATARI ST IMPLEMENTATION X There are four files supplied: the program abc.tos itself, abckeys.tos X for changing your key bindings, the help file abc.hlp, and the error X messages file abc.msg. (See FILES above.) X If you start ABC up from the desktop, and you want to use the options X given above, like -w, you should rename abc.tos to abc.ttp. There is an X additional facility for redirecting input and output: the parameter X >outfile redirects all output from ABC to the file called outfile, and X similarly <infile takes its input from the file called infile. X XIBM PC IMPLEMENTATION X There are four files for running ABC, the program abc.exe itself, X abckeys.exe for changing your key bindings, the help file abc.hlp, and X the error messages file abc.msg. (See FILES above.) X If your screen size is non-standard, or your machine is not 100% BIOS X compatible (which is unusal these days), you can specify the screen-size, X and whether to use the BIOS or ANSI.SYS for output, by typing after the X A> prompt, before you start ABC up, one of the following: X SET SCREEN=ANSI lines cols X SET SCREEN=BIOS lines cols X If you are going to use ANSI.SYS, be sure you have the line X DEVICE=ANSI.SYS X in your CONFIG.SYS file. Consult the DOS manual for further details. X XAPPLE MACINTOSH IMPLEMENTATION X There are three files supplied: MacABC, the application itself, X MacABC.help, the help file, and MacABC.doc, a MacWrite document X containing a variant of this text. The help file should be in the same X folder as MacABC, or in your System Folder. X MacABC runs in a single window. You'll notice that most operations are X menu entries, as well as being possible from the keyboard. You can start X ABC up by double-clicking the MacABC icon in which case you start up in X the last workspace used, or by double-clicking on any icon in a X workspace, in which case you start in that workspace. In this latter X case, if the filename of the icon you clicked on ends in .cmd, that how- X to is executed, but the how-to may not have any parameters. X Instead of the special option flags mentioned above, most of the tasks, X like recovering a workspace, can be done from the File menu. X * Notes for Macintosh guru's: X The messages are STR# resources in MacABC; you must use a resource editor X to change them. X MacABC uses Monaco 9 for the screen, and Courier 10 for printing. You X can change them with ResEdit, by editing the resource with type Conf and X ID 0. The horizontal and vertical window-size and the window-title can X also be adapted there. To facilitate this, first Paste the TMPL resource X with ID 5189 named Conf from MacABC to (a copy of) ResEdit. But beware, X MacABC only works properly with Fixed-width Fonts like Monaco and X Courier. X XSEE ALSO X Leo Geurts, Lambert Meertens and Steven Pemberton, The ABC Programmer's X Handbook, Prentice-Hall, Englewood Cliffs, New Jersey, 1989, X ISBN 0-13-000027-2. X Steven Pemberton, An Alternative Simple Language and Environment for PCs, X IEEE Software, Vol. 4, No. 1, January 1987, pp. 56-64. X The ABC Newsletter. Available free from CWI. X XAUTHORS X Frank van Dijk, Leo Geurts, Timo Krijnen, Lambert Meertens, Steven X Pemberton, Guido van Rossum. X XADDRESS X ABC Distribution, CWI/AA, Postbox 4079, 1009 AB Amsterdam, The X Netherlands. X E-mail: 'abc@cwi.nl'. X END_OF_FILE if test 20503 -ne `wc -c <'abc/abc.hlp'`; then echo shar: \"'abc/abc.hlp'\" unpacked with wrong size! fi # end of 'abc/abc.hlp' fi if test -f 'abc/bint2/i2gen.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'abc/bint2/i2gen.c'\" else echo shar: Extracting \"'abc/bint2/i2gen.c'\" \(19819 characters\) sed "s/^X//" >'abc/bint2/i2gen.c' <<'END_OF_FILE' X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */ X X/* Code generation */ X X#include "b.h" X#include "bint.h" X#include "feat.h" X#include "bobj.h" X#include "i0err.h" X#include "i2nod.h" X#include "i2gen.h" /* Must be after i2nod.h */ X#include "i2par.h" X#include "i3env.h" X#include "i3int.h" X#include "i3sou.h" X XVisible Procedure fix_nodes(pt, code) parsetree *pt; parsetree *code; { X context c; value *setup(), *su; X sv_context(&c); X curline= *pt; curlino= one; X su= setup(*pt); X if (su != Pnil) analyze(*pt, su); X if (still_ok) no_mysteries(); X curline= *pt; curlino= one; X inithreads(); X fix(pt, su ? 'x' : 'v'); X endthreads(code); X cleanup(); X#ifdef TYPE_CHECK X if (cntxt != In_wsgroup && cntxt != In_prmnv) X type_check(*pt); X#endif X set_context(&c); X} X XHidden Procedure no_mysteries() { X value names= keys(mysteries); X int i, n= length(names); X for (i= 1; i <= n; ++i) { X value name= thof(i, names); X value f; X if (!is_zerfun(name, &f)) { X value *aa= envassoc(mysteries, name); X if (locals != Vnil) X e_replace(*aa, &locals, name); X else X e_replace(zero, &globals, name); X } X } X release(names); X} X X/* ******************************************************************** */ X X/* Utilities used by threading. */ X X/* A 'threaded tree' is, in our case, a fixed(*) parse tree with extra links X that are used by the interpreter to determine the execution order. X __________ X (*) 'Fixed' means: processed by 'fix_nodes', which removes UNPARSED X nodes and distinguishes TAG nodes into local, global tags etc. X fix_nodes also creates the threads, but this is accidental, not X essential. For UNPARSED nodes, the threads are actually laid X in a second pass through the subtree that was UNPARSED. X __________ X X A small example: the parse tree for the expression 'a+b*c' looks like X X (DYOP, X (TAGlocal, "a"), X "+", X (DYOP, X (TAGlocal, "b"), X "*", X (TAGlocal, "c"))). X X The required execution order is here: X X 1) (TAGlocal, "a") X 2) (TAGlocal, "b") X 3) (TAGlocal, "c") X 4) (DYOP, ..., "*", ...) X 5) (DYOP, ..., "+", ...) X X Of course, the result of each operation (if it has a result) is pushed X on a stack, and the operands are popped from this same stack. Think of X reversed polish notation (well-known by owners of HP pocket calculators). X X The 'threads' are explicit links from each node to its successor in this X execution order. Conditional operations like IF and AND have two threads, X one for success and one for failure. Loops can be made by having the X thread from the last node of the loop body point to the head of the loop. X X Threading expressions, locations and simple-commands is easy: recursively X thread each of the subtrees, then lay a thread from the last threaded X to the current node. Nodes occurring in a 'location' context are X marked, so that the interpreter knows when to push a 'location' on X the stack. X X Tests and looping commands cause most of the complexity of the threading X utilities. The basic technique is 'backpatching'. X Nodes that need a conditional forward jump are chained together in a X linked list, and when their destination is reached, all nodes in the X chain get its 'address' patched into their secondary thread. There is X one such chain, called 'bpchain', which at all times contains those nodes X whose secondary destination would be the next generated instruction. X This is used by IF, WHILE, test-suites, AND and OR. X X To generate a loop, both this chain and the last normal instruction X (if any) are diverted to the node where the loop continues. X X For test-suites, we also need to be capable of jumping unconditionally X forward (over the remainder of the SELECT-command). This is done by X saving both the backpatch chain and the last node visited, and restoring X them after the remainder has been processed. X*/ X X/* Implementation tricks: in order not to show circular lists to 'release', X parse tree nodes are generated as compounds where there is room for two X more fields than their length indicates. X*/ X X#define Flag (MkSmallInt(1)) X /* Flag used to indicate Location or TestRefinement node */ X XHidden parsetree start; /* First instruction. Picked up by endthreads() */ X XHidden parsetree last; /* Last visited node */ X XHidden parsetree bpchain; /* Backpatch chain for conditional goto's */ XHidden parsetree *wanthere; /* Chain of requests to return next tree */ X X#ifdef MSDOS X#ifdef M_I86LM X X/* Patch for MSC 3.0 large model bugs... */ XVisible parsetree *_thread(p) parsetree p; { X return &_Thread(p); X} X XVisible parsetree *_thread2(p) parsetree p; { X return &_Thread2(p); X} X X#endif /* M_I86LM */ X#endif /* MSDOS */ X X/* Start threading */ X XHidden Procedure inithreads() { X bpchain= NilTree; X wanthere= 0; X last= NilTree; X here(&start); X} X X/* Finish threading */ X XHidden Procedure endthreads(code) parsetree *code; { X jumpto(Stop); X if (!still_ok) start= NilTree; X *code= start; X} X X X/* Fill 't' as secondary thread for all nodes in the backpatch chain, X leaving the chain empty. */ X XHidden Procedure backpatch(t) parsetree t; { X parsetree u; X while (bpchain != NilTree) { X u= Thread2(bpchain); X Thread2(bpchain)= t; X bpchain= u; X } X} X XVisible Procedure jumpto(t) parsetree t; { X parsetree u; X if (!still_ok) return; X while (wanthere != 0) { X u= *wanthere; X *wanthere= t; X wanthere= (parsetree*)u; X } X while (last != NilTree) { X u= Thread(last); X Thread(last)= t; X last= u; X } X backpatch(t); X} X XHidden parsetree seterr(n) int n; { X return (parsetree)MkSmallInt(n); X} X X/* Visit node 't', and set its secondary thread to 't2'. */ X XHidden Procedure visit2(t, t2) parsetree t, t2; { X if (!still_ok) return; X jumpto(t); X Thread2(t)= t2; X Thread(t)= NilTree; X last= t; X} X X/* Visit node 't' */ X XHidden Procedure visit(t) parsetree t; { X visit2(t, NilTree); X} X X/* Visit node 't' and flag it as a location (or test-refinement). */ X XHidden Procedure lvisit(t) parsetree t; { X visit2(t, Flag); X} X X#ifdef NOT_USED XHidden Procedure jumphere(t) parsetree t; { X Thread(t)= last; X last= t; X} X#endif X X/* Add node 't' to the backpatch chain. */ X XHidden Procedure jump2here(t) parsetree t; { X if (!still_ok) return; X Thread2(t)= bpchain; X bpchain= t; X} X XHidden Procedure here(pl) parsetree *pl; { X if (!still_ok) return; X *pl= (parsetree) wanthere; X wanthere= pl; X} X XVisible Procedure hold(pl) struct state *pl; { X if (!still_ok) return; X pl->h_last= last; pl->h_bpchain= bpchain; pl->h_wanthere= wanthere; X last= bpchain= NilTree; wanthere= 0; X} X XVisible Procedure let_go(pl) struct state *pl; { X parsetree p, *w; X if (!still_ok) return; X if (last != NilTree) { X for (p= last; Thread(p) != NilTree; p= Thread(p)) X ; X Thread(p)= pl->h_last; X } X else last= pl->h_last; X if (bpchain != NilTree) { X for (p= bpchain; Thread2(p) != NilTree; p= Thread2(p)) X ; X Thread2(p)= pl->h_bpchain; X } X else bpchain= pl->h_bpchain; X if (wanthere) { X for (w= wanthere; *w != 0; w= (parsetree*) *w) X ; X *w= (parsetree) pl->h_wanthere; X } X else wanthere= pl->h_wanthere; X} X XHidden bool reachable() { X return last != NilTree || bpchain != NilTree || wanthere != 0; X} X X X/* ******************************************************************** */ X/* *********************** code generation **************************** */ X/* ******************************************************************** */ X XForward bool is_variable(); XForward bool is_cmd_ref(); XForward value copydef(); X XVisible Procedure fix(pt, flag) parsetree *pt; char flag; { X struct state st; value v, function; X parsetree t, l1= NilTree, w; X typenode nt, nt1; string s; char c; int n, k, len; X X t= *pt; X if (!Is_node(t) || !still_ok) return; X nt= Nodetype(t); X if (nt < 0 || nt >= NTYPES) syserr(MESS(2200, "fix bad tree")); X s= gentab[nt]; X if (s == NULL) return; X n= First_fieldnr; X if (flag == 'x') curline= t; X while ((c= *s++) != '\0' && still_ok) { X switch (c) { X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X case '8': X case '9': X n= (c - '0') + First_fieldnr; X break; X case 'c': X v= *Branch(t, n); X if (v != Vnil) { X len= Nfields(v); X for (k= 0; k < len; ++k) X fix(Field(v, k), flag); X } X ++n; X break; X case '#': X curlino= *Branch(t, n); X ++n; X break; X case 'g': X case 'h': X ++n; X break; X case 'a': X case 'l': X if (flag == 'v' || flag == 't') X c= flag; X /* Fall through */ X case 'b': X case 't': X case 'u': X case 'v': X case 'x': X fix(Branch(t, n), c); X ++n; X break; X case 'f': X f_fpr_formals(*Branch(t, n)); X ++n; X break; X X case ':': /* code for WHILE loop */ X curlino= *Branch(t, WHL_LINO); X here(&l1); X visit(t); X fix(Branch(t, WHL_TEST), 't'); X v= *Branch(t, WHL_SUITE); X if (nodetype((parsetree) v) != COLON_NODE) X syserr(BAD_WHILE); X visit(v); X fix(Branch(v, COLON_SUITE), 'x'); X jumpto(l1); X jump2here(v); X break; X X case ';': /* code for TEST_SUITE */ X if (*Branch(t, TSUI_TEST) == NilTree) { X sk_tsuite_comment(t, &w); X if (w != NilTree) X fix(&w, 'x'); X break; X } X curlino= *Branch(t, TSUI_LINO); X visit(t); X curline= *Branch(t, TSUI_TEST); X fix(Branch(t, TSUI_TEST), 't'); X v= *Branch(t, TSUI_SUITE); X if (nodetype((parsetree) v) != COLON_NODE) X syserr(BAD_TESTSUITE); X visit2(v, seterr(1)); X fix(Branch(v, COLON_SUITE), 'x'); X hold(&st); X sk_tsuite_comment(t, &w); X if (w != NilTree) { X jump2here(v); X fix(&w, 'x'); X } X let_go(&st); X break; X X case '?': X if (flag == 'v') X f_eunparsed(pt); X else if (flag == 't') X f_cunparsed(pt); X else X syserr(MESS(2201, "fix unparsed with bad flag")); X fix(pt, flag); X break; X case '@': X f_trim_target(t, '@'); X break; X case '|': X f_trim_target(t, '|'); X break; X case 'C': X v= *Branch(t, REL_LEFT); X nt1= nodetype((parsetree) v); X if (Comparison(nt1)) X jump2here(v); X break; X case 'D': X v= (value)*Branch(t, DYA_NAME); X if (!is_dyafun(v, &function)) X fixerrV(NO_DEFINITION, v); X else X *Branch(t, DYA_FCT)= copydef(function); X break; X case 'E': X v= (value)*Branch(t, DYA_NAME); X if (!is_dyaprd(v, &function)) X fixerrV(NO_DEFINITION, v); X else X *Branch(t, DYA_FCT)= copydef(function); X break; X case 'F': X if (*Branch(t, NUM_VALUE) == Vnil) { X *Branch(t, NUM_VALUE)= X numconst(*Branch(t, NUM_TEXT)); X } X break; X case 'G': X jumpto(l1); X break; X case 'H': X here(&l1); X break; X case 'I': X if (*Branch(t, n) == NilTree) X break; X /* Else fall through */ X case 'J': X jump2here(t); X break; X case 'K': X hold(&st); X break; X case 'L': X let_go(&st); X break; X case 'M': X v= (value)*Branch(t, MON_NAME); X if (is_variable(v) || !is_monfun(v, &function)) X fixerrV(NO_DEFINITION, v); X else X *Branch(t, MON_FCT)= copydef(function); X break; X case 'N': X v= (value)*Branch(t, MON_NAME); X if (is_variable(v) || !is_monprd(v, &function)) X fixerrV(NO_DEFINITION, v); X else X *Branch(t, MON_FCT)= copydef(function); X break; X case 'Q': /* don't visit comment SUITE nodes */ X if (*Branch(t, n) != NilTree) X visit(t); X break; X#ifdef REACH X case 'R': X if (*Branch(t, n) != NilTree && !reachable()) X fixerr(MESS(2202, "command cannot be reached")); X break; X#endif X case 'S': X jumpto(Stop); X break; X case 'T': X if (flag == 't') X f_ctag(pt); X else if (flag == 'v' || flag == 'x') X f_etag(pt); X else X f_ttag(pt); X break; X case 'U': X f_ucommand(pt); X break; X case 'V': X visit(t); X break; X case 'X': X if (flag == 'a' || flag == 'l' || flag == 'b') X lvisit(t); X else X visit(t); X break; X case 'W': X/*!*/ visit2(t, seterr(1)); X break; X case 'Y': X if (still_ok && reachable()) { X if (nt == YIELD) X fixerr(YIELD_NO_RETURN); X else X fixerr(TEST_NO_REPORT); X } X break; X case 'Z': X if (!is_cmd_ref(t) && still_ok && reachable()) X fixerr(MESS(2203, "refinement returns no value or reports no outcome")); X *Branch(t, REF_START)= copy(l1); X break; X } X } X} X X/* skip test-suite comment nodes */ X XHidden Procedure sk_tsuite_comment(v, w) parsetree v, *w; { X while ((*w= *Branch(v, TSUI_NEXT)) != NilTree && X Nodetype(*w) == TEST_SUITE && X *Branch(*w, TSUI_TEST) == NilTree) X v= *w; X} X X/* ******************************************************************** */ X XHidden bool is_cmd_ref(t) parsetree t; { /* HACK */ X value name= *Branch(t, REF_NAME); X string s; X X if (!Valid(name)) X return No; X s= strval(name); X /* return isupper(*s); */ X return *s <= 'Z' && *s >= 'A'; X} X XVisible bool is_name(v) value v; { X if (!Valid(v) || !Is_text(v)) X return No; X else { X string s= strval(v); X /* return islower(*s); */ X return *s <= 'z' && *s >= 'a'; X } X} X XVisible value copydef(f) value f; { X if (f == Vnil || Funprd(f)->pre == Use) return Vnil; X return copy(f); X} X XHidden bool is_basic_target(v) value v; { X if (!Valid(v)) X return No; X return locals != Vnil && envassoc(locals, v) != Pnil || X envassoc(globals, v) != Pnil; X} X XHidden bool is_variable(v) value v; { X value f; X if (!Valid(v)) X return No; X return is_basic_target(v) || X envassoc(refinements, v) != Pnil || X is_zerfun(v, &f); X} X XHidden bool is_target(p) parsetree *p; { X value v; X int k, len; X parsetree w, *left, *right; X typenode trimtype; X typenode nt= nodetype(*p); X X switch (nt) { X X case TAG: X v= *Branch(*p, First_fieldnr); X return is_basic_target(v); X X case SELECTION: X case BEHEAD: X case CURTAIL: X case COMPOUND: X return is_target(Branch(*p, First_fieldnr)); X X case COLLATERAL: X v= *Branch(*p, First_fieldnr); X len= Nfields(v); X k_Overfields { X if (!is_target(Field(v, k))) return No; X } X return Yes; X case DYAF: X if (trim_opr(*Branch(*p, DYA_NAME), &trimtype)) { X left= Branch(*p, DYA_LEFT); X if (is_target(left)) { X right= Branch(*p, DYA_RIGHT); X w= node3(trimtype, copy(*left), copy(*right)); X release(*p); X *p= w; X return Yes; X } X } X return No; X X default: X return No; X X } X} X XHidden bool trim_opr(name, type) value name; typenode *type; { X value v; X X if (!Valid(name)) X return No; X if (compare(name, v= mk_text(S_BEHEAD)) == 0) { X release(v); X *type= BEHEAD; X return Yes; X } X release(v); X if (compare(name, v= mk_text(S_CURTAIL)) == 0) { X release(v); X *type= CURTAIL; X return Yes; X } X release(v); X return No; X} X X/* ******************************************************************** */ X X#define WRONG_KEYWORD MESS(2204, "wrong keyword %s") X#define NO_ACTUAL MESS(2205, "missing actual parameter after %s") X#define EXP_KEYWORD MESS(2206, "can't find expected %s") X#define ILL_ACTUAL MESS(2207, "unexpected actual parameter after %s") X#define ILL_KEYWORD MESS(2208, "unexpected keyword %s") X XHidden Procedure f_actuals(formals, actuals) parsetree formals, actuals; { X /* name, actual, next */ X parsetree act, form, next_a, next_f, kw, *pact; X X do { X kw= *Branch(actuals, ACT_KEYW); X pact= Branch(actuals, ACT_EXPR); act= *pact; X form= *Branch(formals, FML_TAG); X next_a= *Branch(actuals, ACT_NEXT); X next_f= *Branch(formals, FML_NEXT); X X if (compare(*Branch(formals, FML_KEYW), kw) != 0) X fixerrV(WRONG_KEYWORD, kw); X else if (act == NilTree && form != NilTree) X fixerrV(NO_ACTUAL, kw); X else if (next_a == NilTree && next_f != NilTree) X fixerrV(EXP_KEYWORD, *Branch(next_f, FML_KEYW)); X else if (act != NilTree && form == NilTree) X fixerrV(ILL_ACTUAL, kw); X else if (next_a != NilTree && next_f == NilTree) X fixerrV(ILL_KEYWORD, *Branch(next_a, ACT_KEYW)); X else if (act != NilTree) X act_expr_gen(pact, form); X actuals= next_a; X formals= next_f; X } X while (still_ok && actuals != NilTree); X} X X/* Fix and generate code for an actual parameter. X This generates 'locate' code if it looks like a target, X or 'evaluate' code if the parameter looks like an expression. X The formal parameter's form is also taken into account: X if it is a compound, and the actual is also a compound, X the number of fields must match and the decision between 'locate' X and 'evaluate' code is made recursively for each field. X (If the formal is a compound but the actual isn't, X that's OK, since it might be an expression or simple location X of type compound. X The reverse is also acceptable: then the formal parameter has X a compound type.) */ X XHidden Procedure act_expr_gen(pact, form) parsetree *pact; parsetree form; { X while (Nodetype(form) == COMPOUND) X form= *Branch(form, COMP_FIELD); X while (Nodetype(*pact) == COMPOUND) X pact= Branch(*pact, COMP_FIELD); X if (Nodetype(form) == COLLATERAL && Nodetype(*pact) == COLLATERAL) { X value vact= *Branch(*pact, COLL_SEQ); X value vform= *Branch(form, COLL_SEQ); X int n= Nfields(vact); X if (n != Nfields(vform)) X fixerr(MESS(2209, "compound parameter has wrong length")); X else { X int k; X for (k= 0; k < n; ++k) X act_expr_gen(Field(vact, k), *Field(vform, k)); X visit(*pact); X } X } X else { X if (is_target(pact)) X f_targ(pact); X else X f_expr(pact); X } X} X XHidden Procedure f_ucommand(pt) parsetree *pt; { X value t= *pt, *aa; X parsetree u, f1= *Branch(t, UCMD_NAME), f2= *Branch(t, UCMD_ACTUALS); X release(*Branch(t, UCMD_DEF)); X *Branch(t, UCMD_DEF)= Vnil; X if ((aa= envassoc(refinements, f1)) != Pnil) { X if (*Branch(f2, ACT_EXPR) != Vnil X || *Branch(f2, ACT_NEXT) != Vnil) X fixerr(MESS(2210, "refinement with parameters")); X else *Branch(t, UCMD_DEF)= copy(*aa); X } X else if (is_unit(f1, Cmd, &aa)) { X u= How_to(*aa)->unit; X f_actuals(*Branch(u, HOW_FORMALS), f2); X } X else fixerrV(MESS(2211, "you haven't told me HOW TO %s"), f1); X} X XHidden Procedure f_fpr_formals(t) parsetree t; { X typenode nt= nodetype(t); X X switch (nt) { X case TAG: X break; X case MONF: case MONPRD: X f_targ(Branch(t, MON_RIGHT)); X break; X case DYAF: case DYAPRD: X f_targ(Branch(t, DYA_LEFT)); X f_targ(Branch(t, DYA_RIGHT)); X break; X default: X syserr(MESS(2212, "f_fpr_formals")); X } X} X XVisible bool modify_tag(name, tag) parsetree *tag; value name; { X value *aa, function; X *tag= NilTree; X if (!Valid(name)) X return No; X else if (locals != Vnil && (aa= envassoc(locals, name)) != Pnil) X *tag= node3(TAGlocal, name, copy(*aa)); X else if ((aa= envassoc(globals, name)) != Pnil) X *tag= node2(TAGglobal, name); X else if ((aa= envassoc(refinements, name)) != Pnil) X *tag= node3(TAGrefinement, name, copy(*aa)); X else if (is_zerfun(name, &function)) X *tag= node3(TAGzerfun, name, copydef(function)); X else if (is_zerprd(name, &function)) X *tag= node3(TAGzerprd, name, copydef(function)); X else return No; X return Yes; X} X XHidden Procedure f_etag(pt) parsetree *pt; { X parsetree t= *pt; value name= copy(*Branch(t, TAG_NAME)); X if (modify_tag(name, &t)) { X release(*pt); X *pt= t; X if (Nodetype(t) == TAGzerprd) X fixerrV(MESS(2213, "%s cannot be used in an expression"), name); X else X visit(t); X } else { X fixerrV(NO_INIT_OR_DEF, name); X release(name); X } X} X XHidden Procedure f_ttag(pt) parsetree *pt; { X parsetree t= *pt; value name= copy(*Branch(t, TAG_NAME)); X if (modify_tag(name, &t)) { X release(*pt); X *pt= t; X switch (Nodetype(t)) { X case TAGrefinement: X fixerr(REF_NO_TARGET); X break; X case TAGzerfun: X case TAGzerprd: X fixerrV(NO_INIT_OR_DEF, name); X break; X default: X lvisit(t); X break; X } X } else { X fixerrV(NO_INIT_OR_DEF, name); X release(name); X } X} X X#define NO_REF_OR_ZER MESS(2214, "%s is neither a refined test nor a zeroadic predicate") X XHidden Procedure f_ctag(pt) parsetree *pt; { X parsetree t= *pt; value name= copy(*Branch(t, TAG_NAME)); X if (modify_tag(name, &t)) { X release(*pt); X *pt= t; X switch (Nodetype(t)) { X case TAGrefinement: X lvisit(t); /* 'Loc' flag here means 'Test' */ X break; X case TAGzerprd: X visit(t); X break; X default: X fixerrV(NO_REF_OR_ZER, name); X break; X } X } else { X fixerrV(NO_REF_OR_ZER, name); X release(name); X } X} END_OF_FILE if test 19819 -ne `wc -c <'abc/bint2/i2gen.c'`; then echo shar: \"'abc/bint2/i2gen.c'\" unpacked with wrong size! fi # end of 'abc/bint2/i2gen.c' fi if test -f 'abc/bint3/i3bws.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'abc/bint3/i3bws.c'\" else echo shar: Extracting \"'abc/bint3/i3bws.c'\" \(10277 characters\) sed "s/^X//" >'abc/bint3/i3bws.c' <<'END_OF_FILE' X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1988. */ X X#include "b.h" X#include "bint.h" X#include "bfil.h" X#include "bmem.h" X#include "bobj.h" X#include "args.h" X#include "feat.h" X#include "i2par.h" X#include "i3bws.h" X#include "i3env.h" X#include "i3sou.h" X X/* ******************************************************************** */ X/* workspace routines */ X/* ******************************************************************** */ X XVisible char *bwsdir= (char *) NULL; /* group name workspaces */ X XVisible value ws_group= Vnil; /* index workspaces */ XVisible bool groupchanges= No; /* if Yes index is changed */ X XVisible value curwskey= Vnil; /* special index key for cur_ws */ XVisible value lastwskey= Vnil; /* special index key for last_ws */ X XVisible value cur_ws= Vnil; /* the current workspace */ X /* only visible for m1bio.c */ XHidden value last_ws= Vnil; /* the last visited workspace */ X XHidden bool path_workspace= No; /* if Yes no workspace change allowed */ X X#define gr_exists(name, aa) (in_env(ws_group, name, aa)) X#define def_group(name, f) (e_replace(f, &ws_group, name), groupchanges= Yes) X#define free_group(name) (e_delete(&ws_group, name), groupchanges= Yes) X X#ifndef DIRMODE X#define DIRMODE 0777 X#endif X X/* ******************************************************************** */ X X#define DEFAULT_WS "first" X X#define CURWSKEY ">" X#define LASTWSKEY ">>" X XHidden Procedure initgroup() { X wsgroupfile= (string) makepath(bwsdir, WSGROUPFILE); X curwskey= mk_text(CURWSKEY); X lastwskey= mk_text(LASTWSKEY); X if (F_exists(wsgroupfile)) { X value fname= mk_text(wsgroupfile); X ws_group= getval(fname, In_wsgroup); X release(fname); X if (!still_ok) { X still_ok= Yes; X rec_wsgroup(); X } X X } X else ws_group= mk_elt(); X groupchanges= No; X} X XHidden Procedure endgroup() { X save_curlast(curwskey, cur_ws); X save_curlast(lastwskey, last_ws); X only_default(); X put_wsgroup(); X} X XHidden Procedure save_curlast(wskey, ws) value wskey, ws; { X value *aa; X X if (Valid(ws) && (!gr_exists(wskey, &aa) || (compare(ws, *aa) != 0))) X def_group(wskey, ws); X} X X/* X * removes the default entry if it is the only one; X * the default is [CURWSKEY]: DEFAULT_WS; X * this has to be done to create the possibility of removing an empty X * wsgroupfile and bwsdefault directory; X * still this will hardly happen (see comments in endbws() ) X */ X XHidden Procedure only_default() { X value *aa; X X if (length(ws_group) == 1 && X Valid(curwskey) && gr_exists(curwskey, &aa) X ) { X value defws= mk_text(DEFAULT_WS); X if (compare(defws, *aa) == 0) X free_group(curwskey); X release(defws); X } X} X XHidden Procedure put_wsgroup() { X value fn; X intlet len; X X if (!groupchanges || !Valid(ws_group)) X return; X fn= mk_text(wsgroupfile); X /* Remove the file if empty */ X len= length(ws_group); X if (len == 0) X f_delete(fn); X else X putval(fn, ws_group, Yes, In_wsgroup); X release(fn); X groupchanges= No; X} X X/* ******************************************************************** */ X XHidden bool wschange(ws) value ws; { X value name, *aa; X bool new= No, changed; X char *path; X X if (gr_exists(ws, &aa)) X name= copy(*aa); X else { X name= new_fname(ws, Wsp); X if (!Valid(name)) X return No; X new= Yes; X } X path= makepath(bwsdir, strval(name)); X VOID Mkdir(path); X changed= chdir(path) == 0 ? Yes : No; X if (changed && new) X def_group(ws, name); X freepath(path); X release(name); X return changed; X} X XHidden Procedure wsempty(ws) value ws; { X char *path, *permpath; X value *aa; X X if (!gr_exists(ws, &aa)) X return; X path= makepath(bwsdir, strval(*aa)); X permpath= makepath(path, permfile); X if (F_exists(permpath)); X else if (strcmp(startdir, path) == 0); X else if (rmdir(path) != 0); X else free_group(ws); X freepath(path); X freepath(permpath); X} X X/* ******************************************************************** */ X XVisible Procedure goto_ws() { X value ws= Vnil; X bool prname; /* print workspace name */ X X if (path_workspace) { X parerr(MESS(2900, "change of workspace not allowed")); X return; X } X if (Ceol(tx)) { X if (Valid(last_ws)) X ws= copy(last_ws); X else X parerr(MESS(2901, "no previous workspace")); X prname= Yes; X } X else if (is_tag(&ws)) X prname= No; X else X parerr(MESS(2902, "I find no workspace name here")); X X if (still_ok && (compare(ws, cur_ws) != 0)) { X can_interrupt= No; X endworkspace(); X X if (wschange(ws)) { X release(last_ws); last_ws= copy(cur_ws); X release(cur_ws); cur_ws= copy(ws); X } X else { X parerrV(MESS(2903, "I can't goto/create workspace %s"), ws); X still_ok= Yes; X prname= No; X } X X init_workspace(prname); X wsempty(last_ws); X can_interrupt= Yes; X } X release(ws); X} X XVisible Procedure lst_wss() { X value wslist, ws; X value k, len, m; X X if (path_workspace) { X print_wsname(); X return; X } X wslist= keys(ws_group); X X if (!in(cur_ws, wslist)) X insert(cur_ws, &wslist); X X k= one; len= size(wslist); X while (numcomp(k, len) <= 0) { X ws= item(wslist, k); X if (compare(ws, curwskey) == 0); X else if (compare(ws, lastwskey) == 0); X else if (compare(ws, cur_ws) == 0) X putSstr(stdout, ">%s ", strval(ws)); X else X putSstr(stdout, "%s ", strval(ws)); X release(ws); X k= sum(m= k, one); X release(m); X } X if (numcomp(len, zero) > 0) X putnewline(stdout); X fflush(stdout); X release(k); release(len); X release(wslist); X} X X/************************************************************************/ X X#define NO_PARENT MESS(2905, "*** I cannot find parent directory\n") X#define NO_WORKSPACE MESS(2906, "*** I cannot find workspace\n") X#define NO_DEFAULT MESS(2907, "*** I cannot find your home directory\n") X#define USE_CURRENT MESS(2908, "*** I shall use the current directory as your single workspace\n") X#define NO_ABCNAME MESS(2909, "*** %s isn't an ABC name\n") X#define TRY_DEFAULT MESS(2910, "*** I shall try the default workspace\n") X XHidden Procedure wserr(m, use_cur) int m; bool use_cur; { X putmess(errfile, m); X if (use_cur) X wscurrent(); X} X XHidden Procedure wserrV(m, v, use_cur) int m; value v; bool use_cur; { X putSmess(errfile, m, strval(v)); X if (use_cur) X wscurrent(); X} X XHidden Procedure wscurrent() { X putmess(errfile, USE_CURRENT); X path_workspace= Yes; X} X X/* ******************************************************************** */ X XHidden bool wsinit() { X value *aa; X X initgroup(); X cur_ws= Vnil; X last_ws= Vnil; X if (wsp_arg) { X /* wsp_arg is a single name here, not a pathname */ X#ifdef WSP_DIRNAME X /* on the mac wsp_arg is a mac foldername, not an ABC wsname */ X cur_ws= abc_wsname(wsp_arg); X if (!Valid(cur_ws)) X return No; X#else X /* wsp_arg is here an ABC workspace name, not a path */ X cur_ws= mk_text(wsp_arg); X#endif X if (!is_abcname(cur_ws)) { X wserrV(NO_ABCNAME, cur_ws, No); X wserr(TRY_DEFAULT, No); X release(cur_ws); cur_ws= Vnil; X } X } X if (gr_exists(curwskey, &aa)) { X if (!Valid(cur_ws)) X cur_ws= copy(*aa); X else if (compare(cur_ws, *aa) != 0) X last_ws= copy(*aa); X if (!Valid(last_ws) && gr_exists(lastwskey, &aa)) X last_ws= copy(*aa); X } X if (!Valid(cur_ws)) X cur_ws= mk_text(DEFAULT_WS); X if (!is_abcname(cur_ws)) X wserrV(NO_ABCNAME, cur_ws, Yes); X else if (wschange(cur_ws)) { X path_workspace= No; X return Yes; X } X else wserr(NO_WORKSPACE, Yes); X return No; X} X XVisible Procedure initbws() { X if (is_gr_reccall) { /* recover index of group workspaces */ X if (!setbwsdir() || !D_exists(bwsdir)) { X wserr(NO_PARENT, No); X immexit(1); X } X initgroup(); X return; X } X if (is_path(wsp_arg)) { X /* !bws_arg already assured in main.c */ X if (chdir(wsp_arg) != 0) X wserr(NO_WORKSPACE, Yes); X else X path_workspace= Yes; X } X else if (setbwsdir()) { X if (!D_exists(bwsdir)) X wserr(NO_PARENT, Yes); X else if (!wsinit()) X wsrelease(); X } X else wserr(NO_DEFAULT, Yes); X if (path_workspace) { X release(cur_ws); X cur_ws= mk_text(curdir()); X } X init_workspace(Yes); X} X XVisible Procedure endbws() { X if (!is_gr_reccall) { X endworkspace(); X VOID chdir(startdir); X if (path_workspace) { X release(cur_ws); X cur_ws= Vnil; X return; X } X else wsempty(cur_ws); X } X /* else: only index of group workspaces recovered */ X X endgroup(); X /* X * if the bwsdefault directory is used and empty, remove it; X * because of the savings of the last two visited workspaces X * in the file `bwsdefault`/`wsgroupfile` this will hardly happen; X * only if you stays for ever in the default workspace. X */ X if (!bws_arg && bwsdefault) X VOID rmdir(bwsdefault); /* fails if not empty */ X wsrelease(); X} X XVisible bool is_path(path) char *path; { X if (path == (char *) NULL) X return No; X if (strcmp(path, CURDIR) == 0 || strcmp(path, PARENTDIR) == 0) X return Yes; X for (; *path; path++) { X if (Isanysep(*path)) return Yes; X } X return No; X} X XHidden bool setbwsdir() { X if (bws_arg || bwsdefault) { X if (!bws_arg) { X bwsdir= savepath(bwsdefault); /* full path name */ X VOID Mkdir(bwsdir); X } X else if (!Isabspath(bws_arg)) X bwsdir= makepath(startdir, bws_arg); X else X bwsdir= savepath(bws_arg); X return Yes; X } X return No; X} X XHidden Procedure wsrelease() { X release(last_ws); last_ws= Vnil; X release(cur_ws); cur_ws= Vnil; X release(lastwskey); lastwskey= Vnil; X release(curwskey); curwskey= Vnil; X release(ws_group); ws_group= Vnil; X freepath(wsgroupfile); wsgroupfile= (string) NULL; X freepath(bwsdir); bwsdir= (char *) NULL; X} X X/************************************************************************/ X XHidden Procedure init_workspace(prname) bool prname; { X if (interactive && prname) X print_wsname(); X initworkspace(); X if (!still_ok) { X still_ok= Yes; X rec_workspace(); X } X} X XVisible Procedure initworkspace() { X initsou(); X initfpr(); X initenv(); X#ifdef USERSUGG X initsugg(); X#endif X#ifdef SAVEPOS X initpos(); X#endif X#ifdef TYPE_CHECK X initstc(); X#endif X setprmnv(); X initperm(); X} X XVisible Procedure endworkspace() { X endperm(); X endsou(); X endenv(); X#ifdef USERSUGG X endsugg(); X#endif X#ifdef SAVEPOS X endpos(); X#endif X#ifdef TYPE_CHECK X endstc(); X#endif X enderro(); X} X X/************************************************************************/ X XVisible bool wsp_writable() { X return F_writable(CURDIR) ? Yes : No; X} X XHidden Procedure print_wsname() { X putSstr(errfile, ">%s\n", strval(cur_ws)); X fflush(errfile); X} X X/************************************************************************/ END_OF_FILE if test 10277 -ne `wc -c <'abc/bint3/i3bws.c'`; then echo shar: \"'abc/bint3/i3bws.c'\" unpacked with wrong size! fi # end of 'abc/bint3/i3bws.c' fi if test -f 'abc/ex/try/position.abc' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'abc/ex/try/position.abc'\" else echo shar: Extracting \"'abc/ex/try/position.abc'\" \(12 characters\) sed "s/^X//" >'abc/ex/try/position.abc' <<'END_OF_FILE' Xstart.cmd 4 END_OF_FILE if test 12 -ne `wc -c <'abc/ex/try/position.abc'`; then echo shar: \"'abc/ex/try/position.abc'\" unpacked with wrong size! fi # end of 'abc/ex/try/position.abc' fi echo shar: End of archive 7 \(of 25\). cp /dev/null ark7isdone MISSING="" 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 if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 25 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still must unpack the following archives: echo " " ${MISSING} fi exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.