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