|
|
1.1 root 1: .so tmac.tr
2: .DA "May 6, 1986"
3: .TR 86-12
4: .Gi
5: .TL
6: Personalized Interpreters for Version 6.0 of Icon
7: .AU
8: Ralph E. Griswold
9: .AE
10: .tr *\(**
11: .NH
12: Introduction
13: .PP
14: Despite the fact that the Icon programming language has a large repertoire
15: of functions and operations for string and list manipulation, as
16: well as for more conventional computations [1], users frequently
17: need to extend that repertoire. While many extensions can be
18: written as procedures that build on the existing repertoire, there
19: are some kinds of extensions for which this approach is unacceptably
20: inefficient, inconvenient, or simply impractical.
21: .PP
22: Icon itself is written C and its built-in functions
23: are written as corresponding C functions. Thus, the natural way to
24: extend Icon's computational repertoire is to add new C functions to it.
25: .PP
26: The Icon system is organized so that this is comparatively easy to do.
27: Adding a new function
28: does not require changes to the Icon translator,
29: since all functions have a common syntactic form. An entry must be made in
30: a table that is used by the linker and the run-time system in order to
31: identify built-in functions and connect references to them to the
32: code itself.
33: .PP
34: One method of adding new functions to Icon
35: is to
36: add the corresponding C functions to the Icon system itself
37: and to rebuild the entire system. This approach is impractical
38: for many applications. If the extensions are not of general
39: interest, it is inappropriate to include them in the public
40: version of Icon. On the other hand, Icon is a large and complicated system,
41: and having many private versions may create serious problems of
42: maintenance and disk usage. Furthermore, rebuilding the Icon system
43: is expensive. This approach therefore
44: may be impractical in a situation
45: such as a class in which students implement their own versions
46: of an extension.
47: .PP
48: To remedy these problems, a mechanism for building ``personalized
49: interpreters'' is included in \*U implementations of Icon.
50: This mechanism
51: .Un
52: allows a user to add C functions and to build a corresponding
53: interpreter quickly, easily, and without the necessity to have
54: a copy of the source code for the entire Icon system.
55: .PP
56: To construct a personalized interpreter, the user must perform
57: a one-time set up that copies relevant source files to a
58: directory specified by the user and builds the nucleus of a run-time system. Once this is
59: done, the user can add and modify C functions and include them
60: in the personalized run-time system with little effort.
61: .PP
62: Since the linker must know the names of built-in functions,
63: a personalized linker also is constructed. In order to run
64: Icon programs in a self-contained personalized run-time system,
65: personalized versions of the translator, \*Mpitran\fR, and the
66: command processor, \*Mpicont\fR,
67: are provided also.
68: .PP
69: The modifications that can be made to Icon via a personalized
70: interpreter essentially are limited to the run-time system: the
71: addition of new functions, modifications to existing functions
72: and operations, and modifications and additions to support routines. There
73: is no provision for changing the syntax of Icon, incorporating
74: new operators, keyword, or control structures.
75: .NH
76: Building and Using a Personalized Interpreter
77: .NH 2
78: Setting Up a Personalized Interpreter System
79: .PP
80: To set up a personalized interpreter, a new directory should
81: be created solely for the use of the interpreter; otherwise
82: files may be accidentally destroyed by the setup process.
83: For the purpose of example, suppose this directory is
84: named \*Mmyicon\fR. The setup consists of
85: .Ds
86: mkdir myicon
87: cd myicon
88: icon_pi
89: .De
90: Note that \*Micon_pi\fR must be run from the area in which the personalized
91: interpreter is to be built.
92: The
93: location of \*Micon_pi\fR may vary from site to site.
94: .PP
95: The shell script \*Micon_pi\fR constructs three subdirectories:
96: \*Mh\fR, \*Mstd\fR, and \*Mpi\fR. The subdirectory \*Mh\fR
97: contains header files that are needed in C routines. The subdirectory
98: \*Mstd\fR contains the machine-independent portions of the Icon system that are needed
99: to build a personalized interpreter.
100: The subdirectory \*Mpi\fR
101: contains a \*MMakefile\fR for building a personalized interpreter
102: and also is the place where source code for new C functions normally
103: resides. Thus, work on the personalized interpreter is done in
104: \*Mmyicon/pi\fR.
105: .PP
106: The \*MMakefile\fR that is constructed by \*Micon_pi\fR
107: contains two definitions to facilitate building personalized
108: interpreters:
109: .RS
110: .IP \*MOBJS\fR .5i
111: a list of object modules that are to be added to or replaced
112: in the run-time system. \*MOBJS\fR initially is empty.
113: .IP \*MLIB\fR
114: a list of library options that are used when the run-time system
115: is built. \*MLIB\fR initially is empty, but the math library is
116: loaded as a normal part of building the run-time system.
117: .RE
118: .LP
119: See the listing of the generic version of this \*MMakefile\fR in
120: Appendix A.
121: .NH 2
122: Building a Personalized Interpreter
123: .PP
124: Performing a \fImake\fR in \*Mmyicon/pi\fR creates four files
125: in \*Mmyicon\fR:
126: .Ds
127: .ta 1i
128: picont \fRcommand processor\*M
129: pilink \fRlinker\*M
130: piconx \fRrun-time system\*M
131: piconx.hdr \fRheader file for linker output\*M
132: .De
133: A link to \*Mpicont\fR also is constructed in \*Mmyicon/pi\fR so that
134: the new personalized interpreter can be tested in the directory in
135: which it is made.
136: .PP
137: The file \*Mpicont\fR normally is built only on the first \fImake\fR. The
138: file \*Mpilink\fR is built on the first \fImake\fR and is
139: rebuilt whenever the repertoire of built-in functions is changed
140: as a result of modifications to \*Mh/fdef.h\fR.
141: The file \*Mpiconx\fR is rebuilt whenever the source code in the
142: run-time system is changed.
143: .PP
144: The user of the personalized interpreter uses \*Mpicont\fR in
145: the same fashion that the standard \*Micont\fR is used.
146: (Note that the accidental use of \*Micont\fR in place of
147: \*Mpicont\fR may produce mysterious results.)
148: In turn, \*Mpicont\fR translates a source program using
149: \*Mpitran\fR and links it using \*Mpilink\fR.
150: The resulting icode file uses \*Mpiconx\fR.
151: .PP
152: The relocation bits and symbol tables in
153: \*Mpiconx\fR can be removed by
154: .Ds
155: make Stripx
156: .De
157: in \*Mmyicon/pi\fR. This reduces the size of this file substantially
158: but may interfere with debugging.
159: .PP
160: If a \fImake\fR is performed in \*Mmyicon/pi\fR before any
161: run-time files are added or modified, the resulting personalized
162: interpreter is identical to the standard one. Such a \fImake\fR can
163: be performed to verify that the personalized interpreter system
164: is performing properly.
165: .NH 2
166: Adding a New Function
167: .PP
168: To add a new function to the personalized interpreter, it is first
169: necessary to provide the C code, adhering to the conventions and
170: data structures used throughout Icon. Some examples of
171: C functions are included in Appendix B
172: of this report. The source code for several such functions is contained in
173: \*Mv6/pi/pil\fR, where \*Mv6\fR is the root of the Icon system.
174: The directory
175: \*Mv6/src/iconx\fR contains the source code for the standard
176: functions, which also can be used as models for new ones.
177: .PP
178: Suppose that \*Mgetenv\fR from \*Mv6/pi/pil\fR is to be
179: added to a personalized interpreter.
180: The source code can be obtained by
181: .Ds
182: cp v6/pi/pil/getenv.c myicon/pi
183: .De
184: (Note that the actual paths depend on the
185: local hierarchy.)
186: .PP
187: Three things now need to be done to
188: incorporate this function in the personalized interpreter:
189: .IP 1.
190: Add a line consisting of
191: .Ds
192: FncDef(getenv)
193: .De
194: to \*Mmyicon/h/fdef.h\fR in proper alphabetical order.
195: This causes the linker and the run-time system to know about the new function.
196: .IP 2.
197: Add \*Mgetenv.o\fR to the definition of \*MOBJS\fR in
198: \*Mmyicon/pi/Makefile\fR.
199: This causes \*Mgetenv.c\fR to be compiled and the resulting
200: object file to be loaded with the run-time system when a \fImake\fR is performed.
201: .IP 3.
202: Perform a \fImake\fR in \*Mmyicon/pi\fR. The result is
203: new versions of \*Mpilink\fR and \*Mpiconx\fR in \*Mmyicon\fR.
204: .LP
205: The function \*Mgetenv\fR now can be used like any other built-in
206: function.
207: .PP
208: More than one function can be included in a single source file.
209: See \*Mmath.c\fR in Appendix B.
210: To incorporate these functions in
211: a personalized interpreter, \*MFncDef\fR entries should be
212: made for each function in \*Mmath.c\fR and \*Mmath.o\fR should be added to
213: \*MOBJS\fR.
214: .NH 2
215: Modifying the Existing Run-Time System
216: .PP
217: The use of personalized interpreters is not limited to the addition
218: of new functions. Any module in the standard run-time system can
219: be modified as well.
220: .PP
221: To modify an existing portion of the Icon run-time system,
222: copy the source code file from \*Mv6/src/iconx\fR to \*Mmyicon/pi\fR.
223: (Source code for a few run-time routines is placed in \*Mmyicon/std\fR
224: when a personalized interpreter is set up. Check this directory
225: first and use that file, if appropriate, rather than making
226: another copy in \*Mmyicon/pi\fR.) When a source-code file in
227: \*Mmyicon/pi\fR has been modified, place it in the \*MOBJS\fR
228: list just like a new file and perform a \fImake\fR. Note that
229: an entire module must be replaced, even if a change is made to
230: only one routine.
231: Any module that is replaced must contain all the global variables in
232: the original module to prevent \fIld(1)\fR from also loading the
233: original module. There is no way to delete routines from the run-time
234: system.
235: .PP
236: The directory \*Mmyicon/h\fR contains header files that are included
237: in various source-code files.
238: The file \*Mmyicon/h/rt.h\fR contains declarations and definitions that
239: are used throughout the run-time system. This is where the declaration
240: for the structure of a new type of data object would be placed.
241: .PP
242: Care
243: must be taken when modifying header files not to make changes that
244: would produce inconsistencies between previously compiled components
245: of the Icon run-time system and new ones.
246: .SH
247: Reference
248: .IP 1.
249: Griswold, Ralph E. and Griswold, Madge T. \fIThe Icon Programming
250: Language\fR. Prentice-Hall, Inc., Englewood Cliffs, New Jersey. 1983.
251: .am Ds
252: .ps 8
253: .vs 9
254: ..
255: .am De
256: .ps 10
257: .vs 12
258: ..
259: .de Ta
260: .ta .8i +.8i +.8i +.8i +.8i +.8i +.8i +.8i
261: ..
262: .Ap "Appendix A \(em Makefile for Personalized Interpreters"
263: .sp
264: .PP
265: The ``generic'' \*MMakefile\fR for personalized interpreters follows.
266: A copy, with the
267: value of \*MDir\fR filled in and appropriate definitions for the flags,
268: is placed in \*Mmyicon/pi\fR when \*Micon_pi\fR is run.
269: .Ds
270: Dir=
271: .Dd
272: RHDRS= ../h/rt.h ../h/config.h ../h/cpuconf.h ../h/memsize.h
273: #
274: # To add or replace object files, add their names to the OBJS list below.
275: # For example, to add nfncs.o and iolib.o, use:
276: #
277: # OBJS=nfncs.o iolib.o (this is a sample line)
278: #
279: # For each object file added to OBJS, add a dependency line to reflect files
280: # that are depended on. In general, new functions depend on $(RHDRS).
281: # For example, if nfncs.c contains new functions, use
282: #
283: # nfncs.o: $(RHDRS)
284: #
285: .Dd
286: OBJS=
287: LIB=
288: .Dd
289: RTOBJS=../std/rconv.o ../std/idata.o $(OBJS)
290: .Dd
291: Pi: ../picont ../piconx ../pilink ../piconx.hdr
292: .Dd
293: \&../picont: ../std/icont.c ../h/config.h
294: rm -f ../picont picont
295: $(CC) $(CFLAGS) -o ../picont -DItran="\e"$(Dir)/pitran\e""\e
296: -DIconx="\e"$(Dir)/piconx\e"" \e
297: -DIlink="\e"$(Dir)/pilink\e"" ../std/icont.c
298: strip ../picont
299: ln ../picont picont
300: .Dd
301: \&../pilink: ../std/linklib ../std/builtin.o ../std/ilink.o
302: $(CC) $(LDFLAGS) -o ../pilink ../std/builtin.o ../std/ilink.o\e
303: ../std/linklib
304: strip ../pilink
305: .Dd
306: \&../std/ixhdr.o: ../h/config.h
307: cd ../std; $(CC) -c $(XCFLAGS) -DIconx="\e"$(Dir)/piconx\e"" ixhdr.c
308: .Dd
309: \&../piconx.hdr: ../std/ixhdr.o
310: $(CC) $(XLDFLAGS) ../std/ixhdr.o -o ../piconx.hdr
311: strip ../piconx.hdr
312: .Dd
313: \&../piconx: ../std/rtlib $(RTOBJS)
314: $(CC) $(LDFLAGS) -o ../piconx $(RTOBJS) ../std/rtlib $(LIB) -lm
315:
316: \&../std/idata.o: $(RHDRS) ../h/fdef.h
317: cd ../std; $(CC) -c $(CFLAGS) idata.c
318: .Dd
319: \&../std/rconv.o: $(RHDRS) ../h/fdef.h
320: cd ../std; $(CC) -c $(CFLAGS) rconv.c
321: .Dd
322: \&../std/builtin.o: ../std/ilink.h ../h/config.h ../h/fdef.h
323: cd ../std; $(CC) -c $(CFLAGS) builtin.c
324: .Dd
325: \&../std/ilink.o: ../std/ilink.h ../h/config.h ../h/header.h ../h/paths.h
326: cd ../std; $(CC) -c $(CFLAGS) -DHeader="\e"$(Dir)/piconx.hdr\e"" ilink.c
327: .Dd
328: Stripx: ../piconx
329: strip ../piconx
330: .De
331: .Ap "Appendix B \(em Sample C Functions"
332: .sp
333: .SH
334: getenv.c:
335: .LP
336: .de Ta
337: .ta 3i
338: ..
339: .Ds
340: .ta .8i
341: /*
342: * GETENV
343: *
344: * Get values of environment variables.
345: *
346: * Stephen B. Wampler
347: *
348: * Last modified 5/2/86 by Ralph E. Griswold
349: *
350: */
351: .Dd
352: #include "../h/rt.h"
353: .Dd
354: /*
355: * getenv(s) - return contents of environment variable s
356: */
357: .Dd
358: FncDcl(getenv,\*b1)
359: {
360: register char *p;
361: register int len;
362: char sbuf\^[256];
363: extern char *getenv();
364: extern char *alcstr();
365: .Dd
366: if (!Qual(arg1)) /* check legality of argument */
367: runerr(103, &arg1);
368: if (StrLen(arg1) \*(<= 0 || StrLen(arg1) \*(>= MaxCvtLen)
369: runerr(401, &arg1);
370: qtos(&arg1, sbuf); /* convert argument to C-style string */
371: .Dd
372: if ((p = getenv(sbuf)) != NULL) { /* get environment variable */
373: len = strlen(p);
374: strreq(len);
375: StrLen(arg0) = len;
376: StrLoc(arg0) = alcstr(p, len);
377: Return;
378: }
379: else /* fail if variable not in environment */
380: Fail;
381: }
382: .De
383: .bp
384: .SH
385: math.c:
386: .LP
387: .Ds
388: .ta .8i
389: /*
390: * MATH
391: *
392: * Miscellaneous math functions.
393: *
394: * Ralph E. Griswold
395: *
396: * Last modified 5/2/86
397: *
398: */
399: .Dd
400: #include "../h/rt.h"
401: #include <errno.h>
402: .Dd
403: int errno;
404: /*
405: * exp(x)
406: */
407: FncDcl(exp,\*b1)
408: {
409: int t;
410: double y;
411: union numeric r;
412: double exp();
413:
414: if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
415: y = exp(r.real);
416: if (errno == ERANGE) runerr(252, NULL);
417: mkreal(y,\*b&arg0);
418: Return;
419: }
420: .Dd
421: /*
422: * log(x)
423: */
424: FncDcl(log,\*b1)
425: {
426: int t;
427: double y;
428: union numeric r;
429: double log();
430:
431: if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
432: y = log(r.real);
433: if (errno == EDOM) runerr(251, NULL);
434: mkreal(y,\*b&arg0);
435: Return;
436: }
437: .Dd
438: /*
439: * log10(x)
440: */
441: FncDcl(log10,\*b1)
442: {
443: int t;
444: double y;
445: union numeric r;
446: double log10();
447:
448: if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
449: y = log10(r.real);
450: if (errno == EDOM) runerr(251, NULL);
451: mkreal(y,\*b&arg0);
452: Return;
453: }
454: .Dd
455: /*
456: * sqrt(x)
457: */
458: FncDcl(sqrt,\*b1)
459: {
460: int t;
461: double y;
462: union numeric r;
463: double sqrt();
464:
465: if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
466: y = sqrt(r.real);
467: if (errno == EDOM) runerr(251, NULL);
468: mkreal(y,\*b&arg0);
469: Return;
470: }
471: .De
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.