File:  [Research Unix] / researchv10dc / cmd / icon / docs / tr86-12.roff
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:34 2018 UTC (8 years, 3 months ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Dan Cross

.so tmac.tr
.DA "May 6, 1986"
.TR 86-12
.Gi
.TL
Personalized Interpreters for Version 6.0 of Icon
.AU
Ralph E. Griswold
.AE
.tr *\(**
.NH
Introduction
.PP
Despite the fact that the Icon programming language has a large repertoire
of functions and operations for string and list manipulation, as
well as for more conventional computations [1], users frequently
need to extend that repertoire. While many extensions can be
written as procedures that build on the existing repertoire, there
are some kinds of extensions for which this approach is unacceptably
inefficient, inconvenient, or simply impractical.
.PP
Icon itself is written C and its built-in functions
are written as corresponding C functions. Thus, the natural way to
extend Icon's computational repertoire is to add new C functions to it.
.PP
The Icon system is organized so that this is comparatively easy to do.
Adding a new function
does not require changes to the Icon translator,
since all functions have a common syntactic form. An entry must be made in
a table that is used by the linker and the run-time system in order to
identify built-in functions and connect references to them to the
code itself.
.PP
One method of adding new functions to Icon
is to
add the corresponding C functions to the Icon system itself
and to rebuild the entire system. This approach is impractical
for many applications. If the extensions are not of general
interest, it is inappropriate to include them in the public
version of Icon. On the other hand, Icon is a large and complicated system,
and having many private versions may create serious problems of
maintenance and disk usage. Furthermore, rebuilding the Icon system
is expensive. This approach therefore
may be impractical in a situation
such as a class in which students implement their own versions
of an extension.
.PP
To remedy these problems, a mechanism for building ``personalized
interpreters'' is included in \*U implementations of Icon.
This mechanism
.Un
allows a user to add C functions and to build a corresponding
interpreter quickly, easily, and without the necessity to have
a copy of the source code for the entire Icon system.
.PP
To construct a personalized interpreter, the user must perform
a one-time set up that copies relevant source files to a
directory specified by the user and builds the nucleus of a run-time system. Once this is
done, the user can add and modify C functions and include them
in the personalized run-time system with little effort.
.PP
Since the linker must know the names of built-in functions,
a personalized linker also is constructed. In order to run
Icon programs in a self-contained personalized run-time system,
personalized versions of the translator, \*Mpitran\fR, and the
command processor, \*Mpicont\fR,
are provided also.
.PP
The modifications that can be made to Icon via a personalized
interpreter essentially are limited to the run-time system: the
addition of new functions, modifications to existing functions
and operations, and modifications and additions to support routines. There
is no provision for changing the syntax of Icon, incorporating
new operators, keyword, or control structures.
.NH
Building and Using a Personalized Interpreter
.NH 2
Setting Up a Personalized Interpreter System
.PP
To set up a personalized interpreter, a new directory should
be created solely for the use of the interpreter; otherwise
files may be accidentally destroyed by the setup process.
For the purpose of example, suppose this directory is
named \*Mmyicon\fR. The setup consists of
.Ds
mkdir myicon
cd myicon
icon_pi
.De
Note that \*Micon_pi\fR must be run from the area in which the personalized
interpreter is to be built.
The
location of \*Micon_pi\fR may vary from site to site.
.PP
The shell script \*Micon_pi\fR constructs three subdirectories:
\*Mh\fR, \*Mstd\fR, and \*Mpi\fR. The subdirectory \*Mh\fR
contains header files that are needed in C routines. The subdirectory
\*Mstd\fR contains the machine-independent portions of the Icon system that are needed
to build a personalized interpreter.
The subdirectory \*Mpi\fR
contains a \*MMakefile\fR for building a personalized interpreter
and also is the place where source code for new C functions normally
resides. Thus, work on the personalized interpreter is done in
\*Mmyicon/pi\fR.
.PP
The \*MMakefile\fR that is constructed by \*Micon_pi\fR
contains two definitions to facilitate building personalized
interpreters:
.RS
.IP \*MOBJS\fR .5i
a list of object modules that are to be added to or replaced
in the run-time system. \*MOBJS\fR initially is empty.
.IP \*MLIB\fR
a list of library options that are used when the run-time system
is built. \*MLIB\fR initially is empty, but the math library is
loaded as a normal part of building the run-time system.
.RE
.LP
See the listing of the generic version of this \*MMakefile\fR in
Appendix A.
.NH 2
Building a Personalized Interpreter
.PP
Performing a \fImake\fR in \*Mmyicon/pi\fR creates four files
in \*Mmyicon\fR:
.Ds
.ta 1i
picont	\fRcommand processor\*M
pilink	\fRlinker\*M
piconx	\fRrun-time system\*M
piconx.hdr	\fRheader file for linker output\*M
.De
A link to \*Mpicont\fR also is constructed in \*Mmyicon/pi\fR so that
the new personalized interpreter can be tested in the directory in
which it is made.
.PP
The file \*Mpicont\fR normally is built only on the first \fImake\fR. The
file \*Mpilink\fR is built on the first \fImake\fR and is
rebuilt whenever the repertoire of built-in functions is changed
as a result of modifications to \*Mh/fdef.h\fR.
The file \*Mpiconx\fR is rebuilt whenever the source code in the
run-time system is changed.
.PP
The user of the personalized interpreter uses \*Mpicont\fR in
the same fashion that the standard \*Micont\fR is used.
(Note that the accidental use of \*Micont\fR in place of
\*Mpicont\fR may produce mysterious results.)
In turn, \*Mpicont\fR translates a source program using
\*Mpitran\fR and links it using \*Mpilink\fR.
The resulting icode file uses \*Mpiconx\fR.
.PP
The relocation bits and symbol tables in
\*Mpiconx\fR can be removed by
.Ds
make Stripx
.De
in \*Mmyicon/pi\fR. This reduces the size of this file substantially
but may interfere with debugging.
.PP
If a \fImake\fR is performed in \*Mmyicon/pi\fR before any
run-time files are added or modified, the resulting personalized
interpreter is identical to the standard one. Such a \fImake\fR can
be performed to verify that the personalized interpreter system
is performing properly.
.NH 2
Adding a New Function
.PP
To add a new function to the personalized interpreter, it is first
necessary to provide the C code, adhering to the conventions and
data structures used throughout Icon. Some examples of
C functions are included in Appendix B
of this report. The source code for several such functions is contained in
\*Mv6/pi/pil\fR, where \*Mv6\fR is the root of the Icon system.
The directory
\*Mv6/src/iconx\fR contains the source code for the standard
functions, which also can be used as models for new ones.
.PP
Suppose that \*Mgetenv\fR from \*Mv6/pi/pil\fR is to be
added to a personalized interpreter.
The source code can be obtained by
.Ds
cp v6/pi/pil/getenv.c myicon/pi
.De
(Note that the actual paths depend on the
local hierarchy.)
.PP
Three things now need to be done to
incorporate this function in the personalized interpreter:
.IP 1.
Add a line consisting of
.Ds
FncDef(getenv)
.De
to \*Mmyicon/h/fdef.h\fR in proper alphabetical order.
This causes the linker and the run-time system to know about the new function.
.IP 2.
Add \*Mgetenv.o\fR to the definition of \*MOBJS\fR in
\*Mmyicon/pi/Makefile\fR.
This causes \*Mgetenv.c\fR to be compiled and the resulting
object file to be loaded with the run-time system when a \fImake\fR is performed.
.IP 3.
Perform a \fImake\fR in \*Mmyicon/pi\fR. The result is
new versions of \*Mpilink\fR and \*Mpiconx\fR in \*Mmyicon\fR.
.LP
The function \*Mgetenv\fR now can be used like any other built-in
function.
.PP
More than one function can be included in a single source file.
See \*Mmath.c\fR in Appendix B.
To incorporate these functions in
a personalized interpreter, \*MFncDef\fR entries should be
made for each function in \*Mmath.c\fR and \*Mmath.o\fR should be added to
\*MOBJS\fR.
.NH 2
Modifying the Existing Run-Time System
.PP
The use of personalized interpreters is not limited to the addition
of new functions. Any module in the standard run-time system can
be modified as well.
.PP
To modify an existing portion of the Icon run-time system,
copy the source code file from \*Mv6/src/iconx\fR to \*Mmyicon/pi\fR.
(Source code for a few run-time routines is placed in \*Mmyicon/std\fR
when a personalized interpreter is set up. Check this directory
first and use that file, if appropriate, rather than making
another copy in \*Mmyicon/pi\fR.) When a source-code file in
\*Mmyicon/pi\fR has been modified, place it in the \*MOBJS\fR
list just like a new file and perform a \fImake\fR. Note that
an entire module must be replaced, even if a change is made to
only one routine.
Any module that is replaced must contain all the global variables in
the original module to prevent \fIld(1)\fR from also loading the
original module. There is no way to delete routines from the run-time
system.
.PP
The directory \*Mmyicon/h\fR contains header files that are included
in various source-code files.
The file \*Mmyicon/h/rt.h\fR contains declarations and definitions that
are used throughout the run-time system. This is where the declaration
for the structure of a new type of data object would be placed.
.PP
Care
must be taken when modifying header files not to make changes that
would produce inconsistencies between previously compiled components
of the Icon run-time system and new ones.
.SH
Reference
.IP 1.
Griswold, Ralph E. and Griswold, Madge T. \fIThe Icon Programming
Language\fR. Prentice-Hall, Inc., Englewood Cliffs, New Jersey. 1983.
.am Ds
.ps 8
.vs 9
..
.am De
.ps 10
.vs 12
..
.de Ta
.ta .8i +.8i +.8i +.8i +.8i +.8i +.8i +.8i
..
.Ap "Appendix A \(em Makefile for Personalized Interpreters"
.sp
.PP
The ``generic'' \*MMakefile\fR for personalized interpreters follows.
A copy, with the
value of \*MDir\fR filled in and appropriate definitions for the flags,
is placed in \*Mmyicon/pi\fR when \*Micon_pi\fR is run.
.Ds
Dir=
.Dd
RHDRS=	../h/rt.h ../h/config.h ../h/cpuconf.h ../h/memsize.h
#
#  To add or replace object files, add their names to the OBJS list below.
#  For example, to add nfncs.o and iolib.o, use:
#
#	OBJS=nfncs.o iolib.o         (this is a sample line)
#
#  For each object file added to OBJS, add a dependency line to reflect files
#  that are depended on.  In general, new functions depend on $(RHDRS).
#  For example, if nfncs.c contains new functions, use
#  	
#	nfncs.o:	$(RHDRS)
#
.Dd
OBJS=
LIB=
.Dd
RTOBJS=../std/rconv.o ../std/idata.o $(OBJS)
.Dd
Pi:	../picont ../piconx ../pilink ../piconx.hdr
.Dd
\&../picont: ../std/icont.c ../h/config.h
	rm -f ../picont picont
	$(CC) $(CFLAGS) -o ../picont -DItran="\e"$(Dir)/pitran\e""\e
 		-DIconx="\e"$(Dir)/piconx\e"" \e
		-DIlink="\e"$(Dir)/pilink\e""  ../std/icont.c
	strip ../picont
	ln ../picont picont
.Dd
\&../pilink: ../std/linklib ../std/builtin.o ../std/ilink.o
	$(CC) $(LDFLAGS) -o ../pilink ../std/builtin.o ../std/ilink.o\e
		 ../std/linklib
	strip ../pilink
.Dd
\&../std/ixhdr.o:	../h/config.h
	cd ../std;	$(CC) -c $(XCFLAGS) -DIconx="\e"$(Dir)/piconx\e"" ixhdr.c
.Dd
\&../piconx.hdr:	../std/ixhdr.o
	$(CC) $(XLDFLAGS) ../std/ixhdr.o -o ../piconx.hdr
	strip ../piconx.hdr
.Dd
\&../piconx: ../std/rtlib $(RTOBJS)
	$(CC) $(LDFLAGS) -o ../piconx $(RTOBJS) ../std/rtlib $(LIB) -lm
	
\&../std/idata.o:		$(RHDRS) ../h/fdef.h
	cd ../std;	$(CC) -c $(CFLAGS) idata.c
.Dd
\&../std/rconv.o:		$(RHDRS) ../h/fdef.h
	cd ../std;	$(CC) -c $(CFLAGS) rconv.c
.Dd
\&../std/builtin.o:	../std/ilink.h ../h/config.h ../h/fdef.h
	cd ../std;	$(CC) -c $(CFLAGS) builtin.c
.Dd
\&../std/ilink.o:		../std/ilink.h ../h/config.h ../h/header.h ../h/paths.h
	cd ../std;	$(CC) -c $(CFLAGS) -DHeader="\e"$(Dir)/piconx.hdr\e""  ilink.c
.Dd
Stripx:	../piconx
	strip ../piconx
.De
.Ap "Appendix B \(em Sample C Functions"
.sp
.SH
getenv.c:
.LP
.de Ta
.ta 3i
..
.Ds
.ta .8i
/*
 *	GETENV
 *
 *	Get values of environment variables.
 *
 *	Stephen B. Wampler
 *
 *	Last modified 5/2/86 by Ralph E. Griswold
 *
 */
.Dd
#include "../h/rt.h"
.Dd
/*
 * getenv(s) - return contents of environment variable s
 */
.Dd
FncDcl(getenv,\*b1)
   {
   register char *p;
   register int len;
   char sbuf\^[256];
   extern char *getenv();
   extern char *alcstr();
.Dd
   if (!Qual(arg1))			/* check legality of argument */
      runerr(103, &arg1);
   if (StrLen(arg1) \*(<= 0 || StrLen(arg1) \*(>= MaxCvtLen)
      runerr(401, &arg1);
   qtos(&arg1, sbuf);			/* convert argument to C-style string */
.Dd
   if ((p = getenv(sbuf)) != NULL) {	/* get environment variable */
      len = strlen(p);
      strreq(len);
      StrLen(arg0) = len;
      StrLoc(arg0) = alcstr(p, len);
      Return;
      }
   else					/* fail if variable not in environment */
      Fail;
   }
.De
.bp
.SH
math.c:
.LP
.Ds
.ta .8i
/*
 *	MATH
 *
 *	Miscellaneous math functions.
 *
 *	Ralph E. Griswold
 *
 *	Last modified 5/2/86
 *
 */
.Dd
#include "../h/rt.h"
#include <errno.h>
.Dd
int errno;
/*
 * exp(x)
 */
FncDcl(exp,\*b1)
   {
   int t;
   double y;
   union numeric r;
   double exp();
   
   if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
   y = exp(r.real);
   if (errno == ERANGE) runerr(252, NULL);
   mkreal(y,\*b&arg0);
   Return;
   }
.Dd
/*
 * log(x)
 */
FncDcl(log,\*b1)
   {
   int t;
   double y;
   union numeric r;
   double log();
   
   if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
   y = log(r.real);
   if (errno == EDOM) runerr(251, NULL);
   mkreal(y,\*b&arg0);
   Return;
   }
.Dd
/*
 * log10(x)
 */
FncDcl(log10,\*b1)
   {
   int t;
   double y;
   union numeric r;
   double log10();
   
   if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
   y = log10(r.real);
   if (errno == EDOM) runerr(251, NULL);
   mkreal(y,\*b&arg0);
   Return;
   }
.Dd
/*
 * sqrt(x)
 */
FncDcl(sqrt,\*b1)
   {
   int t;
   double y;
   union numeric r;
   double sqrt();
   
   if ((t = cvreal(&arg1, &r)) == NULL) runerr(102, &arg1);
   y = sqrt(r.real);
   if (errno == EDOM) runerr(251, NULL);
   mkreal(y,\*b&arg0);
   Return;
   }
.De

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.