|
|
1.1 root 1: .so tmac.tr
2: .DA "August 22, 1984"
3: .TR 84-14
4: .Gr
5: .TL
6: Personalized Interpreters for Icon
7: .AU
8: Ralph E. Griswold
9: .AU
10: Robert K. McConeghy
11: .AU
12: William H. Mitchell
13: .AE
14: .tr *\(**
15: .NH
16: Introduction
17: .PP
18: Despite the fact that the Icon programming language has a large repertoire
19: of functions and operations for string and list manipulation, as
20: well as for more conventional computations [1], users frequently
21: need to extend that repertoire. While many extensions can be
22: written as procedures that build on the existing repertoire, there
23: are some kinds of extensions for which this approach is unacceptably
24: inefficient, inconvenient, or simply impractical.
25: .PP
26: Icon itself is written primarily in C [2] and its built-in functions
27: are written as corresponding C functions. Thus the natural way to
28: extend Icon's computational repertoire is to add new C functions to it.
29: .PP
30: The Icon system is organized so that this is comparatively easy to do.
31: Adding a new function
32: does not require changes to the Icon translator,
33: since all functions have a common syntactic form. An entry must be made in
34: a table that is used by the linker and the run-time system in order to
35: identify built-in functions and connect references to them to the
36: code itself.
37: .PP
38: The problem arises in incorporating the C code in the Icon run-time
39: system. Prior to Version 5.9 of Icon, there were two separate but
40: similar implementations of Icon: a compiler [3] and an interpreter [4].
41: The primary difference between the two systems is that the linker for
42: the compiler generates assembly-language code, while the linker
43: for the interpreter generates code that is ready to be interpreted.
44: The interpreter
45: uses a
46: preconstructed run-time
47: system, so that the assembly and loading phases of the compiler implementation
48: is not needed.
49: .PP
50: The loading phase in the compiler is quite slow, so that when the
51: compiler implementation of Icon is used, there is a substantial delay
52: before getting into execution. This is a significant problem during
53: program debugging. Furthermore, a compiled Icon program runs only
54: slightly faster than an interpreted Icon program. This is due in large part
55: to the fact that most programs spend only a small percentage
56: of their time in
57: code generated for the program itself; most of the time is spent
58: executing code in the run-time system, which is essentially the
59: same in the two implementations.
60: .PP
61: The primary advantage of the compiler is that it is possible to
62: add new functions during the loading phase. In order to communicate
63: the names of new functions to the linker, it is necessary to
64: include ``external'' declarations in the Icon source programs that
65: use these functions. There is no way to do this in the interpreter
66: implementation, since the run-time system is preconstructed, rather
67: than being built when
68: the source-language program is processed.
69: .PP
70: One disadvantage of the external function approach is that every source
71: program that uses an external function must contain a declaration for
72: that function. In addition to the necessity for having to remember
73: these declarations, external functions are, by their nature,
74: not logically part of Icon proper. This results in problems of documentation
75: and distribution of such functions to other users.
76: .PP
77: An alternative method of adding new functions to either the
78: compiler or the interpreter implementation of Icon is to
79: add the corresponding C functions to the Icon system itself
80: and to rebuild the entire system. This approach is impractical
81: for many applications. If the extensions are not of general
82: interest, it is inappropriate to include them in the public
83: version of Icon. On the other hand, Icon is a large and complicated system,
84: and having many private versions may create serious problems of
85: maintenance and disk usage. Furthermore, rebuilding the Icon system
86: is slow, cumbersome, and comparatively complicated. This approach therefore
87: is impractical in a situation
88: such as a class in which students implement their own versions
89: of an extension.
90: .PP
91: To remedy these problems, a mechanism for building ``personalized
92: interpreters'' has been added to Version 5.9 of Icon. This mechanism
93: allows a user to add C functions and to build a corresponding
94: interpreter quickly, easily, and without the necessity to have
95: a copy of the source code for the entire Icon system.
96: .PP
97: To construct a personalized interpreter, the user must perform
98: a one-time set up that copies relevant source files to a
99: directory specified by the user and builds the nucleus of a run-time system. Once this is
100: done, the user can add and modify C functions and include them
101: in the personalized run-time system with little effort.
102: .PP
103: Since the linker must know the names of built-in functions,
104: a personalized linker is constructed. In order to run
105: Icon programs with the personalized run-time system, a
106: personalized command processor, which knows the location of
107: the personalized linker and run-time system, is provided also.
108: .PP
109: The modifications that can be made to Icon via a personalized
110: interpreter essentially are limited to the run-time system: the
111: addition of new functions, modifications to existing functions
112: and operations, and modifications and additions to support routines. There
113: is no provision for changing the syntax of Icon, incorporating
114: new operators, keyword, or control structures.
115: .NH
116: Building and Using a Personalized Interpreter
117: .NH 2
118: Setting Up a Personalized Interpreter System
119: .PP
120: To set up a personalized interpreter, a new directory should
121: be created solely for the use of the interpreter; otherwise
122: files may be accidentally destroyed by the set-up process.
123: For the purpose of example, suppose this directory is
124: named \*Mmyicon\fR. The set-up process consists of
125: .Ds
126: mkdir myicon
127: cd myicon
128: icon\-pi
129: .De
130: Note that \*Micon\-pi\fR must be run in the area in which the personalized
131: interpreter is to be built.
132: The
133: location of \*Micon\-pi\fR may vary from site to site [5].
134: .PP
135: The shell script \*Micon\-pi\fR constructs three subdirectories:
136: \*Mh\fR, \*Mstd\fR, and \*Mpi\fR. The subdirectory \*Mh\fR
137: contains header files that are needed in C routines. The subdirectory
138: \*Mstd\fR contains the portions of the Icon system that are needed
139: to build a personalized interpreter. The subdirectory \*Mpi\fR
140: contains a \*MMakefile\fR for building a personalized interpreter
141: and also is the place where source code for new C functions normally
142: resides. Thus work on the personalized interpreter is done in
143: \*Mmyicon/pi\fR.
144: .PP
145: The \*MMakefile\fR that is constructed by \*Micon\-pi\fR
146: contains two definitions to facilitate building personalized
147: interpreters:
148: .IP \*MOBJS\fR .5i
149: a list of object modules that are to be added to or replaced
150: in the run-time system. \*MOBJS\fR initially is empty.
151: .IP \*MLIB\fR
152: a list of library options that are used when the run-time system
153: is built. \*MLIB\fR initially is empty.
154: .LP
155: See the listing of a generic version of this \*MMakefile\fR in
156: Appendix A.
157: .NH 2
158: Building a Personalized Interpreter
159: .PP
160: Performing a \fImake\fR in \*Mmyicon/pi\fR creates three files
161: in \*Mmyicon\fR:
162: .Ds
163: .ta 1i
164: picont \fRcommand processor\*M
165: pilink \fRlinker\*M
166: piconx \fRrun-time system\*M
167: .De
168: A link to \*Mpicont\fR also is constructed in \*Mmyicon/pi\fR so that
169: the new personalized interpreter can be tested in the directory in
170: which it is made.
171: .PP
172: The file \*Mpicont\fR normally is built only on the first \fImake\fR. The
173: file \*Mpilink\fR is built on the first \fImake\fR and is
174: rebuilt whenever the repertoire of built-in functions is changed.
175: The file \*Mpiconx\fR is rebuilt whenever the source code in the
176: run-time system is changed.
177: .PP
178: The user of the personalized interpreter uses \*Mpicont\fR in
179: the same fashion that the standard \*Micont\fR is used [4].
180: (Note that the accidental use of \*Micont\fR in place of
181: \*Mpicont\fR may produce mysterious results.)
182: In turn, \*Mpicont\fR translates a source program using the
183: standard Icon translator and links it using \*Mpilink\fR.
184: The resulting icode file uses \*Mpiconx\fR.
185: .PP
186: The relocation bits and symbol tables in \*Mpicont\fR, \*Mpilink\fR,
187: and \*Mpiconx\fR can be removed by
188: .Ds
189: make Strip
190: .De
191: in \*Mmyicon/pi\fR. This reduces the sizes of these files substantially
192: but may interfere with debugging.
193: .PP
194: If a \fImake\fR is performed in \*Mmyicon/pi\fR before any
195: run-time files are added or modified, the resulting personalized
196: interpreter is identical to the standard one. Such a \fImake\fR can
197: be performed to verify that the personalized interpreter system
198: is performing properly.
199: .PP
200: Note that a personalized interpreter inherits the parameters and
201: configuration of the locally installed version of Icon in \*Mv5g\fR, including
202: optional language extensions [6].
203: The file \*Mmyicon/h/config.h\fR contains configuration information.
204: The definitions in this file should not be changed.
205: .NH 2
206: Adding a New Function
207: .PP
208: To add a new function to the personalized interpreter, it is first
209: necessary to provide the C code, adhering to the conventions and
210: data structures used throughout Icon. See [2]. Some examples of
211: C functions taken from the Icon program library [7] are included in Appendix B
212: of this report. The source code for these functions is contained in
213: \*Mv5g/pifunc\fR, where \*Mv5g\fR is the root of the Icon system.
214: The location of \*Mv5g\fR varies from site to site [5].
215: The directory
216: \*Mv5g/functions\fR contains the source code for the standard built-in
217: functions, which also can be used as models for new ones.
218: .PP
219: Suppose that \*Mgetenv\fR from the Icon program library is to be
220: added to a personalized interpreter. The source code can be obtained by
221: .Ds
222: cp v5g/pifuncs/getenv.c myicon/pi
223: .De
224: (Note that the actual paths will be different, depending on the
225: local hierarchy.)
226: .PP
227: Three things now need to be done to
228: incorporate this function in the personalized interpreter:
229: .IP 1.
230: Add a line consisting of
231: .Ds
232: PDEF(getenv)
233: .De
234: to \*Mmyicon/h/pdef.h\fR in proper alphabetical order.
235: This causes the linker and the run-time system to know about the new function.
236: .IP 2.
237: Add \*Mgetenv.o\fR to the definition of \*MOBJS\fR in
238: \*Mmyicon/pi/Makefile\fR.
239: This causes \*Mgetenv.c\fR to be compiled and the resulting
240: object file to be loaded with the run-time system when a \fImake\fR is performed.
241: .IP 3.
242: Perform a \fImake\fR in \*Mmyicon/pi\fR. The result is
243: new versions of \*Mpilink\fR and \*Mpiconx\fR in \*Mmyicon\fR.
244: .LP
245: The function \*Mgetenv\fR now can be used like any other built-in
246: function.
247: .PP
248: More than one function can be included in a single source file.
249: See \*Mmath.c\fR in Appendix B. Note that \*Mmath.c\fR uses the
250: math library. To add this module to the run-time system of
251: a personalized interpreter, \*MPDEF\fR entries should be
252: made for each function in \*Mmath.c\fR, \*Mmath.o\fR should be added to
253: \*MOBJS\fR, and \*M\-lm\fR should be added to \*MLIB\fR in
254: the \*MMakefile\fR.
255: .NH 2
256: Modifying the Existing Run-Time System
257: .PP
258: The use of personalized interpreters is not limited to the addition
259: of new functions. Any module in the standard run-time system can
260: be modified as well. The run-time system is divided into five
261: parts:
262: .RS
263: .IP \*Mv5g/functions\fR 1.2i
264: built-in functions
265: .IP \*Mv5g/operators\fR
266: built-in operators
267: .IP \*Mv5g/rt\fR
268: run-time support routines
269: .IP \*Mv5g/lib\fR
270: routines called by the interpreter
271: .IP \*Mv5g/iconx\fR
272: the interpreter and start-up routines
273: .RE
274: .LP
275: For example, storage allocation routines are contained in \*Mv5g/rt/alc.c\fR.
276: .PP
277: To modify an existing portion of the Icon run-time system,
278: copy the source code file from the standard system to \*Mmyicon/pi\fR.
279: (Source code for a few run-time routines is placed in \*Mmyicon/std\fR
280: when a personalized interpreter is set up. Check this directory
281: first and use that file, if appropriate, rather than making
282: another copy in \*Mmyicon/pi\fR.) When a source-code file in
283: \*Mmyicon/pi\fR has been modified, place it in the \*MOBJS\fR
284: list just like a new file and perform a \fImake\fR. Note that
285: an entire module must be replaced, even if a change is made to
286: only one routine.
287: Any module that is replaced must contain all the global variables in
288: the original module to prevent \fIld(1)\fR from also loading the
289: original module. There is no way to delete routines from the run-time
290: system.
291: .PP
292: The directory \*Mmyicon/h\fR contains header files that are included
293: in various source-code files. For example, error message text for
294: a new run-time error can be provided by adding it to \*Mmyicon/h/err.h\fR.
295: The file \*Mmyicon/h/rt.h\fR contains declarations and definitions that
296: are used throughout the run-time system. This is where the declaration
297: for the structure of a new type of data object would be placed.
298: .PP
299: Care
300: must be taken when modifying header files not to make changes that
301: would produce inconsistencies between previously compiled components
302: of the Icon run-time system and new ones.
303: .SH
304: References
305: .IP 1.
306: Griswold, Ralph E. and Griswold, Madge T. \fIThe Icon Programming
307: Language\fR. Prentice-Hall, Inc., Englewood Cliffs, New Jersey. 1983.
308: .IP 2.
309: Griswold, Ralph E., Robert K. McConeghy, and William H. Mitchell.
310: \fIA Tour Through the C Implementation of Icon; Version 5.9\fR.
311: Technical Report TR 84-11, Department of Computer Science,
312: The University of Arizona. August 1984.
313: .IP 3.
314: Griswold, Ralph E. and William H. Mitchell. \fIICONC(1)\fR,
315: manual page for \fIUNIX Programmer's Manual\fR, Department of
316: Computer Science, The University of Arizona. July 1983.
317: .IP 4.
318: Griswold, Ralph E. and William H. Mitchell. \fIICONT(1)\fR,
319: manual page for \fIUNIX Programmer's Manual\fR, Department of
320: Computer Science, The University of Arizona. August 1984.
321: .IP 5.
322: Griswold, Ralph E. and William H. Mitchell.
323: \fIInstallation and Maintenance Guide for Version 5.9 of Icon\fR.
324: Technical Report TR 84-13, Department of Computer Science, The
325: University of Arizona, Tucson, Arizona. August 1984.
326: .IP 6.
327: Griswold, Ralph E., Robert K. McConeghy, and William H. Mitchell.
328: \fIExtensions to Version 5 of the Icon Programming Language\fR.
329: Technical Report TR 84-10a, Department of Computer Science,
330: The University of Arizona. August 1984.
331: .IP 7.
332: Griswold, Ralph E. \fIThe Icon Program Library\fR, Technical Report
333: TR 84-12, Department of Computer Science, The University of
334: Arizona. August 1984.
335: .am Ds
336: .ps 8
337: .vs 9
338: ..
339: .am De
340: .ps 10
341: .vs 12
342: ..
343: .de Ta
344: .ta .8i +.8i +.8i +.8i +.8i +.8i +.8i +.8i
345: ..
346: .Ap "Appendix A \(em Makefile for Personalized Interpreters"
347: .sp
348: .PP
349: The ``generic'' \*MMakefile\fR for personalized interpreters follows.
350: The values of \*MPATH\fR and \*MDIR\fR are filled in when \*MPimake\fR is run.
351: .Ds
352: CFLAGS=
353: LDFLAGS=
354: LIB=
355: iroot=PATH
356: V5GBIN=$(iroot)/bin
357: DIR=
358: .Dd
359: #
360: # To add or replace object files, add their names to the OBJS list below.
361: # For example, to add foo.o and bar.o, use:
362: #
363: # OBJS=foo.o bar.o (this is a sample line)
364: #
365: # For each object file added to OBJS, add a dependency line to reflect files
366: # that are depended on. For example, if foo.c includes rt.h
367: # which is located in the h directory use
368: #
369: # foo.o: ../h/rt.h
370: #
371: .Dd
372: OBJS=
373: .Dd
374: PIOBJS=../std/init.o ../std/strprc.o
375: RTOBJS=$(PIOBJS) $(OBJS)
376: .Dd
377: Pi: ../picont ../piconx ../pilink
378: .Dd
379: ../picont: ../std/icont.c
380: rm -f ../picont picont
381: cc -o ../picont -DIntBin="\e"$(DIR)\e"" -DIconx="\e"$(DIR)/piconx\e"" \e
382: -DIconxEnv="\e"ICONX=$(DIR)/piconx\e"" \e
383: -DILINK="\e"$(DIR)/pilink\e"" \e
384: -DITRAN="\e"$(V5GBIN)/itran\e"" -DFORK=QFORK \e
385: ../std/icont.c
386: ln ../picont
387: .Dd
388: ../pilink: ../std/linklib ../std/builtin.o
389: cc $(LDFLAGS) -X -o ../pilink ../std/builtin.o ../std/linklib
390: .Dd
391: ../piconx: ../std/rtlib $(RTOBJS)
392: cc $(LDFLAGS) -X -o ../piconx -e start -u start $(RTOBJS) ../std/rtlib $(LIB)
393:
394: ../std/init.o: ../h/rt.h ../h/err.h ../h/config.h ../h/pdef.h
395: cd ../std; cc -c init.c
396: .Dd
397: ../std/builtin.o: ../std/ilink.h ../h/config.h ../h/pdef.h
398: cd ../std; cc -c builtin.c
399: .Dd
400: ../std/strprc.o: ../h/rt.h ../h/pnames.h ../h/config.h ../h/pdef.h
401: cd ../std; cc -c strprc.c
402: .Dd
403: Strip: ../picont ../piconx ../pilink
404: strip ../picont ../piconx ../pilink
405: .De
406: .Ap "Appendix B \(em C Functions from the Icon Program Library"
407: .sp
408: .SH
409: getenv.c:
410: .LP
411: .Ds
412: /*
413: # GETENV(3.icon)
414: #
415: # Get contents of environment variables
416: #
417: # Stephen B. Wampler
418: #
419: # Last modified 8/19/84
420: #
421: */
422: .Dd
423: #include "../h/rt.h"
424: .Dd
425: /*
426: * getenv(s) - return contents of environment variable s
427: */
428: .Dd
429: Xgetenv(nargs, arg1, arg0)
430: int nargs;
431: struct descrip arg1, arg0;
432: {
433: register char *p;
434: register int len;
435: char sbuf\^[MAXSTRING];
436: extern char *getenv();
437: extern char *alcstr();
438: .Dd
439: DeRef(arg1)
440: .Dd
441: if (!QUAL(arg1)) /* check legality of argument */
442: runerr(103, &arg1);
443: if (STRLEN(arg1) \*(<= 0 || STRLEN(arg1) \*(>= MAXSTRING)
444: runerr(401, &arg1);
445: qtos(&arg1, sbuf); /* convert argument to C-style string */
446: .Dd
447: if ((p = getenv(sbuf)) != NULL) { /* get environment variable */
448: len = strlen(p);
449: sneed(len);
450: STRLEN(arg0) = len;
451: STRLOC(arg0) = alcstr(p, len);
452: }
453: else /* fail if variable not in environment */
454: fail();
455: }
456: .Dd
457: Procblock(getenv,\*b-1)
458: .De
459: .bp
460: .SH
461: math.c:
462: .LP
463: .Ds
464: /*
465: # MATH(3.icon)
466: #
467: # Miscellaneous math functions
468: #
469: # Ralph E. Griswold
470: #
471: # Last modified 8/19/84
472: #
473: */
474: .Dd
475: #include "../h/rt.h"
476: #include <errno.h>
477: .Dd
478: int errno;
479: /*
480: * exp(x), x in radians
481: */
482: Xexp(nargs, arg1, arg0)
483: int nargs;
484: struct descrip arg1, arg0;
485: {
486: int t;
487: double y;
488: union numeric r;
489: double exp();
490:
491: if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
492: y = exp(r.real);
493: if (errno == ERANGE) runerr(252, NULL);
494: mkreal(y,\*b&arg0);
495: }
496: Procblock(exp,\*b1)
497: .Dd
498: /*
499: * log(x), x in radians
500: */
501: Xlog(nargs, arg1, arg0)
502: int nargs;
503: struct descrip arg1, arg0;
504: {
505: int t;
506: double y;
507: union numeric r;
508: double log();
509:
510: if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
511: y = log(r.real);
512: if (errno == EDOM) runerr(251, NULL);
513: mkreal(y,\*b&arg0);
514: }
515: Procblock(log,\*b1)
516: .Dd
517: /*
518: * log10(x), x in radians
519: */
520: Xlog10(nargs, arg1, arg0)
521: int nargs;
522: struct descrip arg1, arg0;
523: {
524: int t;
525: double y;
526: union numeric r;
527: double log10();
528:
529: if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
530: y = log10(r.real);
531: if (errno == EDOM) runerr(251, NULL);
532: mkreal(y,\*b&arg0);
533: }
534: Procblock(log10,\*b1)
535: .Dd
536: /*
537: * sqrt(x), x in radians
538: */
539: Xsqrt(nargs, arg1, arg0)
540: int nargs;
541: struct descrip arg1, arg0;
542: {
543: int t;
544: double y;
545: union numeric r;
546: double sqrt();
547:
548: if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
549: y = sqrt(r.real);
550: if (errno == EDOM) runerr(251, NULL);
551: mkreal(y,\*b&arg0);
552: }
553: Procblock(sqrt,\*b1)
554: .De
555: .bp
556: .SH
557: seek.c:
558: .Ds
559: /*
560: # SEEK(3.icon)
561: #
562: # Seek to position in stream
563: #
564: # Stephen B. Wampler
565: #
566: # Last modified 8/19/84
567: #
568: */
569: .Dd
570: #include "../h/rt.h"
571: .Dd
572: /*
573: * seek(file,\*boffset,\*bstart) - seek to offset byte from start in file.
574: */
575: .Dd
576: Xseek(nargs, arg3, arg2, arg1, arg0)
577: int nargs;
578: struct descrip arg3, arg2, arg1, arg0;
579: {
580: long l1, l2;
581: int status;
582: FILE *fd;
583: long ftell();
584: .Dd
585: DeRef(arg1)
586: if (arg1.type != D_FILE)
587: runerr(106);
588: .Dd
589: defint(&arg2, &l1, 0);
590: defshort(&arg3, 0);
591: .Dd
592: fd = BLKLOC(arg1)->file.fd;
593: .Dd
594: if ((BLKLOC(arg1)->file.status == 0) ||
595: (fseek(fd, l1, arg3.value.integr) == -1))
596: fail();
597: mkint(ftell(fd), &arg0);
598: }
599: .Dd
600: Procblock(seek,\*b3)
601: .De
602: .LP
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.