|
|
1.1 ! root 1: |make(rp) ! 2: ! 3: |insert(../monk/monk.mac) ! 4: ! 5: |comment(VOL2HEADER)|set_counter(page 325-1)|set_string(page_headers "'''")|set_string(even_headers "'The C Interpreter: A Tutorial for Cin Version 0.18''\f(NIcin\fP'")|set_string(odd_headers "'\f(NIcin\fP''The C Interpreter: A Tutorial for Cin Version 0.18'")|set_string(even_footers "_\\nP__UNIX Papers_")|set_string(odd_footers "'Research Tenth Edition''\\nP'") ! 6: ! 7: |environment(computeroutput; ! 8: verbatim on, file.information, line.spacing 1, ! 9: fill off, size -1, space -1, font cw, blank.lines -1, ! 10: tab.stops "\w' 'u 2u*\w' 'u 3u*\w' 'u 4u*\w' 'u 5u*\w' 'u 6u*\w' 'u 7u*\w' 'u 8u*\w' 'u 9u*\w' 'u 10u*\w' 'u 11u*\w' 'u"; ! 11: ! 12: tab.stops, blank.lines -1, SPACE) ! 13: ! 14: |author(name "T. J. Kowalski", initials TJK, location MH, department 11229, ! 15: extension x2771, room 2C-568) ! 16: |document(number 11229-880606-07TMS, file_case 25952, ! 17: work_program 311401-2199) ! 18: ! 19: |author(name "H. H. Goguen", initials HHG, location MH, department 11229, ! 20: extension x2771, room 2C-568) ! 21: |document(number 11229-880606-07TMS, file_case 25952, ! 22: work_program 311401-2199) ! 23: ! 24: |author(name "J. J. Puttress", initials JJP, location MH, department 11229, ! 25: extension x7290, room 2C-577) ! 26: |document(number 11229-880606-07TMS, file_case 25952, ! 27: work_program 311401-2199) ! 28: ! 29: |date(June 6, 1988) ! 30: ! 31: |title(The C Interpreter: ! 32: A Tutorial for Cin Version 0.18) ! 33: ! 34: |begin(abstract) ! 35: The C interpreter, |i(cin), is the core of an interactive programming environment for ! 36: the C programming language. ! 37: We believe that by providing integrated facilities to create, ! 38: edit, ! 39: browse, ! 40: execute, ! 41: and debug programs, ! 42: this environment should enhance the productivity ! 43: of C programmers at |s(AT&T) and improve the quality of their code. ! 44: Furthermore, ! 45: we feel that |i(cin) provides an easy-to-use instructional environment. ! 46: |p ! 47: This memorandum is a tutorial guide to help users get started. ! 48: Although it does not cover everything, ! 49: it provides enough information for most users' daily needs. ! 50: Topics discussed include ! 51: creating simple programs, ! 52: testing individual functions and expressions, ! 53: inspecting and modifying variables, ! 54: using program views, and setting breakpoints. ! 55: |end(abstract) ! 56: ! 57: |titlebox ! 58: ! 59: |style(two_column) ! 60: ! 61: |unnumbered_section(Introduction) ! 62: ! 63: Interactive programming environments are common for |s(LISP), ! 64: |reference(Teitelman Masinter Interlisp Programming Environment) ! 65: |reference(Sandewall Programming in an Interactive Environment 1978) ! 66: |s(PASCAL), ! 67: |reference(Delisle Menicosy Schwartz Viewing a Programming Environment) ! 68: |reference(Reiss Graphical Program Development with PECAN) ! 69: |reference(Brown Sedgewick A System for Algorithm Animation) ! 70: |s(PL/C), ! 71: |reference(Archer Conway COPE: A Cooperative Programming Environment) ! 72: |reference(Teitelbaum Reps The Cornell Program Synthesizer 1981) ! 73: and Smalltalk. ! 74: |reference(Goldberg Robson Smalltalk-80: The Language and Its Implementation) ! 75: |reference(Tesler The Smalltalk Environment) ! 76: Some work has been done on various pieces of a C program environment, including ! 77: syntax directed editors, ! 78: |reference(Horgan Moore Techniques for Improving Language-Based Editors) ! 79: interpreters, ! 80: |reference(Saber-C 1988) ! 81: |reference(Feuer si - An Interpreter for the C Language) ! 82: |reference(Ostby A C interpreter) ! 83: debuggers,|reference(Adams Muchnick Dbxtool A Window-Based Symbolic Debugger) ! 84: |reference(Cargill The Feel of Pi) ! 85: and browsers. ! 86: |reference(Steffen Interactive Examination of a C Program with Cscope) ! 87: |p ! 88: |i(Cin) is a C interpreter: an interactive program ! 89: for creating, testing, modifying, and debugging a C program, ! 90: using directions provided by a user at a terminal. ! 91: The program can be a single function in a single file, ! 92: or a large collection of files and functions as in System 75. ! 93: |reference(System 75: Project Development Environment 1985) ! 94: |i(Cin) is part of the Integrated C Programming Environment, ! 95: |cw(cens), ! 96: currently being developed by Department 11229. ! 97: It implements correct full C, ! 98: enables rapid prototyping, ! 99: permits extensive error checking, ! 100: facilitates incremental update, ! 101: manages multiple software views, ! 102: and ! 103: provides a programmable command language. ! 104: |p ! 105: This tutorial is meant to simplify learning |i(cin). ! 106: We suggest that you read this document, ! 107: simultaneously using |i(cin) to follow the examples, ! 108: then read the manual page in the appendix ! 109: while continuing to experiment with |i(cin). ! 110: Furthermore, ! 111: we strongly recommend completing the exercises. ! 112: They both reinforce material covered in the text ! 113: and explore material not thoroughly discussed. ! 114: |p ! 115: This is an introduction and a tutorial. ! 116: For that reason, ! 117: no attempt is made to cover ! 118: more than a part of the facilities that |i(cin) offers ! 119: (although this fraction includes the most useful and frequently needed parts). ! 120: Explanations of the C language and the |s(UNIX)|sp(registered) system ! 121: are beyond the scope of this paper. ! 122: We assume that you know how to log on to a |s(UNIX) system ! 123: and how to express algorithms in C. ! 124: Information on both the |s(UNIX) system ! 125: and C is readily available from a variety of sources. ! 126: |reference(Kernighan Pike Prentice-Hall) ! 127: |reference(Kernighan Ritchie Prentice-Hall) ! 128: ! 129: |section(Getting Started) ! 130: ! 131: We'll assume you have logged in to a |s(UNIX) system ! 132: and have just received the shell prompt, e.g. ``$''. ! 133: The easiest way to start |i(cin) is to type ! 134: ! 135: |begin(computeroutput) ! 136: |i($ )cin -i ! 137: |i(cin>) ! 138: |end(computeroutput) ! 139: ! 140: You are now ready to go ! 141: |sp(Em dash) |i(cin) is waiting for your instructions. ! 142: |i(Cin) shows this by echoing a ! 143: ! 144: |begin(computeroutput) ! 145: |i(cin>) ! 146: |end(computeroutput) ! 147: ! 148: to your terminal. ! 149: Throughout this tutorial, responses from |i(cin) are in |i(italics). ! 150: |p ! 151: This section shows how to use the interactive mode of |i(cin), ! 152: that is, a mode where we can enter and execute programs interactively. ! 153: Later we'll talk about changing and debugging programs. ! 154: As our first problem, ! 155: let's leap the hurdle of creating, compiling, loading, and running ! 156: a program that prints ``hello, world'' on our terminal. ! 157: Though this is a painful task when we use the normal editor, compiler, ! 158: loader, and shell to run the program, ! 159: it's easy in |i(cin). ! 160: |p ! 161: When |i(cin) is started with the |cw(-i) option, ! 162: it is like working with a blank piece ! 163: of paper |sp(Em dash) there is no program or data present. ! 164: They must be supplied by the person using |i(cin). ! 165: The program, ! 166: with its data, ! 167: can be entered interactively ! 168: or read into |i(cin) from a file. ! 169: We will start by typing in a program ! 170: and return shortly to the reading of files. ! 171: |p ! 172: First a bit of terminology. ! 173: In |i(cin) jargon, ! 174: the program currently worked on is said to be ! 175: ``kept in the current |cw(view)''. ! 176: Think of the |cw(view) as a work space, ! 177: if you like, ! 178: or simply as the information that you are going to be ! 179: using. ! 180: The |cw(view) is like a piece of paper, ! 181: on which we will write things, ! 182: then change some of them, ! 183: and finally file the whole thing away for another day. ! 184: |p ! 185: The user tells |i(cin) what to do to the |cw(view) ! 186: by typing C expressions and declarations. ! 187: C expressions are executed immediately, ! 188: while declarations are stored in the |cw(view). ! 189: When an expression is executed, ! 190: |i(cin) uses both local and global variables. ! 191: |p ! 192: Now we're ready to solve our problem. ! 193: The easiest way is to write a C expression that calls the |cw(printf) ! 194: library routine. ! 195: ! 196: |begin(computeroutput) ! 197: |i(cin>) printf("hello, world|sp(\)n"); ! 198: |i(hello, world ! 199: cin>) ! 200: |end(computeroutput) ! 201: ! 202: |p ! 203: Another way to solve our problem is to write a declaration for a |cw(main) function ! 204: and call it using a C expression. ! 205: ! 206: |begin(computeroutput) ! 207: |i(cin>) void main() ! 208: { ! 209: printf("hello, world|sp(\)n"); ! 210: } ! 211: |i(cin>) main(); ! 212: |i(hello, world ! 213: cin>) ! 214: |end(computeroutput) ! 215: ! 216: |p ! 217: We draw your attention to the |cw(void main) declaration. ! 218: When you're in |i(cin)'s interactive mode, ! 219: you need to declare a return type for each function. ! 220: This allows |i(cin)'s interactive mode ! 221: to tell the difference between an expression calling |cw(main) ! 222: and a declaration of |cw(main). ! 223: Don't panic! ! 224: You don't have to change all your C programs. ! 225: This is only true when typing directly to interactive mode. ! 226: The normal default declaration, |cw(int), still applies when files are read in. ! 227: We could have designed |i(cin) to work like the ! 228: C interpreters referenced in the introduction, which require you to ! 229: type a special character to enter and leave a command mode, ! 230: but we felt that declaring a return type was more consistent with C syntax. ! 231: |p ! 232: You also saw that |i(cin) prompts only for a C expression ! 233: or a declaration. ! 234: Thus, there are no prompts for the function body of |cw(main). ! 235: This silence is preferred by experienced users, ! 236: but sometimes disturbs beginners. ! 237: |p ! 238: Finally finished with our problem, we'd like to return to our shell. ! 239: Exit |i(cin) by typing ! 240: ! 241: |begin(computeroutput) ! 242: |i(cin>) cin_quit(); ! 243: |i($) ! 244: |end(computeroutput) ! 245: ! 246: or by typing the end-of-file character (hold the |s(CTRL) key down ! 247: and press |cw(d)). ! 248: ! 249: |section(I Seemed To Have Confused It) ! 250: ! 251: If you didn't get a ``hello, world'', ! 252: then |i(cin) is confused by the directions it got. ! 253: Let's look at some possible problems that may have occurred ! 254: and how to correct them. ! 255: |p ! 256: One possibility is ! 257: ! 258: |begin(computeroutput) ! 259: |i($) cin -i ! 260: |i(cin: not found) ! 261: |i($) ! 262: |end(computeroutput) ! 263: ! 264: The C interpreter, |i(cin), is not available on your system in the ! 265: directories specified by your |s(PATH) shell variable. ! 266: Please contact your system administrator. ! 267: If your system has |s(EXPTOOLS), ! 268: the administrator can get |i(cin) from Alan Hastings. ! 269: Otherwise, ! 270: your administrator can ask for |i(cin) by sending mail to |cw(research!frodo), ! 271: including his/her name, ! 272: department number, ! 273: telephone number, ! 274: location, ! 275: and room number. ! 276: |p ! 277: Another possibility is ! 278: ! 279: |begin(computeroutput) ! 280: |i($) cin -i ! 281: |i(cin>) printff("hello, world|sp(\)n"); ! 282: |i(interactive mode: 1: warning: 'printff' undefined ! 283: breakpoint in function 'cin_system' ! 284: at line 1 of file 'interactive mode' ! 285: cin>) ! 286: |end(computeroutput) ! 287: ! 288: |cw(printf) was misspelled. ! 289: Whenever |i(cin) encounters an undefined function or variable, ! 290: it recursively calls a breakpoint function, |cw(cin_system), ! 291: which places you in |i(cin)'s interactive mode waiting for input. ! 292: The simplest corrective action is to return and ignore the problem. ! 293: We can do this by typing ! 294: ! 295: |begin(computeroutput) ! 296: |i(cin>) cin_return(); ! 297: |i[interactive mode: 2: warning: ! 298: call of undefined function (returning 0L) ! 299: cin>] ! 300: |end(computeroutput) ! 301: ! 302: or by typing the end-of-file character. ! 303: This acts as if you decided to define a function, |cw(printff), ! 304: that returns a |cw(long) zero. ! 305: A future release of |i(cin) will allow you to modify the prompt to show ! 306: the number of recursive calls to |cw(cin_system). ! 307: Later we'll talk about additional corrective actions and ! 308: other predefined |cw(cin_) functions and variables. ! 309: |p ! 310: Yet another possibility is ! 311: ! 312: |begin(computeroutput) ! 313: |i($) cin -i ! 314: |i(cin>) printf("hello, world|sp(\)n") ! 315: |end(computeroutput) ! 316: ! 317: Neither ``hello, world'', nor the |cw(|i(cin>)) prompt appears. ! 318: You probably forgot to type the last semicolon (|cw(;)). ! 319: Even experienced users forget the terminating semicolon (|cw(;)) ! 320: sometimes. ! 321: If |i(cin) seems to be ignoring you, ! 322: ! 323: |begin(computeroutput) ! 324: |i($) cin -i ! 325: |i(cin>) printf("hello, world|sp(\)n); ! 326: |i(interactive mode: 1: newline in string) ! 327: |end(computeroutput) ! 328: ! 329: type an extra line with just a semicolon (|cw(;)) on it, ! 330: or in some rare cases ! 331: ! 332: |begin(computeroutput) ! 333: |i($) cin -i ! 334: |i(cin>) void main() ! 335: { ! 336: printf("hello, world|sp(\)n); ! 337: } ! 338: |i(interactive mode: 3: newline in string ! 339: interactive mode: 4: syntax error ! 340: in parameter list of function call) ! 341: |end(computeroutput) ! 342: ! 343: an extra line with just a semicolon (|cw(;)) ! 344: followed by an extra line with just a closing curly brace (|cw(})) on it. ! 345: Isn't error recovery wonderful! ! 346: The next release of |i(cin) will be more friendlier. ! 347: |p ! 348: Throughout the rest of the tutorial, ! 349: we will assume that our typing is perfect. ! 350: We use the |cw(samuel)|reference(Puttress 1986 browser) ! 351: editor to remember C statements and declarations in a scratch pad, ! 352: sending them to |i(cin) whenever we are happy with the syntax. ! 353: However, you can also remember and send ! 354: C statements and declarations with |cw(sam), |cw(jim), |cw(emacs), or |cw(inedit). ! 355: ! 356: |subsection(Exercise 1) ! 357: ! 358: Enter |i(cin) and use the formula |e<degree~ F ~=~ ( 9 / 5 ) ~*~ degree~ C ~+~ 32> ! 359: to create a conversion table from centigrade or Celsius temperatures to Fahrenheit ! 360: for 20|sp(degree) C to 30|sp(degree) C. ! 361: Do this exercise in two different ways: ! 362: |begin(number_list) ! 363: |item Write a C expression that calls the |cw(printf) library routine. ! 364: |item Declare a |cw(main) function and run it in |i(cin). ! 365: |end(number_list) ! 366: ! 367: |section(Writing A Small Program) ! 368: ! 369: Our next problem is to write a few routines to ! 370: print algebraic expression trees. ! 371: Let's start by declaring the template |cw(node) for our tree. ! 372: ! 373: |begin(computeroutput) ! 374: |i(cin>) struct node { ! 375: struct node *left; ! 376: struct node *right; ! 377: char *value; ! 378: int type; ! 379: }; ! 380: |i(cin>) ! 381: |end(computeroutput) ! 382: ! 383: |p ! 384: The |cw(left) and |cw(right) fields are pointers to other |cw(node)s. ! 385: The |cw(value) field holds a character string representing ! 386: the operator, variable, or constant associated with the node. ! 387: The |cw(type) field shows the kind of operator, ! 388: variable, or constant held in |cw(value) field. ! 389: The allowable types are: ! 390: ! 391: |begin(computeroutput) ! 392: |i(cin>) #define ADD 1 ! 393: #define SUB 2 ! 394: #define MUL 3 ! 395: #define DIV 4 ! 396: #define EXPT 5 ! 397: #define UMINUS 6 ! 398: #define CONST 7 ! 399: #define VAR 8 ! 400: |end(computeroutput) ! 401: ! 402: |p ! 403: We'd like to pause and talk about prompts once again. ! 404: You're probably puzzled why there was only one |i(cin>) for the above set ! 405: of pre-processor statements. ! 406: Well, ! 407: in the 0.18 release |i(cin) prompts only for a C expression ! 408: or a declaration, and C pre-processor statements are a little different. ! 409: We think this is a botch and will change it in the next release, ! 410: but until then it's a feature.|dagnote(Features are ! 411: bugs that are not yet fixed.) ! 412: |p ! 413: Now that we have a data structure, ! 414: let's write a |cw(prt) routine to display the tree ! 415: in the format normally used for an equation. ! 416: This requires an in-order walk; in other words |sp(Em dash) ! 417: go left as far as you can, ! 418: print the node, ! 419: then go right as far as you can. ! 420: ! 421: |begin(computeroutput) ! 422: |i(cin>) void ! 423: prt(n) ! 424: struct node *n; ! 425: { ! 426: switch(n->type) { ! 427: ! 428: default: ! 429: prt(n->left); ! 430: printf("%s ", n->value); ! 431: prt(n->right); ! 432: break; ! 433: ! 434: case UMINUS: ! 435: printf("%s ", n->value); ! 436: prt(n->right); ! 437: break; ! 438: ! 439: case CONST: ! 440: case VAR: ! 441: printf("%s ", n->value); ! 442: break; ! 443: ! 444: } ! 445: } ! 446: |i(cin>) ! 447: |end(computeroutput) ! 448: ! 449: |p ! 450: A powerful feature of |i(cin) enables a routine ! 451: to be tested as soon it is written. ! 452: This way you can make sure it does what you want ! 453: before incorporating it into a large program. ! 454: |i(Cin) also takes care of allocating and deallocating ! 455: data structures for testing. ! 456: |p ! 457: Let's test the |cw(prt) function. ! 458: First we'll include the standard I/O header file ! 459: so we can turn off output buffering. ! 460: ! 461: |begin(computeroutput) ! 462: |i(cin>) #include <stdio.h> ! 463: |i(cin>) setbuf(stdout, NULL); ! 464: |i(cin>) setbuf(stderr, NULL); ! 465: |i(cin>) ! 466: |end(computeroutput) ! 467: ! 468: Next we let |i(cin) allocate storage space for a sample node, ! 469: |cw(a1), ! 470: and set it to hold a constant, |cw(CONST), with a value of |cw(17). ! 471: Finally, ! 472: we call |cw(prt) and see it print |cw(17). ! 473: ! 474: |begin(computeroutput) ! 475: |i(cin>) struct node a1; ! 476: |i(cin>) a1.type = CONST; ! 477: |i(cin>) a1.value = "17"; ! 478: |i(cin>) prt(&a1); ! 479: |i(17 cin>) ! 480: |end(computeroutput) ! 481: ! 482: For constants, ! 483: |cw(left) and |cw(right) are unused. ! 484: |p ! 485: It's likely that we'll want to save our work for later use. ! 486: A simple and easy way to do this ! 487: is to save an image of our program and data definitions as an executable file. ! 488: Let's do this by calling the predefined function |cw(cin_dump) ! 489: with the name of a file, |cw(./saved). ! 490: ! 491: |begin(computeroutput) ! 492: |i(cin>) cin_dump("./saved"); ! 493: |i(cin>) cin_quit(); ! 494: |i($) ! 495: |end(computeroutput) ! 496: ! 497: Any time afterwards we can invoke our saved executable and use the program ! 498: and data definitions we have just entered. ! 499: ! 500: |begin(computeroutput) ! 501: |i($) ./saved ! 502: |i(cin>) prt(&a1); ! 503: |i(17 cin>) ! 504: |end(computeroutput) ! 505: ! 506: This feature is useful for customizing our |i(cin) environment, ! 507: but in the 0.18 release of |i(cin) there is no way to print out ! 508: the definition of a given function. ! 509: We plan to enhance |i(cin) to do this in the future, ! 510: but for now we recommend using an editor to keep your functions ! 511: in files. ! 512: |p ! 513: Thus, we need to learn how to ! 514: load source or object files into |i(cin). ! 515: We'll assume you've returned to your shell, ! 516: placed the definition for |cw(node) ! 517: and its |cw(#define)s in |cw(node.h), ! 518: and placed |cw(#include "node.h") ! 519: along with the definition for |cw(prt) in |cw(prt.c). ! 520: |p ! 521: Now let's go back to |i(cin) and load in the |cw(prt) function. ! 522: ! 523: |begin(computeroutput) ! 524: |i($) cin -i ! 525: |i(cin>) cin_load("prt.c"); ! 526: |i(cin>) ! 527: |end(computeroutput) ! 528: ! 529: |p ! 530: When |i(cin) loaded |cw(prt.c), it placed ! 531: the structure definition for |cw(node), ! 532: the |cw(#define)s, ! 533: and the definition for |cw(prt) ! 534: in a |cw(view) called |cw(prt.c). ! 535: A |cw(view) is the internal representation of a C source file |sp(Em dash) ! 536: |cw(#define)s, static variables and functions, and global declarations. ! 537: Outside |i(cin), the functions and data of a C program are packaged in a file; ! 538: inside |i(cin) they are contained in a |cw(view). ! 539: Earlier, when we typed declarations directly into the interpreter, ! 540: they were placed into a default |cw(view) called ``interactive mode''. ! 541: To use the declarations, ! 542: we need to be in the |cw(view) where they are stored. ! 543: So if we are sure we defined something, but |i(cin) can't find it, ! 544: we have probably gotten into the wrong |cw(view). ! 545: We can see what |cw(view)s are available by using the predefined function ! 546: |cw(cin_views), and we can change our |cw(view) by using |cw(cin_view). ! 547: ! 548: |begin(computeroutput) ! 549: |i(cin>) cin_views(); ! 550: |i( prt.c ! 551: |sp(*) interactive mode ! 552: cin>) cin_view("prt.c"); ! 553: |i(cin>) cin_views(); ! 554: |i( |sp(*) prt.c ! 555: interactive mode ! 556: cin>) ! 557: |end(computeroutput) ! 558: ! 559: |p ! 560: We have just seen that |cw(cin_views) marks our current |cw(view) ! 561: with an asterisk (|cw(*)). ! 562: Do not confuse the ``interactive mode'' session, ! 563: which is entered by typing |cw(cin -i), ! 564: with the default interactive mode |cw(view). ! 565: In interactive mode, ! 566: you may access any |cw(view) ! 567: and enter C expressions or declarations in the context of that |cw(view). ! 568: The interactive mode |cw(view) is simply the default |cw(view), ! 569: used for storing C declarations not associated with an external file. ! 570: |p ! 571: Let's use the declaration of |cw(struct node) ! 572: and the |cw(#define) for |cw(CONST) in the current or |cw(prt.c) |cw(view) ! 573: to initialize a |cw(struct node a1). ! 574: ! 575: |begin(computeroutput) ! 576: |i(cin>) struct node a1; ! 577: |i(cin>) a1.type = CONST; ! 578: |i(cin>) a1.value = "17"; ! 579: |i(cin>) ! 580: |end(computeroutput) ! 581: ! 582: |p ! 583: Although we said our typing would be prefect,|dagnote(as you can see it's not) ! 584: let's see what happens if we make the common mistake of passing ! 585: a structure instead of a pointer to the structure. ! 586: ! 587: |begin(computeroutput) ! 588: |i(cin>) prt(a1); ! 589: |i(prt.c: 7: null pointer access ! 590: breakpoint in function 'prt' at line 7 of file 'prt.c' ! 591: cin>) ! 592: |end(computeroutput) ! 593: ! 594: |p ! 595: At this point we can escape to our shell and print a numbered listing ! 596: of |cw(prt.c). ! 597: ! 598: |begin(computeroutput) ! 599: |i(cin>) system("pr -n -t prt.c"); ! 600: |i[ 1 #include "node.h" ! 601: 2 ! 602: 3 void ! 603: 4 prt(n) ! 604: 5 struct node |sp(*)n; ! 605: 6 { ! 606: 7 switch(n|cw(->)type) { ! 607: 8 ! 608: 9 default: ! 609: 10 prt(n|cw(->)left); ! 610: 11 printf("%s ", n|cw(->)value); ! 611: 12 prt(n|cw(->)right); ! 612: 13 break; ! 613: 14 ! 614: 15 case UMINUS: ! 615: 16 printf("%s ", n|cw(->)value); ! 616: 17 prt(n|cw(->)right); ! 617: 18 break; ! 618: 19 ! 619: 20 case CONST: ! 620: 21 case VAR: ! 621: 22 printf("%s ", n|cw(->)value); ! 622: 23 break; ! 623: 24 ! 624: 25 } ! 625: 26 } ! 626: cin>] ! 627: |end(computeroutput) ! 628: ! 629: |p ! 630: By a quick process of elimination, ! 631: we realize that ! 632: |cw(n) must be our problem, ! 633: because line 7 only has one pointer variable. ! 634: When you are in a |i(cin) breakpoint function, ! 635: |i(cin) computes the value of expressions in the current execution context ! 636: |sp(Em dash) an expression is evaluated just as though ! 637: it were placed in the program source at the current point of execution. ! 638: Thus, we can check to see if |cw(n) is zero by printing its value. ! 639: ! 640: |begin(computeroutput) ! 641: |i(cin>) printf("%d|sp(\)n", n); ! 642: |i(0) ! 643: |i(cin>) ! 644: |end(computeroutput) ! 645: ! 646: |p ! 647: If we failed to notice our ``passing ! 648: a structure instead of a pointer to the structure'' typo, ! 649: we might think that |cw(prt) got into trouble because it called itself. ! 650: We can check this by using the predefined function |cw(cin_where). ! 651: ! 652: |begin(computeroutput) ! 653: |i(cin>) cin_where(); ! 654: |i{cin_system() [prt.c:1] ! 655: prt(n = 0x0) [prt.c:7] ! 656: cin_system() [interactive mode:32] ! 657: cin>} ! 658: |end(computeroutput) ! 659: ! 660: This tells us that we are currently in |i(cin)'s breakpoint function, ! 661: |cw(cin_system), ! 662: looking at a call of |cw(prt) that was made from ! 663: interactive mode. ! 664: Because there are not two calls to |cw(prt), ! 665: we are assured it didn't recursively call itself. ! 666: |p ! 667: As you can see from the reference to line number 32, ! 668: the authors need to struggle further with what line numbers should mean in ! 669: interactive mode. ! 670: In particular, |cw(cin_where) and |cw(cin_break), ! 671: discussed later, ! 672: don't seem to use sensible line numbers for functions defined in interactive mode. ! 673: |p ! 674: Let's fix the problem with |cw(n) by modifying its value to be ! 675: |cw(&a1) and allowing the program to continue. ! 676: ! 677: |begin(computeroutput) ! 678: |i(cin>) n = &a1; ! 679: |i(cin>) cin_return(); ! 680: |i(17 cin>) ! 681: |end(computeroutput) ! 682: ! 683: Most debuggers don't permit you to continue after a serious error. ! 684: Whenever possible, ! 685: |i(cin) allows you to recover from an error ! 686: once you've taken corrective action. ! 687: If we don't want to take corrective action, ! 688: we can remove all calls of |i(cin)'s breakpoint function by calling |cw(exit). ! 689: ! 690: |begin(computeroutput) ! 691: |i(cin>) exit(0); ! 692: |i(cin>) ! 693: |end(computeroutput) ! 694: ! 695: Sometimes there is no way to fix the problem ! 696: and all we can do is |cw(cin_quit). ! 697: |p ! 698: Now let's define a function that creates a node, ! 699: placing the function in |cw(create.c). ! 700: We can enter our favorite editor by ! 701: ! 702: |begin(computeroutput) ! 703: |i(cin>) system("${EDITOR-/bin/ed} foo.c"); ! 704: |i(?foo.c) ! 705: |end(computeroutput) ! 706: ! 707: and printing out our file ! 708: ! 709: |begin(computeroutput) ! 710: |i(cin>) system("pr -n -t create.c"); ! 711: |i[ 1 #include <stdio.h> ! 712: 2 #include "node.h" ! 713: 3 ! 714: 4 struct node |sp(*) ! 715: 5 create(left, right, type, value) ! 716: 6 struct node |sp(*)left, |sp(*)right; ! 717: 7 char |sp(*)value; ! 718: 8 { ! 719: 9 struct node |sp(*)n; ! 720: 10 struct node |sp(*)memory(); ! 721: 11 ! 722: 12 if (n = memory( ! 723: 13 sizeof(struct node))) { ! 724: 14 n|cw(->)left = left; ! 725: 15 n|cw(->)right = right; ! 726: 16 n|cw(->)type = type; ! 727: 17 n|cw(->)value = value; ! 728: 18 return(n); ! 729: 19 } ! 730: 20 ! 731: 21 fprintf(stderr, ! 732: 22 "No memory to create a node|sp(\)n"); ! 733: 23 exit(1); ! 734: 24 } ! 735: cin>] cin_load("create.c"); ! 736: |i[create.c: 8: warning: function 'create' ! 737: has implicit return and 'return e;' (line 18) ! 738: cin>] ! 739: |end(computeroutput) ! 740: ! 741: |p ! 742: The error message warns us that the function |cw(create), ! 743: which is declared starting on line 8, ! 744: ends without returning a value. ! 745: This is fine, because the function |cw(exit) ! 746: would never let us get to the end of the routine. ! 747: |p ! 748: Now let's change our |cw(view) to the |cw(create.c) declarations, ! 749: make a few nodes, and print the expression tree ! 750: for |cw[2 * (17 - x)]. ! 751: We can represent the expression tree graphically as ! 752: ! 753: |begin(here) ! 754: |begin(picture) ! 755: scale=100 ! 756: box invis ht 96 wid 144 with .sw at 0,0 ! 757: "\fR\s10\&|sp(-) (t1)\f1\s0" at 122,42 ! 758: "\fR\s10\&x (t3)\f1\s0" at 160,-10 ! 759: "\fR\s10\&17 (t2)\f1\s0" at 80,-10 ! 760: line from 104,40 to 144,0 ! 761: line from 104,40 to 64,0 ! 762: "\fR\s10\&2 (t5)\f1\s0" at 24,26 ! 763: "\fR\s10\&|sp(*) (t4)\f1\s0" at 80,86 ! 764: line from 64,80 to 104,40 ! 765: line from 64,80 to 24,40 ! 766: |end(picture) ! 767: |end(here) ! 768: ! 769: where the labels in parentheses are the variable names for the |cw(struct node) ! 770: pointers ! 771: and the other symbols are the |cw(value)s for the |cw(node)s. ! 772: ! 773: |begin(computeroutput) ! 774: |i(cin>) cin_view("create.c"); ! 775: |i(cin>) struct node *t1, *t2, *t3; ! 776: |i(cin>) t3 = create((struct node *)0, ! 777: (struct node *)0, VAR, "x"); ! 778: |i(create.c: 12: warning: 'memory' undefined ! 779: breakpoint in function 'create' ! 780: at line 12 of file 'create.c' ! 781: cin>) ! 782: |end(computeroutput) ! 783: ! 784: |p ! 785: A common programming practice is to leave ``stubs'', ! 786: or functions to be defined at a later date. ! 787: |i(Cin) will stop when it encounters functions or variables that are not defined, ! 788: permitting you to define them. ! 789: Here |i(cin) has stopped because it can't find a definition for |cw(memory). ! 790: ! 791: |begin(computeroutput) ! 792: |i(cin>) struct node * ! 793: memory(n) ! 794: unsigned n; ! 795: { ! 796: struct node *malloc(); ! 797: return malloc(n); ! 798: } ! 799: |i(cin>) cin_return(); ! 800: |i(cin>) t2 = create((struct node *)0, ! 801: (struct node *)0, CONST, "17"); ! 802: |i(cin>) t1 = create(t2, t3, ADD, "+"); ! 803: |i(cin>) struct node *t4, *t5; ! 804: |i(cin>) t5 = create((struct node *)0, ! 805: (struct node *)0, CONST, "2"); ! 806: |i(cin>) t4 = create(t5, t1, MUL, "*"); ! 807: |i(cin>) prt(t4); ! 808: |i(2 |sp(*) 17 + x cin>) ! 809: |end(computeroutput) ! 810: ! 811: We'd like to emphasize that declarations can be mixed ! 812: with C expressions in interactive mode. ! 813: ! 814: |subsection(Exercise 2) ! 815: ! 816: Use |i(cin) and your favorite editor to enhance the |cw(prt) function ! 817: by adding parentheses to the output that show the nesting levels; ! 818: e.g., |cw<prt(t4)> should output |cw<( 2 * ( 17 + x ) )>. ! 819: ! 820: |section(Debugging With Breakpoints) ! 821: ! 822: We've already seen that any legal C expression can be used ! 823: when |i(cin) enters the breakpoint function, ! 824: but we haven't seen how to force |i(cin) ! 825: to enter a breakpoint function. ! 826: The easiest way is to use your editor and insert calls to the ! 827: predefined function |cw(cin_system) into your program. ! 828: ! 829: |begin(computeroutput) ! 830: 1 hello() ! 831: 2 { ! 832: 3 int i; ! 833: 4 i = 17; ! 834: 5 printf("hello, %d", i); ! 835: 6 cin_system(); ! 836: 7 printf("world %d times|sp(\)n", i); ! 837: 8 } ! 838: |end(computeroutput) ! 839: ! 840: |p ! 841: So if we were to load in |cw(hello.c) and run it: ! 842: ! 843: |begin(computeroutput) ! 844: cin> |i($) cin -i ! 845: |i(cin>) cin_load("hello.c"); ! 846: |i(cin>) hello(); ! 847: |i(breakpoint in function 'hello' at line 6 of file 'hello.c' ! 848: hello, 17cin>) i = 3; ! 849: |i(cin>) cin_return(); ! 850: |i(world 3 times ! 851: cin>) ! 852: |end(computeroutput) ! 853: ! 854: We'd be able to change the value of |cw(i), ! 855: or anything else, for that matter, ! 856: to whatever we want. ! 857: This is like placing |cw(printf)'s in our code that allow us ! 858: to print or modify anything. ! 859: |p ! 860: We can obtain a less permanent breakpoint using the predefined function ! 861: |cw(cin_break), and remove it using |cw(cin_unbreak). ! 862: Let's return to the original |cw(prt) routine contained in |cw(prt.c), ! 863: assert a breakpoint on line 7, ! 864: and run it with |cw(t4). ! 865: Because we've already debugged |cw(create) and |cw(memory), ! 866: we can use the C compiler to create object files for them, ! 867: continuing to debug |cw(prt) in source form. ! 868: By mixing object files with source files, we get the speed of compiled code ! 869: for functions that are debugged, ! 870: combined with the error checking of interpreted code ! 871: for functions we are testing. ! 872: ! 873: |begin(computeroutput) ! 874: |i($) cc -O -c create.c memory.c ! 875: |i(create.c: ! 876: memory.c: ! 877: $) cin -i prt.c create.o memory.o ! 878: |i(cin>) cin_view("prt.c"); ! 879: |i(cin>) struct node *t1, *t2, *t3; ! 880: |i(cin>) struct node *create(); ! 881: |i(cin>) #include <stdio.h> ! 882: |i(cin>) t3 = create((struct node *)0, ! 883: (struct node *)0, VAR, "x"); ! 884: |i(cin>) t2 = create((struct node *)0, ! 885: (struct node *)0, CONST, "17"); ! 886: |i(cin>) t1 = create(t2, t3, ADD, "+"); ! 887: |i(cin>) struct node *t4, *t5; ! 888: |i(cin>) t5 = create((struct node *)0, ! 889: (struct node *)0, CONST, "2"); ! 890: |i(cin>) t4 = create(t5, t1, MUL, "*"); ! 891: |i(cin>) ! 892: |end(computeroutput) ! 893: ! 894: |p ! 895: |cw(Cin_break) and |cw(cin_unbreak) both require us to be in the ! 896: |cw(view) where the function is defined and restrict us to functions ! 897: that are being interpreted. ! 898: We plan to enhance |i(cin) to remove these restrictions in the future. ! 899: ! 900: |begin(computeroutput) ! 901: |i(cin>) cin_break("prt", 7); ! 902: |i(breakpoint in function prt at line 7 ! 903: cin>) prt(t4); ! 904: |i(breakpoint in function 'prt' at line 7 of file 'prt.c' ! 905: cin>) cin_return(); ! 906: |i(breakpoint in function 'prt' at line 7 of file 'prt.c' ! 907: cin>) cin_return(); ! 908: |i(breakpoint in function 'prt' at line 7 of file 'prt.c' ! 909: 2 |sp(*) cin>) cin_where(); ! 910: |i{cin_system() [prt.c:1] ! 911: prt(n = 0x9382C) [prt.c:7] ! 912: prt(n = 0x93854) [prt.c:12] ! 913: cin_system() [stdio.h:50] ! 914: cin>} cin_unbreak("prt", 7); ! 915: |i(breakpoint removed from line 7 in prt ! 916: cin>) cin_return(); ! 917: |i(17 + x cin>) cin_quit(); ! 918: |i($) ! 919: |end(computeroutput) ! 920: ! 921: We plan to enhance |i(cin) by adding another argument to |cw(cin_break). ! 922: This argument will be a string that is executed when the breakpoint function ! 923: is entered. ! 924: This will let us set breakpoints that remove themselves, ! 925: print interesting things, ! 926: or even set other breakpoints. ! 927: ! 928: |section(Program Equals Data) ! 929: ! 930: A common trick of interpreters, ! 931: especially in the |s(LISP) world, ! 932: is to use the same representation for data handled by a program ! 933: and the program text itself. ! 934: |p ! 935: As our last programming task in this tutorial, ! 936: let's write a simple desk calculator. ! 937: To accomplish this, ! 938: we need to read a string from the user, ! 939: wrap it in a |cw(printf) C expression, ! 940: and pass it to the predefined function |cw(cin_eval). ! 941: ! 942: |begin(computeroutput) ! 943: |i($) cin -i -lm ! 944: |i(cin>) #include <stdio.h> ! 945: |i(cin>) #include <math.h> ! 946: |i(cin>) char buf[1024], buf2[1024]; ! 947: |i(cin>) while(gets(buf) != NULL) { ! 948: sprintf(buf2, ! 949: "printf(|sp(\)"%%g|sp(\)|sp(\)n|sp(\)",(double)(%s));", ! 950: buf); ! 951: cin_eval(buf2); ! 952: } ! 953: sqrt(2.0) * sqrt(2.0) ! 954: |i(2) ! 955: |end(computeroutput) ! 956: ! 957: In writing the |cw(printf) expression shown above, ! 958: the trickiest part was ensuring that the argument would be appropriate ! 959: to the |cw(g) format. ! 960: That's what the |cw<(double)> accomplished. ! 961: This example is also plagued with getting the right number of ! 962: |sp(\)s and |cw(%)s. ! 963: ! 964: |subsection(Exercise 3) ! 965: ! 966: Enhance the desk calculator C expression to remember the ! 967: last value as |cw(t) ! 968: and make it into a shell file that can be easily executed. ! 969: ! 970: |section(Bugs) ! 971: ! 972: |center(You find 'em. ! 973: We squash 'em!) ! 974: |p ! 975: The interactive mode is new with the 0.18 release of |i(cin). ! 976: It's hard to anticipate all the errors you may encounter, ! 977: and because of this we need your help to improve our tool. ! 978: Thus, we welcome bug reports sent to research!frodo. ! 979: Please include a short program along with the terminal input and ! 980: output that creates the |i(cin) problem. ! 981: ! 982: |section(Summary Of Predefined Functions) ! 983: ! 984: Several pre-defined functions are provided for the user, ! 985: where |i(name), |i(string), |i(file), |i(line), |i(func), |i(func_mod), ! 986: and |i(func_ref) are declared as: ! 987: ! 988: |begin(computeroutput) ! 989: char *|i(name), *|i(string), *|i(file); ! 990: int |i(line); ! 991: long (*|i(func))(), (*|i(func_mod))(), (*|i(func_ref))(); ! 992: |end(computeroutput) ! 993: ! 994: |blank_space(-1) ! 995: |begin(computeroutput) ! 996: void cin_bind(|i(name), |i(func)) ! 997: |end(computeroutput) ! 998: |blank_space(-1) ! 999: Set an alias of |i(name) for the function |i(func). ! 1000: ! 1001: |begin(computeroutput) ! 1002: int cin_break(|i(name), |i(line)) ! 1003: |end(computeroutput) ! 1004: |blank_space(-1) ! 1005: Set a breakpoint in function |i(name) at line number |i(line) in the current ! 1006: |cw(view). ! 1007: Returns 0 if breakpoint cannot be set. ! 1008: ! 1009: |begin(computeroutput) ! 1010: int cin_dump(|i(name)) ! 1011: |end(computeroutput) ! 1012: |blank_space(-1) ! 1013: Create an |cw(a.out) and place it in the file |i(name). ! 1014: Returns 0 if |i(name) cannot be created. ! 1015: ! 1016: |begin(computeroutput) ! 1017: int cin_eval(|i(string)) ! 1018: |end(computeroutput) ! 1019: |blank_space(-1) ! 1020: Execute the C statement |i(string) ! 1021: as if it were present in the program where the |cw(cin_eval) is located. ! 1022: Returns 0 if |i(string) could not be parsed. ! 1023: ! 1024: |begin(computeroutput) ! 1025: int cin_load(|i(file)) ! 1026: |end(computeroutput) ! 1027: |blank_space(-1) ! 1028: Load |i(file) into a new |cw(view), ! 1029: using the standard file-naming conventions for |i(cc)(1). ! 1030: Returns 0 if |i(file) can not be loaded. ! 1031: ! 1032: |begin(computeroutput) ! 1033: void cin_return() ! 1034: |end(computeroutput) ! 1035: |blank_space(-1) ! 1036: Return from a breakpoint. ! 1037: ! 1038: |begin(computeroutput) ! 1039: int cin_spy(|i(name), |i(func_mod), |i(func_ref)) ! 1040: |end(computeroutput) ! 1041: |blank_space(-1) ! 1042: Call the function |i(func_mod) whenever the variable |i(name) is modified. ! 1043: Call the function |i(func_ref) whenever the variable |i(name) is referenced. ! 1044: Either |i(func_mod) or |i(func_ref) can be |cw<(long (*)())0>. ! 1045: Returns 0 if there are no spies active. ! 1046: ! 1047: |begin(computeroutput) ! 1048: void cin_system() ! 1049: |end(computeroutput) ! 1050: |blank_space(-1) ! 1051: Enter ``interactive mode''. ! 1052: ! 1053: |begin(computeroutput) ! 1054: int cin_unbreak(|i(name), |i(line)) ! 1055: |end(computeroutput) ! 1056: |blank_space(-1) ! 1057: Remove a breakpoint in function |i(name) at line number |i(line) in the current ! 1058: |cw(view). ! 1059: Returns 0 if the breakpoint was not set. ! 1060: ! 1061: |begin(computeroutput) ! 1062: int cin_view(|i(name)) ! 1063: |end(computeroutput) ! 1064: |blank_space(-1) ! 1065: Change the current |cw(view) to |i(name). ! 1066: Returns 0 if the |cw(view) was not found. ! 1067: ! 1068: |begin(computeroutput) ! 1069: void cin_views() ! 1070: |end(computeroutput) ! 1071: |blank_space(-1) ! 1072: Print the available |cw(view)s. ! 1073: The current |cw(view) is marked with an asterisk (|cw(*)). ! 1074: ! 1075: |begin(computeroutput) ! 1076: void cin_whatis(|i(name)) ! 1077: |end(computeroutput) ! 1078: |blank_space(-1) ! 1079: Print the type of the variable |i(name). ! 1080: ! 1081: |begin(computeroutput) ! 1082: void cin_where() ! 1083: |end(computeroutput) ! 1084: |blank_space(-1) ! 1085: Print the trace of subroutine calls. ! 1086: ! 1087: |begin(computeroutput) ! 1088: void cin_quit() ! 1089: |end(computeroutput) ! 1090: |blank_space(-1) ! 1091: Exit |i(cin). ! 1092: ! 1093: |section(Summary Of Predefined Variables) ! 1094: ! 1095: Several predefined variables are provided for the user. ! 1096: ! 1097: |begin(computeroutput) ! 1098: extern char *cin_libpath ! 1099: |end(computeroutput) ! 1100: |blank_space(-1) ! 1101: A colon (|cw(:)) -separated list of libraries to search for undefined routines ! 1102: (defaults to libraries specified on the command line and ! 1103: ``|cw(-lc)''). ! 1104: ! 1105: |begin(computeroutput) ! 1106: extern char *cin_prompt ! 1107: |end(computeroutput) ! 1108: |blank_space(-1) ! 1109: The ``interactive mode'' prompt (default ``|cw(cin>) ''). ! 1110: ! 1111: |section(Answers) ! 1112: ! 1113: |subsection(Answer 1) ! 1114: ! 1115: |blank_space(-1) ! 1116: |begin(computeroutput) ! 1117: |i($) cin -i ! 1118: |i(cin>) int i; ! 1119: |i(cin>) for (i = 20; i <= 30; ++i) ! 1120: printf("%d %g|sp(\)n", ! 1121: i, 9. / 5. * i + 32.); ! 1122: |i(20 68 ! 1123: 21 69.8 ! 1124: 22 71.6 ! 1125: 23 73.4 ! 1126: 24 75.2 ! 1127: 25 77 ! 1128: 26 78.8 ! 1129: 27 80.6 ! 1130: 28 82.4 ! 1131: 29 84.2 ! 1132: 30 86 ! 1133: cin>) void main() ! 1134: { ! 1135: int i; ! 1136: ! 1137: for (i = 20; i <= 30; ++i) ! 1138: printf("%d %g|sp(\)n", ! 1139: i, 9. / 5. * i + 32.); ! 1140: } ! 1141: |i(cin>) main(); ! 1142: |i(20 68 ! 1143: 21 69.8 ! 1144: 22 71.6 ! 1145: 23 73.4 ! 1146: 24 75.2 ! 1147: 25 77 ! 1148: 26 78.8 ! 1149: 27 80.6 ! 1150: 28 82.4 ! 1151: 29 84.2 ! 1152: 30 86 ! 1153: cin>) cin_quit(); ! 1154: |i($) ! 1155: |end(computeroutput) ! 1156: |blank_space(-1) ! 1157: ! 1158: |subsection(Answer 2) ! 1159: ! 1160: |blank_space(-1) ! 1161: |begin(computeroutput) ! 1162: void ! 1163: prt(n) ! 1164: struct node *n; ! 1165: { ! 1166: switch(n->type) { ! 1167: ! 1168: default: ! 1169: printf("( "); ! 1170: prt(n->left); ! 1171: printf("%s ", n->value); ! 1172: prt(n->right); ! 1173: printf(") "); ! 1174: break; ! 1175: ! 1176: case UMINUS: ! 1177: printf("%s ", n->value); ! 1178: prt(n->right); ! 1179: break; ! 1180: ! 1181: case CONST: ! 1182: case VAR: ! 1183: printf("%s ", n->value); ! 1184: break; ! 1185: ! 1186: } ! 1187: } ! 1188: |end(computeroutput) ! 1189: |blank_space(-1) ! 1190: ! 1191: |subsection(Answer 3) ! 1192: ! 1193: |blank_space(-1) ! 1194: |begin(computeroutput) ! 1195: (echo 'extern char *cin_prompt; ! 1196: cin_prompt=""; ! 1197: #include <stdio.h> ! 1198: #include <math.h> ! 1199: char buf[1024], buf2[1024]; ! 1200: double t; ! 1201: while(gets(buf) != NULL) { ! 1202: sprintf(buf2, ! 1203: "printf(|sp(\)"%%g|sp(\)|sp(\)n|sp(\)",t=(double)(%s));", ! 1204: buf); ! 1205: cin_eval(buf2); ! 1206: }'; cat ) | cin -i ! 1207: |end(computeroutput) ! 1208: |blank_space(-1) ! 1209: ! 1210: |section(Acknowledgements) ! 1211: ! 1212: We thank Brian Kernighan ! 1213: for permission to draw inspiration and borrow phrases from his editor tutorial. ! 1214: We also thank ! 1215: Sumit Bandyopadhyay, ! 1216: Bill Carpenter, ! 1217: Paul De Bra, ! 1218: Alan Hastings, ! 1219: Jonathan Helfman, ! 1220: Andrew Hume, ! 1221: Leonard Kasday, ! 1222: Brian Kernighan, ! 1223: Tom Kirk, ! 1224: David Korn, ! 1225: Lisa Kowalski, ! 1226: Richard Maus, ! 1227: Lawrence Mayka, ! 1228: Doug McIlroy, ! 1229: Marcel Meth, ! 1230: Eric Muehrcke, ! 1231: Jishnu Mukerji, ! 1232: Rob Murray, ! 1233: Sharon Peeters, ! 1234: Mike Riley, ! 1235: Larry Satz, ! 1236: Judy Schmidt, ! 1237: Timothy Schroeder, ! 1238: Jonathan Shapiro, ! 1239: Joe Steffen, ! 1240: Andy Tripp, ! 1241: Tom Walsh, ! 1242: William Wetzel, ! 1243: and ! 1244: Myron Wish ! 1245: for useful comments on previous versions of this paper. ! 1246: ! 1247: |comment< ! 1248: |style(one_column) ! 1249: ! 1250: |signature(MH-11229-TJK/HHG/JJP-tjk/hhg/jjp) ! 1251: > ! 1252: ! 1253: |comment< ! 1254: |notation(Att. ! 1255: References) ! 1256: ! 1257: |other ! 1258: > ! 1259: ! 1260: |reference_placement ! 1261: ! 1262: |keywords(Rapid Prototyping, ! 1263: Incremental Update, ! 1264: C Programming) ! 1265: ! 1266: |comment< ! 1267: |mercury(cmp, elc) ! 1268: ! 1269: |att(is_release yes) ! 1270: ! 1271: |distribute_complete_memo(Executive Directors 112 ! 1272: Directors 112 ! 1273: Department Heads 1122 ! 1274: Sumit Bandyopadhyay ! 1275: Bill Carpenter ! 1276: Paul De Bra ! 1277: Alan Hastings ! 1278: Jonathan Helfman ! 1279: Yean-Ming Huang ! 1280: Andrew Hume ! 1281: Leonard Kasday ! 1282: Brian Kernighan ! 1283: Tom Kirk ! 1284: David Korn ! 1285: Lisa Kowalski ! 1286: Richard Maus ! 1287: Lawrence Mayka ! 1288: Doug McIlroy ! 1289: Marcel Meth ! 1290: Eric Muerhcke ! 1291: Jishnu Mukerji ! 1292: Rob Murray ! 1293: Sharon Peeters ! 1294: Mike Riley ! 1295: Larry Satz ! 1296: Judy Schmidt ! 1297: Timothy Schroeder ! 1298: Jonathan Shapiro ! 1299: Joe Steffen ! 1300: Andy Tripp ! 1301: Tom Walsh ! 1302: William Wetzel) ! 1303: ! 1304: |distribute_cover_sheet(A. A. Penzias ! 1305: 1122 MTS ! 1306: Miguel Abdo ! 1307: Tom Beattie ! 1308: Jim Burnash ! 1309: Tom Cargill ! 1310: John Carter ! 1311: Craig Cleaveland ! 1312: Don deCourcelle ! 1313: Helen Diamantidis ! 1314: Laura Eaves ! 1315: Faiq Fazal ! 1316: Tom Foregger ! 1317: Carol Franklin ! 1318: Narain Gehani ! 1319: Richard Greer ! 1320: John Gregg ! 1321: Jim Grenier ! 1322: Inars Gruntals ! 1323: Roy Harkness ! 1324: Kurt Haserodt ! 1325: Alan Hewett ! 1326: Viet Hoang ! 1327: James Holmes ! 1328: Mike Hudson ! 1329: Douglas Johnston ! 1330: Jon Kaplowitz ! 1331: Kevin Kinnear ! 1332: Peter Kirslis ! 1333: Balachander Krishnamurthy ! 1334: Ajoy Kumar ! 1335: David Lubinsky ! 1336: Robert Lyons ! 1337: John Malleo-Roach ! 1338: Pat McGowan ! 1339: Al McPherson ! 1340: Douglas Miller ! 1341: Datta Miruke ! 1342: John Mocenigo ! 1343: Dave Neal ! 1344: Eric Olson ! 1345: Joseph Patterson ! 1346: Virginia Piccininni ! 1347: Thomas Pisciotta ! 1348: David Potter ! 1349: Demetri Prountzos ! 1350: Benjamin Reytblat ! 1351: Ernie Rice ! 1352: James Rowland ! 1353: Ed Schan ! 1354: William Schell ! 1355: Carl Seaquist ! 1356: Steve Shepherd ! 1357: John Sherman ! 1358: Tyrone Shiu ! 1359: Les Shupe ! 1360: David Smull ! 1361: G. Mark Stewart ! 1362: Art Storm ! 1363: Rich Struse ! 1364: Mark Swartz ! 1365: Rick Thomas ! 1366: Tim Thompson ! 1367: Peter Ting ! 1368: Gregg Vesonder ! 1369: Yu-Lien Yen ! 1370: John Young ! 1371: Avi Zahavi) ! 1372: ! 1373: |add_totals(other 4) ! 1374: ! 1375: |cover_sheet ! 1376: >
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.