|
|
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.