AU710748B2 - A system for viewing the structure of computer graphical elements - Google Patents

A system for viewing the structure of computer graphical elements Download PDF

Info

Publication number
AU710748B2
AU710748B2 AU55985/96A AU5598596A AU710748B2 AU 710748 B2 AU710748 B2 AU 710748B2 AU 55985/96 A AU55985/96 A AU 55985/96A AU 5598596 A AU5598596 A AU 5598596A AU 710748 B2 AU710748 B2 AU 710748B2
Authority
AU
Australia
Prior art keywords
doc
string
int
return
null
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Ceased
Application number
AU55985/96A
Other versions
AU5598596A (en
Inventor
Timothy Merrick Long
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Canon Inc
Original Assignee
Canon Information Systems Research Australia Pty Ltd
Canon Inc
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Priority claimed from AUPN3603A external-priority patent/AUPN360395A0/en
Application filed by Canon Information Systems Research Australia Pty Ltd, Canon Inc filed Critical Canon Information Systems Research Australia Pty Ltd
Priority to AU55985/96A priority Critical patent/AU710748B2/en
Publication of AU5598596A publication Critical patent/AU5598596A/en
Application granted granted Critical
Publication of AU710748B2 publication Critical patent/AU710748B2/en
Assigned to CANON KABUSHIKI KAISHA reassignment CANON KABUSHIKI KAISHA Alteration of Name(s) in Register under S187 Assignors: CANON INFORMATION SYSTEMS RESEARCH AUSTRALIA PTY LTD, CANON KABUSHIKI KAISHA
Anticipated expiration legal-status Critical
Ceased legal-status Critical Current

Links

Landscapes

  • Information Retrieval, Db Structures And Fs Structures Therefor (AREA)

Description

-1 A SYSTEM FOR VIEWING THE STRUCTURE OF COMPUTER GRAPHICAL ELEMENTS Field of the Invention The present invention relates to the construction or creation of computer graphics images and, more particularly, provides a simplified form of visualising the interrelationships between elements or objects contained in an image created using a computer graphics applications package.
Background of the Invention With the pace of advancement of computers, computer systems including software application packages for the creation of full color computer images of substantial complexity are becoming ever more prevalent. The complexity of the images created is also increasing so that created images made up of hundreds, or even 15 thousands, of separate objects are common.
S" :The human creator of such a complex image often relies on a hierarchical, or top-down, approach to deal with the complexity of the image. In this respect, "grouping" operations well know to those skilled in the art of creating complex computer graphics are used to treat a group of objects as a single entity for copying, moving, rescaling, or other complex operations.
As the complexity of an image increases, the complexity of the hierarchy of interrelated objects also increases. Often the creator of an image wishes to access a certain object or group of objects within the hierarchy. However, these objects can be either partially or fully obscured by other objects and can form part of a large collection of different groups of objects. Thus, even if a given object has a certain number of associated control points, as is normal in the art, it is unlikely that a particular object can be selected within a large complex hierarchy of objects. This is particularly the case where the object to be selected or changed is "buried" deep within the hierarchy with other objects also overlapping the current object.
[N:\1ibccl00537:SDB At the very least, a considerable disadvantage of the prior art resides in the substantial frustration and annoyance experienced by the creator in having to move and "ungroup" a substantial number of objects within the hierarchy merely to alter the characteristics of one of those objects. Further, another disadvantage arises because the particular groupings are often of great importance and cannot be readily recovered once an ungrouping operation has been performed.
Summary of the Invention It is an object of the present invention to provide a system for simply and efficiently dealing with images having a substantial number of objects which are interrelated in a complex manner and to overcome one or more disadvantages of the prior art.
In accordance with a first aspect of the present invention, there is provided a method for displaying a grouped structure in a computer graphics image, said method 15 comprising the steps of: providing at least one selection tag for said grouped structure; utilising a group display mode, whereby portions of the structure of said grouped structure are determined as a selection tag of said grouped structure is selected in said group display mode; and 20 displaying said portions of the structure of said grouped structures in a tree format; whereby said portions provide details of the structure of said grouped st. *u structure.
343322 CFP0461AU Open22 [o\cisra\open\open221343322.doc 2A In accordance with a second aspect of the invention, there is provided an an apparatus for displaying a grouped structure in a computer graphics image, comprising: means for providing at least one selection tag for said grouped structure; means for providing a group display mode and for determining portions of the structure of said grouped structure in response to selection of a selection tag of said grouped structure in a group display mode; and means for displaying said portions of the structure of said grouped structures in a tree format, said display means coupled to said group display mode means, whereby said portions provide details of the structure of said grouped structure e ee 343322 CFP0461AU Open22 [o\cisra\open\open22]343322.doc -3- Brief Description of the Drawings The embodiments of the invention will now be described with reference to the accompanying drawings, in which:- Fig. 1 illustrates an object drawn utilising a computer graphics package; Fig. 2 illustrates a "tree-view" of 4the object of Fig. 1 according to the preferred embodiment; Fig. 3 illustrates two objects constructed in accordance with Fig. 1 and grouped together; Figs. 4 and 5 illustrate various tree-views of the grouped structure of Fig. 3; Fig. 6 illustrates two objects constructed in accordance with Fig. 3 which have been grouped together; Figs. 7 and 8 illustrate various tree-views of the object of Fig. 6; Fig. 9 illustrates an object constructed from two objects constructed in accordance with Fig. 6; 15 Fig. 10 illustrates a tree-view of the object of Fig. 9; Fig. 11 illustrates the selection of an object within a group in accordance with the preferred embodiment; Fig. 12 is a block diagram of a general purpose computer with which the preferred embodiment can be implemented; Fig. 13 is a flow diagram illustrating the method according to the preferred embodiment; Fig. 14 is a detailed flow diagram illustrating a number of steps that can be practiced in step 1304 of Fig. 13; and Fig. 15 is a detailed flow diagram illustrating a number of steps that can be practiced in step 1306 of Fig. 13.
Detailed Description Embodiments of the invention will now be described with reference to Figs. 1 to 15. In particular, a method and apparatus according to the preferred embodiment is [N:\Iibcc]00537:SDB provided for producing a "tree-view" on demand of a group structure in a computer graphics image when required by a user. The method and apparatus facilitate control over the complexity of the hierarchical ordering of the objects in an image. This enables a user to interrogate the structure of a given image and individually access the objects within it.
In accordance with the preferred embodiment, the system can be practiced using a conventional general purpose computer such as the one shown in Fig. 12. The computer system 1200 consists of the computer 1202, a video display 1216, and input devices 1218, 1220. In addition, the computer 1200 system can also have any of a number of other output devices including line printers, laser printers, plotters, and other reproduction devices connected to the computer 1202. The computer system 1200 can be connected to one or more other computers using an appropriate communication channel such as a modem communications path, a computer network, or the like.
15 The computer 1202 itself consists of a central processing unit(s) (simply referred to as a processor hereinafter) 1204, a memory 1206 which can include random access memory (RAM) and read-only memory (ROM), an input/output (IO) interface 1208, a video interface 1210, and one or more storage devices generally represented by S"a block 1212 in Fig. 12. The storage device(s) 1212 can consist of one or more of the following: a floppy disc, a hard disc drive, a magneto-optical disc drive, CD-ROM or any other of a number of non-volatile storage devices well known to those skilled in the art. Each of the components 1204 to 1212 is typically connected to one or more of the other devices via a bus 1214 that in turn can consist of data, address, and control buses.
The video interface 1210 is connected to the video display 1216 and provides video signals from the computer 1202 for display on the video display 1216. User input to operate the computer 1202 can be provided for one or more input devices. A user can use the keyboard 1218 and/or a pointing device such as the mouse 1220 to provide input to the computer 1202. The input devices 1218, 1220 are further described below in relation to the preferred embodiment.
[N:\fibcc100537:SDB The system for viewing the structure of computer graphical elements according to the preferred embodiment is preferably implemented using a general purpose computer, such as computer system 1200 of Fig. 12. Operation of the system is now described with reference to Figs. 13 to In Fig. 13, processing begins at step 1300. In step 1302, an image is displayed having a group structure, where the image has at least one object within the group. In step 1304, the system provides a group display mode for displaying portions of the group structure. When a selection tag of the grouped structure is selected in the group display mode, portions of the structure of the grouped structure are determined.
The selection tag is selected by a user operating an input device 1218, 1220, which is preferably the mouse 1220. The selection tag of the group structure is displayed on the video display 1216 by the computer 1202. In step 1308, processing stops.
Preferably, step 1304 of Fig. 13 comprises two further sub-steps, as shown in .Fig. 14 and indicated by dashed lines. In step 1402, a top-level portion of the group structure is displayed on the video display 1216 by the computer 1202. In step 1404, one or more sub-level portions of the group structure can be displayed on the video display 1216.
Fig. 15 is a detailed flow diagram illustrating a number of steps that can be practiced as part of step 1306 of Fig. 13. In step 1502, the portions of the group structure are displayed in a tree format. In step 1504, means for selecting a current node within the tree format is provided. Optionally, in step 1506, the child nodes of the current node are displayed when the current node is selected. Optionally, in step 1508, means for selecting a sub-portion of the displayed portions of the group structure and for interactively accessing the selected sub-portion are provided.
The method and apparatus in accordance with the preferred embodiment shown in Figs. 12 to 15 will now be described by way of a number of examples shown in Figs. 1 to 11.
Fig. 1 illustrates a square 1 having a blend from white to black which gradually increases from, white in the bottom, left-had corner 2 .to black in the top, (N:\Iibccl100537:SDB right-hand corner 3. The square 1 has the usual control points 4 at each corner in addition to central control point 5 indicated by a cross. The control points 4,5 allow for the manipulation of the square 1 in the usual manner. A more detailed discussion of conventional control point techniques can be found in a standard text in the field see Foley, James et al., Computer Graphics: Principles and Practice, Addison- Wesley Publishing Company, Inc., Reading, Massachusetts, 1990, Chapters 8 to The method and apparatus according to the preferred embodiment provides a tree-view as a mode of operation of a computer graphics application. Once this mode is set, an interactive input device, such as "mouse" or the like, 1220 can be utilised to select one of the control points 4,5. Upon selection of the object 1, a "tree-view" of the hierarchical structure of the object is immediately illustrated over the object 1.
Fig. 2 illustrates a corresponding tree-view of the object 1 having nodes 10 and 11 when the central control point 5 is selected in tree-viewing mode. The two nodes 10,11 of the tree-view show information relevant to the hierarchical structure of the 5is selected element 1. In this example, the node 10 indicates that the object 1, which :exists by itself, is in a group having one element. The node 11 also informs the user that the object 1 has four corner control points 4 that can be manipulated. While the following embodiments will be described in terms of four or five control points, it will be apparent to a person skilled in the art that the system can be practised with other numbers of control points without departing from the scope and spirit of the invention.
The preferred embodiment will now be described with reference to a graphics application package that allows for grouping together of objects in the conventional manner, well known to those skilled in the art. For example, in Fig. 3, two objects 16,17 are shown having the same form as the object 1 of Fig. 1. The object 17 has been produced from the object 1 using conventional copy and paste operations. The two objects 16,17 have also been conventionally grouped together to form a grouped object 23, generally indicated by dashed lines. Five group control points 18 to 22 have also been provided for the manipulation of the overall group structure 23.
[N:\Iibcc00537:SDB -7- Fig. 4 illustrates an initial tree-view 24 in accordance with the preferred embodiment that includes nodes 25,26 describing the structure of the group 23 of Fig.
3. The node 25, being the roof node of the tree-view, is used to inform the user that the group 23 is grouped together. Node 26 informs the user that the group 23 comprises two sub-elements or groups.
In tree-viewing mode, when the node 26 is selected by the user using an interactive pointing device 1220, the displayed presentation of Fig. 4 is transformed into the displayed presentation of Fig. 5. In the latter view, a further level of the "tree" indicated by a node 26 shows more detail of the structure of the overall object 23 of Fig. 3. In particular, two further nodes 27,28 show that the two squares 16,17 in the group 23 of Fig. 3 each have four independent control points.
Fig. 6 illustrates two copies of the object 23 of Fig. 3 which have been grouped together to form a grouped object 30. This grouped object 30 can be easily produced by copying and pasting the object 23 of Fig. 3 and subsequently grouping the S: 15 two objects together. Upon grouping, the object 30 is displayed with five control points 31 to Fig. 7 illustrates a tree-view of the object 30 of Fig. 6 when the control point *31 is chosen in tree-view mode. Initially, only the highest nodes 40 and 41 in the hierarchy are illustrated. However, when node 41 is selected using the interactive pointing device, nodes 42 and 45 appear in the tree-view mode. Further, upon selection of the node 42, nodes 43 and 44 appear in the tree-view mode. By the process of node selection, the user of the tree-view system is able to determine the level to which the tree is displayed using the interactive pointing device 1220.
When the node 45 is selected instead of node 42, the tree-view of Fig. 7 is transformed to be that shown in Fig. 8. In Fig. 8, the sub-tree nodes of the node 42 have been removed and the sub-tree nodes 46,47 of the selected node 45 are shown.
The preferable displaying of only one set of child nodes 42 and 45 results in an increase in the clarity and the ease of operation of the tree-view system.
[N:\IibcclOO537:SDB -8- Fig. 9 illustrates an object 50 comprising two of the objects 30 of Fig. 6, which are placed beside one another and grouped together in the conventional manner.
The resulting object 50 has five control points 51 to 55 for the selection and/or modification thereto.
Fig. 10 illustrates the corresponding tree-view 59 of the object 50. The treeview 59 is illustrated when the control point 53 (Fig. 9) is selected in tree-viewing mode. Initially, in this mode, only nodes 60 and 61 are displayed. However, when the node 61 is selected using an interactive pointing device 1220, nodes 62 and 63 are further illustrated. When the node 63 is selected using the interactive pointing device, nodes 64 and 65 are displayed. Further, when the node 65 is selected using the interactive pointing device, nodes 66 and 67 are further illustrated. Thus, the tree-view 59 provides for the selective display of the grouped structure of all the objects making up the object .Preferably, the tree-viewing system has a further mode in which nodes 15 the nodes 60 to 67 of Fig. 10) can be individually selected. In this alternative mode, once a node 67) is individually selected, the group structure 50 is "ungrouped" to the extent necessary to allow access to the corresponding object 67).
Fig. 11 illustrates the resultant display when the node 67 of Fig. 10 is selected in this alternative mode. The node 67 corresponds to an object 70 in the overall object 20 50, which is "ungrouped" to the extent necessary to allow access to the object 70. The attributes of the object 70 can then be selectively altered. For example, the blend of object 70 can be altered using blend control points 71,72.
As can be seen from the foregoing description of the embodiments of the invention, utilisation of the tree-viewing system allows for the effective control of the hierarchical complexity of an image that is made up of a substantial number of grouped objects.
In the attached Appendix A, the implementation according to the preferred embodiment is written in two computer languages. The first language is the "C" programming language and the second is "ICI" programming language. In particular, [N:\ibcc100537:SDB the preferred embodiment has been implemented using :hie Microsoft Windows (Trade Mark) operating system and the programming language Micrcsoft Visual C Both Microsoft Windows and Microsoft Visual are well known in the art and commonly used to create graphical application programs.
Additionally, use has been made of tht "ICI' programming language which is an interpreted language having a like syntax. Appendix A also contains ICI source code for implementing the preferred embodiment. It will be apparent to a person skilled in the art that this language has a C-like pseudccode syntax. The ICI programming language has very similar constructs to the C roTrarmming language, but extends the C programming language.
A description of the ICI programming language is provided in Appendix B, which is incorporated herein by cross-reference. For deals on obtaining the ICI language, reference is made to the regular list of language and compilers posted to the Internet news group comp.compilers, amongst others. Additionally, subscription to the 15 Internet ICI mailing list can be obtained by sending a message to the Internet address ici-request@research.canon. oz. au.
The code of the Appendix A assumes, for example. That the overall structure of a selected group of objects is readily available and stored in rhe form of an accessible tree. The code in the Appendix includes instructions for dealing with the selection of a node using an interactive pointing device, and the subsezuent display of child nodes of a selected node. Additionally, there is included code for the rendering of the tree-view node structure as illustrated by the figures of the present applicarion.
Accordingly, the method and apparatus accordim o te preferred embodiment can be readily implemented in the programming o-.age or another comparable high-level programming language.
The foregoing only describes a small number of embodiments of the present invention. However, it will be apparent to those skilled in re art that modifications and changes can be made thereto without departing frcm _cope and spirit of the invention.
(N:',ibcclOO537:SDB APPENDIX A treeview.ici static horz_step; static vert_step; static node_width; static node_height; paint_node_set extern paint_node_set(nodes) auto g; auto p; auto tl; auto t2; First draw all the joining lines. For each node on display, if it has a parent and it is on disply, draw a connecting line.
25 forall (g in nodes) if (!nodes[p g._parent]) continue; tree line 30 doc, g. tree_x, g._treey node_height p. tree x, p._tree_y, Now draw the nodes themselves.
forall (g in nodes) tl g.what; t2 switch (tl) case "group": [N:\Iibcc]00537:SDB 11 if (g.op ="over") ti g.op; else t2 =sprintf("of nels(g.gobs)); break; case "coladj: t2 "Color Adjustor"; break; case shape" if (nels(g.edges) t2 sprintf(" %d pts", nels(g. edges points)); else t2 sprintf(" %d edg", nels(g.edges)); break; case text t2 vis(interval(implode(g. text) $rgxp"[ 0, break; case "rtf": :t2 T **break; **.case "char": :t2 sprintf("%s char); break; case "image" t2 g.fname t2 t2 break; tree node doc, g. tree x, g tree_y, ti, t2, !doc._select[g] static [N:\ibc00537:SDB 12update tree -nodes 0 auto old; auto cur; auto main; auto gob; auto g; auto x, y; old doc._tree-nodes; main =seto; gob doc._tree-now; x gob.-tree -x y gob._tree y; for (g gob; g !=NULL; g g -_parent) if (!doc. _treejplaced[g]) g._tree_x =x; g._tree-y y doe._treejdlaced[g] =1; y vert-step; else *x g._tree-x; :y g._tree_y vert step; main[g] =1 cur =copy(main); forall (gob in main) if (gob.gobs ==NULL) 35 continue; x 0. 0; forall (g in gob.gobs) if (doe._tree-placed[g]) break; x horz-step; if (doe._treeplaced[g]) x g._tree_x x else x gob._tree -x (nels(gob.gobs) 1) *horz step /2; if (x nels(gob.gobs) horz step window edge(doc, 1)) [N:\ibcc]00537:SDB 13x window_edge(doc, 1) nels(gob.gobs) horz step; if (x window edge(doc, 0)) x window_edge(doc, 0); y gob._treey vert step; forall (g in gob.gobs) g. tree x x; g._tree y y; x horzstep; doc._treeplaced[g] 1; cur[g] 1; forall (g in (old cur) (cur old)) damage tree node(doc, g._treex, g._tree_y); if (g.9arent NULL) damagerect(doc, g._tree x, g._treey node height g._parent._tree x, g._parent. _tree_y); doc._tree nodes cur; a.
tree view mouse down hit extern treeviewmousedownhitO auto gob; tree sizes(doc, &node width, &node height); horz step node width 1.2; vertstep node-height gob doc._hitt._gob; doc. hit t gob; doc._tree down gob; 40 doc. tree now gob; doc._tree nodes seto; doc._treeplaced seto; gob._treex doc._hitx; gob. tree y doc.hity; update tree nodes(); mousemovefunc tree view mousemove; mouseup func tree view mouse up; add_overlay invertfunc(invert treeview overlay box); IN:\ibcc]00537:SDB 14return 1; static treeview_mousemoveO auto g; auto half height; auto half width; half_height nodeheight half width node_width forall (g in doc._tree_nodes) if doc._nowx g._tree_x half width doc._nowx g._tree_x half width doc._nowy g._tree_y half_height doc._nowy g._tree_y halfheight i.
if (doc. tree now g) doc. _tree now g; update_tree_nodes(); if (doc. _tree_hit! g) remove_overlays(); doc. hit t g; S 35 restore_overlays(); return 0; a}
"V"
40 if (doc. hit t NULL) remove_overlays(); doc. hitt NULL; restore_overlays(); return 0; [N:\Iibcc0537:SDB static tree-view-mouse-upO auto g; kill-all-overlayso; forall (g in doc._tree-nodes) damage-tree-node(doc, g._tree_x, g._tree_y); if (g._parent =NULL) damage reet(doc, g._tree-x, g._treey g. parent._-tree-x, g._parent. _tree_y);
I
doc._tree-nodes =seto; if (doe._hit-t ==NULL) return; for (g =doe,_hit-t; g =NULL; g =g._parent) f g.closed 0; doe._seleet[g] =0;
I
g doe,_hit-t; g.closed 1; if (doe._shift) doe._select[gJ 1; else doe._select set(g); 0* extern 0 invert-treeview-overlay boxo :00.0 auto g; if doe. hit t) ==NULL) return; rgb(1, 1, 1); xorpen(doc, 1); 00 40 frame(doe, g._xmin, g._ymin, g._xmax, g._ymax); xorpen(doe, 0); #include "icihdrsh" 4 #include "kit h" #include "app.h" #include "doe. h" #include "modals .h" LN:\Iibcc]00537: SOB 16- #include "csc.h" #include <ctype.h> int float_ret(double); should be in ici fwd.h BOOL TI_construct spline outlines(char const *rtf, object_t *doc, object t *gob, int, FloatXY int to_cache); Tree view geometry in pixels.
#define TV_NODE WIDTH #define TVNODEHEIGHT static COLORREF currentcolour; static HBRUSH current_brush; static HPEN current_pen; static POINT *points; static int npoints; kd_from_pic Return a pointer to the KIT_Doc structure associated with the given ICI structure. Should ever attempt to return NULL, it would indicate that some ICI code had held onto a document after it was closed and 30 then called us to do something with it.
static KIT_Doc kd_from_pic(structt *pic) 35 KIT Doc *kd; for (kd ka.ka_Docs; kd NULL kd->kd_Pic pic; kd kdkd Next) 40 ASSERT(kd NULL, "No doc to match pic"); return kd; static int f help keyword() char *key; [N:\IibcclOO537:SDB 17if (typecheck("s", &key)) return 1; Win~lelp(frame -window_handle, help fileo, HELP_KEY, (unsigned long)key); return loose-ret(objof(&o null)); static int f debug() f char *8; if (type check(" return 1; MessageBox(frame -window -handle, s, "ICI Debug", MB_OK); return loose ret(objof(&o_null)); *ICI: rgb(r, g, b) *Set the current colour based on .1 R, G B values.
static mnt f rgb() double c[3]; inti[ if (typecheck("nnn", return 1; 5 i[0] (int)(c[0] 255); i[2] 255); current colour RGB(i[0], if (current-brush
=NULL)
*.*DeleteObject(current -brush); **.*current brush =NULL; 40 if (currentjpen =NULL) DeleteObject(currentpen); current-Pen
=NULL;
return loose ret(objof(&o null)); [N:\Iibcc]00537:SDB 18- *ICI: frame(xmin, ymin, xmax, yrnax) F ill the rectangle based on the current colour..
static int f-frame() dobe{mn double xmin; ymin; xmax; int x[2]; inty[] HGDIOBJ saved; KITDoc *kd; struct-t *Pic; if (typecheck("dninnn", &pic, &xmin, &ymin, &xmax, &ymax)) return 1; kd kd -frompic(pic); ASSERT(kd NULL kd- kd -DC !=NULL, "No doc or DC") yIIO] yw from ymm(kd, ymin); xIIO] xw-from-xmm(kd, xmin); y[l] yw -from ymm(kd, ymax); X[1] xw-from-xmm(kd, xmax); if (currentpen NULL) currentpen CreatePen(PS_-SOLID, 1, current colour); saved SelectObject(kd- >kd_-DC, currentpen); >kdDC, NULL); LineTo(kd->kd DC, LineTo(kd- >kdDC, y[l); :LineTo(kd->kd_DC, SelectObject(kd- kd_-DC, saved); return loose ret(objof(&o null)); }C rend~x y ettx2 eetd IcI Te xcodo h cnr ftenodex cy, piexti, sepaseeced *y rwaTee vie noode.boe (NA\1bccj00537:SDB 19 textl The first line of the two line label.
text2 The second line of the two line label.
S selected 1 if the node is to be drawn selected, else 0.
static int f_tree_nodeO double cx; double cy; char *textl; char *text2; long selected; RECT r; KIT_Doc *kd; struct t *pic; HGDIOBJ saved; if (typecheck("dnnssi", &pic, &cx, &cy, &textl, &text2, &selected)) return 1; kd kd_from_pic(pic); ASSERT(kd NULL kd-> kd DC NULL, "No doc or DC'); r.top yw_from_ymm(kd, cy) TV_NODEHEIGHT 2; r.left xw_from_xmm(kd, cx) TV_NODE_WIDTH 2; r.bottom r.top TV_NODE_HEIGHT; r.right r.left TV_NODE_WIDTH; FillRect(kd- kd_DC, ltgray_brush); FrameRect(kd-> kd DC, selected red brush black brush); 30 saved SelectObject(kd- kd_DC, black_pen); SelectObject(kd- kd_DC, smallfont); SetBkMode(kd- kd_DC, TRANSPARENT); SetTextAlign(kd- kd_DC, TA_TOP I VTA_CENTER); ExtTextOut(kd->kd_DC, r.left TV_NODE_WIDTH 2, r.top, ETO_CLIPPED, textl, strlen(textl),
NULL);
SetTextAlign(kd->kd_DC, TA_BOTTOM VTA_CENTER); ExtTextOut(kd- kd_DC, r.left TVNODE_WIDTH r.bottom.
ETO_CLIPPED, text2, strlen(text2), NULL); SelectObject(kd- kd_DC, saved); 40 return loose_ret(objof(&o null)); ICI: damage tree node(cx, cy) S Parameters: cx The x coord of the centre of the node in picture space.
J t;icCGS37:S38 20 *cy The y coord as above.
static int f-damagze_tree_nodeO dobe{x double cx; RECT r; KITDoe *kd; struct-t *Pic; if (typecheck("dnn", &pic, &cx, &cy)) return 1; kd kd-frompic(pic); r. top =yw -fromymm(kd, cy) TV_-NODE_-HEIGHT /2; r. left =xw -from -xmm(kd, cx) TV_-NODEWIDTH /2; r.bottom =r.top TV_-NODE_-HEIGHT; r.right r.left TVNODEWIDTH; InvalidateRect(kd- >kd_WindowHandle, FALSE); return loose ret(objof(&o_null)); *ICI: tree-line(xO, yO, xl, yl) static mnt f tree-lineo double xO; **double yO; double xl; double yl; KITDoe *kd; struct -t *Pic; HGDIOBJ saved; if (typecheck("dnnnn", &pic, &xO, &yO, &xl, &yl)) return 1; 40 kd =kd -fromjpic(pic); ASSERT(kd !=NULL kd- >kd DC !=NULL, "No doe or DC") saved SelectObject(kd-> kd_-DC, blackpen); MoveToEx(kd- >kdDC, xw-from-xmm(kd, xO), yw from Ymm(kd, yO),
NULL);
~LineTo(kd- >kd_-DC, xw -from -xmm(kd, xl), yw-from-ymm(kd, yl)); SelectObject(kd- kd_-DC, saved); return loose ret(objof(&o null));
I
(N:\IbclOOS37:SDB ICI: tree_sizes(&width, &height) Return the size of a tree node, which is constant size in pixel space, in the current picture (mm) space.
static int f tree sizeso double width; double height; KIT Doc *kd; structt *pic; if (typecheck("d--", &pic)) return 1; kd kd_from_pic(pic); ASSERT(kd NULL, "No doc"); width TV_NODE_WIDTH kd_Scale win horz_ppmm); height TV_NODE_HEIGHT (kd- kd_Scale winvert_ppmm); if (retcheck("-ff", &width, &height)) return 1; return loose_ret(objof(&o_null)); static fwindow_edgeo 30 long which; double edge; KIT Doc *kd; struct t *pic; if (typecheck("di", &pic, &which)) return 1; kd kd_from_pic(pic); ASSERT(kd NULL kd- kd_DC NULL, "No doc or DC"); switch (which) 40 case 0: left edge xmmfrom_xw(kd, 0); break; case 1: right edge xmm_from_xw(kd, kd- kd_WindowSize.x); break; [N:\libcc]OO537:SDB 22 return float-ret(edge); static int f-polyline() array_t*a object-t *0; long flag; int n; int HGDIOBJ saved; KITDoc *kd; struct-t *Pic; if (typecheck("dai", &pic, &flag)) return 1; kd =kd -from-pic(pic); ASSERT(kd =NULL kd- >kdDC NULL. "No doc or DC") if (npoints (n a top a- a base) points realloc(points, n *sizeof(POINT)); npoints n for (i i<n; o base[i 2]; if (isfloat(o)) return argerror(O); points .x xw -from-xmm(kd, floatof(o)- f value); o a->a baseli 2 1]; if (!isfloat(o)) :return argerror(O); points[i] .y ywfromiymm(kd, floatof(o)- fvalue); 1 if (currentpen =NULL) svdcurrentypen =CreatePen(PSSOLED, 1, current colour); svd= SelectObject(kd-> kdDC, currenypen); switch ((int)CF_ARG1O)) 40 case 0: Polyline(kd- kd_DC, points, n); break; case 1: if 1)1/3) 3 1) 4) bez(kd-> kd_DC, points, n); break; [N:\Iib c]00537:SDB 23 case 2: for (i 1; i n; i 3) /*paint-cpoint(flag, 0, points, npoints,
I
break; case 3: for (i 0; 1 n; +i abs(pointslji].x kd- >kdMouseDown.x) 3 abs(points[iJ.y kd- >kdMouseDown.y) 3 SelectObject(kd- kd DC, saved); return int-ret(i); break; 1 SelectObject(kd- kd_-DC, saved); return loose-ret(objof(&o null));
I
static int f paint -cpoint() long double
POINT
KITDoc struct t selected; *kd; *Pic; if (typecheck('dinnnnnn", &pic, &selected, &d[01, return 1; kd kd-frompic(pic); ASSERT(kd. NULL kd- >kd DC !=NULL, 'No doc or DC") pIIO].x xw from xmm(kd, p y yw from ymm(kd, pI[l].x xw from xmm(kd, p11].y yw from,_ymm(kd, d[311); pjI2].x xw-from-xnim(kd, p[2] .y yw from Ymm(kd, [N:\IibccJOO537:SOB 24 paint -cpoint(kd, selected, p); return loose-ret(objof(&o-null)); static int f xor-Pen()
I
long on; KITDoc *kd; struct-t *Pic; if (typecheck('di", &pic, &on)) return 1; kd kd -frompic(pic); ASSERT(kd !=NULL kd- >kdDC !=NULL, "No doc or DC") if (on) SetROP2(kd- >kdDC, R2_XORPEN); else SetROP2(kd- kd_-DC, R2 COPYPEN); return loose-ret(objof(&o-null));
I
static mnt f rect-tags() f double d[4]; ShortXYMinMax r; mnt long selected; KITDoc *kd; struct-t*Pc if (typecheck("dinnnn", &pic, &selected, &d[31)) return 1; kd kd -frompic(pic); **ASSERT(kd NULL kd- >kd DC! NULL, "No doe or DC") r.x.min xw from xmm(kd, d[OIJ);- :r.y.min yw from ymm(kd, r. x.max =xw -from-xmm(kd, 40 r.y.max yw -from ymm(kd, if (r.x.min r.x.max) t r. x. min; x.min x.max; r.x.max t; if (r.y.min r.y.max) (N:XlibcC]00537:SDB 25 t= r.y.min; r.y.min =r.y.max; r. y. max t ~paint tag(kd- kd DC, 0, selc paint tag(kd- kd DC, 1, sele paint tag(kd- >kd_DC, 2, seke paint-tag(kd- kd_DC, 3, sele paint -tag(kd- >kd_DC, 4, seke r.y, min) 2); return loose-ret(objof(&o_null)); ~cted, r.x.max, r.y.min); ~cted, r.x.max, r.y.max); ~cted, r.x.nmdn, r.y.max); ,cted, (r.x.max r.x.min) 2, (r.y.max f dottedjrectO double ShortXYMinMax int long KITDoe struct t d[41; ;elected; *kd; 'Pic; if (typecheck("dinnnn", &pic, &selected, return 1; kd kd -frompic(pic); ASSERT(kd NULL kd- >kdDC =NULL, "No doe or DC') r.x.min xw_from-xnim(kd, d[QJ); r.y.min yw from ymmr(kd, r.x.max xw-fromn-xmm(kd, d[12]); r. y.max yw -from -ymm(kd, if (r.x.min r.x.max)
S
S
S S
S
t r. x. min; r.x.min =r.x.max; r. x. max t; if (r.y.min r.y.max) t r.y.min; r.y.min =r.y.max; r max t; dotted rect(kd, selected, return loose ret(objof(&o null)); f rect-outlineo
I
[N:\IibccJOO537:SDB.
26 double d[8]; HGDIOBJ saved; KITDoc *kd; struct -t *Pic; static HPEN blue_dashpen; if (blue dash~pen ==NULL) blue-dashpen CreatePen(PSDOT, 1, RGB(O, 0, 255)); if (typecheck("dnnnnnnnn", &pic, &d[21, &d[51, return 1; kd =kd-frompic(pic); ASSERT(kd NULL kd- >kdDC !=NULL, "No doc or DC) saved SelectObject(kd- kd DC, blue_dashjpen); MoveToEx(kd- >kdDC, xw-from xmm(kd, d[O]D, yw from ymm(kd,
NULL);
LineTo(kd- kd_-DC, xw -from -xmlm(kd, yw from ynnn(kd, LineTo(kd-> kdDC, xw-from-xmm(kd, yw_from ymm(kd, LineTo(kd- kd_-DC, xw -from -xmm(kd, yw-from ymm(kd, LineTo(kd->kdDC, xw-from-xmm(kd, yw-from ymm(kd, SelectObject(kd- kd_-DC, saved); return loose-ret(objof(&o null)); static mnt f cpoint-outline() double d[8]; POINT p[14]; JJGDIOBJ saved; :KITDoc *kd; *struct t*Pc static HPEN blue dashjpen; :if (blue dash-pen ==NULL) :blue-dashpen =CreatePen(PS_DOT, 1, RGB(O, 0, 255)); if (typecheck("dnnnnnnnn", &pic, &d[41, return 1; kd kd-frompic(pic); ASSERT(kd NULL kd- >kd DC! NULL, "No doe or DC") p[O].x =xw-from-xmm(kd, p[O].y yw from -ynim(kd, p[11I.x xw from -xmm(kd, P[1.y yw from -ymm(kd, p[211.x xw-fromxm(kd, [N:\libcc)00537:SDB 27 p[1].y yw from ymm(kd, d[51); p[3].x xw from xmm(kd, p[3].y =yw-from-ymm(kd, saved SelectObject(kd- >kdDC, bez(kd- >kdDC, p, 4); SelectObject(kd- kdDC, saved); return loose-ret(objof(&o_null)); blue_dashpen); Not used (apparently).
static int f blob_tago double ShortXY long KITDoe struct-t selected; *kd; *Pic; if (typecheck("dinn", &pic, &selected, &dfl])) return 1; kd kd -frompic(pic); ASSERT(kd NULL kd- >kd_-DC !=NULL, "No doe or DC") r.x xw -from xmm(kd, r.y yw from Ymm(kd, d[11); paint -tag(kd- >kd_-DC, 6, selected, r.x, rny); return loose ret(objof(&o null)); static mnt f xtag() f doubled[] ShortXY r:
S.
S.
S
S
long KITDoc struct t selected; *kd; *Pic; if (typecheck("dinn", &pie, &selected, return 1; kd kd -frompic(pic); ASSERT(kd !=NULL kd- kd_DC =NULL, "No doe or DC") r.x xw-from-xmm(kd, r.y yw-from ~ymm(kd, paint -tag(kd- >kdDC, 6, selected, r.x, rny); return loose-ret(objof(&o null)); [N:XlibccJO0537:SDB 28
I
static int f code_dir() extern char *ici-dir; if (ici-dir =NULL) return loose_ret(objof(&o_null)); return str ret(ici dir); static int f file-dialogo KITDoc *kd; long for save; char *extension; char *initial; object -t *fijnc; char name-buf [FILENAMEMAX]; if ((kd =current doco) NULL) f set-status(SERROR, error); return loose_ret(objof(&o-null));
I
if (typecheck("isso", &for-save, &extension, &initial, &func)) return 1; ~.strncpy(name-buf, initial, sizeof(name_but) 1); for if file dialog *.name buf, sizeof(name buf), for-save, extension, "OpenCraft kit)\O*.kit\O" "All images\O*. tif; *.tiff; *.pcd; *.bmp\O" "TIFF files tif; tiffj\O* tiff\O", "PhotoCD files (*.pcd)\O*.pcd\O" "BMP files (*.bmp)\O*.bmp\OI "All files [N:\IibccJOO537:SDB 29 FALSE !Note recent. break; if (ici-func(func, os kd- kdPic, name-but) ==NULL) break; set status(SERROR, error); return loose-ret(objof(&o-null)); static int f rename fileo char *old fname; char *new-fname; if (typecheck("ss", &old-fname, &new_fname)) return 1; CopyFile(old -fname, new -fname, FALSE); return loose_ret(objof(&o-null));
I
static iut f set-title-baro char *title; KITDoc *kd; struct-t *Pic; if (typecheck("ds", &pic, &title)) return 1; kd kd-fromyic(pic); ASSERT(kd! NULL, "No doc") kd_-WindowHandle, title); return loose ret(objof(&o null)); **static mnt f set-statuso B. B switch (NARGSO) **.*case 0: set -status((int)CF ARG1O), NULL); break; case 1: [N:\ibc00537:SDB if (!isstring(ARG(O))) return argerror(O); set -status ((int)CFARG1O(, stringof(ARG(O))-> s-chars); break; default: return argcount( 1); I
A
return loose-ret(objof(&o null)); i static int f set-pagesize() double width; double height; KITDoc *kd; if (typecheck('nn", &width, &height)) return 1; This is very special. setpage sizeo is only called during old -docO before the ICI structure has been assigned. The relevent doc is the first one in the list.
kd ka.kaDocs; ASSBRT(kd- >kd -Pic ==NULL, setpage size with old doc"); kd- kd PageSizelnnim.x =(float)width; kd- kd PageSizelnmmn.y (float~height; return loose-ret(objof(&o null)); static int fgetpage sizeO :double width; ::~.double height; KITDoc *kd; *struct-t *Pic; if (typecheck("d--", &pic)) return 1; kd kd -frompic(pic); ASSERT(kd =NULL, "No doc') width =kd- >kd FPageSizelnmm.x; height =kd- >kd PageSizelnmnm.y; if (retcheck(" &width, &height)) return 1; jN:\1ibcc100537:SDB return loose-ret(objof(&o null)); static int f get image size O char
S
OP_Imagelnfo ii; 1 0 if (typecheck(" return 1; if (!OP image_file_info(s, &ii))
I
ii-ii -Widthlnm =150.0; ii.ii-Heightlnnim =100.0;
I
if (retcheck("-ff", &ii.iiWidthlnmnm, &ii.iiHeightlnrnm)) return 1; return loose-ret(objof(&o_null)); static mnt f hypot() f double d[2]; if (typecheck( &d[0j, return 1; return float-ret(_hypot(d[0], static mnt f hit-threshold() 35 KIT Doc *i;*kd; *tuc- *Pic if (typecheck("d", &pic)) return 1; kd kd-frompic(pic); ASSERT(kd NULL, "No doe") return float-ret(fabs(xmm-from-xp(kd, ka.ka HitTolerance))); static mnt f undo deptho KITDoc *kd; 1NA\ibcc]00537:SDB 32 struct-t *Pic; if (typecheck("d", &pic)) return 1; kd kd-frompic(pic); ASSERT(kd NULL, "No doc") return int-ret(ka. ka-UndoDepth); 1 0 static int f-damagerect() double d[4]; RECT r; long t KITDoc *kd; struct-t *Pic; if (typecheck("dnnnn", &pic, &dLO], return 1; kd kd -frompic(pic); ASSERT(kd NULL, "No doc") r.left xw from xmm(kd, d[OI); r.top yw from,_ymm(kd, r.right xw -from-xmm(kd, r bottom yw from ymnm(kd, if (r.left r.right) f t r.left; r.left r.right; r. right t if (r.top r.bottom) t top; r.top r.bottom; :r.bottom t left 3; r. right 3; r. top 3; r. bottom 3; InvalidateRect(kd- kdWindowHandle, FALSE); return loose-ret(objof(&o-null)); static int f damagerender() [N:\IibcJOO537:SDB 33 double int slop; int xO, yO, Xl, yl; *kd; struct-t *Pic; if (typecheck(7'dnnnnn", &pic, return 1; kd =kd -frompic(pic); ASSERT(kd =NULL, "No doe") A xw from-xmm(kd, yO yw from -ymm(kd, dj~l]); x1l xw-from-xmim(kd, yl yw from Ymim(kd, slop =(long)(dr5] kd- kdScale win-horzppmm); damage -render(kd, AO, yO, xl, yi, slop); return loose-ret(objof(&o null)); static int f flush render-damageo flush -render -damage 0; return loose_ret(objof(&o null));
I
static int f toinspector() if (NARGS() 1) return argcount( 1); if (!isstring(ARG(O))) return argerror(O); *:if to inspector(stringof(ARG(O))- schars)) return 1; return loose-ret(objof null)); static mnt fCrp.w {e if (!isstring(ARG(O))) return argerror(O); /*ripwrite(stringof(ARG(O))->schars, stringof(ARG(O))->s_nchars);*/ C return loose-ret(objof(&Q~null)); [N:\1ibccJOO537:SDB 34 static int f_rip flush() rip_flushjob(); return loose_ret(objof(&o_null)); 1 0 static int f_option() char *s; int m; if (typecheck("s", return 1; if (strcmp(s, "OPTIONS_ANTIALIAS") =0) m ID_MENU_OPTIONS_ANTIALIAS; else if (strcmp(s, "OPTIONS_OUTLINE") 0) m ID_MENU_OPTIONS_OUTLINE; else if (strcmp(s, "OPTIONS_DRAG_SNAP") 0) m ID_MENU_OPTIONS_DRAG_SNAP; else if (strcmp(s, "OPTIONS_MOVE_SNAP") 0) m ID_MENU_OPTIONS_MOVE_SNAP; else argerror(0); if (GetMenuState(frame_window_menu_handle, m, 0) MF_CHECKED) return loose_ret(objof(o_one)); return looseret(objof(o_zero)); 35 ICI: ropen Open a resource as a file. A read-only copy of the resource is opened. The resource is named with "type/id". Eg: "TEXT/30001" 40 Only allows a numeric id.
int f ropen() file t *f; char *name; char *mode; HRSRC resource_handle; [N:\IibccI00537:SDB HGLOBAL data-handle; char *data; mode if (typecheck(NARGSO 1 'SS" &name, &mode)) return 1; if (strcmp(mode, !0 strcmp(mode, =0) sprintf(error errbuf, "attempt to use mode to ropen V mode, name); return 1; resource-handle FindResource(applications-handle, name, "TEXT"); if (resource-handle =NULL) sprintf(error =errbuf, "could not find resource name); return 1; data-handle LoadResource(applications-handle, resource-handle); if (data-handle ==NULL) sprintf(error =errbuf, "could not load resource name); return 1; data LockResource(data-handle); if (ff sopen(data, SizeofResource (applications handle, resource handle))) 30 NULL) return 1; f->f fname stringof(ARG(0)); Obsolete calls but Win32s might still need them.
*UnlockResource(resource handle); FreeResource(resource handle); return objret(objof(f)); static int f locate imageo char *old image; char *old doc; char *new-doc; [NA:Iibcc 100 537: SOB 36 char new-image rFILENAME_-MAX int -access(char const int); clash. if (typecheck("sss", &old_image, &old_ return 1; 128]; Can't include io.h because of sopen() doc, &new doc)) if (strcmp(old-doc, new-doc) =0) char *fl; char *mn; char *0; char *i; The dccument as a whole has moved. First try and locate the image by assuming it moved in the same way as the document.
7or 1 old -image, o old doc; *i tclcwer(*i) ==tolcwer(*o); ++0 old -image..i is now the old 'directory'.
old-dcc. .o is also the old 'directory'.
i. .old image[strlen(cld -image)] is the old image 'basename'.
c. .old-dcc[strlen(cld-dcc)] is the old doc 'basename.
for n new-dcc strlen(new dcc) 1, mn old dcc strlen(cld dcc) n new dcc mn o tclcwer(*n) ==tclcwer(*m); n, in *new-dc. .n is now the new dcc 'directory'.
memcpy(new image, new -dcc, n new -dcc); strcpy (new -image (n new -dcc), i); if (_access(new-image, 4/*Read*I) 0) return str ret(new-image); [N:\Iibcc]00537:SDB 37 Either the document didn't move, or if it did, the image didn't move with it. Try the original image name.
if (_access(old_image, 4/*Read*/) 0) return loose_ret(ARG(0)); Can't find the image in either of the possible places.
Time to ask the user about it.
for sprintf(new_image, "Opening old_doc); sprintf(errbuf, "Could not access the image %s.\nChoose a replacement?", old image); switch (MessageBox(frame window handle, errbuf, new_image, MB_YESNOCANCEL MB_ICONQUESTION)) case IDYES: default: Not expected. if (GetFileTitle(old_image, new_image, sizeof(new_image)) 0) new_image[0] if !file_dialog new_image, sizeof(new_image), 30 FALSE, !For save. NULL, No default extension. "All images\0*.tif; *.tiff; *.pcd; *.bmp\0" "TIFF files (*.tif;*.tiff)\0*.tif;*.tiff\0" "PhotoCD files (*.pcd)\O*.pcd\0" "BMP files (*.bmp)\0*.bmp\0" "All files FALSE !Note recent. 40 continue; Ask again. return str_ret(new_image); case IDNO: sprintf(errbuf, will be displayed as a grey box.", old_image); 45 MessageBox(frame_window handle, errbuf, new_image, MB_OK); return loose_ret(objof(&o_null)); case IDCANCEL: [N:\Iibccj00537:SDB 38 error "0pe canceled."; return 1; static int f seypic-extent() f long double KIT-Doc arg; d[41; *kd; if (typecheck("iffff", &arg, return 1; kd =(KIT_-Doc *)arg; kd- kdPicExtentlnmm.x.min =(float)d[QJ; kd- kdPicExtentlnmim.y .min (floatod[1]; kd- kd PicExtentlnmm.x.max (float)d[2]; kd- kdPicExtentlnmm.y.max (float)d[3]; return loose-ret(objof(&o null)); static int fupdate-nhidden() f a *e a.
a a a. a a long KITDoc struct t *kd; *Pic; if (typecheck(" di", &Pic, return 1; kd kd-frompic(pic); ASSERT(kd =NULL, "No doe") kd- kdHideBarNltems n recalc -hidebar geometry (kd); return loose ret(objof(&o null)); static mnt f-lowprec() double d; #define P1 mEC (1.0 /20.0) if (typecheck(" return 1; [N:\1ibcclOO537:SDB if (d 0) d PREC else d -PREC d fmod(d, PREC); return float-ret(d); 1 0 static int f-write_directo char *string; if (typecheck('s", &string)) return 1; write -direct(string); return loose-ret(objof(&o-null)); static int f set-text-runs-and rules()
S
S 5S5S *S S .5 S S object-t struct t double array~t array~t FloatXY char TextRun TextRun TextRun TextRuledLine TextRuledLine TextRuledLine int *codes; *widths; block-size; *runs; *tr; *trnext; *gob; *run; rtf *rules; *trl; *trlnext; if (typecheck("osff', &gob, &rtf, return 1; block-size.x =(float)d[0]; block-size.y =(float)d[1]; MTJset text rtf, IN:\Iibc1O537:SDB 40 1, &block-size, &runs, &rules error "Could not set text"; return 1; 1 for (tr =runs; tr NULL; tr =trnext) trnext tr- trNext; if ici call append text run", "o=oisfffiii", &run, gob, tr- trBlockIndex, tr- tr-TypefaceName, tr- >tr -SizelnHalfPoints *72.0) *25.4, tr- >trStartPoint. x, tr- tr_-StartPoint.y, tr- trRGB[0], tr- trRGB[2]
:NULL
return 1; 35 codes (array -t *)fetch(run, get-cname(" codes")); if (pushcheck(codes, tr-> tr NumChars)) return 1; widths =(arraytj *)fetch(run, get -cname(" widths") if (pushcheck(widths, tr- >trNumChars)) return 1; for (i 0; i tr- >trNumChars; if ((*codes-> atop =obj of(new int(tr- tr Chars .scCharC ode)))
==NULL)
return 1; +±+codes-> a -top; if ((*widths- a-top =objof(new float(tr- trChars[i].sc Width)))
-=NULL)
IN :\IibcclOOS 37: SD0B 41 return 1; +widths-> a_top; free((void tr-TypefaceName); free(tr- trChars); free(tr); #ifdef NOTDEF for (trI rules; tri! NULL; tri trlnext) trlnext =tri- triNext; if ici call append -text -rulet "oiffffiii, gob, trBlocklndex,*/ trl- >trl Start.x, trl- >trStart.y, trl- >trl End.x, trl- >tr_-End.y, trl- trlRGB[O], trl- >trRGB[1], tri- trlRGB [2] 0
NULL
return 1; free(trl); #endif return loose-ret(objof(&o null)); static int f-convert-rtf to-splines() S9*. 40 f object-t *doc; object -t *gob; char *rtf; double dx; double dy; FloatXY block size; int sum; int total; [N:\Iibcc]00537:SDB 42 int to cache; char buffer[iOG]; if (typecheck("oosffiii", &doc, &gob, &rtf, &dx, &dy, &sum, &total, &to-cache)) 5 return 1; block size.x dx; block-size.y dy; if (to-cache) sprintf(buffer, "Converting text object to a group of chars..... ,sum,total); else sprintf(buffer, Converting text obj ect d/ %d to a "sum,total); start-gauge (buffer); TI -construct -spline outlines(rtf, cloc, gob, 1, &block-size, to-cache); return loose-ret(objof(&o_null)); static int f update-completion-gauge() f int pos; if (typecheck("i", &pos)) return 1; update gauge(pos, NULL); return loose-ret(objof(&o-null));
I
:static int ffinish completion auge() 30 :finish gaugeo; return loose_ret(objof(&o-null)); static int f csc-converto long 1; CSC_Map *csc; double in[3]; double out[3]; float inf[3]; float outf[3]; if (typecheck("iFFF", return 1; csc (CSC -Map inf[O] in[O]; tNAIibccIOO537:SDB 43 inf[l] in~l]; inf[2] in[2]; if (!CSC-convert spot(csc, inf, outf)) f error CSC error mes sage; return 1;
I
out[O] ourf[O]; out[1] =outf[1]; out[2j outf[2]; if (retcheck("-fff', &out[O], &out[1], &out[2])) return 1; return loose-ret(objof(&o_null));
C
a static cfunc-t
{CF-OBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
fCFOBJ, 30 {CFOBJ,
{CFOBJ,
CFOBJ,
CFOBJ,
{CFOBJ,
35 {CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
40
{CFOBJ,
{CF-OBJ,
{CF-OBJ,
{CF-OBJ,
f CF-OBJ,
{CFOBJ,
{CF-OBJ,
{CFOBJ,
{CF-OBJ,
kit-cfuncs[] "iget image size", f get-imagesize}, floption", f option}, "frip_write", f ripwrite} "rip flush", f rip~flush}, "flush-render damage",f fflush-render-damagel, "damage render", f damagerender}, "to inspector", f toinspector}, "damage rect", f damagejrect), "hit-threshold", f hit-threshold}, "hypot", f hypot}, "1paint-cpoint", f paint-cpoint}, "1cpoint -outline f cpoint -outline}, "orect-outline f rect -outline}, "dotted-rect", f dotted-rect},I "code-dir", f code_dir}, "tsetpage size", f setpage-size}, "getpage size", f getypagesize), file-dialog f file -dialog}, "frename-file f rename-file}, "set-title-bar", f set-title-bar}, "help-keyword", f help -keyword} "fdebug" f debug}, "xorpen", f xorpen}, rgb f rgb), "frame", f-frame}, "tree -node" f tree_node}, "fdamage tree_node" f damage-tree-node},I "tree-line", f tree_line}, "tree -sizes f tree-sizes}, "fwindow-edge", f window -edge}, "trect-tags" f rect-tags}, LN:\ibc00537:SDB 44
{CF_OBJ,
{CF-OBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFIOBJ,
{CF-OBJ,
{CF -OBJ,
{CF-OBJ,
{CF-OBJ,
f{CF-OBJ, {CF OBJ,
{CF-OBJ,
{CF-OBJ,
{CFOBJ,
{CFOBJ,
{CFOBJ,
{CFIOBJ,
{CF-OBJI
"blob_ta", "x -tag", "1polyline", "ipolycurve", "fpolypoint", "hitpoints", "1notice", "iwhy busy" "what-selected", "1set-error", "tmode", f -blob-tag), f xtag}, f polyline, (int()O} f polyline, (int(*)1 f-polyline, (int(*)2 folyline, (ilt())3 f set-status, (int (*)O))S_-NOTICE), P set -status, (int
BUSY},
f set status, (it (*)O)S_-WHAT_-SELECTED}, f set-status, (int f set_ status, (int MODEL "1ropen", f ropenj, "setypic extent",f fsetpic extent), "locate -image", f locate-image), "update -nhidden", f updatenhidden}, "lowprec", f lowprec}, "fwrite -direct", f write direct), "set-text-runs-and-rules",f set-text-runs-and-r-ules), "undo depth", f undo -depth), "convert -rtf to-splines" ,f convert-rtf tosplinesl, "update -completion_gauge" ,f update-completion -gauge), "1finish -completion_gauge" ,f finish -completion gauge), "1csc conver-t", f csc convert), got.
0..
of
BOOL
register -ici -funcs(void)
I
if (def cfuncs(kit cfuncs)) set -status(SERROR, error); return FALSE; return TRUE; *Exports: left-mouse-down-func() *Handle the left mouse going down in the document window.
extern.
left-mouse-down-func() auto old, i, g, gobs, gob; \Iibcc]OO5 37:SDB 45 First, we check to see if the user wants to create a rectangle or or an ellipse.
switch (doc._defered) case "CREATE RECTANGLE": case "CREATECIRCLE": Create a new gob (either rectangle or circle) which will be scaled to suit, later on.
if (doc._defered "CREATE_RECTANGLE") g unit_rect shape(doc._downx, doc._downy); else g unitcircle_shape(doc._downx, doc._downy); Clear the deferred variable, as well as any active modifiers, and remove any prompting messages currently visible in the status bar.
doc._defered NULL; doc._modifiers show mode(); We which to scale the gob which was just created so we add this to the modifier set. We then copy the select set to a temporary variable and then repaint the previously selected tags, causing them all to look unselected. The select is set to contain the new object (no tags drawn 30 yet).
doc._modifiers set("GRAPHICS_SCALE"); old doc._select; 35 doc._select set(g); paint_tag set(old); declare_that tags_etclook_ok(); Set up all the required drag variables for a scaling operation 40 doc._hotx doc._downx; doc._hoty doc._downy; doc._dragx0 doc._downx 1; doc._dragy0 doc._downy 1; doc. dragxl doc. downx; doc._dragyl doc._downy; doc. drag_ctrl doc._ctrl; doc._drag shift doc. shift; |N:\libcc]00537:SDB type Let "drag_selection" take care of the rest, as we have set the modifier to "GRAPHICSSCALE".
drag_selection(); return 1; If there is nothing to interact with, there is nothing to do...
if (doc. tags NULL) return; Check to see if any tags have been hit....
if (hit()) 25 30 doesn't 35 We check to see if there are any actions previously defered which are waiting for a hit...
switch (doc._defered) case "GRAPHICS ADD TO GROUP": Check to see that what was hit is actually a group, otherwise it make much sense, does it?? if ((gob doc. hit t._gob).what "group") gobs gob.gobs; forall (g in selected_gobs()) if (g._parent NULL) seterror("Attempt to include document as a whole in nter it first."); continue; a group E reference array..
Remove the current selected gob from its parent's gob elide_from_array(g.jparent.gobs, g); [N:\libccl00537:SDB 47 Otherwise, tell the parent If there parent has no more children, delete it.
to recalc its geometry.
if (nels(g._parent.gobs) 0) delete_gob(g._parent); else schedule_geometry_update(g ._parent); Add the current selected gob to the group, and set its push(gobs, g); g._parent gob; backptr.
Recalc the group's geometry..
schedule_geometry_update(gob); return 0; case "VIEW TREE VIEW": return tree_view_mouse_down_hit(); Check for a hit on a cpoint.
if (doc._hit t._tagtype "cpoint") if handle_any_deferedcpoint hit action()) 0) return i; if(doc. hit i 1) Hit on an in/out handle thingy.
return hit on cpointangle_handle("hit-handle"); if (!doc._select[doc._hitt]) Hit on unselected object.
if (!doc._shift) (N:\Iibcc]00537:SDB 48 currently then The shift key wasn't down. Therefore, we deselect all the selected tags, and set the select set to the newly hit tag. We repaint the tag set...
old doc._select; doc._select set(doc._hitt); painttagset(old); paint tag set(doc._select); Just add the newly clicked tag to the select set, and repaint the else
S
S
S.
S
S*~
*SSSS.
it out...
else doc._select[doc._hitt] 1; paint_tag set(set(doc. hit declare_thattags_etc_look ok(); if (doc._defered NULL nels(doc._select) 0) We now have something selected, so we are now able to carry action(doc, doc._defered); return 0; Hit on selected object.
if (doc._shift) But now it is unselected. Can't do anything with an unselected object.
doc._select[doc._hitt] 0; return 0; IN:\IibcclOO537:SDB 49 There is a selection and it has been grabbed. We display a message in the status bar sumarising what is selected.
say_whatselected(); Set up the initial values of the drag parameters. Then, calculate the initial transformation matrix required fQr the drag.
setup_selection_drag_points(); calc_transform(); We want to draw representions of the currently selected objects inverted, transformed by the current transformation matrix. Therefore, we add the function which does this "inverttransformed" to the overlay function set.
add_overlay_invert_func(invert_transformed); Since must set "mouse_move_func" to specify what occurs when the mouse moves during a drag mouse_move_func [funco 2 Clear the status bar...
what_selected(); 30 Extract the latest mouse and keyboard info, and upate the drag parameters, using "update selection drag_points". In addition, this function calls "remove overlays" to XOR out the current overlays. We use this new data to calculate the new transformation matrix.
update_selection_drag_points calc_transform(); We draw the overlays in their new position..
restore_overlays(); return 0; mouse_up_func [func(nomove) fN:\IibccIO0537:SDB 50 Clear the message area.
what_selected(); not needed. Job done by kill_all_overlays below.
removeoverlays();
A
if (nomove) ORIGINAL CODE I THINK IT IS MOSTLY
REDUNDANT
*if (nels(doc._modifiers) 0) kill all overlays(); return; *update_selection_drag_points(); *calc_transform(); the overlays and starting the drag If the mouse did not move during a drag, then we simply kill get out. This is to prevent any "crawling" due to the user at a point slightly away from the centre of the tag.
kill_all overlays(); return; If the mouse did move, purge the overlay set. Then, "solidify" the drag by applying the current transformation matrix to the currently result of the selected objects.
killalloverlays(); apply_transform to selection(); return 1; else [N:\libcc)00537:SDB 51 The left button went down, but didn't hit anything. Therefore this is a selection drag, where the user drags out a rectangle which contains the tags he/she wants selected.
if (!doc._shift) 4 If the shift key is not down, then the user doesn't want to keep any 1 o current selections.
Therefore, use the usual method of repainting the tags of the current selections so that they are no longer selected.
old doc._select; doc._select set(); paint_tag_set(old); declare_that_tags etc look_ok(); Since no tag was hit, we remove any current modifiers, and clear the status bar.
S. doc. modifiers set(); 25 showmode(); e*m:.y Since at the start of the drag, the selection rectangle contains nothing, we empty "_inrect". We then call the selection rectangle initialisation function "start drag rect" S: 30 which initialises (suprise, suprise!) the global drag parameters.
doc. inrect set(); startdrag_rect(); Add a function which draws an XORed rectangle (geometry dependent on the drag parameters) to the overlay function set.
add overlay_invert func(invert drag_rect); Must define a function which handles a mouse move during a selection drag.
mouse movefunc [funco auto t, new, old; [N:\Iibcc]00537:SDB 52 "tags inrect" is called, which examines the contents of inrect", and includes in "new" the set of tags which are now inside the rectangle but weren't before; and including in "old" the set of tags which used to be part of inrect" but aren't now.
tags_in rect(doc._inrect, new set(), old set()); Remove the current overlays, and update the drag parameters using the latest mouse position data.
remove_overlays(); update_drag_rect(); For all the elements of "old", remove them from the select set, remove them from "_inrect", and repaint their tags.
if (nels(old) 0) 25 forall (t in old) doc._select[t] !doc._select[t]; doc._inrect[t] 0; 30 paint tag_set(old); For all the elements of "new", add them from the select set, add them to inrect", and repaint their tags.
if (nels(new) 0) forall (t in new) doc._select[t] !doc._select[t]; doc._inrect[t] 1; painttagset(new); Repaint the overlays in their new position and get out [N:\Iibcc]00537:SDB restore_overlays(); return 0; mouse_up_func [func(nomove) functions Remove the overlays and nuke the set containing the overlay kill_alloverlays(); if (doc._defered NULL nels(doc. select) 0) If we have a deferred action ready to go, call action to the newly selected tags.
action(doc, doc._defered); else perform it on asserting that Otherwise, stop any unnecessary redrawing of the tags by they must currently be fine...
declarethat tags_etc_look_ok(); *00 .s too.
*9* 00 return 1; drag_selection handles a drag on selected objects. It uses functions such as "calctransform" and "update_selection drag_points" which query the global state (modifiers etc) and draw the intermediate result of the drag as appropriate.
static drag selection() Calculate the initial transform to be applied to the selected tags, according to the current mouse position, active modifiers etc.
calc_transform(); Add a function which draws outlines of the selected objects in XOR mode to the overlay set.
[N:\lIibcclOO537:SDB 54 add_overlay_invert_func(invert_transformed); Must redefine the mouse move function to describe what happens when the mouse moves during the drag.
mouse_move_func [func() Update the drag variables according to the current mouse position etc.
This function also calls "remove_overlays" to XOR out the currently displayed overlays.
update_selection drag_points(); Recalculate the required transform, according to the new mouse position.
Then, redraw the overlays using this new transform.
calc_transform(); restore_overlays(); return 0; S: 25 We must redefine the mouse up function, to specify what occurs when the mouse button comes up and the drag is completed.
30 mouse_up_func [func(nomove) I think some of this code is a little redundant 35 remove_overlays(); if (nomove) if (nels(doc._modifiers) =0) killalloverlays(); return; update_selection_drag_points(); calctransform(); kill all overlays(); apply_transformtoselection(); [N:\libccJ00537:SDB 55 *Establish initial values in the doc for: dragf 11 hot(x,y} *Using: The extent of the current selection.
downfx,y) -!t extern setup selection-dragpoints() auto ex; *Obtain the bounding box of the selected tags ex selection extento; if (doc._modifiersl'"GRAPHICS_-ROTATE_-CENTERED"] doc._modifiers["GRAPHICSSCALECENTERED"]) 25 1 -0 *Set the hot point to the centre of the selection.
::.doc._-hotx (ex._xmin ex._-xmax) doc._hoty (ex._ymin ex._ymax) 1 else Set the hot point to the corner furthest from the mouse down point.
if (abs(ex._-xmin doc._downx) abs(ex._xmax doc._downx)) doc._hotx ex._xmin; else doc._hotx =ex._xmax; if (abs(ex._ymin doc._downy) abs(ex. ymax doc. downy)) doc._hoty ex._ymin; else doc._hoty ex._ymax; if (doc._hit-t !=NULL) [NA~ibcc10OS37:SD8 else 56 If we know what was hit, we can "snap" the drag start position to the exact position of the selection.
doc._dragxO doc. hit x; doc._dragyO doc._hit_y; Otherwise, we just start at the current mouse position.
doc._dragxO doc._downx; doc. dragy0 =doc. downy; Set the initial endpoint of the drag to be current mouse position, and load current state of the CTRL and SHIFT keys into their drag equivalents.
doc._dragxl doc._downx; doc._dragyl doc._downy; doc. drag_ctrl doc. ctrl; doc._drag_shift doc._shift; 25 Update the drag paramaters in the document structure according to the latest mouse position extern 30 update_selection_drag_points() if (is enabled("OPTIONS_DRAG_SNAP")) If "drag snapping" is enabled, draw the snapping lines as required. Note that the drag position etc is updated inside the function which handles the tag snapping.
snap_drag_to_tags(); else Otherwise, we simply XOR out the current overlays and update the drag endpoint using the current mouse position.
remove_overlays(); doc._dragxl doc. nowx; [N:\libccI00537:SDB doc._dragyl doc._nowy; Update the keyboard stuff we are interested in...
doc._drag_ ctrl doc._ctrl; doc._drag_shift doc._shift; start_drag_rect initialise the drag parameters for a selection drag (an XOR rectangle) extern start_drag_rectO doc._dragx0 doc._downx; doc._dragy0 doc._downy; doc._drag_ctrl doc._ctrl; doc._drag_shift doc._shift; doc._dragxl doc._downx; doc._dragyl doc._downy; update_drag_rect a function to update the drag parameters according to the new mouse position and keyboard status.
30 extern update_drag_rect() doc. dragxl doc. nowx; doc. dragyl doc._nowy; doc._drag_ctrl doc._ctrl; doc. drag_shift doc._shift; invertdrag_rect function to draw an XORed rectangle, according to the current drag parameters.
extern invert_drag_recto Use a white pen, as when it's XORed onto white, it will become black.
[N:\libcc]00537:SDB 58 rgb(1, 1, 1); Switch on the XOR drawing mode, draw the rectangle, and then switch off XOR drawing.
xor_pen(doc, 1); frame(doc, doc._dragx0, doc._dragy0, dc._dragxl, doc._dragyl); xor_pen(doc, 0); add_overlay_invert_func adds a function which adds an overlay drawing function to the "overlay_restorers" set. It then calls "restore_overlays" is to draw the overlay in its initial position. Therefore, the initial drag info must already have been calculated before this function is called.
extern addoverlay_invert func(func) doc. overlay_restorers[func] 1; restoreoverlays(); restore_overlays Executes all the overlay drawing functions in the "overlayrestorers" set and then moves them to the "overlay_removers" set for later removal.
o* 30 extern restore_overlaysO auto func; forall (func in doc._overlay_restorers) funcO; doc._overlay_removers[func] 1; doc._overlay_restorers set(); remove overlays Executes all the overlay drawing functions in the "overlay_removers" set, effectively removing overlays which have already been drawn. They functions [N:\libcc)00537:SDB 59 are then moved to the 'overlay restorers" set to be drawn later in a new position.
extern remove overlays()
I
auto func; forall (fiinc in doc._overlay removers) 1 funcO); doc._overlay restorers[func] 1;
I
doc._overlay_removers =seto; *kill-all-overlays removes all current overlays by executing all the functions in the "remove-overlays set. It then empties both sets.
extern kill-all_overlays 0 f auto func; forall (func in doc._overlay removers) funco; doc._overlay removers =seto; doc._overlay restorers =seto; 30 extern duplicate-selectionO f auto g; auto p; forall (g in selected gobso) push(g._parent =NULL doc.gobs g._parent.gobs, deep copy_gob(g, set-back refs (g.yarent NULL doc :g._parent); a.
a a a a.
a a extern deep copy gob(g, selection-only) f [N:kIibcc]00537:SDB 60 auto auto auto newg, child; e, newe; p, newp; auto k, v; switch (g.what) case case Itgroup'": "colad"': newg =copy(g); forall k in newg) typeof(k) k 1string" a
*S
a a k "gobs" newg[k] deep copy(v); newg.gobs arrayo; forall (child in g.gobs) f push(newg gobs, deep copy gob (child,
I
break; case "shape": newg copy(g); forall k in newg) if typeof(k) ="string" k #A k !="edges" newg[k] =deep_copy(v);
I
newg.edges arrayo; forall (e in g.edges) f{ angles_frompoints points); [N:\tibccJCO5S7:SDB 61 newe ==copy(e); newe.points =array(); forall (p in e.points) if (!selection-only doc._select[p] doc._select[g]) push(newe. points, newp copy(p)); if (doc._-select[p]); doe. -select[p] 0; doe. select[newpj 1; newp._gob newg; if (nels(newe. points) points_from -angles (newe. points); push(newg edges, newe); :1:break; case "text": case "rtf": ~:case char~ :case image newg =deep copy(g); break; if (doe._select~g]) :.doc._select[g] 0; doe._select[newg] 1; newg._gob newg; return newg; *deep copy *Deep copy the saveable portions of x. ILe. the things which *don't start with an underbar.
static deep copy(x) [N :\libc c 005 37:SOB 62 auto v, k; if (!isatom(x)) x copy(x); forall k in x) if (typeof(k) "string" &d k x[k] NULL; else if (isatom(v)) continue; else x[k] deep_copy(v); return x; 4 Set all backward references in this gob sub-tree. Sets: _parent The parent gob of this object.
_gob The gob associated with this object.
edge The edge a cpoint is in.
25 extern setback_refs(gob) auto g, e, p; gob._gob gob; switch (gob.what) case "group": case "coladj": forall (g in gob.gobs) g._parent gob; g._gob g; set backrefs(g); break; case "shape": forall (e in gob.edges) e._parent gob; e._gob gob; IN:\libcc]00537:SDB -63 forall (p in e.points) p._parent =gob; p._gob =gob; p._edge e; case "text": case rtf forall (p in gob.points) p._parent =gob; p._gob gob; break; extern extract-gob(g) if (g._parent NULL) return; do doc._bad geometry[g] =0; :doc._select[g] =0; if (g._parent =NULL) elide-from-array (g._parent. gobs, g); }while g._parent) !=NULL nels(g. gobs) 0); schedule geometry update(g NULL g :doc); extern delete gob(g) if (g doc._shape) doe._shape NULL; doc. edge =NULL; doc._point =NULL; if (g._parent NULL) return; [N:\ibcc]00537:SDB_ 64 do doe._bad geometry rg] 0; doc._-select[g] =0; if (g.-Parent =NULL) elide from array (g._parent. gobs, g); }while g._parent) !=NULL iels(g,.g~obs) 0); schedule geometry update(g NULL doc); extern delete-selectionO f auto select-Point; auto t, g; selectypoint nels(doc._-select) I doe._-selectr[doc._point]; set-back-refs(doc); forall (t in doe. _select) g =t._gob; *:switch (t._tagtype) case "reef": case spots delete gob(g); break; *case "epoint": angles from~points _edge. points); ~elide -from -array(t. _edge. points, t); if (doe._point t) doc._point top(t._edge. points); if (nels(t. _edge. points) 0) elide -from -array(g.edges, t._edge); if (nels(g.edges) 0) delete gob(g); else points from angles(t. edge. points); schedule geometry update break; [N:\Iibcc]OO537:SDB
I
if (selectypoint doc._point =NULL) doe._select set(doc.joint); else doe._select =seto;
I
static say what-selectedO f auto g; if (nels (doc._-select) f what-selectedO; return;
I
if (nels (doc._-select) 1) what-selected(sprintf(" %d objects.", nels(doc._select))); return; .0forall (g in doe._select) break; if(g._gob :switch what) case "group": what selected(sprintf("An group of %d object(s)%s; fmm x g. op, nels(g .gobs), g. ckeys !=NULL "(with emap)' g._xlnax -g._xmin, g._ymax -g._ymln, break; case "coladj": what-selected(sprintf("An color adjusted object; lfmm x Ilfmm. g._xmax -g._xmin, g._ymax g._ymin, break; case "text": what-selected(sprintf("A text object; A lfmm x lfmim." [N:\Iibcc]00537:SDB 66 g._xmax -g._xmin, g._ymax -g._ymin, break; case "rtf": what-selected(sprintf("An RTF text object; %lfmmr x fram." g dh, g.dv, break; case "char': what-selected(sprintf(" A character; I lfrnm x Ifmnm." g. dh, g.dv, break; case "image" what-selected(sprintf(" The image 's 1 .fmm x I 1fni." g fname, g._xmax -g._xmin, g._ymax g._ymln, 25 break; :case "shape": if (nels(g.edges) 1) f 30 what-selected(sprintf("A d edge shape; %.Ilfmm x %.Ilfmm." *9*nels(g edges), g._xmax -g._xmin, *.g._ymax -g._ymnn, else 999999what selected(sprintf(" A single edge, d point shape lfnm x I.fmam." nels edges points), g._xmax g._xmin, g._ymax -g._ymin,
D}
break; (N:%Vibcc]OO537:SDB 67
APPENDIX
ICI Technical Description Version Tim Long Portions 1992-1995 Canon Information Systems Research Australia Portions 1992-1995 Tim Long Permission granted to reproduce as is for non-commercial use.
The ICI interpreter's execution engine calls on the parser to read and compile a statement from an input stream. The parser in turns calls on the lexical analyser to read tokens. Upon return from the parser the execution engine executes the compiled statement. When the statement has finished execution, the execution engine repeats the sequence.
The lexical analyser The ICI lexical analyser breaks the input stream into tokens, optionally separated by whitespace (which includes comments as described below). The next token is always the longest string of following characters which could possibly be a token. The following are tokens: S *The following are also tokens: *"The character followed by any sequence of characters except a newline, then another This token is a regular-expression.
The character' (single quote) followed by a single character (other than a newline) or a single backslash character sequence (described below), followed by another single quote.
This token is a character-code. A single quote followed by other than the above sequence will result in an error.
The character (double quote) followed by any sequence of characters (other than a newline) and backslash character sequences, up to another double quote character. This token is a string.
A backslash character sequence is any of the following: \n newline (ASCII Ox0A) t tab (ASCII Ox09) tab (ASCII 0x09) 68 \v vertical tab (ASCII OxOB) \b back space (ASCII 0x08) \r carriage return (ASCII OxOD) \f form feed (ASCII Ox0C) \a audible bell (ASCII 0x07) \e escape (ASCII OxIB) backslash (ASCII single quote (ASCII 0x27) double quote (ASCII 0x22) question mark (ASCII Ox3F) \cx control-x the character with hex code S. \n the character with octal code n. 2 or 3 octal digits) Consecutive string-literals, seperated only by white-space, are concatenated to form a single strings-literal.
Any upper or lower case letter, any digit, or'' (underscore) followed by any number of the same (or other characters which may be involved in a floating point number while that o is a valid interpretation). A token of this form may be one of three things: I* If it can be interpreted as an integer, it is an integer-number.
Otherwise, if it can be interpreted as a floating point number, it is afloating-point-number.
Otherwise, it is an identifier.
Notice that keywords are not recognised directly by the lexical analyser. Instead, certain iden- S tifiers are recognised as keywords by the parser as described below.
Comments (which are white-space) are started with the characters and continue until the next Also, lines which start with a character are ignored.
An introduction to variables, modules and scope Variables are simple identifiers which have a value associated with them. They are in themselves typeless, depending on the type of the value currently assigned to them.
The term module in ICI refers to a collection of functions, declarations and code which share the same variables. Typically each source file is a module, but not necessarily.
In ICI, modules may be nested in a hierarchical fashion. Within a module, variables can be declared as either static or extern. When a variable is declared as static it is visible to code defined in the module of its definition, and to code defined in sub-modules of that one. This is termed the scope of the variable.
When a variable is defined as extern it is declared static in the parent module. Thus the parent lodule and all sub-modules of the parent module have that variable in their scope. Variables 69 of this type, whether originally declared extern or static, will be henceforward referred to as static variables.
Static variables are persistent variables. That is they remain in existence even when execution completely leaves their scope, despite not being visible to any executing code. They are visible again when code flow again enters their scope.
The scoping of static variables is strictly governed by the nesting of the modules, not by the flow of execution. For example. Suppose two neighbouring modules (call them module A and module B) each define a variable called theVariable. When some code in module A calls a function defined in module B and that function refers to theVariable; it is referring to the version of theVariable defined in module B, not the one defined in module A.
Variables in sub scopes hide variables of the same name defined in outer scopes.
S The second type of variable in ICI is the automatic, or auto, variable. Automatic variables S are not persistent. They last only as long as a module is being parsed or a function is being executed. For instance, each time a function is entered a copy is made of the auto variables which were declared in the function. This group of variables generally only persists during the execution of the function; once the function returns they are discarded.
The parser The parser uses the lexical analyser to read a source input stream. The parser also has refer- Sence to the variable-scope within which this source is being parsed, so that it may define vari- Sables.
a* S* The parser will define variables within the current scope, and, when code is parsed at the outermost level, return it to the execution engine for execution.
For some constructs the parser will in turn call upon the execution engine to evaluate a subconstruct within a statement.
The following sections will work through the syntax of ICI with explanations and examples.
Occasionally constructs will be used ahead of their full explanation. Their intent should be obvious.
The following notation is used in the syntax in these sections. Note that the syntax given in the text is not always exact, but rather designed to aid comprehension. The exact syntax is given in a later section.
bold The bold text is literal ASCII text.
italic The italic text is a construct further described elsewhere.
xxx The xxx is optionally present.
xxx... The xxx may be present zero or more times.
As noted previously there are no reserved words reeczinsed by he lexical anaylyser, but certain identifiers will be recognised by the parser in cerain syncacdc positions (as seen below).
While these identifiers are not otherwise restricted, special acden may need to be taken if they are used as simple variable names. They probably should be avoided. The complete list is:
NULL
continue extern in switch auto default for onerror try break do forall retu--n while t rC We now turn our attention to the syntax itself.
Firstly consider the basic statement which is the urnt ofoeranon of the parser. As stated earlier the execution engine will call on the parser to 17p-se one top-level statement at a time. We split the syntax of a statement into two categories puraely for semantic clarity): p
S
p *5 S S
S
a .Sp S a p
S
S S
*SSS
statement executable-statement declaration That is, a statement is either an executable-statement or a dedaration. We will first consider the executable-statement.
These are statements that, at the top-level of parsing- can be translated into code which can be returned to the execution engine. This is by far the largest category of statements: executable-statement .5 S S
S
a a.
expression compound-statement i£ expression stareT.ez if expression starerr.eri else _staement while expression saremrer do statement while expresor. for [expression]; £'esson 1 exDression statement forall expression f. resscn in expression statement switch expression :o7o7vai-s7rement case parser-evaluated-errsszon default break; continue; return expression try statement onerror sc:r r These are the basic executable statement types. M=ny ofiese !vclve expressions, so before examining each statement in turn we will examine ie We will do this by starting with the most primitive elements of expressions ma wo-±g back up to the top level.
The lowest level building block of an expressions :s be -2cr: 71 factor integer-number character-code floating-point-number string regular-expression identifier
NULL
expression array expression-list set expression-list struct expression, assignment-list] func Junction-body I The constructs integer-number, character-code, floating-point-number, string, and regularexpression are primitive lexical elements (described above). Each is converted to its internal form and is an object of type int, int, float, string, or regexp respectively.
A factor which is an identifier is a variable reference. But its exact meaning depends upon its context within the whole expression. Variables in expressions can either be placed so that their value is being looked up, such as in: a 1 Or they can be placed so that their value is being set, such as in: a 1 Or they can be placed so that their value is being both looked up and set, as in: a 1 Only certain types of expression elements can have their value set. A variable is the simplest S. example of these. Any expression element which can have its value set is termed an lvalue because it can appear on the left hand side of an assignment (which is the simplest expression construct which requires an Ivalue). Consider the following two expressions: 1 2 WRONG a 2 OK The first is illegal because an integer is not an lvalue, the second is legal because a variable reference is an Ivalue. Certain expression elements, such as assignment, require an operand to be an Ivalue. The parser checks this.
The next factor in the list above is NULL. The keyword NULL stands for the value NULL which is the general undefined value. It has its own type, NULL. Variables which have no explicit initialisation have an initial value of NULL. Its other uses will become obvious later in this document.
72 Next is the construct expression The brackets serve merely to make the expression within the bracket act as a simple factor and are used for grouping, as in ordinary mathematics.
Finally we have the four constructs surrounded by square brackets. These are textual descriptions of more complex data items; typically known as literals. For example the factor: [array 5, 6, 7] is an array of three items, that is, the integers 5, 6 and 7. Each of these square bracketed constructs is a textual description of a data type named by the first identifier after the starting square bracket. A full explanation of these first requires an explanation of the fundamental aggregate types.
An introduction to arrays, sets and structs There are three fundamental aggregate types in ICI: arrays, sets, and structs. Certain properties are shared by all of these (and other types as will be seen later). The most basic property is that they are each collections of other values. The next is that they may be "indexed" to reference values within them. For example, consider the code fragment: a [array 5, 6, 7] i a[0] The first line assigns the variable a an array of three elements. The second line assigns the variable i the value currently stored at the first element of the array. The suffixing of an expression element by an expression in square brackets is the operation of "indexing", or referring to a sub-element of an aggregate, and will be explained in more detail below.
Notice that the f irst element of the array has index zero. This is a fundamental property of ICI arrays.
The next ICI aggregate we will examine is the set. Sets are unordered collections of values.
Elements "in" the set are used as indexes when working with the set, and the values looked up and assigned are interpreted as a booleans. Consider the following code fragment: s [set 200, 300, "a string"]; if (s [200] printf ("200 is in the set\n"); if (s[400]) printf("400 is in the set\n"); if string"]) printf("\"a string\" is in the set\n"); s [200] 0; if (s [200] printf("200 is in the set\n"); When run, this will print: 73 200 is in the set "a string" is in the set Notice that there was no second printing of "200 is in the set" because it was removed from the set on the third last line by assigning zero to it.
Now consider structs. Structs are unordered collections of values indexed by any values.
Other properties of structs will be discussed later. The typical indexes of structs are strings.
For this reason notational shortcuts exist for indexing structures by simple strings. Also, because each element of a struct is actually an index and value pair, the syntax of a struct literal is slightly different from the arrays and sets seen above. Consider the following code fragment: s [struct a 123, b 456, xxx "a string"]; printf printf("s.a s.a); printf("s.xxx s.xxx); S Will print: .s 123 s. a 123 s.xxx "a string" Notice that on the second line the structure was indexed by the string but that the assignment in the struct literal did not have quotes around the a. This is part of the notational shortcut which will be discussed further, below. Also notice the use of s.a in place of This is a similar shortcut, also discussed below.
Back to expression syntax The aggregate literals, which in summary are: array expression-list set expression-list struct expression, assignment-list funcfincrion-body involve three further constructs, the expression-list, which is a comma separated list of expressions; the assignment-list, which is a comma separated list of assignments; and the function-body, which is the argument list and code body of a function. The syntax of the first of these is: expression-list empty expression expression expression-list The expression-list is fairly simple. The construct empty is used to indicate that the whole 74 list may be absent. Notice the optional comma after the last expression. This is designed to allow a more consistent formatting when the elements are line based, and simpler output from programmatically produced code. For example: [array "This is the first element", "This is the second element", "This is the third element", The assignment list has similar features: assignment-list assignment struct-key empty assignment assignment assignment-list struct-key expression identifier expression 9* *9 9* 9* 9 9 9 9 9 9 9* 9 .99 .9 9 9 .9 .9 9 9* 9* 9 Each assignment is either an assignment to a simple identifier or an assignment to a full expression in brackets. The assignment to an identifier is merely a notational abbreviation for an assignment to a string. The following two struct literals are equivalent: [struct abc 4] [struct 4] The syntax of a function-body is: Junction-body identifier-list identifier-list compound-statement empty identifier identifier identifier-list That is, an identifier-list is an optional comma separated list of identifiers with an optional trailing comma. Literal functions are rare in most programs; functions are normally named and defined with a special declaration form which will be seen in more detail below. The following two code fragments are equivalent; the first is the abbreviated notation: static fred(a, b){return a b;} and: static fred [func b){return a The meaning of functions will discussed in more detail below.
75 Aggregates in general, and literal aggregates in particular, are fully nestable: [array [struct a 1, c 2], [set 1.2, 3], "a string", Note that aggregate literals are entirely evaluated by the parser. That is, each expression is evaluated and reduced to a particular value, these values are then used to build an object of the required type. For example: [struct a sin(0.5), b Causes the functions sin and cos to be called during the parsing process and the result assigned to the keys a and b in the struct being constructed. It is possible to refer to variables which may be in existence while such a literal is being parsed 1 This ends our consideration of the lowest level element of an expression, the factor.
A simple factor may be adorned with a sequence of primary-operations to form a primaryexpression. That is: primary-expression factor primary-operation...
primary-operation expression identifier expression identifier (expression) expression-list) The first primary-operation (above) we have already seen. It is the operation of "indexing" which can be applied to aggregate types. For example, if xxx is an array: xxx refers to the element of xxx at index 10. The parser does not impose any type restrictions (because typing is dynamic), although numerous type restrictions apply at execution time (for instance, arrays may only be indexed by integers, and floating point numbers are not able to be indexed at all).
The second form, identifier, is a notational abbreviation of "identifier" as seen previ- 1.Literal aggregates are analagous to literal strings in K&R C. And likewise they have the property that modifications to the literal are persistent. Returning to the original use of the literal after it has been modified does not magically restore it to its original value.
76 ously. Similarly the third form is again just a notational variation. Thus the following are all equivalent: xxx ["aaa"] XXX .[aaa xxx. aaa xxx. ("aaa") And the following are also equivalent to each other: xxx[1 2] xxx. (1 2) Note that factors may be suffixed by any number of primary-operations. The only restriction is that the types must be right during execution. Thus: xxx[123] .aaa[101 is legal.
The two constructs identifier expression) i. S are again notational variations. In general, constructs of the form:
S
primary-expression identifier primary-expression expression are re-written as: primary-expression identifer primary-expression expression The unary operator used here is the indirection operator, its meaning is discussed later.
The last of the primary-operations: expression-list is the function call operation. Although, as usual, no type checking is performed by the parser; at execution time the thing it is applied to must be a function: For example: my_function(1, 2, "a string") 77 and are both function calls. Function calls will be discussed in more detail below.
This concludes the examination of a primary-expression.
Primary-expressions are combined with prefix and postfix unary operators to make terms: term [prefix-operator...] primary-expression [postfix-operator... prefix-operator Any ofpostfix-operator Any of That is, a term is aprimary-expression surrounded on both sides by any number of prefix and postfix operators. Postfix operators bind more tightly than prefix operators. Both types bind a right-to-left when concatenated together. That is: x is the same as As in all expression compilation, no type checking is performed by the parser, because types are an execution-time consideration.
Some of these operators touch on subjects not yet explained and so will be dealt with in detail in later sections. But in summary: Prefix operators Indirection; applied to a pointer, gives target of the pointer.
Address of; applied to any lvalue, gives a pointer to it.
Negation; gives negative of any arithmetic value.
Positive; no real effect.
S! Logical not; applied to 0 or NULL, gives 1, else gives 0.
Bit-wise complement.
Pre-increment; increments an lvalue and gives new value.
Pre-decrement; decrements an lvalue and gives new value.
Atomic form of; gives the (unique) read-only version of any value.
Immediate evaluation; see below.
Postfix operators Post-increment; increments an lvalue and gives old value.
Post-increment; decrements an Ivalue and gives old value.
78 One of these operators, is only a pseudo-operator. It actually has its effect entirely at parse time. The operator causes its subject expression to be evaluated immediately by the parser and the result of that evaluation substituted in its place. This is used to speed later execution, to protect against later scope or variable changes, and to construct constant values which are better made with running code than literal constants. For example, an expression involving the square root of two could be written as: x y 1.414213562373095; Or it could be written more clearly, and with less chance of error, as: x y But this construct will call the square root function each time the expression is evaluated. If the expression is written as: x y The square root function will be called just once, by the parser, and will be equivalent to the first form.
When the parser evaluates the subject of a operator it recursively invokes the execution engine to perform the evaluation. As a result there is no restriction on the activity which can be performed by the subject expression. It may reference variables, call functions or even read Sfiles. But it is important to remember that it is called at parse time. Any variables referenced will be immediately interrogated for their current value. Automatic variables of any expression which is contained in a function will not be available, because the function itself has not yet been invoked; in fact it is clearly not yet even fully parsed.
The operator as used above increased speed and readability. Another common use is to avoid later re-definitions of a variable. For instance: o° ($printf) ("Hello world\n"); Will use the printffunction which was defined at the time the statement was parsed, even if it is latter re-defined to be some other function. It is also slightly faster, but the difference is small when only a simple variable look-up is involved. Notice the bracketing which has been used to bind the to the wordprintf Function calls are primary operations so the S would have otherwise referred to the whole function call as it did in the first example.
This concludes our examination of a term (remember that the full meaning of other prefix and postfix operators will be discussed in later sections). We will now turn to the top level of expressions where terms are combined with binary operators: expression term expression infix-operator expression 79 infix-operator Any of
A
11 a a.
a a a a.
a a a a a a a a a. a a a a.
a.
a a a.
a a a a. a a.
a 9 A= j= That is, an expression can be a simple term, or two expressions separated by an infix-operator. The ambiguity amongst expressions built from several binary-operator separated expressions is resolved by assigning each operator a precedence and also applying rules for order of binding amongst equal precedence levels 2 The lines of binary operators in the syntax rules above summarise their precedence. Operators on higher lines have higher precedence than those on lower lines. Thus 1+2 3 is the same as 1 (2 Operators which share a line have the same precedence. All operators except those on the second last line group left-toright. Those on the second last line (the assignment operators) group right-to-left. Thus a b c is the same as: (a b) c But: a b c is the same as: a (b c) As with unary operators, the full meaning of each will be discussed in a later section. But in summary: Binary operators Multiplication, Set intersection 2.The precedences and rules are identical to those of C.
Division Modulus Addition, Set union Subtraction, Set difference Right shift (shift to lower significance) Left shift (shift to higher significance) Logical test for less than, Proper subset Logical test for greater than, Proper superset Logical test for less than or equal to, Subset Logical test for greater than or equal to, Superset Logical test for equality Logical test for inequality Logical test for regular expression match Logical test for regular expression non-match Regular expression sub-string extraction 0 S~ Regular expression multiple sub-string extraction Bit-wise and Bit-wise exclusive or Bit-wise or Logical and I Logical or Choice separator (must be right hand subject of operator) Choice (right hand expression must use: operator) Assignment Add to Subtract from o Multiply by Divide by Modulus by Right shift by Left shift by And by A= Exclusive or by Or by Replace by regular expression extraction Swap values I Multiple expression separator 81 This concludes our consideration of expressions. We will now move on to each of the executable statement types in turn.
Simple expression statements The simple expression statement: expression Is simply an expression followed by a semicolon. The parser translates this expression to its executable form. Upon execution the expression is evaluated and the result discarded. Typically the expression will have some side-effect such as assignment, or make a function call which has a side-effect, but there is no explicit requirement that it do so. Typical expression statements are: printf("Hello world.\n"); X y Z; Note that an expression statement which could have no side-effects other than producing an error may be completely discarded and have no code generated for it.
Compound statements The compound statement has the form: statement... That is, a compound statement is a series of any number of statements surrounded by curly braces. Apart from causing all the sub-statements within the compound statement to be treated as a syntactic unit, it has no effect. Thus: printf ("Line f. ft printf ("Line printf("Line printf("Line When run, will produce: Line 1 Line 2 Line 3 Line 4 Note that the parser will not return control to the execution engine until all of a top-level compound statement has been parsed. This is true in general for all other statement types.
82 The if statement The if statement has two forms: if expression statement if expression statement else statement The parser converts both to an internal form. Upon execution, the expression is evaluated.
If the expression evaluates to anything other than 0 (integer zero) or NULL, the following statement is executed; otherwise it is not. In the first form this is all that happens, in the second form, if the expression evaluated to 0 or NULL the statement following the else is executed; otherwise it is not.
The interpretation of both 0 and NULL as false, and anything else as true, is common to all logical operations in ICI. There is no special boolean type.
The ambiguity introduced by multiple if statements with an lesser number of else clauses is resolved by binding else clauses with their closest possible if. Thus: if if dox() else doy() .If equivalent to: o if (a) if (b) dox() else doy The while statement The while statement has the form: while expression statement The parser converts it to an internal form. Upon execution a loop is established. Within the loop the expression is evaluated, and if it is false (0 or NULL) the loop is terminated and flow of control continues after the while statement. But if the expression evaluates to true (not 0 and not NULL) the statement is executed and then flow of control moves back to the start of the loop where the test is performed again (although other statements, as seen below, can be used to modify this natural flow of control).
The do-while statement The do-while statement has the following form: 83 do statement while expression The parser converts it to an internal form. Upon execution a loop is established. Within the loop the statement is executed. Then the expression is evaluated and if it evaluates to true, flow of control resumes at the start of the loop. Otherwise the loop is terminated and flow of control resumes after the do-while statement.
The for statement Thefor statement has the form: for [expression]; [expression]; [expression] statement The parser converts it to an internal form. Upon execution the first expression is evaluated (if present). Then, a loop is established. Within the loop: If the second expression is present, it is evaluated and if it is false the loop is terminated. Next the statement is executed. Finally, the third expression is evaluated (if present) and flow of control resumes at the start of the loop. For example: .for (i 0; i 4; printf("Line i); When run will produce: o Line 0 Line 1 Line 1 Line 3 Theforall statement Theforall statement has the form: foral expression expression] in expression statement The parser converts it to an internal form. In doing so the first and second expressions are required to be lvalues (that is, capable of being assigned to). Upon execution the first expression is evaluated and that storage location is noted. If the second expression is present the same is done for it. The third expression is then evaluated and the result noted; it must evaluate to an array, a set, a struct, a string, or NULL; we will call this the aggregate. If this is NULL, thejbrall statement is finished and flow of control continues after the statement; otherwise, a loop is established.
Within the loop, an element is selected from the noted aggregate. The value of that element is assigned to the location given by the first expression. If the second expression was present, it is assigned the key used to access that element. Then the statement is executed. Finally, flow of control resumes at the start of the loop.
0* a a 84- Each arrival at the start of the loop will select a different element from the aggregate. If no as yet unselected elements are left, the loop terminates. The order of selection is predictable for arrays and strings, namely first to last. But for structs and sets it is unpredictable. Also, while changing the values of the structure members is acceptable, adding or deleting keys, or adding or deleting set elements during the loop will have an unpredictable effect on the progress of the loop.
As an example: forall (colour in [array "red", "green", "blue"]) printf("%s\n", colour); when run will produce: red green blue And: forall (value, key in [struct a 1, b 2, c 31]) printf("%s key, value); when run will produce (possibly in some other order): c 3 a 1 b 2 Note in particular the interpretation of the value and key for a set. For consistency with the access method and the behavior of structs and arrays, the values are all 1 and the elements are regarded as the keys, thus: forall (value, key in [set "cI]) printf("%s key, value); when run will produce: C 1 a=1 b= 1 But as a special case, when the second expression is omitted, the first is set to each "key" in turn, that is, the elements of the set. Thus: forall (element in [set printf("%s\n", element); 85 when run will produce: c a b When a forall loop is applied to a string (which is not a true aggregate), the "sub-elements" will be successive one character sub-strings.
Note that although the sequence of choice of elements from a set or struct is at first examination unpredictable, it will be the same in a second forall loop applied without the structure or set being modified in the interim.
The switch, case, and default statements These statements have the forms: switch expression compound-statement case expression default The parser converts the switch statement to an internal form. As it is parsing the compound statement, it notes any case and default statements it finds at the top level of the compound S statement. When a case statement is parsed the expression is evaluated immediately by the parser. As noted previously for parser evaluated expressions, it may perform arbitrary actions, but it is important to be aware that it is resolved to a particular value just once by the parser. As the case and default statements are seen their position and the associated expressions are noted in a table.
Upon execution, the switch statement's expression is evaluated. This value is looked up in the table created by the parser. If a matching case statement is found, flow of control immediately moves to immediately after that case statement. If there is a default statement, flow of control immediately moves to just after that. If there is no matching case and no default statement, flow of control continues just after the entire switch statement.
For example: switch string") case "another string": printf("Not this one.\n"); case 2: printf("Not this one either.\n"); case "a string": printf("This one.\n"); default: printf("And this one too.\n"); -86- When run will produce: This one.
And this one too.
Note that the case and default statements, apart from the part they play in the construction of the look-up table, do not influence the executable code of the compound statement. Notice that once flow of control had transferred to the third case statement above, it continued through the default statement as if it had not been present. This behavior can be modified by the break statement described below.
It should be noted that the "match" used to look-up the switch expression against the case expressions is the same as that used for structure element look-up. That is, to match, the switch expression must evaluate to the same object as the case expression. The meaning of this will be made clear in a later section.
The break and continue statements Sg" The break and continue statements have the form: break continue The parser converts these to an internal form. Upon execution of a break statement the execution engine will cause the nearest enclosing loop (a while, do, for or forall) or switch statement within the same scope to terminate. Flow of control will resume immediately after the affected statement. Note that a break statement without a surrounding loop or switch in the same function or module is illegal.
Upon execution of a continue statement the execution engine will cause the nearest enclosing loop to move to the next iteration. For while and do loops this means the test. Forfor loops it means the step, then the test. Forforall loops it means the next element of the aggregate.
The return statement The return statement has the form: return expression The parser converts this to an internal form. Upon execution, the execution engine evaluates the expression if it is present. If it is not, the value NULL is substituted. Then the current function terminates with that value as its apparent value in any expression it is embedded in.
It is an error for there to be no enclosing function.
-87- The try statement The try statement has the form: try statement onerror statement The parser converts this to an internal form. Upon execution, the first statement is executed.
If this statement executes normally flow continues after the try statement; the second statement is ignored. But if an error occurs during the execution of the first statement control is passed immediately to the second statement.
Note that "during the execution" applies to any depth of function calls, even to other modules or the parsing of sub-modules. When an error occurs both the parser and execution engine unwind as necessary until an error catcher (that is, a try statement) is found.
Errors can occur almost anywhere and for a variety of reasons. They can be explicitly generated with the fail function (described below), they can be generated as a side-effect of execution (such as division by zero), and they can be generated by the parser due to syntax or •semantic errors in the parsed source. For whatever reason an error is generated, a message (a S string) is always associated with it.
When any otherwise uncaught error occurs during the execution of the first statement, two things are done: Firstly, the string associated with the failure is assigned to the variable error. The assignment is made as if by a simple assignment statement within the scope of the try statement.
Secondly, flow of control is passed to the statement following the onerror keyword.
Once the second statement finishes execution, flow of control continues as if the whole try statement had executed normally.
For example: static div b) try return a b; onerror return 0; printf("4 2 div(4, printf("4 0 div(4, When run will print: 88 4 2 2 4/ 0 =o The handling of errors which are not caught by any try statement is implementation dependent. A typical action is to prepend the file and line number on which the error occurred to the error string, print this, and exit.
The null statement The null statement has the form: The parser may convert this to an internal form. Upon execution it will do nothing.
Declaration statements There are two types of declaration statements: declaration storage-class declaration-list; storage-class identifier function-body storage-class extern 'static auto The first is the general case while the second is an abbreviated form for function definitions.
Declaration statements are syntactically equal to any other statement, but their effect is made entirely at parse time. They act as null statements to the execution engine. There are no restrinction on where they may occur, but their effect is a by-product of their parsing, not of any execution.
Declaration statements must start with one of the storage-class keywords listed above 3 Considering the general case first, we next have a declaration-list.
declaration-list identifier expression declaration-list, identifier expression That is, a comma separated list of identifiers, each with an optional initialisation, terminated by a semicolon. For example: static a, b 2, c [array 1, 2, 3] The storage class keyword establishes which scope the variables in the list are established in, as discussed earlier. Note that declaring the same identifier at different scope levels is per- 3.Note that, unlike C, function definitions must be prefixed by a storage class. As executable code may occur anywhere, this is required to distinguish them from a function call.
89 missible and that they are different variables.
A declaration with no initialisation first checks if the variable already exists at the given scope. If it does, it is left unmodified. In particular, any value it currently has is undisturbed.
If it does not exist it is established and is given the value NULL.
A declaration with an initialisation establishes the variable in the given scope and gives it the given value even if it already exists and even if it has some other value.
Note that initial values are parser evaluated expressions. That is they are evaluated immediately by the parser, but may take arbitrary actions apart from that. For example: static fibonacci (n) if (n 1) return 1 return fibonacci(n 1) fibonacci(n 2) static fiblO The declaration offiblO calls a function. But that function has already been defined so this will work.
Note that the scope of a static variable is (normally) the entire module it is parsed in. For example: static func static aStatic "The value of a static."; 9* printf aStatic); when run will print: The value of a static.
That is, despite being declared within a function, the declaration of aStatic has the same effect as if it had been declared outside the function. Also notice that the function has not been called. The act of parsing the function caused the declaration to take effect.
The behavior of extern variables has already been discussed, that is, they are declared as static in the parent module. The behavior of auto variables, and in particular their initialisation, will be discussed in a later section.
90 Abbreviated function declarations As seen above there are two forms of declaration. The second: storage-class identifier fiinction-body is a shorthand for: storage-class identifier [func function-body and is the normal way to declare simple functions. Examples of this have been seen above.
Functions As with most ICI constructs there are two parts to understanding functions; how they are parsed and how they execute.
When a function is parsed four things are noted: the names and positions of the formal parameters; the names and initialisation of auto variables; o the static scope in which the function is declared; the code generated by the statements in the function.
The formal parameters (that is, the identifiers in the bracket enclosed listjust before the compound statement) are actually implicit auto variable declarations. Each of the identifiers is declared as an auto variable without an initialisation, but in addition, its name and position in the list is noted.
Upon execution (that is, upon a function call), the following takes place: The auto variables, as noted by the parser, along with any initialisations, are copied as a group. This copy forms the auto variables of this invocation.
Any actual parameters (that is, expressions provided by the caller) are matched positionally with the formal parameter names, and the value of those expressions are assigned to the auto variables of those names.
If there were more actual parameters than formal parameters, and there is an auto variable called vargs, the remaining argument values are formed into an array which is assigned to vargs.
The variable scope is set such that the auto variables are the inner-most scope, the static variables noted with the function are the next outer scope etc.
The flow of control is diverted to the code generated by parsing the function.
A return statement executed within the function will cause the function to return to the caller and act as though its value were the expression given in the return statement. If no expression was given in the return statement, or if execution fell through the bottom of the function, the -91 apparent return value is NULL. In any event, upon return the scope is restored to that of the caller. All internal references to the group of automatic variables are lost (although as will be seen later explicit program references may cause them to remain active).
Simple functions have been seen in earlier examples. We will now consider further issues.
It is very important to note that the parser generates a prototype set of auto variables which are copied, along with their initial values, when the function is called. The value which an auto variable is initialised with is a parser evaluated expression just like any other initialisation. It is not evaluated on function entry. But on function entry the value the parser determined is used to initialise the variable. For example: static myVar 100; static myFunc auto anAuto myVar; printf("%d\n", anAuto); anAuto 500; S I myFunc myVar 200; myFunc When run will print: 100 100 .o Notice that the initial value of anAuto was computed just once, changing myVar before the second call did not affect it. Also note that changing anAuto during the function did not affect its subsequent re-initialisation on the next invocation.
As stated above, formal parameters are actually uninitialised auto variables. Because of the behavior of variable declarations it is possible to explicitly declare an auto variable as well as include it in the formal parameter list. In addition, such an explicit declaration may have an initialisation. In this case, the explicit initialisation will be effective when there is no actual parameter to override it. For example: static print (msg, file) auto file stdout; Default value. 92 fprintf(file, msg) print ("Hello world"); print ("Hello world", stderr); In the first call to the function print there is no second actual parameter. In this case the explicit initialisation of the auto variablefile (which is the second formal parameter) will have its effect unmolested. But in the second call to print a second argument is given. In this case this value will over-write the explicit initialisation given to the argument and cause the output to go to stderr.
As indicated above there is a mechanism to capture additional actual parameters which were not mentioned in the formal parameter list. Consider the following example: static sum auto vargs; auto total 0; auto arg; fforall (arg in vargs) total arg; return total; printf("l+2+3 sum(l, 2, printf("l+2+3+4 sum(l, 2, 3, Which when run will produce: 1+2+3 6 1+2+3+4 In this example the unmatched actual parameters were formed into an array and assigned to the auto variable vargs, a name which is recognised specially by the function call mechanism.
And also consider the following example where a default initialisation to vargs is made. In the following example the function call is used to invoke a function with an array of actual parameters, the function array is used to form an array at run-time, and addition is used to concatenate arrays; all these features will be further explained in later sections: static debug (fmt) auto fmt "Reached here.\n";- 93 auto vargs [array]; call(fprintf, array(stderr, fmt) vargs) debug() debug("Done that.\n"); debug("Result total 123, 456); When run will print: Reached here.
Done that.
Result 123, total 456.
In the first call to debug no arguments are given and both explicit initialisations take effect.
In the second call the first argument is given, but the initialisation of vargs still takes effect.
But in the third call there are unmatched actual parameters, so these are formed into an array and assigned to vargs, overriding its explicit initialisation.
Objects Up till now few exact statements about the nature of values and data have been made. We will now examine values in more detail. Consider the following code fragment: static x; static y; x [array 1, 2, 3, 4]
*X
After execution of this code the variable x refers to an array. The assignment of x to y causes y to refer to the same array. Diagrammatically: x 1 2 3 4 y If the assignment: y[l] 200; is performed, the result is: x 1 200 3 4 y 94 We say that x and y refer to the same object. Now consider the following code fragment: static x; static y; x [array 1, 2, 3, 4]; y [array 1, 2, 3, 4]; Diagrammatically: y 2 3 In this case, x and y refer to different objects, despite that fact they are equal.
Now consider one of the unary operators which was only briefly mentioned in the sections above. The operator returns a read-only version of the sub-expression it is applied to.
Consider the following statement: After this has been executed the result could be represented diagrammatically as: statement: *3* y 4 After this has been executed the result could be represented diagrammatically as: 2 I 3 i 95 Notice that x now refers to the same read-only array that y refers to. This is a fundamental property of the operator. It returns the unique read-only version of its argument value.
Such read-only objects are referred to as atomic objects. The array which x used to refer to was non-atomic, but the array it refers to now is an atomic array. Aggregate types such as arrays, sets and structs are generally non-atomic, but atomic versions can be obtained (as seen above). But most other types, such as integers floats, strings and functions are intrinsically atomic. That is, no matter how a number, say 10, is generated, it will be the same object as every other number 10 in the interpreter. For-instance, consider the following example: x "ab" "cdefg"; y "abcde" After this is executed the situation can be represented diagrammatically as: x "abcdefg" y It is important to understand when objects are the same object, when they are different and the effects this has.
o: Equality We saw above how two apparently identical arrays were each distinct object. But these two arrays were equal in the sense of the equality testing operator If two values are the same object they are said to be eq 4 and there is a function of that name to test for this condition.
T: wo objects are equal (that is if: t €i they are the same object; or they are both arithmetic (int and float) and have equivalent numeric values; or they are aggregates of the same type and all the sub-elements are the same objects.
This definition of equality is the basis for resolving the merging of aggregates into unique read-only (atomic) versions. Two aggregates will resolve to the same atomic object if they are equal. That is, they must contain exactly the same objects as sub-elements, not just equal objects. For example: static x [array 1, [array 2, 4, 5] static y [array 1, [array 2, 4, 5] 4.As in LISP.
96 Could be represented diagrammatically as: Now, if the following statements were executed: x @x; y @y; The result could be represented diagrammatically as: 9 *9t C
S.
C
C
9* 0*C&
C
C 9 9.
C C
C
C.
C
CC. C C 9 C 9
CC..
C.
o C C
C
C *9
C
C
C.
9* C C C 9.
C
That is, both x and y refer to new read-only objects, but they refer to different read-only objects because they have an element which is not the same object. The simple integers are the same objects because integers are intrinsically atomic objects. But the two sub-arrays are distinct objects. Being equal was not sufficient. The top-level arrays needed to have exactly the same objects as contents to make x and y end up referring to the same read-only array. In contrast to this consider the following similar situation: static z static x static y [array 2, 3]; [array 1, z, 4, 5] [array 1, z, 4, 5] 97- This could be represented diagrammatically as: z 2 3 y -l 4 Now, if the following statements were executed: x @x; y @y; The result could be represented diagrammatically as: x 23 In this case both x and y refer to the same read-only ,array because the original arrays where equal, that is, all their elements were the same objects. Notice that one of the elements is still 2 3 *a w a array can be changed, but the reference to it from the top level array can not. Thus: will result in: whereas the statement: x[i] 200; will just result in an error.
98 Structure and set keys Any object, not just a string, can be used as a key in a structure. For instance: static x [struct] static z [array 10, 11] x["abc"] 1; x[56] 2; x[z] 3; Could be represented diagrammatically as: x "abc" 56 1 2 3 And the assignment: x[z] 300; would replace the 3 in the above diagram with 300. But the assignment: x[[array 10, 11]] 300; would result in a new element being added to the structure because the array given in the above statement is a different object from the one which z refers to.
Similarly, elements of sets may be any objects.
Indexing structures by complex aggregates is as efficient as indexing by intrinsically atomic types such as strings and integers.
Structure super types Up till now structures have been described as simple lookup tables which map a key, or index, to a value. But a structure may have associated with it a super structure.
The function super can be used to discover the current super of a struct and to set a new super.
With just one argument it returns the current super of that struct, with a second argument it also replaces the super by that value.
When a key is being looked-up in a structure for reading, and it is not found and there is a super struct, the key is further looked for in the super struct, if it is found there its value from that struct is returned. If it is not found it will be looked for in the next super struct etc. If no 99structures in the super chain contain the key, the special value NULL is returned.
When a key is being looked up in a structure for writing, it will similarly be searched for in the super chain. If it is found in a writeable structure the value in the structure in which it was found will be set to the new value. If it was never found, it will be added along with the given value to the very first struct, that is, the structure at the base, or root, of the super chain.
Consider the following example: static theSuper [struct a 1, b 2, c 3] static theStruct [struct x 100, y 200]; super(theStruct, theSuper); After this statement the situation could be represented diagrammatically as: c S1 2 3 i
A
theStct "x"y 100 200 then if the following statements were executed: theStruct.a 123; theStruct.x 456; theStruct.z 789; the situation could be diagrammatically represented as: c" -123 2 3 theStruct x" 456 200 789 If a super struct is not writeable (that is, it is atomic) values will not be written in it and will lodge in the base structure instead. Thus consider what happens if we replace the super structure in the previous example by its read-only version: 100super(theStruct, @theSuper); The situation could now be represented diagrammatically as: "c" 123 2 3 theStruct z 456 200 789 If the assignment statement: theStruct.a were executed, the value of the element a will first be read from the super structure, this value will then have ten added to it, and the result will be written back into the base structure; because the super structure is read-only and cannot be modified. The finally situation can be represented diagrammatically as: "c" 123 2 3 theStruct y I S 133 456 200 789 Note that many structs may share the same super struct. Thus a single read-only super struct can be used hold initial values; saving explicit initialisations and storage space.
The function assign may be used to set a value in a struct explicitly, without reference to any super structs; and the function fetch may be used to read a value from a struct explicitly, without reference to any super structs.
Within a struct-literal a colon prefixed expression after the struct identifier is used as the super struct. For example, the declarations used in the previous example could be written as: static theSuper [struct a 1, b 2, c 3] static theStruct [struct:theSuper, x 100, y 200];
SEC
104 V-r o 101 An aside on variables and scope Now that structs and their super have been described a more precise statement about variables and scope can be made.
ICI variables are entries in ordinary structs. At all times, the current scope is identified by a structure. The auto variables are the entries in this base structure. Its super is the struct containing the static variables. The next super struct contains the externs, and successive super structs are successive outer scopes.
Auto, static and extern declarations make explicit assignments to the appropriate structure.
In these terms it can be said that an un-adorned identifier in an expression is an implicit reference to an element of the current scope structure. The inheritance and name hiding of the variable scope mechanism is a product of the super chain. The only difference is that undefined entries produce errors rather than a default value of NULL or implicit creation.
The function scope can be used to obtain the current scope structure; and to set it (use with care).
Note that when there is an atomic structure in the scope chain the mechanism described at the end of the previous section does not operate correctly. Writing to a variable in the atomic struct will give a spurious undefined error rather than lodging it in the base structure. This is a deficiency which will be corrected in a later release.
Pointers Pointers are references to storage locations. Storage locations are the elements of anything which can be indexed. That is, array elements, set elements, struct elements and others S (which we will see below) can be pointed to. Variables (which are just struct elements) can be pointed to. In more general terms, any lvalue can be pointed to.
The operator is used to obtain a pointer to a location. Thus if the following were executed: static x; static y [array 1, 2, 3] static pl &x; static p2 The variable p] would be a pointer to x and the variables p 2 would be a pointer to the second element ofy. Reference to the object a pointer points to can be obtained with the operator.
Thus if the following were executed: *pl 123; *p2 456; printf y[1] x, 102the output would be: x 123, y[1] 456 Pointers are really a bundle of two objects, one is the object pointed into, the other is the key used to access the location in question. For instance, in the example above p2 remembers the array, and the number 1; that is, the aggregate and the index. The generation of a pointer does not affect the location being pointed to. In fact the location may not even exist yet. When a pointer is referenced the same operation takes place as if the location was referenced explicitly. Thus a search down the super chain of a struct may occur, or an array may be extended to include the index being written to, etc.
In addition to simple indirection (that is the operator), pointers may be indexed. But the index values must be an integer, and the key stored as part of the pointer must also be an integer.
When a pointer is indexed, the index is added to the key which is stored as part of the pointer, the sum forms the actual index to use to when referencing the aggregate recorded by the pointer. For instance, continuing the example above: p2[1] 789; 1 would set the last element of the array to 789, because the pointer currently references ele- 0* ment 1, and the given index is 1, and 1 1 is 2 which is the last element. The index arithmetic provided by pointers will work with any types, as long as the indexes are integers, thus: So* static s [struct (20) 1, (30) 2, (40) 3]; static p p[-10] -1; geee p -2; p [10] -3; Would replace each of the elements in the struct s by their negative value.
S. This concludes the general discussion of ICI as a whole. We will now examine the exact nature of each of the data types, then each of the expression operators, and finally each of the standard functions.
Data types ICI supports a base set of standard data types. Each is identified by a simple name. In summary these are: array An ordered sequence of other objects.
file An open file reference.
float A double precision floating point number.
func A function.
103 int A signed 32 bit integer.
mem References to raw machine memory.
ptr A reference to a storage location.
regexp A compiled regular expression.
set An unordered collection of other objects.
string An ordered sequence of 8 bit characters.
struct An unordered set of pairs of objects.
A full explanation of the semantics of each type (including the semantics of indexing an object of that type) will be included in a future version of this document.
Operators The following table details each of the unary and binary operators with all of the types they may be applied to. Within the first column the standard type names are used to stand for operands of that type, along with any to mean any type and num to mean an int or afloat. In general, where an int and afloat are combined in an arithmetic operation, the int is first converted to afloat and then the operation is performed.
The following table is in precedence order.
*ptr Indirection: The result references the thing the pointer points to. The result is an lvalue.
&any Address of: The result is a pointer to any. If any is an Ivalue the epointer references that storage location. If any is not an Ivalue but is a term other than a bracketed non-term, as described in the syntax above, a one element array containing any will be fabricated and a pointer to that storage location returned. For example: P &1; sets p to be a pointer to the first element ofan un-named array, which currently contains the number 1.
-num Negation: Returns the negation of num. The result is the same type as the argument. The result is not an Ivalue.
+any Has no effect except the result is not an Ivalue.
!any Logical negation: If any is 0 (integer) or NULL, I is returned, else 0 is returned.
-int Bit-wise complement: The bit-wise complement of int is returned.
104- ++any any @any $any
S
p *5
S
S
5* S a S p S S p p
S
S
S.
S p
S.
C
p
C*
*5 p p *5
C
any+ any- numl num2 set] set2 numl num2 intl int2 numl num2 Pre-increment: Equivalent to (any any must be an Ivalue and obey the restrictions of the binary operator. See below.
Pre-decrement: Equivalent to (any any must be an Ivalue and obey the restrictions of the binary operator. See below.
Atomic form of: Returns the unique, read-only form of any. If any is already atomic, it is returned immediately. Otherwise an atomic form of any is found or generated and returned; this is of execution time order equal to the number of elements in any. See the section on objects above for more explanation.
Immediate evaluation: Recognised by the parser. The sub-expression any is immediately evaluated by invocation of the execution engine.
The result of the evaluation is substituted directly for this expression term by the parser.
Post-increment: Notes the value of any, then performs the equivalent of (any except any is only evaluated once, and finally returns the original noted value, any must be an Ivalue and obey the restrictions of the binary operator. See below.
Post-increment: Notes the value of any, then performs the equivalent of (any except any is only evaluated once, and finally returns the original noted value, any must be an Ivalue and obey the restrictions of the binary operator. See below.
Multiplication: Returns the product of the two numbers, if both nums are ints, the result is int, else the result is float.
Set intersection: Returns a set that contains all elements that appear in both set] and set2.
Division: Returns the result of dividing numl by num2. If both numbers are ints the result is int, else the result is float. If num2 is zero the error division by 0 is generated, or division by 0.0 if the result would have been a float.
Modulus: Returns the remainder of dividing intl by int2. If int2 is zero the error modulus by 0 is generated.
Addition: Returns the sum of numl and num2. If both numbers are ints the result is int, else the result is float.
~SEC'
~14 IA-T c 105ptr int string] string2 array] array2 Pointer addition: ptr must point to an element of an indexable object whose index is an int. Returns a new pointer which points to an element of the same aggregate which has the index which is the sum of ptr's index and int. The arguments may be in any order.
String concatenation: Returns the string which is the concatenation of the characters of string] then string2. The execution time order is proportional to the total length of the result.
Array concatenation: Returns a new array which is the concatenation of the elements from array] then array2. The execution time order is proportional to the total length of the result. Note the difference between the following: a [array 1] push(a, 1) 4 4 4 .4* 4t 4 44* 44* 44 .4* 4 4 4* 4 4 4 4 4 4 a 44* c* 44 4* 4 4 44« 94 4 go« *o go In the first case a is replaced by a newly formed array which is the original array with one element added. But in the second case the push function (see below) appends an element to the array a refers to, without making a new array. The second case is much faster, but modifies an existing array.
struct] struct2 Structure concatenation: Returns a new struct which is a copy of struct], with all the elements of struct2 assigned into it. Obeys the semantics of copying and assignment discussed in other sections with regard to super structs.. The execution time order is proportional to the sum of the lengths of the two arguments.
set] set2 Set union: Returns a new set which contains all the elements from both sets. The execution time order is proportional to the sum of the lengths of the two arguments.
numl num2 Subtraction: Returns the result of subtracting num2 from numl. If both numbers are ints the result is int, else the result is float.
set] set2 Set subtraction: Returns a new set which contains all the elements of set], less the elements of set2. The execution time order is proportional to the sum of the lengths of the two arguments.
ptr] ptr2 Pointer subtraction: ptr] andptr2 must point to elements of indexable objects whose indexs are ints. Returns an int which is the the index ofptrl less the index ofptr2.
intl int2 Right shift: Returns the result of right shifting int] by int2. Equivalent to division by 2**int2. int] is interpreted as a signed quantity.
106intl int2 array int numl num2 set] set2 string] string2 pirl ptr2 Left shift: Returns the result of left shifting intl by int2. Equivalent to multiplication by 2 **int2.
Left shift array: Returns a new array which contains the elements of array from index int onwards. Equivalent to the function call interval(array, int) (which is considered preferable, this operator may disappear in future releases).
Numeric test for less than: Returns 1 ifnuml is less than num2, else 0.
Test for subset: Returns 1 if set] contains only elements that are in set2, else 0.
Lexical test for less than: Returns 1 if string] is lexically less than string2, else 0.
Pointer test for less than: ptrl and ptr2 must point to elements of indexable objects whose indexes are ints. Returns 1 ifptrl points to an element with a lesser index than ptr2, else 0.
9 *9 0 0 0 *0 000* 0 0* S S 0t
S
0 0 0SS 0
S.
S
0 0@e S 0 0 0 060.
0**S S S 00 *0 *5 0 0 0
SO
0 S 0* *5 0 0e 0e 6 The and operators work in the same fashion as above. For sets tests for one set being a superset of the other. The and operators test for proper sub- or super-sets. That is one set can contain only those elements contained in the other set but cannot be equal to the other set.
anyl any2 Equality test: Returns 1 if any] is equal to any2, else 0. Two objects are equal when: they are the same object; or they are both arithmetic (int andfloat) and have equivalent numeric values; or they are aggregates of the same type and all the sub-elements are the same objects.
anyl any2 Inequality test: Returns 1 if any] is not equal to any2, else 0. See above.
string regexp string regexp string regexp Logical test for regular expression match: Returns 1 if string can be matched by regexp, else 0. The arguments may be in any order.
Logical test for regular expression non-match: Returns 1 if string can not be matched by regexp, else 0. The arguments may be in any order.
Regular expression sub-string extraction: Returns the sub-string of string which is matched by the first bracket enclosed portion of regexp, or NULL if there is no match or regexp does not contain a portion. The arguments may be in any order. For example, a "basename" operation can be performed with: argv[O] 107- .0 SO. 0 0 0 string regexp Regular expression multiple sub-string extraction: Returns an array of the the sub-strings of string which are matched by the -enclosed portions of regexp, or NULL if there is no match. The arguments may be in any order.
intl int2 Bit-wise and: Returns the bit-wise and of intl and int2.
intl int2 Bit-exclusive or: Returns the bit-wise exclusive or of intl and int2.
intl int2 Bit-wise or: Returns the bit-wise or of intl and int2.
anyl any2 Logical and: Evaluates the expression which determines any], if this evaluates to 0 or NULL false), 0 is returned, else any2 is evaluated and returned 5 Note that if anyl does not evaluate to a true value, the expression which determines any2 is never evaluated.
anyl I any2 Logical or: Evaluates the expression which determines anyl, if this evaluates to other than 0 or NULL true), I is returned, else any2 is evaluated and returned. Note that if anyl does not evaluate to a false value, the expression which determines any2 is never evaluated.
any] any2 any3 Choice: If anyl is neither 0 or NULL true), the expression which determines any2 is evaluated and returned, else the expression which determines any3 is evaluated and returned.. Only one of any2 and any3 are evaluated. The result may be an Ivalue if the returned expression is. Thus: flag a b value is a legal expression and will assign value to either a or b depending on the state offlag.
anyl any2 Assignment: Assigns any2 to anyl. anyl must be an lvalue. The behavior of assignment is a consequence of aggregate access as discussed in earlier sections. In short, an lvalue (in this case anyl) can always be resolved into an aggregate and an index into the aggregate.
Assignment sets the element of the aggregate identified by the index to any2. The returned result of the whole assignment is anyl, after the assigmnent has been performed.
The result is an Ivalue, thus: (a b) that this is different from C where the result is always completely resolved to a 0 or 1. Use to force a 0/1 value from a generic true/false.
00 S. oo
S.
*o
S
108 will assign b to a and then increment a by 1.
Note that assignment operators (this and following ones) associate right to left, unlike all other binary operators, thus: a b c d Will subtract d from c, then add the result to b, then assign the final value to a.
A= Compound assignments: All these operators are defined by the rewriting rule: any] op= any2 S••0 is equivalent to: 'anyl any] op any2 except that any] is not evaluated twice. Type restrictions and the bei havior or op will follow the rules given with that binary operator above. The result will be an lvalue (as a consequence of above).
There are no further restrictions. Thus: 1* 4 a "Hello"; a world. will result in the variable a referring to the string: 4.
"Hello world.\n".
4* anyl any2 Swap: Swaps the current values of any] and any2. Both operands must be lvalues. The result is any] after the swap and is an Ivalue, as in other assignment operators. Also like other assignment operators, associativity is right to left, thus: a b c d rotates the values of a, b and c towards d and brings ds original value back to a.
109anyl any2 Sequential evaluation: Evaluates anyl, then any2. The result is any2 and is an Ivalue if any2 is. Note that in situations where comma has meaning at the top level of parsing an expression (such as in function call arguments), expression parsing precedence starts at one level below the comma, and a comma will not be recognised as an operator.
Surround the expression with brackets to avoid this if necessary.
Standard functions The following list summarises the standard functions. Following this is a detailed descriptions of each of them.
float acos(number) mem alloc(int int]) array array(any...) S: float asin(number) any assign(struct, any, any) float atan(number) float atan2(number, number) any call(func, array) float ceil(number) close(file) any copy(any) float cos (number) file currentfile() del(struct, any) int eq(any, any) int eof(file) exit ([int string I NULL]) float exp(number) array explode(string) fail(string) any fetch(struct, any) float float (any) float floor(number) int flush (file) float fmod(number, number) file fopen(string string]) flush([file]) string getchar([file]) string getfile([file]) string getline([file]) 110st st a st st st string a a.
f.
int j f stJ f] 9 9 9 .9 .9 9* 9* 9 9 .9 9* 9* 9 9 9 9 9 9* ring getenv(string) ring gettoken(ffilelstring [,string]]) rray gettokens([fiielstring [,string [,string]]]) ring gsub(string, regexp, string) ring implode (array) ruct include(string) int nt (any) rray interval(stringlarray, mnt int]) mnt isatom(any) rray keys (struct) loat log (number) loat 10gio (number) mem mem(int, mnt [,int]) file mopen(string string]) int nels (any) loat num(stringlintlfloat) -uct parse(filelstring struct]) any pop(array) file popen(string string]) oat pow(number, number) prinz-f(Lfile,] string any...]1) any push(array, any) put (string).
putenv(string string]) int rand,,K[int]) rexp regexp (string) exp =regexpi (string) uct scope([struct]) seek,fiie, int, int) set set(any.. oat sin(number) mnt sizecf (any) ray smasn-(string, string) ile sope-(string string]) sort ,array, f unc) ing sprir-tf (string any...]1) oat sqrt number) ing =stri-g(any) act struco (any, any...) ing sub(so-ring, regexp, string) reg reg str fi ar str fi str stri str.
-111struct super(struct struct]) int system(string) float tan (number) string tochar(int) int toint (string) any top(array int]) int trace (string) string typeof (any) array vstack() filelintIfloat waitfor(filelintlfloat...) The following is an alphabetic listing of each of the standard functions.
angle acos(x) Returns the arc cosine ofx in the range 0 to pi.
mem alloc(nwords wordz]) Returns a new mem object referring to nwords (an int) of newly allocated and cleared memory. Each word is either 1, 2, or 4 bytes as specified by wordz (an int, default Indexing of mem objects performs the obvious operations, and thus pointers work too.
array array(any...) Returns an array formed from all the arguments. For example: array will return a new empty array; and array(1, 2, "a string") will return a new array with three elements, 1, 2, and "the string".
This is the run-time equivalent of the array literal. Thus the following two expressions are equivalent: $array(l, 2, "a string") [array 1, 2, "a string"] float asin(x) Returns the arc sine of x in the range -pi/2 to pi/2.
SSEC
112value assign(struct, key, value) Sets the element of struct identified by key to value, ignoring any super struct. Returns value.
angle atan(x) Returns the arc tangent of x in the range -pi/2 to pi/2.
angle atan2(y, x) Returns the angle from the origin to the rectangular coordinates x, y (floats in the range -pi to pi.
return call(func, args) Calls the functionfunc with arguments taken from the array args. Returns the return value of the function.
This is often used to pass on an unknown argument list. For example: static db o: auto vargs; if (debug) :return call (printf, vargs) :new copy(old) Returns a copy of old. If old is an intrinsically atomic type such as an int or string, the new will be the same object as the old. But if oldis an array, set, or struct, a copy will be returned.
The copy will be a new non-atomic object (even if old was atomic) which will contain exactly the same objects as oldand will be equal to it (that is If oldis a struct with a super struct, new will have the same super (exactly the same super, not a copy of it).
x cos(angle) Returns the cosine of angle (a float interpreted in radians).
file currentfile( Returns the file associated with the innermost parsing context, or NULL if there is no module being parsed.
This function can be used to include data in a program source file which is out-of-band with respect to the normal parse stream. But to do this it is necessary to know up to what character in the file in question the parser has consumed.
113 In general: after having parsed any simple statement the parser will have consumed up to and including the terminating semicolon, and no more. Also, after having parsed a compound statement the parser will have consumed up to and including the terminating close brace and no more. For example: static help gettokens(currentfile(), [0] ;This is the text of the help message.
It follows exactly after the because that is exactly up to where the parser will have consumed. We are using the gettokens() function (as described below) to read the text.
S. static otherVariable This function can also be used to parse the rest of a module within an error catcher. For example: try parse (currentfile scope()) onerror printf("That didn't work, but never mind.\n"); static this that-; etc() The functions parse and scope are described below.
del(struct, key) Deletes the element ofstruct identified by key. Any super structs are ignored. Returns NULL.
For example: static s [struct a 1, b 2, c 3] static v, k; forall k in s) printf("%s=%d\n", k, v); del(s, printf("\n"); forall k in s) printf("%s=%d\n", k, v); When run would produce (possibly in some other order): a=l c=3 114b=2 a=1 c=3 eq(objl, obj2) Returns 1 (one) if objl and obj2 are the same object, else 0 (zero).
exit([stringJintlNULL]) Causes the interpreter to finish execution and exit. If no parameter, the empty string or NULL is passed the exit status is zero. If an integer is passed that is the exit status. If a non-empty string is passed then that string is printed to the interpreter's standard error output and an exit status of one used. This is implementation dependent and may be replaced by a more general exception mechanism. Avoid.
float exp(x) o* Returns the exponential function ofx.
array explode(string) Returns an array containing each of the integer character codes of the characters in string.
fail(string)
C
Causes an error to be raised with the message string associated with it. See the section of error handling in the try statement above. For example: if (qf 255) fail(sprintf("Q factor %d is too large", qf)); value= fetch(struct, key) Returns the value from struct associated with key, ignoring any super structs. Returns NULL is key is not an element of struct.
value float(x) Returns a floating point interpretation of x, or 0.0 if no reasonable interpretation exists. x should be an int, a float, or a string, else 0.0 will be returned.
file fopen(name mode]) Opens the named file for reading or writing according to mode and returns a file object that may be used to perform I/O on the file. Mode is the same as in C and is passed directly to the C library fopen function. If mode is not specified is assumed.
115fprintf(file, fmt, args...) Formats a string based on fmt and args as per sprintf (below) and outputs the result to file.
See sprintf Changes to ICI's printf have made fprintf redundant and it may be removed in future versions of the interpreter. Avoid.
string gettoken([file seps]]) Read a token (that is, a string) from file.
Seps must be a string. It is interpreted as a set of characters which do not from part of the token. Any leading sequence of these characters is first skipped. Then a sequence of characters not in seps is gathered until end of file or a character from seps is found. This terminating character is not consumed. The gathered string is returned, or NULL if end of file was encountered before any token was gathered.
Iffile is not given the current value of stdin in the current scope is used.
o Ifseps is not given the string t is assumed.
array gettokens([file seps terms]]]) Read tokens (that is, strings) fromfile. The tokens are character sequences separated by seps and terminated by terms. Returns an array of strings, NULL on end of file.
If seps is a string, it is interpreted as a set of characters, any sequence of which will separate one token from the next. In this case leading and trailing separators in the input stream are discarded.
If seps is an integer it is interpreted as a character code. Tokens are taken to be sequences of characters separated by exactly one of that character.
Terms must be a string. It is interpreted as a set of characters, any one of which will terminate the gathering of tokens. The character which terminated the gathering will be consumed.
Iffile is not given the current value of stdin in the current scope will be used.
If seps is not given the string \t is assumed.
If terms is not given the string is assumed.
For example: forall (token in gettokens(currentfile())) printf("<%s>", token) This is my line of data.
printf("\n");
SEC
S104 I 7-/ 116when run will print: <This><is><my><line><of ><data. Whereas: forall (token in gettokens(currentfile() 1*1)) printf("<%s>", token) :abc: :def:ghi:* printf("\n"); when run will print: string gsub(string, stringlregexp, string) gsub performs text substitution using regular expressions. It takes the first parameter, matches it against the second parameter and then replaces the matched portion of the string with the third parameter. If the second parameter is a string it is converted to a regular expression as if the regexp function had been called. Gsub does the replacement multiple times to replace all occurrances of the pattern. It returns the new string formed by the replacement. If there is no match this is original string. The replacement string may contain the special sequence which is replaced by the string that matched the regular expression. Parenthesized portions of the regular expression may be matched by using \n where n is a decimal digit.
string implode(array) Returns a string formed from the concatenation of elements of array. Integers in the array will be interpreted as character codes; strings in the array will be included in the concatenation directly. Other types are ignored.
value =int(x) Returns an integer interpretation of x, or 0 if no reasonable interpretation exists. x should be an int, a float, or a string, else 0 will be returned.
subpart interval(str or array, start length]) Returns a sub-interval of str orarray, which may be either a string or an array.
If start (an integer) is positive the sub-interval starts at that offset (offset 0 is the first element). If start is negative the sub-interval starts that many elements from the end of the string (offset -1 is the last element, -2 the second last etc).
If length is absent, all the elements from the start are included in the interval. Otherwise that many elements are included (or till the end, whichever is smaller).
117- For example, the last character in a string can be accessed with: last interval(str, And the first three elements of an array with: first3 interval(ary, 0, 3) isatom(any) Return 1 (one) if any is an atomic (read-only) object, else 0 (zero). Note that integers, floats and strings are always atomic.
array keys(struct) Returns an array of all the keys from struct. The order is not predictable, but is repeatable if no elements are added or deleted from the struct between calls and is the same order as taken by aforall loop.
o float =Iog(x) Returns the natural logarithm of x (a float).
float logl0(x) Returns the log base 10 of x (a float).
mem mem(start, nwords wordz]) Returns a memory object which refers to a particular area of memory in the ICI interpreter's address space. Note that this is a highly dangerous operation. Many implementations will not include this function or restrict its use. It is designed for diagnostics, embedded systems and controllers. See the alloc function above.
file mopen(mem mode]) Returns afile, which when read will fetch successive bytes from the given memory object.
The memory object must have an access size of one (see alloc and mem above). The file is read-only and the mode, if passed, must be one of"r" or "rb".
int nels(any) Returns the number of elements in any. The exact meaning depends on the type of any. If any is an: array the length of the array is returned; if it is a struct the number of key/value pairs is returned; if it is a set the number of elements is returned; if it is a 118 string the number of characters is returned; and if it is a mem the number of words (either 1, 2 or 4 byte quantities) is returned: and if it is anything else, one is returned.
number num(x) Ifx is an int or float, it is returned directly. Ifx is a string it will be converted to an int or float depending on its appearance; applying octal and hex interpretations accordin- to the normal ICI source parsing conventions. (That is, if it starts with a Ox it will be interpreted as a hex number, else if it starts with a 0 it will be interpreted as an octal number, else it will be interpreted as a decimal number.) If x can not be interpreted as a number the error %s is not a number is generated.
scope parse(source scope]) Parses source in anew variable scope, or, ifscope (a struct) is supplied in that scope Source may either be a file or a string, and in either case it is the source of text for the parse. If the parse is successful, the variables scope structure of the sub-module is reurnmed. If an explicit scope was supplied this will be that structure.
If scope is not supplied a new struct is created for the auto variables. This structure in turn is given a new structure as its super struct for the static variables. Finally, this structure's super is set to the current static variables. Thus the static variables of the current module form the externs of the sub-module.
If scope is supplied it is used directly as the scope for the sub-module. Thus the base structure will be the struct for autos, its super will be the struct for statics etc.
For example: static x 123; parse("static x 456;", scope()) printf("x x); When run will print: x 456 Whereas: static x 123; parse("static x 456;"); printf x) 119- When run will print: x 123 Note that while the following will work: parse(fopen("my-module.ici"l)); It is preferable in a large program to use: parse(file fopen("my-module.ici")); close (file) In the first case the file will eventually be closed by garbage collection, but exactly when this will happen is unpredictable. The underlying system may only allow a limited number of simultaneous open files. Thus if the program continues to open files in this fashion a system limit may be reached before the unused files are garbage collected.
any pop(array) Returns the last element of array and reduces the length of array by one. If the array was 0* empty to start with, NULL is returned.
file popen(string, [flags]) Executes a new process, specified as a shell command line as for the system function, and returns a file that either reads or writes to the standard input or output of the process according to mode. If mode is the reading from the file reads from the standard output of the process.
If mode is writing to the file writes to the standard input of the process. If mode is not speicified it defaults to float pow(x, y) Returns x^y where both x and y are floats.
printf([file,] fmt, args...) Formats a string based on fmt and args as per sprintf(below) and outputs the result to thefile or to the current value of the stdout variable in the current scope if the first parameter is not a file. The current stdout must be a file. See sprintf any push(array, any) Appends any to array, increasing its length in the process. Returns any.
int rand([seed]) Returns an pseudo random integer in the range 0..Ox7FFF. If seed (an int) is supplied the ranm number generator is first seeded with that number. The sequence is predictable based 120on a given seed.
re regexp(string) Returns a compiled regular expression derived from string This is the method of generating regular expressions at run-time, as opposed to the direct lexical form. For example, the following three expressions are similar: str str str except that the middle form computes the regular expression each time it is executed. Note that when a regular expression includes a character the regexp function must be used, as the direct lexical form has no method of escaping a Note that regular expressions are intrinsically atomic. Also note that non-equal strings may sometimes compile to the same regular expression.
re regexpi(string) Returns a compiled regular expression derived from string that is case-insensitive. the regexp will match a string regardless of the case of alphabetic characters. Note that there is no literal form of regular expressions that has this property.
current scope([replacement]) Returns the current scope structure. This is a struct whose base element holds the auto variables, the super of that hold the statics, the super of that holds the externs etc. Note that this is a real reference to the current scope structure. Changing, adding and deleting elements of these structures will affect the values and presence of variables in the current scope.
If a replacement is given, that struct replaces the current scope structure, with the obvious implications. This should clearly be used with caution. Replacing the current scope with a structure which has no reference to the standard functions also has the obvious effect.
set set(any...) Returns a set formed from all the arguments. For example: set will return a new empty set; and set 2, "a string") will return a new set with three elements, 1, 2, and "the string".
121 This is the run-time equivalent of the set literal. Thus the following two expressions are equivalent: $set(1, 2, "a string") [set 1, 2, "a string"] x sin(angle) Returns the sine of angle (a float interpreted in radians).
int sizeof(any) Sizeof is the old name of the nels function (described above).
file sopen(string mode]) Returns afile, which when read will fetch successive characters from the given string. The file is read-only and the mode, if passed, must be one of or "rb".
Files are, in general, system dependent. This is the only standard routine which opens a file.
But on systems that support byte stream files, the functionfopen will be set to the most appropriate method of opening a file for general use. The interpretation of mode is largely system dependent, but the strings and "rw" should be used for read, write, and readwrite file access respectively.
sort(array, func) Sort the content of the array using the heap sort algorithm with func as the comparison function. The comparison function is called with two elements of the array as parameters, a and b. If a is equal to b the function should return zero. If a is less than b, and if a is greater than b, 1.
For example, static cmp(a, b) if (a b) return 0; if (a b) return -1; return 1; static a array(1, 3, 2); sort(a, cmp); 122string sprintf(fmt, args...) Return a formatted string based on frt (a string) and args. Most of the usual format escapes of ANSI C printf are supported. In particular; the integer format letters diouxXc are supported, but if a float is provided it will be converted to an int. The floating point format letters feEgG are supported, but if the argument is an int it will be converted to a float. The string format letter, s is supported and requires a string. Finally the format to get a single works.
The flags, precision, and field width options are supported. The indirect field width and precision options with also work and the corresponding argument must be an int.
For example: sprintf("%08X 123, "cd") will produce the string: 0000007B ab> <cd 9* and sprintf("%0*X", 4, 123) 0 will produce the string: 007 007B x sqrt(float) Returns the square root offloat.
string string(any) Returns a short textual representation of any. If any is an int or float it is converted as if by a %d or %g format. If it is a string it is returned directly. Any other type will returns its type name surrounded by angle brackets, as in <struct>.
struct struct([super,] key, value...) Returns a new structure. This is the run-time equivalent of the struct literal. If there are an odd number of arguments the first is used as the super of the new struct; it must be a struct.
The remaining pairs of arguments are treated as key and value pairs to initialise the structure with; they may be of any type. For example: struct returns a new empty struct; 123 struct(anotherStruc:) returns a new empty struct which has anotherStruct as its super; struct("a", 1, 2) returns a new struct which has two entries a and b with the values I and 2; and struct(anotherStruct, 1, 2) returns a new struct which has two entries a and b with the values 1 and 2 and a super of anotherStruct.
Note that the super of the new struct is set after the assignments of the new elements have been made. Thus the initial elements given as arguments will not affect values in any super struct.
The following two expressions are equivalent: $struct (anotherStruct, 1, 2) [struct:anotherStruct, a 1, b 2] string sub(string, stringjregexp, string) Sub performs text substitution using regular expressions. It takes the first parameter, matches S. it against the second parameter and then replaces the matched portion of the string with the third parameter. If the second parameter is a string it is converted to a regular expression as S. if the regexp function had been called. Sub does the replacement once (unlike gsub). It returns the new string formed by the replacement. If there is no match this is original string. The replacement string may contain the special sequence which is replaced by the string that matched the regular expression. Parenthesized portions of the regular expression may be matched by using \n where n is a decimal digit.
current super(struct replacement]) Returns the current super struct of struct, and, if replacement is supplied, sets it to a new value. If replacement is NULL any current super struct reference is cleared (that is, after this struct will have no super).
x tan(angle) Returns the tangent of angle (a float interpreted in radians).
string tochar(int) Returns a one character string made from the character code specified by int.
124string typeof(any) Returns the type name (a string) of any. See the section on types above for the possible type names.
array vstacko Returns a representation of the call stack of the current program at the time of the call. It can be used to perform stack tracebacks and related debugging operations. The result is an array of structures, each of which is a variable scope (see scope) structure of succesively deeper nestings of the current function nesting.
event waitfor(event...) Blocks (waits) until an event indicated by any of its arguments occurs, then returns that argument. The interpretation of an event depends on the nature of each argument. A file argument is triggered when input is available on the file. A float argument waits for that many seconds to expire, an int for that many millisecond (they then return 0, not the argument given). Other interpretations are implementation dependent. Where several events occur simultaneously, the first as listed in the arguments will be returned.
Note that in some implementations some file types may always appear ready for input, despite the fact that they are not.
a o• go* o 125- Unix System Calls Most Unix implementation of ICI provide access to many of the Unix system calls and other useful C library functions. Note that not all system calls are supported and those that are may be incompletely supported signal). Most system call functions return integers, zero if the call succeeded. Errors are reported using ICI's error handling and "system calls" will never return the -1 error return value. If an error is raised by a system call the value of "error" in the error handler will be the error message (as printed by the perror(3) function or returned by the ANSI C strerror() function).
To assist in the use of system calls ICI pre-defines variables to hold the various flags and other values used when calling the system calls. These variables are equivalent to the macros used in C. Not all systems support all these variables. If the C header files do not define a value then ICI will not pre-define the variable.
The following list summarises the Unix system call interface pre-defined variables. See the documentation for the C macros for information as to their use.
Values for open's flags parameter, *o 0_RDONLY O WRONLY 0o RDWR 0_APPEND O CREAT O TRUNC
EXCL
0_ O SYNC O NDELAY O NONBLOCK Values for access's mode parameter.
R OK W OK X OK F OK Values for Iseek's whence parameter,
SEEKSET
SEEKCUR
SEEK END 126- The following list summarises the Unix system call interface functions. Following this is a detailed descriptions of each of them.
int access (string int]) int creat(string, int) int =dup(int f, int]) exec (string, array) exec(string, string int lseek (int, int int]) int open (string, int int]) array pipe() struct stat(stringlintlfile) int wait() string ctime(int) int time() :..file fdopen(int) alarm (int) acct (string) chdir (string) chmod (string, int) chown(string, int int) chroot (string) _-close (int) exit (int) t fork() t getpid() int getpgrp() t getppid() int getuidi) n t geteuid() mnt getgid() int getegid() link (string, string) mkdir (string, int) mknodistring, int 1 int) nice (int) pauseo( rmdir (string) setpgrpo( setuid (int) 127setgid(int) signal(int, int) synco( ulimit(int, int) umask (int) unlink (string) clock() system (string) lockf(int, int, int) sleep (int) 0 0 0 128int access(string int]) Call the access(2) function to determine the accessibility of a file. The first parameter is the pathname of the file system object to be tested. The second, optional, parameter is the mode (a bitwise combination of R_OK, W_OK and X_OK or the special value. F_OK). If mode is not passed FOK is assumed. Access returns 0 if the file system object is accessible.
int creat(string, int) Create a new ordinary file with the given pathname and mode (permissions and return the file descriptor, open for writing, for the file.
int dup(int int]) Duplicate a file descriptor by calling dup(2) or dup2(2) and return a new descriptor. If only a single parameter is passed dup(2) is called otherwise dup2(2) is called.
exec(string, array) exec(string, string...) g I Execute a new program in the current process. The first parameter to exec is the pathname of an executable file (the program). The remaining parameters are either; an array of strings defining the parameters to be passed to the program, or, a variable number of strings that are passed, in order, to the program as its parameters. The first form is similar to C's execv function and the second form to C's execl functions. Note that no searching of the user's path is performed and the environment passed to the program is that of the current process both are implemented by calls to execv(2)).
mint lseek(int, int intf) Set the read/write position for an open file. The first parameter is the file descriptor associated with the file system object, the second parameter the offset. The third is the whence value which determines how the new file position is calculated. The whence value may be one of SEEK_SET, SEEK_CUR or SEEK_END and defaults to SEEKSET if not specified.
int open(string, int int]) Open the named file for reading or writing depending upon the value of the second parameter, flags, and return a file descriptor. The second parameter is a bitwise combination of the various 0_ values (see above) and if this set includes the O_CREAT flag a third parameter, mode, must also be supplied.
array pipe() Create a pipe and return an array containing two, integer, file descriptors used to refer to the input and output endpoints of the pipe.
129struct stat(stringlint|file) Obtain information on the named file system object, file descriptor or file underlying an ICI file object and return a struct containing that information. If the parameter is a file object that file object must refer to a file opened with ICI's fopen function. The returned struct contains the following keys (which have the same names as the fields of the Unix statbuf structure with the leading prefix removed), dev ino mode nlink uid gid rdev size atime mt ime S ctime blksize blocks All values are integers.
int wait() Wait until a signal is received or a child process terminates or stops due to tracing and return the status returned by system call.
?string ctime(int) Convert a time value (see time, below) to a string of the form "Sun Sep 16 01:03:52 1973\n" and return that string. This is primarily of use when converting the time values returned by 0 •o stat.
9 int time() Return the time since 00:00:00 GMT, Jan. 1, 1970, measured in seconds.
file fdopen(int mode]) Returns a file object that can be used to perform I/O on the specified file descriptor. The file is opened for reading or writing according to mode (see fopen). If mode is specified (reading) is assumed.
alarm(int) Schedule a SIGALRM signal to be posted to the current process in the specified number of
SEC
104 0O 130seconds. If the parameter is zero any alarm is cancelled.
acct(string) Enable accounting on the specified file.
chdir(string) Change the process's current working directory to the specified path.
chmod(string, int) Change the mode of a file system object.
chown(string, int, int) Change the owner and group identifiers for a file system object.
chroot(string) Change root directory for process.
_close(int) Close a file descriptor.
_exit(int) Exit the current process returning an integer exit status to the parent.
int fork() Create a new process. In the parent this returns the process identifier for the newly created process. In the newly created process it returns zero.
int getpid() Get the process identifier for the current process.
int getpgrpO Get the current process group identifier.
int getppido Get the parent process identifier.
int getuidO Get the real user identifier of the owner of the current process.
131 int geteuid( Get the effective user identifier for the owner of the current process.
int getgid 0 Get the real group identifier for the current process.
int getegid() Get the effective group identifier for the current process.
kill(int, int) Post a signal to a process.
link(string, string) Create a link to an existing file.
mkdir(string, int) Create a directory with the specified mode.
mknod(string, int, int) Create a special file.
nice(int) Change the nice value of a process.
pause() Wait until a signal is delivered to the process.
rmdir(string) Remove a directory.
setpgrpO Set the process group.
setuid(int) Set the real and effective user identifier for the current process.
setgid(int) Set the real and effective group identifier for the current process.
f SE.C$ 104 I TO 132signal(int, int) Control signal handling in the process. Note at present handlers cannot be installed so signals are of limited use in ICI programs.
sync() Schedule in-memory file data to be written to disk.
ulimit(int, int) Get and set user limits.
umask(int) Set file creation mask.
unlink(string) Remove a file.
,system(string) Execute a system command and return its exit status.
sleep(int) Suspend the process for the specified number of seconds.
Sockets Interface The sockets extension is available on systems that provide BSD-compatible sockets calls.
The extension allows ICI programs to access network functions. The sockets extension is generally compatible with the C sockets functions but uses types and calling semantics more akin to the ICI environment.
The sockets extension introduces a new type, socket, to hold socket objects. The new intrinsic function, socket, returns a socket object.
Network Addresses The sockets interfaces specifies IP network addresses using strings. Network addresses are of the form port@ host where the @host part is optional. The port may be specified as an integer number or a string which is looked up in the services database. If the port is a service name it may be in the form name/protocol with protocol being either tcp or udp. The host portion of the address may be a domain name, an IP address in dotted decimal notation or one of the special addresses local dot), any or all If the host portion is omitted the default host depends on the context. See the descriptions of the connect and bind functions below.
133 The following list summarises the sockets interface functions. Following this is a detailed descriptions of each of them.
skt skt skt skt skt struct int string string string string string struct string int string int file skt socket(stri socket (string) listen(skt) accept(skt) connect(skt, string) bind(skt, string) select([int,] set set getsockopt(skt, string) setsockopt(skt, string, int) domainname() hostname() username([int]) getpeername(skt) getsockname(skt) sendto(skt, string, string) recvfrom(skt, int) send(skt, string) recv(skt, int) getportno(skt) gethostbyname(string) sktno(skt) sktopen(skt mode]) .ng) set]] S
S
S Create and return a new socket object of the specified protocol. The string, the protocol, may be one of tcp or udp. For example, skt socket("tcp"); skt accept(skt) Accept a connection to a TCP socket and return a new socket for that connection.
skt listen(skt) Allow connections to a TCP socket. Returns the socket passed.
skt connect(skt, address) Establish a TCP connection to the specified address or associate the address with as the destination for messages on a UDP socket. If the host portion of the address is not specified (dot) is used to connect to the local host. The original socket is returned.
134skt bind(skt, address) Associate a local address for the socket (TCP or UDP). If the host portion of the address is not specified (any) is used. Returns the socket.
struct select([int,] setINULL set NULL setGNULL]]) Check sockets for I/O readiness with optional timeout. Select may be passed up to three sets of sockets that are checked for readiness to perform I/O. The first set holds the sockets to test for input pending, the second set the sockets to test for output able and the third set the sockets to test for exceptional states. NULL may be passed in place of a set parameter to avoid passing empty sets. An integer may also appear in the parameter list. This integer specifies the number of milliseconds to wait for the sockets to become ready. If a zero timeout is passed the sockets are polled to test their state. If no timeout is passed the call blocks until at least one of the sockets is ready for I/O.
The result of select is a struct containing three sets, of sockets, identified by the keys read, write and except.
int getsockopt(skt, string, int) Retrieve the value of a socket option. A socket may have various attributes associated with it. These are accessed via the getsockopt and setsockopt functions. The attributes are identifled using string keys from the following list, debug reuseaddr keepalive dontroute useloopback linger broadcast oobinline sndbuf rcvbuf type error setsockopt(skt, string, int) Set a socket option (see getsockopt for option names) to the integer value.
string domainname() Return the domain name of the current host.
string hostname() Return the name of the current host.
135 string username([int] Return the name of the owner of the current process or if an integer, user number, is passed, of that user.
string getpeername(skt) Return the address of the peer of a TCP socket.
string getsockname(skt) Return the local address of a socket.
sendto(skt, string, string) Send the data in the second parameter to the specified address.
struct recvfrom(skt, int) Receive a message on a socket and return a struct containing the data of the message, in string, and the source address of the data. The int parameter gives the maximum number of bytes to receive. The result is a struct with the keys msg and addr used to access the returned information.
send(skt, string) Send the content of the string on a socket.
string recv(skt, int) Receive data from a socket and return it as a string. The int parameter fives the maximum size of message that will be received.
int getportno(skt) Return the local port number assigned to a TCP or UDP socket.
o* string gethostbyname(string) Match a network address against the hosts database and return a hostname.
int sktno(skt) Return the file descriptor associated with a socket.
file sktopen(skt mode]) Open a socket as a file, for input or output according to mode (see fopen).
Future things Structures should have multiple inheritance. an array of super structs.
136- There are a few missing maths functions: round.
There is no built in deepcopyO, deepequalO, and deepatom~. They can be coded fairly easily in ICI (ignoring recusive data structures). But there should be.
a a a a a a a. aa a.
a.
a. a a a. a a a.
137 The claims defining the invention are as follows: 1. A method for displaying a grouped structure in a computer graphics image, said method comprising the steps of: providing at least one selection tag for said grouped structure; utilising a group display mode, whereby portions of the structure of said grouped structure are determined as a selection tag of said grouped structure is selected in said group display mode; and displaying said portions of the structure of said grouped structures in a tree format, whereby said portions provide details of the structure of said grouped structure.
2. The method according to claim 1, wherein said displayed portions initially comprise a top level portion of said grouped structure, and said method further comprises providing a means for displaying further levels of said grouped structure.
3. The method according to claims 1 or 2, wherein said tree format includes nodes denoting part of said grouped structure, and said method further S: 15 comprises the steps of: providing means for selecting a current node within said tree format; and displaying at least the child nodes, if any, of said current node upon selection of said current node.
4. The method according to claim 1, further comprising the step of 20 providing means for selecting a sub-portion of said displayed portions of said grouped structure and providing interactive access to said selected sub-portion.
An apparatus for displaying a grouped structure in a computer graphics image, comprising: means for providing at least one selection tag for said grouped structure; means for providing a group display mode and for determining portions of the structure of said grouped structure in response to selection of a selection tag of said grouped structure in a group display mode; and 343322 CFP0461AU Open22 [o\cisra\open\open2 2 1 3 4 3 3 2 2 .doc

Claims (5)

  1. 6. The apparatus according to claim 5, wherein said means for displaying said portions displays a top level portion of said grouped structure and further comprises means for displaying further levels of said grouped structure.
  2. 7. The apparatus according to claims 5 or 6, wherein said tree format includes nodes denoting part of said grouped structure.
  3. 8. The apparatus according to claim 7, further comprising: means for selecting a current node within said tree format; and means for displaying at least the child nodes, if any, of said current node in response to selection of said current node.
  4. 9. The apparatus according to claim 5, further comprising: means for selecting a sub-portion of said displayed portions of said grouped 15 structure; and means for interactively accessing said selected sub-portion.
  5. 10. A method for displaying a grouped structure in a computer graphics image substantially as hereinbefore described with reference to the accompanying drawings. DATED this twenty-seventh Day of July, 1999 Canon Kabushiki Kaisha Canon Information Systems Research Australia Pty Ltd o Patent Attorneys for the Applicants 25 SPRUSON FERGUSON 343322 CFP0461AU Open22 [o\cisra\open\open22] 343322.doc A System for Viewing the Structure of Computer Graphical Elements ABSTRACT The present invention provides a method and apparatus for displaying a grouped structure (23) in a computer graphics image. This involves providing at least one selection tag (18) for the grouped structure. A group display mode is used so that, when a selection tag (18) of the grouped structure is selected, portions (25,26) of the structure of the group structure are determined. The portions (25,26) of the structure of the grouped structure (23) are then displayed. Preferably, the displayed portions (25,26) initially comprise a top level portion (25) of the grouped structure This further involves displaying further levels (26) of the grouped structure (23). Preferably, the displayed portions of the structure are displayed in a tree format. Optionally, the tree format includes nodes (25,26) denoting part of the grouped 15 structure This involves providing means for selecting a current node (26) within S. the tree format and displaying at least the child nodes (27,28), if any, of the current node upon selection of the current node Optionally, a sub-portion of the S displayed portions of the structure can be selected and interactive access can be provided to the selected sub-portion. *:00 0 [N:\libcclOO537:maa
AU55985/96A 1995-06-16 1996-06-14 A system for viewing the structure of computer graphical elements Ceased AU710748B2 (en)

Priority Applications (1)

Application Number Priority Date Filing Date Title
AU55985/96A AU710748B2 (en) 1995-06-16 1996-06-14 A system for viewing the structure of computer graphical elements

Applications Claiming Priority (3)

Application Number Priority Date Filing Date Title
AUPN3603 1995-06-16
AUPN3603A AUPN360395A0 (en) 1995-06-16 1995-06-16 A system for viewing the structure of computer graphical elements
AU55985/96A AU710748B2 (en) 1995-06-16 1996-06-14 A system for viewing the structure of computer graphical elements

Publications (2)

Publication Number Publication Date
AU5598596A AU5598596A (en) 1997-01-16
AU710748B2 true AU710748B2 (en) 1999-09-30

Family

ID=25631063

Family Applications (1)

Application Number Title Priority Date Filing Date
AU55985/96A Ceased AU710748B2 (en) 1995-06-16 1996-06-14 A system for viewing the structure of computer graphical elements

Country Status (1)

Country Link
AU (1) AU710748B2 (en)

Families Citing this family (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
AU714611B2 (en) * 1997-02-20 2000-01-06 Canon Kabushiki Kaisha A method of linking display images

Citations (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US5016183A (en) * 1988-09-13 1991-05-14 Computer Design, Inc. Textile design system and method
EP0487282A2 (en) * 1990-11-19 1992-05-27 Canon Kabushiki Kaisha Image processing apparatus
AU2261695A (en) * 1994-04-21 1995-11-16 British Telecommunications Public Limited Company A method and apparatus for manipulating graphics

Patent Citations (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US5016183A (en) * 1988-09-13 1991-05-14 Computer Design, Inc. Textile design system and method
EP0487282A2 (en) * 1990-11-19 1992-05-27 Canon Kabushiki Kaisha Image processing apparatus
AU2261695A (en) * 1994-04-21 1995-11-16 British Telecommunications Public Limited Company A method and apparatus for manipulating graphics

Also Published As

Publication number Publication date
AU5598596A (en) 1997-01-16

Similar Documents

Publication Publication Date Title
US6453464B1 (en) Method and apparatus for converting COBOL to Java
US6272672B1 (en) Dataflow processing with events
US5325533A (en) Engineering system for modeling computer programs
US7519577B2 (en) Query intermediate language method and system
JP4662657B2 (en) Unified data type system and method
JP2011070696A (en) System and method for processing data type
JP3230467B2 (en) GDMO translator, GDMO translation method, and recording medium recording GDMO translator program
Reiss The desert environment
JP2006202308A (en) Graphical user interface method, graphical user interface device, and recording medium
Agesen et al. The SELF 4.0 Programmer’s Reference Manual
Plasmeijer et al. Concurrent clean language report
Smith The Newton application architecture
AU710748B2 (en) A system for viewing the structure of computer graphical elements
US7418659B2 (en) System and method for declaring a resource within a markup document
Gallesio STk reference manual
Korn et al. Traversal-based visualization of data structures
Syme et al. The F# 2.0 language specification
Shildt The complete reference C# 4.0
Holt et al. The Turing language report
JP2022531515A (en) Computer-assisted computer programming systems and methods
Willink et al. Preprocessing C++: Meta-class aspects
Herbert C# 4.0 The Complete Reference
CA2266291C (en) Method and apparatus for cobol to java translation
Muth et al. On the complexity of function pointer may-alias analysis
Allen Self Handbook Documentation

Legal Events

Date Code Title Description
PC Assignment registered

Owner name: CANON KABUSHIKI KAISHA

Free format text: FORMER OWNER WAS: CANON KABUSHIKI KAISHA, CANON INFORMATION SYSTEMS RESEARCH AUSTRALIA PTY LTD