home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / compiler / small_c / scinter / prg.man < prev    next >
Encoding:
Text File  |  1979-12-31  |  165.5 KB  |  5,160 lines

  1.           
  2.           
  3.           
  4.           
  5.           
  6.           
  7.           
  8.           
  9.           
  10.           
  11.           
  12.           
  13.                                                      ii
  14.                                                     iiii
  15.                                                      ii
  16.                          sss           cccc             
  17.                        ssssssss      cccccccc      iiiii
  18.                       sss    sss    ccc    ccc     iiiii
  19.                       sssss        ccc               iii
  20.                        sssss       ccc               iii
  21.                           sssss    ccc               iii
  22.                       sss    sss    ccc    ccc       iii
  23.                        ssssssss      cccccccc     iiiiiiiii
  24.                          ssss          cccc       iiiiiiiii
  25.           
  26.           
  27.                              Small C Interpreter
  28.                            Version 1.3 for MS-DOS
  29.                         Copyright (C) 1986 Bob Brodt
  30.           
  31.           
  32.                             Programmer's Manual
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.      Small C Interpreter                                Programmer's Manual
  62.  
  63.  
  64.      1. Introduction to SCI Programming 
  65.  
  66.  
  67.                This section of the manual is a tutorial introduction 
  68.           to the C language.  If you have a casual knowledge of BASIC 
  69.           and understand some of the fundamental concepts of 
  70.           programming, you should have no difficulty in following 
  71.           along.  This tutorial is designed to be used along with SCI, 
  72.           so get out your working copy of the SCI distribution 
  73.           diskette.  You did make a backup copy, didn't you?  If not, 
  74.           DO NOT PASS GO, DO NOT COLLECT $200 until you've read and 
  75.           followed the instructions in the Introduction section of the 
  76.           SCI User's Manual!  
  77.  
  78.                Now go ahead and start up SCI. The interpreter should 
  79.           be loading the default "shell" file, SHELL.SCI. This file 
  80.           simply contains a C program that is run by the SCI 
  81.           interpreter.  It performs several functions (most of which 
  82.           shall remain invisible to you for the moment), but the most 
  83.           important is to allow you to write and test SCI programs 
  84.           immediately.  After the interpreter has started up, you 
  85.           should see SCI's program identification banner and a 
  86.           greater-than symbol (>), like this: 
  87.  
  88.  
  89.                A> SCI
  90.                Small C Interpreter, V1.3 15Mar86 Copyright (C) 1986 Bob Brodt
  91.                Small C Shell, V1.3 15Mar86 Copyright (C) 1986 Bob Brodt
  92.                >
  93.  
  94.  
  95.                The ">" tells you that SCI is now ready to accept input 
  96.           from you.  One of the nicest features of SCI is its ability 
  97.           to immediately perform any C statement that you type.  As 
  98.           you will learn later, every C statement produces a value as 
  99.           a side-effect.  One of the functions of SHELL.SCI is to 
  100.           print this value as a decimal number after the statement has 
  101.           been executed.  Thus, you could enter some arithmetic 
  102.           expression like the following: 
  103.  
  104.  
  105.                > 2+2;
  106.                4
  107.                >
  108.  
  109.  
  110.                and have the SCI shell print the result, just like 
  111.           BASIC.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.                                      - 1 -
  119.  
  120.  
  121.      Small C Interpreter                                Programmer's Manual
  122.  
  123.  
  124.      2. SCI Statement Structure 
  125.  
  126.  
  127.                In the above example, notice the semicolon at the end 
  128.           of the line.  The C language allows you to write programs 
  129.           without regard to "white space" (spaces, tabs and ends of 
  130.           lines).  This means that the components of program 
  131.           statements can be seperated by as many spaces or tabs as you 
  132.           like; program lines can be grouped together seperated from 
  133.           the rest of the program by blank lines, to show the reader 
  134.           that they perform a discrete function; you can indent groups 
  135.           of lines following a program looping statement to show where 
  136.           the loop starts and ends.  By allowing you to "sculpture" 
  137.           your program like this, C lets you write very easy to read 
  138.           and understand programs.  This is very much in contrast to 
  139.           BASIC which requires every program statement to start with a 
  140.           line number, followed by a space and then the statement all 
  141.           on a single line.  Because C is such a free-form language it 
  142.           would have a difficult time recognizing the end of a 
  143.           statement without some kind of "end-of-statement" marker.  
  144.           This is the purpose of the semicolon.  
  145.  
  146.                Now we're going to confuse you even further by telling 
  147.           you that SCI doesn't need a semicolon at the end of a 
  148.           statement!  Because it's an interpreter, SCI recognizes 
  149.           either the end of a line or a semicolon as an 
  150.           end-of-statement marker.  In fact, if a statement spills 
  151.           over onto another program line, SCI will complain - it 
  152.           requires that every statement be completely contained on one 
  153.           line.  This restriction was imposed by the fact that SCI is 
  154.           an interpreter and not a compiler.  This is an important 
  155.           difference between "SCI C" and "standard C" (which allows a 
  156.           single statement to be spread out over several lines).  So 
  157.           if you are an experience "C hacker", please be aware of this 
  158.           fact.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.                                      - 2 -
  179.  
  180.  
  181.      Small C Interpreter                                Programmer's Manual
  182.  
  183.  
  184.      3. SCI Program Structure 
  185.  
  186.  
  187.                When learning a new programming language, it's always 
  188.           helpful to recall fundamentals and ask yourself the question 
  189.           "what is a program?".  Simply stated, a program is a list of 
  190.           instructions that tell the computer exactly what to do.  A 
  191.           program written in the BASIC language is an ideal example of 
  192.           this concept; a list of instructions.  The instructions are 
  193.           numbered to make it easy to see the order in which they'll 
  194.           be performed.  Let's examine a fragment from a BASIC program 
  195.           and identify some of its key components.  
  196.  
  197.  
  198.                100 REM *** sort a list of numbers in ascending order ***
  199.                110 DIM NUM(100),RSP$(80)
  200.                120 REM get the unsorted number list
  201.                     .
  202.                     .
  203.                     .
  204.                220 REM got 'em, now sort 'em then print 'em
  205.                230 GOSUB 500
  206.                240 FOR I=1 TO 100
  207.                250    PRINT NUM(I)
  208.                260 NEXT I
  209.                270 PRINT "Got another list to sort?";
  210.                280 INPUT RSP$
  211.                290 IF RSP$="Y" THEN GOTO 120
  212.                300 END
  213.                500 REM *** bubble sort routine ***
  214.                510 REM sorts the numbers in the array "NUM"
  215.                     .
  216.                     .
  217.                     .
  218.                600 RETURN
  219.  
  220.  
  221.                Even the novice BASIC programmer can glance at this 
  222.           program fragment and tell what's happening: it starts with 
  223.           line 100, which is a note to the (human) reader telling him 
  224.           what the program intends to do - sort a bunch of numbers in 
  225.           ascending order.  Line 110 tells the computer to reserve 
  226.           some memory storage we'll need later.  Remember that BASIC 
  227.           allows variables to be "known" to every instruction in the 
  228.           program.  Thus, you (the programmer) can not effectively 
  229.           control and limit access to variables.  This makes it 
  230.           difficult at times to determine where in the program a 
  231.           variable is being set when it shouldn't be.  This is a very 
  232.           important difference between BASIC and C, as you will find 
  233.           out later.  
  234.  
  235.                The word "GOSUB" at line 230 tells the computer to hold 
  236.  
  237.  
  238.                                      - 3 -
  239.  
  240.  
  241.      Small C Interpreter                                Programmer's Manual
  242.  
  243.  
  244.           its place at the current location in the program, then jump 
  245.           to instruction number 500.  The "RETURN" at line 600 
  246.           corresponds to the "GOSUB" and tells the computer to 
  247.           continue with the instruction following the "GOSUB". Notice 
  248.           that the set of instructions from line 500 to 600 are 
  249.           general-purpose in nature and could possibly be used in 
  250.           another BASIC program that required a number sorting 
  251.           function.  However, to interface this sub-program to another 
  252.           program would probably require modifications to either the 
  253.           other program or the sub-program, or both.  This makes the 
  254.           thought of extracting the number sorting function somewhat 
  255.           less attractive.  
  256.  
  257.                Now look at the instructions from line 270 to 290. 
  258.           Essentially, these ask the program user if there are any 
  259.           more numbers to sort, and jump back to the beginning of the 
  260.           program to start the process all over again.  But, what if 
  261.           the programmer decides at some later time to modify the 
  262.           program and accidentally deletes line 120 - the target of 
  263.           the "GOTO" instruction at 290. BASIC would be totally 
  264.           confused, since it wouldn't be able to find line 120 
  265.           anymore.  Although numbering program instructions, like 
  266.           BASIC does, is very nice and neat and makes a program easy 
  267.           for the human reader to follow, it can become unmanageable 
  268.           as the program grows in complexity.  
  269.  
  270.                Now let's take a look at the comparable program 
  271.           fragment written in C.  Please don't be concerned with the 
  272.           details of this program at the moment, but rather focus on 
  273.           the overall structure: 
  274.  
  275.  
  276.                # *** sort a list of numbers in ascending order ***
  277.                main()
  278.                {
  279.                     char num[100], rsp[80];
  280.                
  281.                     while ( 1 )
  282.                     {
  283.                          # get the unsorted number list
  284.                               .
  285.                               .
  286.                               .
  287.                          # got 'em, now sort 'em then print 'em
  288.                          sort( num );
  289.                          i=0;
  290.                          while ( i<100 )
  291.                          {
  292.                               printf( "%d\n", num[i] );
  293.                               ++i;
  294.                          }
  295.                          puts( "Got another list to sort?" );
  296.  
  297.  
  298.                                      - 4 -
  299.  
  300.  
  301.      Small C Interpreter                                Programmer's Manual
  302.  
  303.  
  304.                          gets( rsp )
  305.                          if ( rsp[0] != 'Y' )
  306.                               break;
  307.                     }
  308.                }
  309.                sort( numlist )
  310.                char numlist[];
  311.                {
  312.                     # bubble sort routine
  313.                          .
  314.                          .
  315.                          .
  316.                }
  317.  
  318.  
  319.                The first thing that strikes the BASIC programmer when 
  320.           he looks at a C program is the absence of line numbers!  The 
  321.           C language relies purely on the location of statements 
  322.           within a program to determine the order of program 
  323.           execution.  
  324.  
  325.                In the above example, notice the presence of the 
  326.           matching left and right curly braces ({ and }). These serve 
  327.           to bind together logical sections of the program.  In 
  328.           particular, notice the first "{" (following "main()") and 
  329.           its partner towards the end of the program.  These 
  330.           particular matching braces are used to "bind" everything 
  331.           between them to make one functional unit.  This functional 
  332.           unit is called a "function" in C.  Each function can be 
  333.           thought of as an autonomous entity - everything within the 
  334.           function is accessible only to statements within that 
  335.           function.  The name of the function can be found immediately 
  336.           before the first "{", in this case, the function's name is 
  337.           "main". Another function can be found towards the end of the 
  338.           program, its name is "sort".  
  339.  
  340.                So, in contrast to BASIC, a C program is a collection 
  341.           of these modular functions rather than just a sequential 
  342.           list of instructions.  
  343.  
  344.  
  345.  
  346.  
  347.  
  348.  
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356.  
  357.  
  358.                                      - 5 -
  359.  
  360.  
  361.      Small C Interpreter                                Programmer's Manual
  362.  
  363.  
  364.      4. Functions 
  365.  
  366.  
  367.                Think of functions as a kind of "black box" machine; 
  368.           raw materials, in the form of information, goes into one end 
  369.           of the machine and a final product comes out of the other 
  370.           end.  The inner workings of the machine are hidden and we 
  371.           don't really care to know how the machine works, as long as 
  372.           the final product is what we expected from the raw materials 
  373.           supplied.  
  374.  
  375.                In C, the "raw materials" passed to a function are 
  376.           known as the function's "arguments" and the "final product" 
  377.           is called the function's "return value".  C allows you to 
  378.           pass as many arguments to a function as needed, but the 
  379.           function always returns one and only one value.  In the 
  380.           section on Variables we will see how a function can be made 
  381.              ____                                   
  382.           to seem to return more than one value.  
  383.  
  384.                To get SCI to execute the statements within a 
  385.           particular function, all you have to do is mention the 
  386.           function's name.  In the program fragment shown above, you 
  387.           would type either "main()", or "sort()" at the SCI prompt.  
  388.           The parentheses following a function's name serve two 
  389.           purposes: they distinguish the entity as being the name of a 
  390.           function as opposed to a variable; and they show SCI where 
  391.           the function's arguments start and end.  If a function does 
  392.           not require any arguments (as in "main()" above), you still 
  393.           need to supply the left and right parentheses.  If a 
  394.           function requires more than one argument, each argument is 
  395.           seperated from the preceding one with a comma (,) like so: 
  396.  
  397.  
  398.                func( 23, 15, 34 )
  399.  
  400.  
  401.                Note that the spaces are optional!  
  402.  
  403.  
  404.      4.1. Library Functions 
  405.  
  406.  
  407.                Beyond using it as a rather dumb integer calculator, 
  408.           you can use the SCI shell to test out any valid C statement 
  409.           with support from a large collection of built-in functions.  
  410.           As you work through this tutorial, you will be introduced to 
  411.           many of these, refered to hereafter as "Library Functions" 
  412.           (see the section on Library Functions for more details).  
  413.           You may, if you like, think of the Library Functions as 
  414.           being analogous to BASIC's built-in commands like "PRINT" 
  415.           and "INPUT". Most of the Library Functions are similar to 
  416.           those shipped with "industrial strength" C compilers, so 
  417.  
  418.  
  419.                                      - 6 -
  420.  
  421.  
  422.      Small C Interpreter                                Programmer's Manual
  423.  
  424.  
  425.           many of the programs you write under SCI should be 
  426.           transportable with some minor changes.  
  427.  
  428.  
  429.      4.1.1. putd() 
  430.  
  431.  
  432.                The Library Function "putd()" prints a number, or the 
  433.           results of a calculation on the console screen.  Try 
  434.           entering the following commands from the shell: 
  435.  
  436.  
  437.                putd(123)
  438.                putd( 235 + 12370 )
  439.  
  440.  
  441.                In the first example, the argument passed to "putd()" 
  442.           is the number 123.  The function should have printed "123" 
  443.           on the console screen.  In the second example, the argument 
  444.           is the sum of 235 and 12370. Note that this calculation is 
  445.           performed first, then the result is passed to "putd()" for 
  446.           printing.  
  447.  
  448.                Below the numbers that were printed by "putd()" you 
  449.           should have seen a zero printed as well.  This zero is the 
  450.           value returned by "putd()" and was printed by the shell.  In 
  451.           this case, the return value of a function was not 
  452.           particularly useful.  We were more interested in the 
  453.           side-effect of this function, namely the displaying of a 
  454.           number on the screen.  
  455.  
  456.  
  457.      4.1.2. getchar() 
  458.  
  459.  
  460.                The Library Function "getchar()" waits for a single 
  461.           keyboard key to be pressed, then returns the value (in 
  462.           ASCII) of that key.  At the shell prompt, try typing 
  463.           "getchar()", hit a carriage return and then hit the letter 
  464.           'a' key.  You should see the number 97 printed by the shell, 
  465.           the ASCII value in decimal of the character 'a'.  
  466.  
  467.                Unlike "putd()", this function required no arguments 
  468.           and returned a useful value.  
  469.  
  470.  
  471.      4.1.3. puts() 
  472.  
  473.  
  474.                The function "puts()" is used to print a sequence of 
  475.           characters (known in C jargon as a "string") on the 
  476.           console.  A string is represented in C as a bunch of 
  477.  
  478.  
  479.                                      - 7 -
  480.  
  481.  
  482.      Small C Interpreter                                Programmer's Manual
  483.  
  484.  
  485.           characters enclosed in quotes ("), just as in BASIC. Try the 
  486.           following command, and be careful to type the string exactly 
  487.           as it appears here: 
  488.  
  489.  
  490.                puts("hello, world\n")
  491.  
  492.  
  493.                Look closely at the string again and notice the 
  494.           backslash (\) just before the letter 'n'. This two-character 
  495.           combination (\n) is standard C shorthand notation for a 
  496.           "newline" character.  Newlines have the effect of performing 
  497.           a cariage return plus linefeed on the console.  Had we 
  498.           omitted the "\n" from the string, "puts()" would have just 
  499.           printed "hello, world" and left the cursor on the same line, 
  500.           after the "d" in "world".  SCI provides other similar 
  501.           shorthand notations, which will be explained in a later 
  502.           section.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.  
  539.                                      - 8 -
  540.  
  541.  
  542.      Small C Interpreter                                Programmer's Manual
  543.  
  544.  
  545.      5. Your First Programs 
  546.  
  547.  
  548.                Now it's time to write your first program.  If you 
  549.           haven't already done so, read the Editor section of the 
  550.           User's Manual and perform the installation as required for 
  551.           your particular computer.  If you are unsuccessful in 
  552.           getting the editor to work properly, you can create the 
  553.           sample programs with your favorite text editor, then start 
  554.           up SCI and load the program file.  This will be tedious and 
  555.           time consuming, but it may just give you enough 
  556.           understanding of C to perform the editor installation 
  557.           properly.  If all else fails, appeal to the author for 
  558.           help!  
  559.  
  560.  
  561.      5.1. Hello again, world!  
  562.  
  563.  
  564.                Either using the built-in editor or a seperate text 
  565.           editor, create the following program: 
  566.  
  567.  
  568.                hi()
  569.                {
  570.                     puts("hello, world\n");
  571.                }
  572.  
  573.  
  574.                Now, from the shell, type the name of the function, 
  575.           "hi()". You should see the following on your screen: 
  576.  
  577.  
  578.                > hi()
  579.                hello world
  580.                0
  581.                >
  582.  
  583.  
  584.                If instead you are rewarded with an error message 
  585.           followed by a question mark, you did something wrong!  Hit a 
  586.           carriage return or two to get back to the shell's ">" 
  587.           prompt, go back into the editor, fix the mistake and try it 
  588.           again.  
  589.  
  590.                Whether you realize it or not, this exercise is an 
  591.           important first step for learning a new programming 
  592.           language.  It teaches you all of the routine motions you 
  593.           will be going through to write programs and gives you 
  594.           confidence to continue on.  
  595.  
  596.  
  597.  
  598.  
  599.                                      - 9 -
  600.  
  601.  
  602.      Small C Interpreter                                Programmer's Manual
  603.  
  604.  
  605.      5.2. Fahrenheit to Celsius 
  606.  
  607.  
  608.                Next, type in the following sample program: 
  609.  
  610.  
  611.                fahr(celsius)
  612.                {
  613.                     return 9 * celsius / 5 + 32;
  614.                }
  615.  
  616.  
  617.                This is a simple celsius to fahrenheit temperature 
  618.           conversion function.  Notice here the symbols for 
  619.           multiplication (*) and division (/) are the same as in most 
  620.           other programming languages.  
  621.  
  622.                Try executing this function with a few different 
  623.           celsius values.  Each time the argument is converted to 
  624.           fahrenheit and is returned to the shell to be printed.  
  625.  
  626.                As an exercise, modify the program to print the 
  627.           fahrenheit value and return a value of zero!  
  628.  
  629.  
  630.  
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.                                      - 10 -
  660.  
  661.  
  662.      Small C Interpreter                                Programmer's Manual
  663.  
  664.  
  665.      6. Statements: Simple and Compound 
  666.  
  667.  
  668.                In C, a "statement" is just what you might expect; an 
  669.           imperative instruction to the computer to perform some 
  670.           calculation.  Statements are generally some kind of 
  671.           arithmetic expression followed by a semicolon (or the end of 
  672.           line in SCI) - we have encountered them before.  The C 
  673.           language also allows you to group together several of these 
  674.           "simple" statements and treat them as a single "compound" 
  675.           statement.  This is done by placing left and right curly 
  676.           braces ({ and }) around the simple statements.  Let's look 
  677.           at the example below: 
  678.  
  679.  
  680.                {puts("hello");puts("world\n");}
  681.  
  682.  
  683.                Here, everything within the left and right braces and 
  684.           the braces themselves are treated as a single statement in 
  685.           C.  The C language also lets us write the above statement 
  686.           like this: 
  687.  
  688.  
  689.                {
  690.                     puts( "hello" );
  691.                     puts( "world\n" );
  692.                }
  693.  
  694.  
  695.                Notice that the program becomes much easier to read 
  696.           when each statement is written on a seperate line.  Also 
  697.           notice that we have indented the two simple statements from 
  698.           the braces.  Indenting is the accepted way of conveying the 
  699.           intended structure of a program.  We are in effect saying 
  700.           that these two lines "belong together" and should be treated 
  701.           as a single unit.  
  702.  
  703.                The compound statement in the above example was 
  704.           obviously created for demonstration purposes only.  If it 
  705.           had been encountered by itself in a real program, the braces 
  706.           would have been superfluous and would not have altered the 
  707.           behavior of the program.  However, earlier we encountered an 
  708.           instance where the curly braces were required, namely 
  709.           immediately following a function definition.  Later on when 
  710.           we discuss program flow control, we will again sing the 
  711.           praises of compound statements.  
  712.  
  713.                We will now make just one more point concerning 
  714.           compound statements and the SCI shell.  From the shell, type 
  715.           the following two statements: 
  716.  
  717.  
  718.  
  719.                                      - 11 -
  720.  
  721.  
  722.      Small C Interpreter                                Programmer's Manual
  723.  
  724.  
  725.                > puts("hello"); puts(" world");
  726.                > {puts("hello"); puts(" world);}
  727.  
  728.  
  729.                In the first instance, you saw that only the word 
  730.           "hello" was printed followed by the shell's ">" prompt.  
  731.           This is because the interpreter executes only the first 
  732.           statement it finds in the input line buffer.  Since a 
  733.           statement is terminated by a semicolon, the second call to 
  734.           "puts" was never seen.  In the second example, the 
  735.           interpreter saw the left curly brace, recognized the entire 
  736.           line as a single statement, and executed both calls to 
  737.           "puts()".  
  738.  
  739.  
  740.      6.1. Comment Statements 
  741.  
  742.  
  743.                Comment statements are completely ignored by C and may 
  744.           be used liberally anywhere within a program for 
  745.           documentation purposes.  Standard C uses the two-character 
  746.           combinations /* (pronounced "slash-star") and */ to mark the 
  747.           beginning and ending of comment statements: 
  748.  
  749.  
  750.                2 + /* this is a comment */ 2 + 2;
  751.  
  752.  
  753.                The /* and */ need not necessarily be on the same 
  754.           program line, as for example: 
  755.  
  756.  
  757.                2 + 2 + 2;
  758.                /*
  759.                this is a comment
  760.                */
  761.  
  762.  
  763.                SCI uses the number symbol (#) to introduce comment 
  764.           statements.  A comment in SCI begins with a # and ends at 
  765.           the end of the line.  Being an interpreter, SCI required 
  766.           that comments appear on a single line, so only a comment 
  767.           start symbol was required.  The above example might appear 
  768.           in SCI like this: 
  769.  
  770.  
  771.                2 + 2 + 2;
  772.                #
  773.                # this is a comment
  774.                #
  775.  
  776.  
  777.  
  778.  
  779.                                      - 12 -
  780.  
  781.  
  782.      Small C Interpreter                                Programmer's Manual
  783.  
  784.  
  785.                Be careful when placing comments because everything to 
  786.           the right of the first # symbol on the line is ignored by 
  787.           SCI.  
  788.  
  789.  
  790.                2 + # this is a comment # 2 + 2;
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.                                      - 13 -
  840.  
  841.  
  842.      Small C Interpreter                                Programmer's Manual
  843.  
  844.  
  845.      7. Expressions 
  846.  
  847.  
  848.                Expressions can be thought of as components of a C 
  849.           statement - the values and operators that, when evaluated, 
  850.           yield a result.  The most common example that comes to mind 
  851.           are arithmetic expressions: 
  852.  
  853.  
  854.                2 + 3 - 5
  855.  
  856.  
  857.                An expression becomes a statement if we simply tack a 
  858.           semicolon at the end of it, thus: 
  859.  
  860.  
  861.                2 + 3 - 5;
  862.  
  863.  
  864.  
  865.      7.1. Operators 
  866.  
  867.  
  868.                Since C provides a plethora of operators, we will not 
  869.           discuss them all in this section but rather introduce them 
  870.           as they become relavent to the discussion.  If you have 
  871.           burning desire to discover all of C's operators, see the 
  872.           Appendix.  First, we will define some commonly used terms.  
  873.  
  874.  
  875.      7.1.1. Binary Operators 
  876.  
  877.  
  878.                The term "binary operator" does not refer to bits and 
  879.           bytes but rather to the class of operators that require two 
  880.           (hence "binary") operands.  Some of these you have probably 
  881.           already seen if you are familiar with other programming 
  882.           languages, like the addition (+), subtraction (-), 
  883.           multiplication (*) and division (/) operators.  
  884.  
  885.  
  886.      7.1.2. Unary Operators 
  887.  
  888.  
  889.                Unary operators perform their functions on only one 
  890.           operand.  The subtraction symbol (-) is used as a unary 
  891.           operator when it stands in front of a number or a variable, 
  892.           like so: 
  893.  
  894.  
  895.                -45
  896.  
  897.  
  898.  
  899.                                      - 14 -
  900.  
  901.  
  902.      Small C Interpreter                                Programmer's Manual
  903.  
  904.  
  905.                You may also use the plus sign (+) as a unary operator, 
  906.           although it would be superfluous since all numbers are 
  907.           assumed to be positive unless preceeded by a minus sign.  C 
  908.           also provides other unary operators that will be discussed 
  909.           later.  
  910.  
  911.  
  912.      7.2. Precedence 
  913.  
  914.  
  915.                If you will recall, in your high school algebra class 
  916.           you learned that in an arithmetic expression containing a 
  917.           combination of addition, subtraction, division and 
  918.           multiplication, the division and multiplication are always 
  919.           done before addition and subtraction.  That is to say that 
  920.           division and multiplication "take precedence" over addition 
  921.           and subtraction.  This property of precedence extends to all 
  922.           operators in the C language, not just the arithmetic 
  923.           operators.  
  924.  
  925.                You may defeat the normal order of evaluation of an 
  926.           expression by using parentheses, just as in modern algebra: 
  927.  
  928.  
  929.                (2 + 3) * 5
  930.  
  931.  
  932.                This will perform the addition first, then the 
  933.           multiplication.  You may use as many matched sets of 
  934.           parentheses as necessary to disambiguate the order of 
  935.           evaluation: 
  936.  
  937.  
  938.                (  ( (2+3) / 2 ) * 5  )
  939.  
  940.  
  941.                In fact, it is a good idea to use parentheses liberally 
  942.           whenever you are unsure of operator precedence.  
  943.  
  944.  
  945.      7.3. Associativity 
  946.  
  947.  
  948.                You also learned (hopefully in the same algebra class) 
  949.           that expressions are always evaluated from left to right.  
  950.           This same rule applys to expressions in C. This property of 
  951.           operators is known as associativity.  In C, most of the 
  952.                                          ____ ____ __ _____              
  953.           binary operators are evaluated from left to right, while the 
  954.                                              _____ __ ____     
  955.           unary operators are evaluated from right to left.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.                                      - 15 -
  962.  
  963.  
  964.      Small C Interpreter                                Programmer's Manual
  965.  
  966.  
  967.      7.4. Arithmetic operators 
  968.  
  969.  
  970.                Now we are finally prepared to formally introduce C's 
  971.           arithmetic operators.  They are listed here in order of 
  972.           decreasing precedence: 
  973.  
  974.  
  975.                * / %   multiplication, division and modulo
  976.                + -     addition and subtraction
  977.  
  978.  
  979.                Most of these should already be familiar to you.  The 
  980.           modulo operator (%) gives the remainder from the division of 
  981.           the left value by the right value.  For example, the result 
  982.           of: 15 % 8 is 7.  
  983.  
  984.  
  985.      7.5. Bitwise Operators 
  986.  
  987.  
  988.                C also offers these bit-manipulation operators (again 
  989.           listed in decreasing precedence): 
  990.  
  991.  
  992.                << >>   left and right SHIFT
  993.                &   bitwise AND
  994.                ^   bitwise exclusive OR
  995.                |   bitwise OR
  996.  
  997.  
  998.                If you have a need to do bit manipulation but are not 
  999.           familiar with the above terms (SHIFT, AND, OR and exclusive 
  1000.           OR), you should probably consult a textbook on computer 
  1001.           programming since this is beyond the scope of this 
  1002.           tutorial.  
  1003.  
  1004.                We will be learning more about other C operators in 
  1005.           later discussions.  
  1006.  
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021.                                      - 16 -
  1022.  
  1023.  
  1024.      Small C Interpreter                                Programmer's Manual
  1025.  
  1026.  
  1027.      8. Variables 
  1028.  
  1029.  
  1030.                Previously, we had only eluded to the fact that C does 
  1031.           allow you to create named data storage locations (a.k.a. 
  1032.           "variables"), now we will formally introduce you to all of 
  1033.           C's data types.  
  1034.  
  1035.                Except for the pre-defined Library Functions and the 
  1036.           editor's system-variables (which are found in SHELL.SCI), 
  1037.           all variables must first be made known to the program before 
  1038.           they may be used.  Unlike BASIC where a variable comes into 
  1039.           existance the very first time it is used in a statement, C 
  1040.           requires that every variable be formally declared before you 
  1041.           may use it within your program.  This section will cover the 
  1042.           fundamentals of C variable declarations.  
  1043.  
  1044.  
  1045.      8.1. Naming Conventions 
  1046.  
  1047.  
  1048.                The precise rules governing the naming of variables 
  1049.           usually varies from one C compiler to another.  The rules 
  1050.           for SCI variable names are as follows: 
  1051.  
  1052.  
  1053.                1) a variable name may contain any number of characters 
  1054.                     from the set of: 
  1055.  
  1056.  
  1057.                          1) the letters "a" through "z" and "A" 
  1058.                               through "Z".  
  1059.  
  1060.                          2) the underscore (_).  
  1061.  
  1062.                          3) the digits "0" through "9".  
  1063.  
  1064.  
  1065.                2) the first character of a variable must not be a 
  1066.                     digit (i.e. it must be either a letter or an 
  1067.                     underscore).  
  1068.  
  1069.                3) the case of a letter is significant, for example: 
  1070.                     "foobar" is not the same as "Foobar" or "FooBar".  
  1071.  
  1072.                4) although a variable may be as long as you like, only 
  1073.                     the first eight characters are signifcant.  For 
  1074.                     example: "return_value" and "return_value_1" refer 
  1075.                     to the same variable, since only the first eight 
  1076.                     characters ("return_v") are significant.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.                                      - 17 -
  1082.  
  1083.  
  1084.      Small C Interpreter                                Programmer's Manual
  1085.  
  1086.  
  1087.      8.2. Data Types 
  1088.  
  1089.  
  1090.                The C language supports many different types of 
  1091.           variables.  The most notable difference between them is the 
  1092.           amount of memory storage each one addresses.  The least 
  1093.           amount of memory a variable can represent depends on the 
  1094.           type of computer the program is written for.  Typically, 
  1095.           this is a byte of information, although some mainframe 
  1096.           machines do not have the capability to access memory in 
  1097.           smaller than 2 or 4 byte gobbles.  Most personal computers, 
  1098.           however can access memory one byte at a time and in C, this 
  1099.           data type is known as the "char", short for "character".  
  1100.  
  1101.  
  1102.      8.2.1. Char 
  1103.  
  1104.  
  1105.                A "char" variable in SCI is one byte long and can 
  1106.           represent a number between -128 and +127.  In order to make 
  1107.           a variable known to the program we must first declare it, so 
  1108.           to declare a "char" variable named "foobar" we would write: 
  1109.  
  1110.  
  1111.                char foobar;
  1112.  
  1113.  
  1114.                We can also declare more than one variable of the same 
  1115.           type on the same line by seperating each with a comma, like 
  1116.           so: 
  1117.  
  1118.  
  1119.                char foobar, snafu, gurgle;
  1120.  
  1121.  
  1122.  
  1123.      8.2.2. Int 
  1124.  
  1125.  
  1126.                Another variable type is the "int", short for 
  1127.           "integer". Again, the amount of memory an "int" addresses is 
  1128.           machine dependent.  In SCI, an "int" addresses two bytes of 
  1129.           memory, and can represent a number between -32768 and 
  1130.           +32767.  "Int"s are declared in a manner similar to "char"s: 
  1131.  
  1132.  
  1133.                int foobar;
  1134.                int snafu, wowbagger;
  1135.  
  1136.           Standard C also defines other data types such as floating 
  1137.           point variables, double precision integer and double 
  1138.           precision floating point.  You may also define your own data 
  1139.  
  1140.  
  1141.                                      - 18 -
  1142.  
  1143.  
  1144.      Small C Interpreter                                Programmer's Manual
  1145.  
  1146.  
  1147.           types that are a combination of these primaries (known as 
  1148.           "structures").  Unfortunately, these are all not supported 
  1149.           by this version of SCI.  
  1150.  
  1151.  
  1152.      8.3. Scope 
  1153.  
  1154.  
  1155.                If you are familiar with BASIC, then you already know 
  1156.           that a BASIC program variable is "known" throughout the 
  1157.           program - that is, any statement within the program may 
  1158.           alter a variable's contents.  This "feature" can lead to 
  1159.           some very difficult to find programming bugs.  For instance, 
  1160.           you may use a variable as a temporary loop counter in one 
  1161.           section of the program, only to discover later that you had 
  1162.           already decided to use that variable for another purpose and 
  1163.           its contents were continually being destroyed.  Ideally, we 
  1164.           would like to be able to use variable names indiscriminantly 
  1165.           in one section of a program without having to worry about 
  1166.           whether the variable name is being used in another section 
  1167.           of the program.  Happily, the C language offers this ability 
  1168.           as you will soon see.  This concept of limited (or rather 
  1169.           "controlled") access to variables is known as "scope".  
  1170.  
  1171.  
  1172.      8.3.1. Global Variables 
  1173.  
  1174.  
  1175.                In C, you may create variables that are known 
  1176.           throughout the program, just like in BASIC.  Variables that 
  1177.           have this property are known as "globals" and just like 
  1178.           BASIC, every statement within the program may retrieve and 
  1179.           store the value of a global variable.  A variable will 
  1180.           attain global status if it was declared outside of any curly 
  1181.           braces ({ and }) that delimit the body of a function.  Here 
  1182.           is an example to illustrate: 
  1183.  
  1184.  
  1185.                char c;            # "c" is a global
  1186.                int i, j;          # and so are "i" and "j"
  1187.                
  1188.                a_function()       # the first function in the program
  1189.                {
  1190.                     .
  1191.                     .
  1192.                     .
  1193.                }
  1194.                
  1195.                char flag, nyuk;   # some more global variables
  1196.                
  1197.                another_function() # another function
  1198.                {
  1199.  
  1200.  
  1201.                                      - 19 -
  1202.  
  1203.  
  1204.      Small C Interpreter                                Programmer's Manual
  1205.  
  1206.  
  1207.                     .
  1208.                     .
  1209.                     .
  1210.                }
  1211.  
  1212.  
  1213.                As you can see, C does not care where within a program 
  1214.           a global variable is declared as long as the declaration 
  1215.           appears outside of any functions.  
  1216.  
  1217.                SCI ensures that global variables are always set to 
  1218.           zero before the program starts up.  This is pretty much 
  1219.           standard behavior for most C compilers as well.  
  1220.  
  1221.                In C, functions are also considered to be globals - 
  1222.           they are known throughout the program, although they 
  1223.           obviously can't be used to store data.  
  1224.  
  1225.  
  1226.      8.3.2. Local Variables 
  1227.  
  1228.  
  1229.                Variables that are declared inside of the curly braces 
  1230.           that mark the beginning and end of a function are known as 
  1231.           "local" variables.  Locals exist only during the life of the 
  1232.           function - that is the variable comes into existence after 
  1233.           it has been declared within a function and ceases to exist 
  1234.           when the function returns to its caller.  See the example 
  1235.           below for clarification: 
  1236.  
  1237.  
  1238.                char c;             # these are global variables
  1239.                int i;
  1240.                a_function()        # a function definition
  1241.                {
  1242.                     char snafu; # a local variable
  1243.                     int x, y;   # some more locals
  1244.                     .
  1245.                     .
  1246.                     .
  1247.                     x = c;      # copy the global to a local
  1248.                }                   # snafu, x and y cease to exist!
  1249.  
  1250.  
  1251.                                      ____                              
  1252.                Variable declarations must appear immediately after a 
  1253.           left curly brace; if a declaration appears anywhere else 
  1254.           within the body of a function SCI will warn you about a 
  1255.           "syntax error".  
  1256.  
  1257.                                                              ___   
  1258.                In addition, variables may be declared within any 
  1259.                                                                  ____   
  1260.           compound statement in a function, but the declarations must 
  1261.           appear immediately after the opening brace.  Variables 
  1262.  
  1263.  
  1264.                                      - 20 -
  1265.  
  1266.  
  1267.      Small C Interpreter                                Programmer's Manual
  1268.  
  1269.  
  1270.           declared in this context exist only for the life of the 
  1271.           compound statement, i.e.  to the matching closing brace.  
  1272.           Thus the memory these variables occupy can be re-used within 
  1273.           the function.  Below is an example to illustrate: 
  1274.  
  1275.  
  1276.                func()
  1277.                {
  1278.                     char a;
  1279.                     int i;
  1280.                     .
  1281.                     .
  1282.                     .
  1283.                     if ( i==0 )
  1284.                     {
  1285.                          int j;      # declare an "int" in a compound stmt
  1286.                          .
  1287.                          .           # "a", "i" and "j" are all locals here
  1288.                          .
  1289.                     }                # "j" no longer exists here
  1290.                     else if ( i==1 )
  1291.                     {
  1292.                          char j;     # a different "j" than above
  1293.                          .
  1294.                          .
  1295.                          .
  1296.                     }
  1297.                }
  1298.  
  1299.  
  1300.                SCI ensures that locals are always zero just after they 
  1301.           have been declared.  On standard C compilers, the initial 
  1302.           contents of locals is unknown, so do not depend on them 
  1303.           being zero.  
  1304.  
  1305.  
  1306.      8.3.3. Function Arguments 
  1307.  
  1308.  
  1309.                Function arguments are also considered to be local 
  1310.           variables.  When a function calls another function and 
  1311.           passes it an argument, the argument's contents is copied 
  1312.           into a local variable in the called function - the value of 
  1313.           the caller's argument is not affected.  This is best 
  1314.           illustrated with an example: 
  1315.  
  1316.  
  1317.                char c;        # the global variable, "c"
  1318.                func1()
  1319.                {
  1320.                     char c;   # a local may have the same name as a global
  1321.                     c = 1;    # and this sets the LOCAL variable "c" to 1!
  1322.  
  1323.  
  1324.                                      - 21 -
  1325.  
  1326.  
  1327.      Small C Interpreter                                Programmer's Manual
  1328.  
  1329.  
  1330.                     func2(c); # now call func2
  1331.                }
  1332.                func2( x )
  1333.                char x;
  1334.                {
  1335.                     char c;   # this "c" is different from func1's "c"
  1336.                     x = 3;    # this does not affect func1's "c"
  1337.                     c = 5;    # this does not affect the global "c"
  1338.                }
  1339.  
  1340.  
  1341.  
  1342.      8.3.4. System Globals 
  1343.  
  1344.  
  1345.                As mentioned earlier, the Library Functions and the 
  1346.           editor's configuration variables that are declared in the 
  1347.           shell are also globals.  These however, are more permanent 
  1348.           than program globals.  A program's global variables can be 
  1349.           zapped into non-existence simply by editing the program and 
  1350.           removing the statement that declares them.  System globals 
  1351.           can not be destroyed since SCI will not allow you to modify 
  1352.           the shell program (or any program for that matter) while it 
  1353.           is still running.  
  1354.  
  1355.  
  1356.      8.4. Location of Variables 
  1357.  
  1358.  
  1359.                At this point it may be useful to discuss where in 
  1360.           memory each of these different types of variables is 
  1361.           located.  Although this depends on the compiler's 
  1362.           implementation and the hardware, most C compilers take 
  1363.           advantage of some commonly used data structures.  
  1364.  
  1365.  
  1366.      8.4.1. The Stack 
  1367.  
  1368.  
  1369.                The stack is simply a chunk of the computer's memory 
  1370.           that can only be accessed (read from and written to) 
  1371.           indirectly through a machine register known as the "stack 
  1372.           pointer".  If the CPU does can not provide a stack pointer 
  1373.           register, the authors of the C compiler will typically write 
  1374.           some subroutines in the machine's language to emulate a 
  1375.           hardware stack.  Reading and writing to the stack proceeds 
  1376.           as follows: before an item is read from the stack, the stack 
  1377.           pointer is decremented to point to the previous item in the 
  1378.           stack memory.  This then, is the item read from the stack; 
  1379.           After an item is written into stack memory, the stack 
  1380.           pointer is incremented to point to the next item in the 
  1381.           stack.  Thus, the operation of the stack can be thought of 
  1382.  
  1383.  
  1384.                                      - 22 -
  1385.  
  1386.  
  1387.      Small C Interpreter                                Programmer's Manual
  1388.  
  1389.  
  1390.           as a stack of pancakes - numbers are piled onto the stack 
  1391.           for temporary storage, then removed from the top as needed.  
  1392.  
  1393.                In general, the C language depends very heavily on the 
  1394.           stack.  Local variables, including function arguments, are 
  1395.           piled onto the stack when a function begins, and then 
  1396.           removed and discarded when it terminates.  As a C statement 
  1397.           is executed, the components of the statement (constants, 
  1398.           variables, etc.) are "pushed" onto the stack until they are 
  1399.           needed.  Then, when the statement is evaluated, the 
  1400.           components are "poped" off the stack.  
  1401.  
  1402.                Most compilers take advantage of the machine's built-in 
  1403.           stack (if the CPU happens to have one, as most do), so 
  1404.           access to the stack is very efficient.  Still, this has 
  1405.           become a major point of criticism by opponents of the C 
  1406.           language.  
  1407.  
  1408.  
  1409.      8.4.2. Program and Data Segments 
  1410.  
  1411.  
  1412.                Global data variables are usually stored in the same 
  1413.           section of memory as program code; most 8 and 16 bit CPU's 
  1414.           do not provide seperate memory segments for program code and 
  1415.           global data.  
  1416.  
  1417.                Some minicomputers and most mainframes do provide 
  1418.           seperate program code and data memory areas.  The machine 
  1419.           then limits access to these segments by disabling the 
  1420.           program from storing data in the code segment and possibly 
  1421.           causing the program to go berserk.  Also, the program is 
  1422.           limited to accessing only its own global data area and 
  1423.           attempts to read or write data outside of this global data 
  1424.           segment is a violation.  
  1425.  
  1426.                Alas, a microcomputer's operating system is at the 
  1427.           mercy of the currently executing program and a careless 
  1428.           program has the ability to corrupt the operating system and 
  1429.           bring the computer to its knees.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.                                      - 23 -
  1445.  
  1446.  
  1447.      Small C Interpreter                                Programmer's Manual
  1448.  
  1449.  
  1450.      9. Constants 
  1451.  
  1452.  
  1453.                You already know about decimal integer constants 
  1454.           because we have been using them throughout this tutorial.  
  1455.           The C language also allows you to represent numbers in 
  1456.           hexadecimal, octal and ASCII.  
  1457.  
  1458.  
  1459.      9.1. Hexadecimal Constants 
  1460.  
  1461.  
  1462.                Hexadecimal numbers are distinguished from other number 
  1463.           representations and variables by preceding them with a "0x" 
  1464.           (zero-"ex"), for example: 
  1465.  
  1466.  
  1467.                0x0
  1468.                0x1b
  1469.                0xfa70
  1470.  
  1471.  
  1472.                are all valid hexadecimal number representations.  You 
  1473.           may also use an upper case "x" if you desire.  
  1474.  
  1475.  
  1476.      9.2. Octal Constants 
  1477.  
  1478.  
  1479.                Octal numbers are distinguished by preceding them with 
  1480.           a zero.  These are all valid octal numbers: 
  1481.  
  1482.  
  1483.                00
  1484.                033
  1485.                0175160
  1486.  
  1487.  
  1488.  
  1489.  
  1490.      9.3. ASCII Character Constants 
  1491.  
  1492.  
  1493.                The numeric value of ASCII characters can be 
  1494.           represented by surrounding the ASCII character in 
  1495.           apostrophes, like this: 
  1496.  
  1497.  
  1498.                 A                                  
  1499.                'A' - is equivalent to decimal 65 
  1500.  
  1501.                ' ' - is a space and is equivalent to decimal 32 
  1502.  
  1503.  
  1504.  
  1505.                                      - 24 -
  1506.  
  1507.  
  1508.      Small C Interpreter                                Programmer's Manual
  1509.  
  1510.  
  1511.                Certain non-printing ASCII characters can also be 
  1512.           conveniently represented as character constants.  By 
  1513.           preceeding certain lower case letters with a backslash 
  1514.           character ("\"), the two-character combination can be used 
  1515.           to represent a single one byte value.  One of these you 
  1516.           already know as the "newline" character, '\n'. Here is a 
  1517.           complete list of these: 
  1518.  
  1519.  
  1520.                  b                                             
  1521.                '\b' - "backspace", equivalent to decimal 8.  
  1522.  
  1523.                  r                                   
  1524.                '\r' - "return", equivalent to 13.  
  1525.  
  1526.                  n                                    
  1527.                '\n' - "newline", equivalent to 10.  
  1528.  
  1529.                  f                                     
  1530.                '\f' - "formfeed", equivalent to 12.  
  1531.  
  1532.                  t                               
  1533.                '\t' - "tab", equivalent to 9.  
  1534.  
  1535.  
  1536.                In addition, you can represent any ASCII character as a 
  1537.           character constant using its octal equivalent preceded by a 
  1538.           backslash.  The only restriction here is that the octal 
  1539.           representation must be exactly 3 octal digits.  For example: 
  1540.  
  1541.  
  1542.                  033                                                   
  1543.                '\033' - is an ASCII "escape" character equivalent to 
  1544.                     27.  
  1545.  
  1546.                  101                                                     
  1547.                '\101' - is an ASCII "A", equivalent to 'A', equivalent 
  1548.                     to 65.  
  1549.  
  1550.                  377                                                    
  1551.                '\377' - is not really a valid ASCII character, but it 
  1552.                     is equivalent to 255.  
  1553.  
  1554.           
  1555.           and so on - you get the idea.  
  1556.  
  1557.  
  1558.      9.4. String Constants 
  1559.  
  1560.  
  1561.                Finally, another type of constant you have already been 
  1562.           using, is the "string" constant - a bunch of ASCII 
  1563.           characters surrounded by quotes, for example: 
  1564.  
  1565.  
  1566.                "this is a string\n"
  1567.  
  1568.  
  1569.                A string always ends with a zero byte, thus the amount 
  1570.           of memory a string takes up is equal to the number of 
  1571.  
  1572.  
  1573.                                      - 25 -
  1574.  
  1575.  
  1576.      Small C Interpreter                                Programmer's Manual
  1577.  
  1578.  
  1579.           characters you can count in the string plus one.  In the 
  1580.           example above, the string requires 18 bytes of storage 
  1581.           (realize that the "\n" sequence is a single character - the 
  1582.           "newline"!).  
  1583.  
  1584.                String constants have an interesting numeric equivalent 
  1585.           - it is an address in the computer's memory where the ASCII 
  1586.           characters in the string can be found by functions that are 
  1587.           equiped to deal with them.  For instance, the Library 
  1588.           Function "puts" expects its parameter to be an address in 
  1589.           memory where ASCII character can be found and sequentially 
  1590.           printed out to the console screen.  
  1591.  
  1592.                If you tried to find out a string constant's numeric 
  1593.           value from the shell by typing: 
  1594.  
  1595.  
  1596.                > "hello?"
  1597.                -5537
  1598.                > "another string..."
  1599.                -5537
  1600.                > "what the?"
  1601.                -5537
  1602.                >
  1603.  
  1604.  
  1605.                you would be surprised to find that they all have the 
  1606.           same address - how could this be?  Actually, all the string 
  1607.           constants in the above examples do have the same address.  
  1608.           Recall that the shell reads a line of input from the console 
  1609.           and hands it off to the interpreter for evaluation.  Since 
  1610.           the strings all get read into the same line buffer by the 
  1611.           shell, they all have the same address, namely the shell's 
  1612.           input line buffer.  
  1613.  
  1614.                We will discuss strings in more detail in the section 
  1615.           on arrays and pointers.  
  1616.  
  1617.  
  1618.  
  1619.  
  1620.  
  1621.  
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628.  
  1629.  
  1630.  
  1631.  
  1632.  
  1633.                                      - 26 -
  1634.  
  1635.  
  1636.      Small C Interpreter                                Programmer's Manual
  1637.  
  1638.  
  1639.      10. Assignment Operator 
  1640.  
  1641.  
  1642.                In C, we assign values to variables using the 
  1643.           "assignment" operator, "=".  Do not confuse the assignment 
  1644.           operator (a single equal sign) with the "is equal to" 
  1645.           relational operator (two consecutive equal signs), which we 
  1646.           will discuss later.  Although C will allow you to do this 
  1647.           under certain conditions, you will get unexpected results.  
  1648.           The expression: 
  1649.  
  1650.  
  1651.                a = (b + 1) * 2;
  1652.  
  1653.           is read as: take the results of the calculation of (b + 1) * 
  1654.           2 and assign it to the variable "a". Note that there may be 
  1655.           only one variable to the left of the equal sign.  
  1656.  
  1657.                You can if you like, string several of these 
  1658.           assignments together like this: 
  1659.  
  1660.  
  1661.                a = flg = x = (b + 1) * 2;
  1662.  
  1663.  
  1664.                Note that even here there is always only one variable 
  1665.           to the left of each equal sign.  This statement is evaluated 
  1666.           like so: take the results of the calculation of (b + 1) * 2 
  1667.           and assign it to the variable "x", then assign the same 
  1668.           number to the variable "flg", and then to "a".  This implies 
  1669.           that the assignment operator is evaluated from 
  1670.           _____ __ ____                                                 
  1671.           right-to-left, instead of the usual left-to-right.  In fact 
  1672.           it is the only binary operator supported by SCI that 
  1673.           exhibits this peculiar behavior.  This feature is most 
  1674.           useful when initializing several variables, like so: 
  1675.  
  1676.  
  1677.                lettercnt = digitcnt = punctcnt = 0;
  1678.  
  1679.           
  1680.           which would set all of the variables to zero.  
  1681.  
  1682.                The assignment operator has the lowest precedence (it 
  1683.           is performed last in an expression) of all the C operators, 
  1684.           except for the "comma" operator (see below).  
  1685.  
  1686.  
  1687.      10.1. Lvalues and Rvalues 
  1688.  
  1689.  
  1690.                It should be intuitively obvious that any attempt to 
  1691.           store a value in what we know as a C constant is illegal.  
  1692.  
  1693.  
  1694.                                      - 27 -
  1695.  
  1696.  
  1697.      Small C Interpreter                                Programmer's Manual
  1698.  
  1699.  
  1700.           In other words, you would never attempt to say, store the 
  1701.           number 3 in place of the number 5: 
  1702.  
  1703.  
  1704.                5 = 3;
  1705.  
  1706.  
  1707.                The same holds true for string constants; you may not 
  1708.           store another string in an existing string constant: 
  1709.  
  1710.  
  1711.                "hello" = "world\n";
  1712.  
  1713.  
  1714.                These types of data (constants) are collectively known 
  1715.           as "rvalues" (pronounced "are-values"). The term rvalue 
  1716.           stems from the fact that they may only be used on the 
  1717.           right-hand-side of an assignment operator.  
  1718.  
  1719.                On the other hand, variables do allow numbers to be 
  1720.           stored and retrieved from them.  This category of data is 
  1721.           known as "lvalues" (pronounced "ell-values") because they 
  1722.           may be used on the left-hand-side of an eual sign.  
  1723.  
  1724.                We will encounter lvalues and rvalues again in a later 
  1725.           discussion.  
  1726.  
  1727.  
  1728.  
  1729.  
  1730.  
  1731.  
  1732.  
  1733.  
  1734.  
  1735.  
  1736.  
  1737.  
  1738.  
  1739.  
  1740.  
  1741.  
  1742.  
  1743.  
  1744.  
  1745.  
  1746.  
  1747.  
  1748.  
  1749.  
  1750.  
  1751.  
  1752.  
  1753.  
  1754.                                      - 28 -
  1755.  
  1756.  
  1757.      Small C Interpreter                                Programmer's Manual
  1758.  
  1759.  
  1760.      11. Comma Operator 
  1761.  
  1762.  
  1763.                In C the punctuation character "," (comma) is 
  1764.           considered to be an operator, although it does nothing more 
  1765.           except insure that sub-expressions within a statement will 
  1766.           be evaluated in order from left to right.  This operator has 
  1767.           the lowest priority of all.  It is useful for when you want 
  1768.           to do more than one thing in a statement, like the 
  1769.           following: 
  1770.  
  1771.  
  1772.                ++a, b=12, c=b+a;
  1773.  
  1774.  
  1775.                Of course, we could also have written the above 
  1776.           statement as: 
  1777.  
  1778.  
  1779.                {
  1780.                     ++a;
  1781.                     b=12;
  1782.                     c=b+a;
  1783.                }
  1784.  
  1785.           
  1786.           but this would not have been as concise as the first form.  
  1787.  
  1788.                Commas are also used to seperate variable names in a 
  1789.           data declaration as you have already seen, and to seperate 
  1790.           arguments in function calls.  
  1791.  
  1792.  
  1793.                                      NOTE   
  1794.                                      NOTE:
  1795.  
  1796.                SCI does not support the use of the comma operator 
  1797.                anywhere   outside   the   context   of   variable
  1798.                seperators or function call  argument  seperators,
  1799.                as in  the first example above.  Any attempt to do
  1800.                so will result in a "syntax  error"  message  from
  1801.                the interpreter.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809.  
  1810.  
  1811.  
  1812.  
  1813.  
  1814.  
  1815.                                      - 29 -
  1816.  
  1817.  
  1818.      Small C Interpreter                                Programmer's Manual
  1819.  
  1820.  
  1821.      12. Flow Control 
  1822.  
  1823.  
  1824.                The previous sections have dealt only with data 
  1825.           elements (variables and constants) and with evaluating 
  1826.           arithmetic combinations of these.  C would be a poor 
  1827.           language indeed if it only allowed a programmer to evaluate 
  1828.           a sequential list of arithmetic expressions without giving 
  1829.           him the opportunity to act on the results of these 
  1830.           calculations.  This section will introduce you to C's 
  1831.           program control structures, also known as "flow control" 
  1832.           structures.  Most of these have constructs that should be 
  1833.           familiar to all you BASIC hackers: the conditional 
  1834.           ("if-else"), looping ("while" and "for") and program control 
  1835.           switching ("switch").  
  1836.  
  1837.  
  1838.      12.1. if and if-else 
  1839.  
  1840.  
  1841.                The most fundamental of the flow control constructs is 
  1842.           the "if".  This allows you to perform a statement (or group 
  1843.           of statements if we talk about a compound statement) "if" 
  1844.           the given condition is true.  In C, a condition is 
  1845.           considered to be true when the value of an expression is 
  1846.           non-zero, that is either a positive or negative number.  It 
  1847.           follows then, that an expression that evaluates to zero is 
  1848.           considered to be a false condition.  We write an "if" 
  1849.           conditional in C like this: 
  1850.  
  1851.  
  1852.                if ( <expression> ) <statement>
  1853.  
  1854.  
  1855.                We will be using the angle brackets (<>) to represent 
  1856.           familiar C concepts so that you will be able to more easily 
  1857.           identify the relavent components: here "<expression>" is any 
  1858.           valid C expression, like "var-5" or "x + 10"; and 
  1859.           "<statement>" may be either a simple or compound statement - 
  1860.           but, more about statements later.  
  1861.  
  1862.                The relavent components in the "if" statement are: 
  1863.           obviously the "if" word which identifies this flow control 
  1864.           construct; a left parenthesis followed by an expression 
  1865.           followed by a right parenthesis; then a C statement.  Now a 
  1866.           few words about syntactics: 
  1867.  
  1868.  
  1869.                1) The "if" must be in lower case letters, most C 
  1870.                     compilers will usually not accept "If", or "IF" or 
  1871.                     "iF" (and neither will SCI!).  
  1872.  
  1873.  
  1874.  
  1875.                                      - 30 -
  1876.  
  1877.  
  1878.      Small C Interpreter                                Programmer's Manual
  1879.  
  1880.  
  1881.                2) The matched left and right parentheses must be 
  1882.                     included, and SCI requires that the "if", the left 
  1883.                     parenthesis, the <expression> and the right 
  1884.                     parenthesis appear on the same line in the 
  1885.                     program.  
  1886.  
  1887.                3) The <statement> may be either a simple statement or 
  1888.                     a compound statement.  
  1889.  
  1890.  
  1891.  
  1892.                                      NOTE   
  1893.                                      NOTE:
  1894.  
  1895.                SCI  requires  that  the  "if" and the parentheses
  1896.                appear on the same line in your program text,  but
  1897.                the  <statement> may appear on the following line.
  1898.                This is only a restriction of the SCI  interpreter
  1899.                -  the  standard  C  language lets you put as much
  1900.                horizontal   and   vertical   "distance"   between
  1901.                elements of an "if" statement as you like.  
  1902.  
  1903.           
  1904.           The "if" flow control construct behaves as follows: 
  1905.  
  1906.  
  1907.                1) The <expression> is evaluated.  
  1908.  
  1909.                2) If the result of <expression> is true (a non-zero 
  1910.                     value) then the <statement> is executed.  
  1911.  
  1912.                3) If the result is false (zero) the <statement> is 
  1913.                     skipped and program control passes to the next 
  1914.                     statement.  
  1915.  
  1916.           
  1917.           For example: 
  1918.  
  1919.  
  1920.                if ( 2 + 2 ) a = 5;
  1921.  
  1922.           
  1923.           would always set the variable "a" to 5 because the 
  1924.           <expression>, which evaluates to 4 in this case, is always 
  1925.           non-zero.  And the <statement> in this example: 
  1926.  
  1927.  
  1928.                if ( 0 ) a = 5;
  1929.  
  1930.           
  1931.           would never be reached because the <expression> is always 
  1932.           false.  As a last example, look at this: 
  1933.  
  1934.  
  1935.  
  1936.                                      - 31 -
  1937.  
  1938.  
  1939.      Small C Interpreter                                Programmer's Manual
  1940.  
  1941.  
  1942.                if ( a = b + c ) b = b + 1;
  1943.  
  1944.  
  1945.                Here the value of the <expression> depends on the 
  1946.           results of the addition of "b" and "c", which we have no way 
  1947.           of knowing just by looking at the example out of context.  
  1948.           As a side-effect, the result of the addition is stored in 
  1949.           the variable "a". It is very important that you realize that 
  1950.           the equal sign in "a = b + c" is not making a comparison 
  1951.           between the value of "a" and "b + c", as you might assume if 
  1952.           you were looking at a similar statement in BASIC.  In other 
  1953.                         ___                                             
  1954.           words, we are not saying "if a is equal to the sum of b and 
  1955.           c".  
  1956.  
  1957.  
  1958.      12.1.1. More About Statements 
  1959.  
  1960.  
  1961.                Earlier we promised to tell you more about the concept 
  1962.           of C statements.  A statement, as you already know, can be 
  1963.           either an expression such as "a = 5 + 5" followed by a 
  1964.           semicolon (don't forget the semicolon!) or it may be a group 
  1965.           of these simple statements surrounded by left and right 
  1966.           curly braces, like this: 
  1967.  
  1968.  
  1969.                { a = b + c; b = b + 1; }
  1970.  
  1971.           
  1972.           or this: 
  1973.  
  1974.  
  1975.                {
  1976.                     a = b + c;
  1977.                     b = b + 1;
  1978.                }
  1979.  
  1980.           
  1981.           or a compound statement within a compound statement as in 
  1982.           this example: 
  1983.  
  1984.  
  1985.                {
  1986.                     { a = b; b = 1; }
  1987.                     a = b + c;
  1988.                     b = b + 1;
  1989.                }
  1990.  
  1991.  
  1992.                We now expand our definition of a C statement to 
  1993.           include the "if" and later all of the other flow control 
  1994.           constructs as well.  In other words, the template for an 
  1995.  
  1996.  
  1997.                                      - 32 -
  1998.  
  1999.  
  2000.      Small C Interpreter                                Programmer's Manual
  2001.  
  2002.  
  2003.           "if" we showed you before: 
  2004.  
  2005.  
  2006.                if ( <expression> ) <statment>
  2007.  
  2008.           
  2009.           can be thought of as a single unit and used wherever a 
  2010.           <statement> is used.  Now we can write multiple "nested 
  2011.           if's" like this: 
  2012.  
  2013.  
  2014.                if ( a + 5 )
  2015.                     if ( b - 1 )
  2016.                          c = 0;
  2017.  
  2018.           
  2019.           which would be "read" by the computer as follows: 
  2020.  
  2021.  
  2022.                1) if "a + 5" is true (non-zero) then go to step 2 
  2023.                     otherwise go to step 3.  
  2024.  
  2025.                2) if "b - 1" is true, then assign 0 to "c".  
  2026.  
  2027.                3) go on to the next statement in the program.  
  2028.  
  2029.  
  2030.                The "if" statement also has an optional "else" clause, 
  2031.           which looks like this: 
  2032.  
  2033.  
  2034.                if ( <expression> ) <statement> else <statement>
  2035.  
  2036.  
  2037.                Notice that the "else" keyword must be in lower case 
  2038.           letters also.  Again, the first <statement>, the "else", and 
  2039.           the second <statement> may be on seperate lines of program 
  2040.           text or they may all be on the same line.  The "if-else" 
  2041.           statement, as it is called, is read as follows: 
  2042.  
  2043.  
  2044.                1) if the <expression> is true, then execute the first 
  2045.                     <statement> and then go to step 3.  
  2046.  
  2047.                2) else, execute the second <statement> and then go to 
  2048.                     step 3.  
  2049.  
  2050.                3) go on to the next statement in the program.  
  2051.  
  2052.  
  2053.                The C language allows you to nest "if-else" statements 
  2054.           as deeply as you wish, for example: 
  2055.  
  2056.  
  2057.                                      - 33 -
  2058.  
  2059.  
  2060.      Small C Interpreter                                Programmer's Manual
  2061.  
  2062.  
  2063.                if ( a + 3 )
  2064.                     if ( b + 5 )
  2065.                          if ( c + 7 )
  2066.                               d = 0;
  2067.                          else
  2068.                               d = 1;
  2069.                     else
  2070.                          d = 2;
  2071.                else
  2072.                     d = 3;
  2073.  
  2074.  
  2075.                It should be obvious from the way the statements were 
  2076.           indented how each "else" matches its "if". As a matter of 
  2077.           definition, an "else" clause matches the nearest preceding 
  2078.           "if" clause.  If there are more "else's" than "if's" in a 
  2079.           program, then this is an error condition and you will be 
  2080.           warned by SCI. If you are ever unsure how nested "if-else" 
  2081.           combinations will match up, you can always use curly braces 
  2082.           to bind them together the way you want: 
  2083.  
  2084.  
  2085.                if ( a + 3 )
  2086.                {
  2087.                     if ( b + 5 )
  2088.                     {
  2089.                          if ( c + 7 )
  2090.                               d = 0;
  2091.                          else
  2092.                               d = 1;
  2093.                     }
  2094.                     else
  2095.                     {
  2096.                          d = 2;
  2097.                     }
  2098.                }
  2099.                else
  2100.                {
  2101.                     d = 3;
  2102.                }
  2103.  
  2104.  
  2105.                You can also use another "if-else" statement in the 
  2106.           "else" clause of a preceding "if-else", for example: 
  2107.  
  2108.  
  2109.  
  2110.  
  2111.  
  2112.  
  2113.  
  2114.  
  2115.  
  2116.  
  2117.                                      - 34 -
  2118.  
  2119.  
  2120.      Small C Interpreter                                Programmer's Manual
  2121.  
  2122.  
  2123.                if ( a + 3 )
  2124.                     d = 1;
  2125.                else
  2126.                {
  2127.                     if ( a + 4 )
  2128.                          d = 2;
  2129.                     else
  2130.                     {
  2131.                          if ( a + 5 )
  2132.                               d = 3;
  2133.                          else
  2134.                               d = 4;
  2135.                     }
  2136.                }
  2137.  
  2138.  
  2139.                Because it is a matter of personal style, there are no 
  2140.           hard and fast rules to follow when indenting program 
  2141.           statements like this.  However, the above example is more 
  2142.           commonly indented like this: 
  2143.  
  2144.  
  2145.                if ( a + 3 )
  2146.                     d = 1;
  2147.                else if ( a + 4 )
  2148.                     d = 2;
  2149.                else if ( a + 5 )
  2150.                     d = 3;
  2151.                else
  2152.                     d = 4;
  2153.  
  2154.  
  2155.                This saves you from running off the right edge of the 
  2156.           screen when writing very deeply nested "if-else's" and it 
  2157.           looks very much like a multi-path switch (an "ON GOTO" 
  2158.           statement in BASIC).  
  2159.  
  2160.  
  2161.      12.1.2. Relational Operators 
  2162.  
  2163.  
  2164.                Sometimes it is necessary to change the program flow 
  2165.           depending on whether a variable is equal to a certain 
  2166.           value.  The C language has this ability to test equality of 
  2167.           two expressions using a set of operators (similar to the 
  2168.           addition, multiplication, assignment, etc.) known as the 
  2169.           "relational operators".  If we wanted to know if a variable 
  2170.           were equal to a certain value, for instance we could say: 
  2171.  
  2172.  
  2173.                a == 5
  2174.  
  2175.  
  2176.  
  2177.                                      - 35 -
  2178.  
  2179.  
  2180.      Small C Interpreter                                Programmer's Manual
  2181.  
  2182.  
  2183.                The "==" (which is read as: "is equal to") operator 
  2184.           compares the two items to the left and right of it and 
  2185.           leaves a value of one if they are equal, zero if they are 
  2186.           unequal.  So the value of this expression would be one if 
  2187.           "a" is equal to 5 and zero otherwise.  Thus, the statement: 
  2188.  
  2189.  
  2190.                if ( a == 5 )
  2191.                     b = 0;
  2192.  
  2193.           
  2194.           would set "b" to zero only if "a" equals 5.  
  2195.  
  2196.                We promised you a set of these operators, so here they 
  2197.           are: 
  2198.  
  2199.  
  2200.                ________    ____ __   
  2201.                operator:   read as:
  2202.                
  2203.                ==          is equal to
  2204.                !=          is not equal to
  2205.                <           is less than
  2206.                >           is greater than
  2207.                <=          is less than or equal to
  2208.                >=          is greater than or equal to
  2209.  
  2210.  
  2211.                Notice that there may be no spaces between the two 
  2212.           equal signs (=) in the "is equal to" operator nor between 
  2213.           the exclamation point (!) and the equal in the "is not equal 
  2214.           to".  If there is a space between them, they will be assumed 
  2215.           to be two seperate operators and you will get a "syntax 
  2216.           error" message from SCI. Needless to say, the same goes for 
  2217.           the <= and >=.  
  2218.  
  2219.  
  2220.      12.1.3. Logical Operators 
  2221.  
  2222.  
  2223.                The C language also allows you to combine groups of 
  2224.           relational expressions with "and" and "or" clauses.  For 
  2225.           example, given two sets of conditions you can determine if 
  2226.           both are true, or if at least one is true.  These "and" and 
  2227.           "or" clauses are known as the "logical operators" in C: 
  2228.  
  2229.  
  2230.                ________    ____ __   
  2231.                operator:   read as:
  2232.                
  2233.                &&          and
  2234.                ||          or
  2235.  
  2236.  
  2237.  
  2238.  
  2239.                                      - 36 -
  2240.  
  2241.  
  2242.      Small C Interpreter                                Programmer's Manual
  2243.  
  2244.  
  2245.                Notice that there may be no spaces between the two 
  2246.           ampersands (&) and vertical bars (|). The expression: 
  2247.  
  2248.  
  2249.                a==5 && b==3
  2250.  
  2251.           
  2252.                                                  ___                   
  2253.           will be true only if "a" is equal to 5 and "b" is equal to 
  2254.           3.  
  2255.  
  2256.  
  2257.                a<0 || 10<a
  2258.  
  2259.  
  2260.                In this example the expression is true if "a" is less 
  2261.                  __                                                      
  2262.           than 0 or greater than 10 (do you see that 10<a and a>10 are 
  2263.           identical?).  
  2264.  
  2265.                One final note about the logical operators: standard C 
  2266.           stops evaluating an expression that contains logical 
  2267.           operators after the truth or falsehood of the expression is 
  2268.           known.  For example: 
  2269.  
  2270.  
  2271.                a==b && c==d
  2272.  
  2273.  
  2274.                Assume that "a" is not equal to "b". Standard C would 
  2275.           not even bother checking the relation "c==d" because the 
  2276.           "and" clause requires both expressions to the left and right 
  2277.           of the "&&" to be true - if one of the components is false, 
  2278.           the entire expression is false.  So, since the first 
  2279.           component encountered ("a==b") was found to be false, the 
  2280.           truth or falsehood of the entire expression is already known 
  2281.           and there is no need to evaluate "c==d".  
  2282.  
  2283.  
  2284.                                      NOTE   
  2285.                                      NOTE:
  2286.  
  2287.                SCI  is  not as smart as a standard C compiler and
  2288.                blindly  evaluates  every  sub-expression   in   a
  2289.                logical expression.    This  can lead to some very
  2290.                hard to find errors if for  example  you  alter  a
  2291.                variable in one of the subexpressions of a logical 
  2292.                operation - sorry folks!  
  2293.  
  2294.  
  2295.  
  2296.      12.1.4. Precedence and Associativity 
  2297.  
  2298.  
  2299.                You can combine as many "and" and "or" clauses as 
  2300.  
  2301.  
  2302.                                      - 37 -
  2303.  
  2304.  
  2305.      Small C Interpreter                                Programmer's Manual
  2306.  
  2307.  
  2308.           necessary: 
  2309.  
  2310.  
  2311.                a==5 || b==3 && c==4
  2312.  
  2313.  
  2314.                This expression will be true under one of two 
  2315.           conditions: 1) b is equal to 3 AND c is equal to 4, or 2) a 
  2316.           is equal to 5. This example shows a very important property 
  2317.           of logical operators that we have already encountered in the 
  2318.           discussion of the arithmetic operators (+, -, *, etc.), 
  2319.           namely precedence.  In C, the && operator takes precedence 
  2320.           (is performed before) the || operator.  
  2321.  
  2322.                As with the arithmetic operators the logical operators 
  2323.           are performed from left to right.  So, if we have more than 
  2324.           one operator of the same precedence in an expression: 
  2325.  
  2326.  
  2327.                a==5 && b==5 && c==5
  2328.  
  2329.           
  2330.           we know that C performs the tests for equality from left to 
  2331.           right.  
  2332.  
  2333.                Although we haven't come right out and said it before, 
  2334.           it should be obvious from the examples that the relational 
  2335.           operators have higher precedence than the logical 
  2336.           operators.  Specifically, >, >=, < and <= have higher 
  2337.           precedence than == and != which have higher precedence than 
  2338.           && which has a higher precedence than ||.  Please refer to 
  2339.           the Language Summary section of the User's Manual for a 
  2340.           complete list of C operators and their order of precedence.  
  2341.  
  2342.                Furthermore, relational operators associate from left 
  2343.           to right, although it is hardly ever necessary to use more 
  2344.           than one consecutive relational: 
  2345.  
  2346.  
  2347.                a == 5 != 1
  2348.  
  2349.  
  2350.                Notice in this example that "a == 5" is performed first 
  2351.           which would result in either a zero or a one.  Examine the 
  2352.           following expression closely: 
  2353.  
  2354.  
  2355.                a < 5 == b < 5
  2356.  
  2357.  
  2358.                                                               ____   
  2359.                This expresion will be true if "a" and "b" are both 
  2360.           ____ ____ _                    ____ _____ __ __ _______ ____   
  2361.           less than 5 or "a" and "b" are both equal to or greater than 
  2362.  
  2363.  
  2364.                                      - 38 -
  2365.  
  2366.  
  2367.      Small C Interpreter                                Programmer's Manual
  2368.  
  2369.  
  2370.           _     
  2371.           5.  
  2372.  
  2373.                As always, whenever you are in doubt about the 
  2374.           associativity or precedence of operators, either use 
  2375.           parentheses to bind operands and operators together, or 
  2376.           consult the table of operators in the User's Manual.  
  2377.  
  2378.  
  2379.      12.1.5. Examples 
  2380.  
  2381.  
  2382.                Finally armed with these new facts about C, we are 
  2383.           ready to try some practical examples using the SCI 
  2384.           interpreter.  Enter the following program using the SCI 
  2385.           editor: 
  2386.  
  2387.  
  2388.                convert(n)
  2389.                {
  2390.                     char c;
  2391.                
  2392.                     puts("to decimal (d), hex (x) or octal (o) ?");
  2393.                     c=getchar();
  2394.                     if(c=='d')
  2395.                          putd(n);
  2396.                     else if(c=='x')
  2397.                          putx(n);
  2398.                     else if(c=='o')
  2399.                          puto(n);
  2400.                     else
  2401.                          puts("what?\n");
  2402.                }
  2403.  
  2404.  
  2405.                As you can probably tell, this is a number conversion 
  2406.           routine.  It asks the operator whether to convert the number 
  2407.           passed to it ("n") to decimal, hexadecimal or octal.  Now at 
  2408.           the shell prompt, type: 
  2409.  
  2410.  
  2411.                > convert( 255 )
  2412.                to decimal (d), hex (x) or octal (o) ?x
  2413.                0xff
  2414.                0
  2415.                >
  2416.  
  2417.  
  2418.                If your screen did not look like the above, there is 
  2419.           something wrong - fix it up and try again.  
  2420.  
  2421.                Now modify the program to accept either lower or upper 
  2422.           case d's, x's and o's (hint: use the || operator).  
  2423.  
  2424.  
  2425.                                      - 39 -
  2426.  
  2427.  
  2428.      Small C Interpreter                                Programmer's Manual
  2429.  
  2430.  
  2431.      12.2. while 
  2432.  
  2433.  
  2434.                One of the things that makes a computer such a powerful 
  2435.           tool is its tireless ability to perform repetitive tasks.  
  2436.           This is why every programming language has some sort of 
  2437.           "looping" flow control.  The C language offers three types 
  2438.           of loop constucts: the "while", "for" and "do-while".  This 
  2439.           version of SCI only supports the "while" and "for".  
  2440.  
  2441.                The "while" flow control looks something like this: 
  2442.  
  2443.  
  2444.                while ( <expression> ) <statement>
  2445.  
  2446.  
  2447.                Notice that its structure is very similar to the "if" 
  2448.           construct and all of the syntactical rules apply as well.  
  2449.           This statement is executed as follows: 
  2450.  
  2451.  
  2452.                1) evaluate <expression> and if it is false, go to step 
  2453.                     4.  
  2454.  
  2455.                2) execute <statement>.  
  2456.  
  2457.                3) go to step 1 
  2458.  
  2459.                4) go on to the next statement in the program.  
  2460.  
  2461.  
  2462.                As with the "if" statement, <expression> is considered 
  2463.           to be true if it evaluates to non-zero, and false if it is 
  2464.           zero.  Let's look at an example: 
  2465.  
  2466.  
  2467.                loop()
  2468.                {
  2469.                     int a;
  2470.                
  2471.                     a = 10;
  2472.                     while ( a > 0 )
  2473.                     {
  2474.                          putd( a );
  2475.                          a = a - 1;
  2476.                     }
  2477.                     puts("all done\n");
  2478.                }
  2479.  
  2480.  
  2481.                This loop will get executed exactly 10 times - each 
  2482.           time the variable "a" is decremented by one until it equals 
  2483.  
  2484.  
  2485.                                      - 40 -
  2486.  
  2487.  
  2488.      Small C Interpreter                                Programmer's Manual
  2489.  
  2490.  
  2491.           zero.  When "a" reaches zero, the expression "a > 0" will 
  2492.           become false and program execution will continue with the 
  2493.           next statement in the program.  
  2494.  
  2495.                There is also a more direct method of breaking out of a 
  2496.           "while" loop without having to wait until control returns 
  2497.           back to the <expression> evaluation and testing.  Using a 
  2498.           "break" statement, you can directly jump out of a "while" 
  2499.           and continue with the next statement in the program.  The 
  2500.           following demonstrates the use of a "break": 
  2501.  
  2502.  
  2503.                loop()
  2504.                {
  2505.                     int i, r;
  2506.                
  2507.                     i = 13560;
  2508.                     putd( i );
  2509.                     while ( 1 )
  2510.                     {
  2511.                          r = i / 10;
  2512.                          if ( r == 0 )
  2513.                               break;
  2514.                          putd( r );
  2515.                          i = r;
  2516.                     }
  2517.                     puts("all done\n");
  2518.                }
  2519.  
  2520.  
  2521.                Since the <expression> is always true (1 is always 
  2522.           non-zero), this loop would be repeated until the cows came 
  2523.           home.  The "if" statement within the loop will break out of 
  2524.           the loop when the remainder of the division results in 
  2525.           zero.  We leave as an exercise for the student to figure out 
  2526.           what this little program does.  
  2527.  
  2528.  
  2529.      12.3. for 
  2530.  
  2531.  
  2532.                The "for" looping construct is similar to the "while". 
  2533.           Its format is as follows: 
  2534.  
  2535.  
  2536.                for ( <expression> ; <expression> ; <expression> ) <statement>
  2537.  
  2538.  
  2539.                The syntactical requirements of the "for" construct are 
  2540.           similiar to those of the "while" - the "for" and the 
  2541.           parentheses and everything between them must be on the same 
  2542.           program line.  Also, the three <expression>'s inside the 
  2543.  
  2544.  
  2545.                                      - 41 -
  2546.  
  2547.  
  2548.      Small C Interpreter                                Programmer's Manual
  2549.  
  2550.  
  2551.           parentheses must be seperated from each other by two 
  2552.           semicolons as shown.  
  2553.  
  2554.                Actually, the "for" is simply a method of clearly 
  2555.           presenting to the reader the most commonly needed elements 
  2556.           relavent to a program loop: an "initialization" part, a 
  2557.           "loop test" part and an "iteration" part.  These three 
  2558.           elements are clearly identifyable, and correspond to 
  2559.           (reading from left to right) the three <expressions> within 
  2560.           the parentheses.  
  2561.  
  2562.                A "for" statement would be executed as follows: 
  2563.  
  2564.  
  2565.                1) evaluate the first <expression>, disregard the 
  2566.                     result.  
  2567.  
  2568.                2) evaluate the second <expression> and if it is false, 
  2569.                     go to step 5.  
  2570.  
  2571.                3) execute <statement>.  
  2572.  
  2573.                4) evaluate the third <expression> and go to step 2.  
  2574.  
  2575.                5) go on to the next statement in the program.  
  2576.  
  2577.  
  2578.                We could have written the first example given for the 
  2579.           "while" using a "for" statement: 
  2580.  
  2581.  
  2582.                loop()
  2583.                {
  2584.                     int a;
  2585.                
  2586.                     for ( a = 10; a > 0; a = a - 1 )
  2587.                          putd( a );
  2588.                }
  2589.  
  2590.  
  2591.                The "break" statement may also be used to break out of 
  2592.           a "for" loop.  One last interesting feature of the "for" is 
  2593.           that any or all of the three <expressions> may be missing.  
  2594.           If the second <expression> is missing, the "loop test" will 
  2595.           always evaluate to true.  Thus, the second example of the 
  2596.           "while" loop above could have been written: 
  2597.  
  2598.  
  2599.  
  2600.  
  2601.  
  2602.  
  2603.  
  2604.  
  2605.                                      - 42 -
  2606.  
  2607.  
  2608.      Small C Interpreter                                Programmer's Manual
  2609.  
  2610.  
  2611.                loop()
  2612.                {
  2613.                     int i, r;
  2614.                
  2615.                     for ( putd( i = 13560 ); ; i = r )
  2616.                     {
  2617.                          r = i / 10;
  2618.                          if ( r == 0 )
  2619.                               break;
  2620.                          putd( r );
  2621.                     }
  2622.                }
  2623.  
  2624.  
  2625.                Here, the three <expressions> are: 
  2626.  
  2627.  
  2628.                putd( i = 12560 )
  2629.                
  2630.                missing!
  2631.                
  2632.                i = r
  2633.  
  2634.  
  2635.                And the most efficient way of writing a "forever" loop 
  2636.           is: 
  2637.  
  2638.  
  2639.                for ( ;; )
  2640.                     puts( "hello, world\n" );
  2641.  
  2642.           
  2643.  
  2644.  
  2645.      12.4. switch 
  2646.  
  2647.  
  2648.                The last and most complex flow control we will examine 
  2649.           is the multi-path "switch" statement.  The "switch" is 
  2650.           similar to BASIC's "ON GOTO" statement.  Here is the 
  2651.           template of a "switch" statement: 
  2652.  
  2653.  
  2654.  
  2655.  
  2656.  
  2657.  
  2658.  
  2659.  
  2660.  
  2661.  
  2662.  
  2663.  
  2664.  
  2665.                                      - 43 -
  2666.  
  2667.  
  2668.      Small C Interpreter                                Programmer's Manual
  2669.  
  2670.  
  2671.                switch ( <expression> )
  2672.                {
  2673.                case <constant expression> : <statement>
  2674.                case <constant expression> : <statement>
  2675.                     .
  2676.                     .
  2677.                     .
  2678.                case <constant expression> : <statement>
  2679.                default : <statement>
  2680.                }
  2681.  
  2682.  
  2683.                Again, the word "switch", the left parenthesis, the 
  2684.           <expression> and the right parenthesis must be on the same 
  2685.           program source line.  The matching left and right curly 
  2686.           brace at the beginning and end of the switch are not 
  2687.           actually required but are necessary as you will soon see.  
  2688.           The words "case" and "default" are only meaningful within 
  2689.           the context of a "switch" statement.  There may be any 
  2690.           number of "case <constant expression> :" sequences but only 
  2691.           one "default :".  The <constant expression>'s are simply 
  2692.           <expression>'s that contain only constants (no variables!).  
  2693.           So, the following would all be examples of <constant 
  2694.           expression>'s: 
  2695.  
  2696.  
  2697.                2 + 2
  2698.                25 * (365 / 7)
  2699.                37/12 > 10
  2700.  
  2701.  
  2702.  
  2703.                                      NOTE   
  2704.                                      NOTE:
  2705.  
  2706.                Standard    C   requires   that   only   <constant
  2707.                expression>'s follow a "case", however SCI  allows
  2708.                you  to  use  any  valid  <expression> as an added
  2709.                bonus.   Keep  this  fact  in  mind  when  writing
  2710.                programs  that  will  eventually be transported to
  2711.                standard C!  
  2712.  
  2713.  
  2714.                The "switch" statement behaves as follows: 
  2715.  
  2716.  
  2717.                1) evaluate the <expression>.  
  2718.  
  2719.                2) compare the results of <expression> to each of the 
  2720.                     <constant expression>'s after the "case's" 
  2721.                     sequentially from top to bottom.  
  2722.  
  2723.                3) if the value of <expression> matches one of the 
  2724.  
  2725.  
  2726.                                      - 44 -
  2727.  
  2728.  
  2729.      Small C Interpreter                                Programmer's Manual
  2730.  
  2731.  
  2732.                     <constant expression>'s, continue program 
  2733.                     execution with the statement immediately following 
  2734.                     the colon.  All other "case" and <constant 
  2735.                     expressions> are ignored.  
  2736.  
  2737.                4) if none of the <constant expression>'s match 
  2738.                     <expression>, jump to the <statement> immediately 
  2739.                     following the word "default" 
  2740.  
  2741.                5) if a "break" statement is encountered, jump to the 
  2742.                     end of the "switch" statement (the <statement> 
  2743.                     immediately following the }).  
  2744.  
  2745.  
  2746.                Although this seems complicated at first, a "switch" is 
  2747.           really just a multi-way program jump.  It allows you to jump 
  2748.           to anywhere within a statement, based on the value of an 
  2749.           expression.  
  2750.  
  2751.                Here's an example of a switch: 
  2752.  
  2753.  
  2754.                convert(n)
  2755.                {
  2756.                     char c;
  2757.                
  2758.                     puts("to decimal (d), hex (x) or octal (o) ?");
  2759.                     switch ( getchar() )
  2760.                     {
  2761.                     case 'd':
  2762.                          putd(n);
  2763.                          break;
  2764.                     case 'x':
  2765.                          putx(n);
  2766.                          break;
  2767.                     case 'o':
  2768.                          puto(n);
  2769.                          break;
  2770.                     default:
  2771.                          puts("what?\n");
  2772.                     }
  2773.                }
  2774.  
  2775.  
  2776.  
  2777.                                      NOTE   
  2778.                                      NOTE:
  2779.  
  2780.                Standard C allows you to place the "default"  word
  2781.                anywhere  within the "switch", and program control
  2782.                will jump  there  only  after  all  of  the  "case
  2783.                <constant  expression>  :"'s have been checked and
  2784.                no match found.   Here  again,  SCI  dares  to  be
  2785.  
  2786.  
  2787.                                      - 45 -
  2788.  
  2789.  
  2790.      Small C Interpreter                                Programmer's Manual
  2791.  
  2792.  
  2793.                different!  If a "default" is encountered before a 
  2794.                matching  "case",  the  program continues with the
  2795.                <statement> following the "default".    Therefore,
  2796.                it  is  a good idea to always place your "default"
  2797.                statements at the end of the "switch".  
  2798.  
  2799.  
  2800.  
  2801.  
  2802.  
  2803.  
  2804.  
  2805.  
  2806.  
  2807.  
  2808.  
  2809.  
  2810.  
  2811.  
  2812.  
  2813.  
  2814.  
  2815.  
  2816.  
  2817.  
  2818.  
  2819.  
  2820.  
  2821.  
  2822.  
  2823.  
  2824.  
  2825.  
  2826.  
  2827.  
  2828.  
  2829.  
  2830.  
  2831.  
  2832.  
  2833.  
  2834.  
  2835.  
  2836.  
  2837.  
  2838.  
  2839.  
  2840.  
  2841.  
  2842.  
  2843.  
  2844.  
  2845.  
  2846.  
  2847.                                      - 46 -
  2848.  
  2849.  
  2850.      Small C Interpreter                                Programmer's Manual
  2851.  
  2852.  
  2853.      13. Arrays 
  2854.  
  2855.  
  2856.                An array in C is a block of contiguous memory locations 
  2857.           (meaning they are located "one after the other" in memory) 
  2858.           that all have the same type ("char" or "int") and can be 
  2859.           accessed individually.  These individual data items in an 
  2860.           array are known as the array's "elements".  You have already 
  2861.           used arrays earlier, in your very first C program, namely 
  2862.           the sequence of ASCII characters in the string "hello, 
  2863.           world\n".  The array's elements are the ASCII characters 
  2864.           'h', 'e', 'l', etc.  This array however, could not be used 
  2865.           to store any information other than that sequence of 
  2866.           characters, just like the integer constant 5 let's say, can 
  2867.           not be used to store a different number.  In this section we 
  2868.           will show you how to create and use arrays for data storage 
  2869.           and retrieval.  
  2870.  
  2871.                Arrays are declared in a similar fashion as simple 
  2872.           variables, but following the array's name you must indicate 
  2873.           how many elements the array will have.  The size of an array 
  2874.           is constant, once it has been declared it can not be 
  2875.           changed.  Below is an example of an array declaration 
  2876.  
  2877.  
  2878.                char vartable[15], macnam[100];
  2879.  
  2880.  
  2881.                This statement declares two arrays that have 15 and 100 
  2882.           elements respectively.  The square brackets ([ and ]) 
  2883.           identifies the variable as being an array, they are also 
  2884.           required when you wish to access one of the array's 
  2885.           elements: 
  2886.  
  2887.  
  2888.                c = vartable[ 5 ];
  2889.  
  2890.  
  2891.                In C, array elements are counted from zero instead of 
  2892.                                                 _____              
  2893.           one, so the above statement takes the sixth element of 
  2894.           "vartable" and stores it in the variable "c". To access the 
  2895.           _____                                         
  2896.           first element of the array, we would write: 
  2897.  
  2898.  
  2899.                vartable[0] = 35;
  2900.  
  2901.                             ____                                 
  2902.           Consequently, the last element of the array would be 
  2903.                              ___                                       
  2904.           "vartable[14]" and not "vartable[15]". In fact, if you did 
  2905.           attempt to store a number in "vartable[15]", you would 
  2906.           overwrite some unknown location in memory that was already 
  2907.           being used as storage for another variable or, worse yet, 
  2908.           that was part of your program code.  The results of 
  2909.  
  2910.  
  2911.                                      - 47 -
  2912.  
  2913.  
  2914.      Small C Interpreter                                Programmer's Manual
  2915.  
  2916.  
  2917.           overrunning a C array like this are unpredictable and are 
  2918.           dependent on the environment the C program is running in 
  2919.           (the type of machine, the C compiler used, etc.) 
  2920.  
  2921.                When the name of an array is used by itself without the 
  2922.           square brackets as in: 
  2923.  
  2924.  
  2925.                i = vartable + 5;
  2926.  
  2927.           it is taken to be a pointer to the first element of the 
  2928.           array.  In the example above, "i" would be assigned the 
  2929.           ______ ________                                        ___   
  2930.           memory location of the sixth element in the array, and not 
  2931.           ___ _____                             
  2932.           the value of this memory location.  
  2933.  
  2934.                The Library Function "gets()" reads a line of input 
  2935.           from the console keyboard and places the characters at the 
  2936.           address pointed to by its argument.  This function waits for 
  2937.           the user to hit a carriage return before it returns to the 
  2938.           caller.  The input line is always terminated with a zero 
  2939.           byte by "gets()" and the carriage return is stripped out.  
  2940.           This makes it suitable for printing by its partner, 
  2941.           "puts()".  Try the following program: 
  2942.  
  2943.  
  2944.                greet()
  2945.                {
  2946.                     char name[ 80 ];
  2947.                
  2948.                     puts("hello, what's your name? ");
  2949.                     gets( name );
  2950.                     puts("nice to meet you, ");
  2951.                     puts( name );
  2952.                     puts(". Have a nice day!\n");
  2953.                }
  2954.  
  2955.  
  2956.  
  2957.  
  2958.  
  2959.  
  2960.  
  2961.  
  2962.  
  2963.  
  2964.  
  2965.  
  2966.  
  2967.  
  2968.  
  2969.  
  2970.  
  2971.  
  2972.  
  2973.                                      - 48 -
  2974.  
  2975.  
  2976.      Small C Interpreter                                Programmer's Manual
  2977.  
  2978.  
  2979.      14. Pointers 
  2980.  
  2981.  
  2982.                The last example above leads us directly into our next 
  2983.           discussion.  In C, you have the ability to access a memory 
  2984.           location by "pointing" at it with a variable.  This type of 
  2985.           variable is known as a "pointer" in C.  
  2986.  
  2987.  
  2988.                                      NOTE   
  2989.                                      NOTE:
  2990.  
  2991.                The number of bytes of storage a pointer  variable
  2992.                needs  depends on the environment the C program is
  2993.                running in.  All 8-bit personal  computers  (8080,
  2994.                z80,   6502,   etc.)   use  2  bytes  for  pointer
  2995.                variables.  The IBM-PC which has an 8088  CPU  may
  2996.                use  either  2  or  4 bytes for pointer variables,
  2997.                depending on the C compiler used.  SCI always uses 
  2998.                2 bytes.  
  2999.  
  3000.  
  3001.                C knows about the type of variable being pointed at 
  3002.           from the pointer's declaration: 
  3003.  
  3004.  
  3005.                char *char_pointer;
  3006.                int *int_pointer;
  3007.  
  3008.  
  3009.                Above we declared two variables, "char_pointer" and 
  3010.           "int_pointer".  The asterisk (*) in the declaration 
  3011.           statement identifies the variables as being pointers.  the 
  3012.           "char" and "int" keywords define the type of variable that 
  3013.           the pointer points to.  To illustrate: 
  3014.  
  3015.  
  3016.                i = *int_pointer;
  3017.  
  3018.  
  3019.                                        _______                      
  3020.                This would retrieve the integer (two bytes in SCI) 
  3021.                                                         ________      
  3022.           found at the memory location addressed by the contents of 
  3023.           "int_pointer", and store it in "i". In this example, we 
  3024.           can't tell what will be stored in "i" because we don't know 
  3025.           what the contents of "int_pointer" is.  Recall from an 
  3026.           earlier discussion that SCI always initializes its variables 
  3027.           to zero so in this case, "i" would contain the two bytes 
  3028.           found in memory locations zero and one 
  3029.  
  3030.                Unless you know what is in memory locations zero and 
  3031.           one, this information is not very useful.  The power of 
  3032.           pointers lies in the fact that they can be made to point at 
  3033.           an array, like this: 
  3034.  
  3035.  
  3036.                                      - 49 -
  3037.  
  3038.  
  3039.      Small C Interpreter                                Programmer's Manual
  3040.  
  3041.  
  3042.                char vartable[15], *cp;
  3043.                
  3044.                cp = vartable;
  3045.                c = *cp;
  3046.                cp = cp+1;
  3047.                d = *cp;
  3048.                cp = cp+1;
  3049.                e = *cp;
  3050.  
  3051.  
  3052.                Here we have set the character pointer "cp" to point at 
  3053.           the first element of the array "vartable", and assigned the 
  3054.           ________                                                     
  3055.           contents of this first element to the variable "c" just by 
  3056.           letting "cp" point at it.  By simply adding one to "cp" we 
  3057.           have made it to point at the next element in "vartable".  
  3058.  
  3059.  
  3060.      14.1. Lvalues and Rvalues Revisited 
  3061.  
  3062.  
  3063.                Pointers are useful because they can be changed (bent?) 
  3064.           to address any location in memory whereas arrays are fixed 
  3065.           and always point to their first element.  For example, if 
  3066.           your tried to do this: 
  3067.  
  3068.  
  3069.                char a[10];
  3070.                
  3071.                a = a + 1;
  3072.  
  3073.  
  3074.                                                                ____   
  3075.                you would get an error message.  The C language does 
  3076.           ___ _____ ___ __ ______ ___ _____ __ __ _____ ________        
  3077.           not allow you to change the value of an array variable.  If 
  3078.           it did there might be the possibility of your program 
  3079.           "forgetting" where the data in the array is located.  Thus 
  3080.           arrays can be put in the same category as strings and 
  3081.           integer constants, namely "rvalues" (see an earlier 
  3082.           discussion on Lvalues and Rvalues).  
  3083.  
  3084.                The attempt to change the array variable "a" in the 
  3085.           example above would therefore reward you with a "need an 
  3086.           lvalue" error message from the SCI interpreter.  
  3087.  
  3088.                Pointers on the other hand are more analagous to 
  3089.           variables - they can be modified and are therefore 
  3090.           considered to be "lvalues".  
  3091.  
  3092.  
  3093.      14.2. Pointer Operator 
  3094.  
  3095.  
  3096.                The asterisk in the examples above is known as the 
  3097.  
  3098.  
  3099.                                      - 50 -
  3100.  
  3101.  
  3102.      Small C Interpreter                                Programmer's Manual
  3103.  
  3104.  
  3105.           "pointer" operator.  This is a unary operator and is used in 
  3106.           the same manner as the negation (-) unary operator.  The 
  3107.           pointer operation tells C to treat its associated pointer 
  3108.           variable as a memory address and to store or retrieve the 
  3109.                                                     _______        
  3110.           data item at that address.  Note that the operand of a 
  3111.           pointer operator must have been declared as a pointer, or C 
  3112.           will complain.  This is in your own best interest because we 
  3113.           humans tend to forget little details like this.  For 
  3114.           example, if you wrote: 
  3115.  
  3116.  
  3117.                char c, d;
  3118.                
  3119.                d = *c;
  3120.  
  3121.           
  3122.           you would get a "not a pointer" error message from SCI.  
  3123.  
  3124.                Now, try typing in this little program using the SCI 
  3125.           editor: 
  3126.  
  3127.  
  3128.                prints(s)
  3129.                char *s;
  3130.                {
  3131.                     while(*s)
  3132.                     {
  3133.                          putchar(*s);
  3134.                          s=s+1;
  3135.                     }
  3136.                }
  3137.  
  3138.  
  3139.                The Library Function "putchar()" accepts a single 
  3140.           argument and prints the ASCII representation of this 
  3141.           argument to the console screen.  This program takes a 
  3142.           pointer to a character string as an argument.  Then, while 
  3143.           the character being pointed at is non-zero, "putchar()" 
  3144.           prints the character onto the console.  The pointer is then 
  3145.           incremented (s=s+1) so that it points at the next character 
  3146.           in the string.  Now execute the following command from the 
  3147.           shell: 
  3148.  
  3149.  
  3150.                > prints("hello, world\n");
  3151.  
  3152.  
  3153.                This should have resulted in the words "hello, world" 
  3154.           printed on the console.  
  3155.  
  3156.                Except for the fact that pointers may be changed and 
  3157.           arrays may not, C treats both of them identically.  For 
  3158.  
  3159.  
  3160.                                      - 51 -
  3161.  
  3162.  
  3163.      Small C Interpreter                                Programmer's Manual
  3164.  
  3165.  
  3166.           example if we have the following two data declarations: 
  3167.  
  3168.  
  3169.                char c, ca[ 10 ];
  3170.                char *cp;
  3171.  
  3172.           we can choose to view the array variable "ca" as a pointer, 
  3173.           and the pointer variable "cp" as an array in our programs, 
  3174.           like so: 
  3175.  
  3176.  
  3177.                c = *ca;
  3178.                cp[ 5 ] = c;
  3179.  
  3180.  
  3181.                So, we could have written the sample program from 
  3182.           before like this: 
  3183.  
  3184.  
  3185.                prints(s)
  3186.                char *s;
  3187.                {
  3188.                     int i;
  3189.                
  3190.                     for ( i=0; s[i]; i=i+1 )
  3191.                          putchar( s[i] );
  3192.                }
  3193.  
  3194.  
  3195.                This would have left the pointer argument "s" unaltered 
  3196.           when the "for" loop was finished.  This is sometimes 
  3197.           necessary, as in the following example: 
  3198.  
  3199.  
  3200.                prints10(s)
  3201.                char *s;
  3202.                {
  3203.                     int i, j;
  3204.                
  3205.                     for ( j=0; j<10; j=j+1 )
  3206.                     {
  3207.                          for ( i=0; s[i]; i=i+1 )
  3208.                               putchar( s[i] );
  3209.                     }
  3210.                }
  3211.  
  3212.           Here the string passed to "prints10()" is printed on the 
  3213.           console ten times.  If we had incremented the character 
  3214.           pointer "s" instead of using the index "i", then the second 
  3215.           time through the outer loop would have started with "s" 
  3216.           pointing to the character after the end of the string.  
  3217.  
  3218.  
  3219.  
  3220.                                      - 52 -
  3221.  
  3222.  
  3223.      Small C Interpreter                                Programmer's Manual
  3224.  
  3225.  
  3226.      14.2.1. Pointer Expressions 
  3227.  
  3228.  
  3229.                We stated that C knows the type of data item a pointer 
  3230.           is pointing to ("char" or "int"). Being a rather dumb (and 
  3231.           therefore compact) interpreter, SCI does not know what type 
  3232.           of data item is being pointed at when the pointer is hidden 
  3233.           in an expression somewhere, like so: 
  3234.  
  3235.  
  3236.                i = *(ip + 5);
  3237.  
  3238.  
  3239.                In this example we are trying to retrieve the data item 
  3240.           pointed at by "ip" and offset by 5. If "ip" was a pointer to 
  3241.           an "int", we would think that we are retrieving the sixth 
  3242.           2-byte integer of the array pointed at by "ip". Physically, 
  3243.           we are interested in the tenth and eleventh bytes in the 
  3244.           array.  The above expression, however, will retrieve only 
  3245.           one byte for us (the sixth byte in the array) instead of 
  3246.           two, and from the wrong place in the array.  This is a 
  3247.           limitation only of SCI - most C compilers are smart enough 
  3248.           to know better and the above statement would have retrieved 
  3249.           the sixth "int" from the array, as expected.  
  3250.  
  3251.                On occasion you may wish to use integer constants as 
  3252.           pointers, like this: 
  3253.  
  3254.  
  3255.                char c;
  3256.                
  3257.                c = *0x0100;
  3258.  
  3259.  
  3260.                When a constant is used as the target of a pointer 
  3261.           operation, SCI will access the two bytes (an "int") at the 
  3262.           location specified by the value of the constant, in this 
  3263.           case at location 100 hex.  You can get as creative as you 
  3264.           want when using constants as pointers: 
  3265.  
  3266.  
  3267.                char c, offs;
  3268.                
  3269.                c = *((0x101 + offs) * 2);
  3270.  
  3271.  
  3272.                Note that SCI will allow you to use variables that have 
  3273.           not been declared as pointers in pointer expressions if they 
  3274.           are enclosed in parentheses as shown above.  
  3275.  
  3276.  
  3277.  
  3278.  
  3279.  
  3280.                                      - 53 -
  3281.  
  3282.  
  3283.      Small C Interpreter                                Programmer's Manual
  3284.  
  3285.  
  3286.                                      NOTE   
  3287.                                      NOTE:
  3288.  
  3289.                Standard C does not  allow  you  to  use  constant
  3290.                expressions as pointers, any attempt to do so will 
  3291.                usually result in an error message.  
  3292.  
  3293.  
  3294.  
  3295.      14.2.2. printf() 
  3296.  
  3297.           C functions do not intrinsically know whether their 
  3298.           arguments are printable strings or just an array or numbers, 
  3299.           like BASIC does.  Therefore there are no C functions that 
  3300.           are analogous to BASIC's PRINT statement which prints either 
  3301.           a number or a string depending on its argument.  The 
  3302.           standard C Library Function "printf()", however, performs a 
  3303.           print operation similar to BASIC's PRINT statement.  
  3304.           "Printf", which is read as "print-eff", stands for "print 
  3305.           formatted".  It is the most unusual standard C function 
  3306.           because it accepts a variable number of arguments, depending 
  3307.           on the contents of its first argument.  The first argument 
  3308.           to "printf" is a string of characters and is known as the 
  3309.           "control string".  "Printf" works like this: it scans 
  3310.           through the characters in the control string and prints them 
  3311.           out on the console screen; if a percent symbol (%) is 
  3312.           encountered in the control string, the character following 
  3313.                                                ________           
  3314.           the "%" determines how printf's next argument will be 
  3315.           processed.  For example, if the character following the "%" 
  3316.           is a lower case letter "s", the next argument is assumed to 
  3317.           be a character string and is printed out to the console 
  3318.           instead of the "%s" character combination.  A "%d" 
  3319.           combination in the control string takes its next argument to 
  3320.           be an integer and prints its decimal value.  "Printf" keeps 
  3321.           track of which arguments have already been printed by a 
  3322.           "%-letter" combination, so that the next "%-letter" 
  3323.           combination affects the next argument in the argument list.  
  3324.  
  3325.                For example, try the following command from the shell: 
  3326.           
  3327.         printf("%s, did you know %d * %d is %d?\n","Bob",376,49,376*49)
  3328.  
  3329.                The "%s" conversion treats the second argument, "Bob" 
  3330.           as a string (which it is!) and prints it; the first "%d" 
  3331.           grabs the next argument in the list (376) and prints it as a 
  3332.           decimal number; the second "%d" prints 49 as a decimal 
  3333.           number; finally, the third "%d" takes the product of 376 and 
  3334.           49 and prints it as a decimal number.  What should have 
  3335.           appeared on your screen is: 
  3336.  
  3337.  
  3338.                Bob, did you know 376 * 49 is 18424?
  3339.  
  3340.  
  3341.  
  3342.                                      - 54 -
  3343.  
  3344.  
  3345.      Small C Interpreter                                Programmer's Manual
  3346.  
  3347.  
  3348.           "Printf" also recognizes these other conversion codes: 
  3349.  
  3350.  
  3351.                 x                                                       
  3352.                %x - prints its argument as a hexadecimal number.  The 
  3353.                     characters "0x" do not appear in the printed 
  3354.                     number - you must add them if needed, like so: 
  3355.  
  3356.  
  3357.                          printf( "%d = 0x%x\n", 376, 376 )
  3358.  
  3359.  
  3360.                 o                                              
  3361.                %o - prints its argument as an octal number.  
  3362.  
  3363.                 c                                                 
  3364.                %c - prints its argument as an ASCII character.  
  3365.  
  3366.  
  3367.  
  3368.      14.3. Address Operator 
  3369.  
  3370.  
  3371.                In an earlier discussion about the scope of variables, 
  3372.           we said when a variable is passed to a function, the called 
  3373.           function creates a clone of the caller's variable and copies 
  3374.           its contents into this local variable.  This way the 
  3375.           function can not alter the contents of the caller's 
  3376.           variable.  How then can we have a function alter the 
  3377.           contents of our local variables if it becomes necessary?  
  3378.           There are several options open to us: 1) write the function 
  3379.           so that it returns a value which we can then assign to our 
  3380.           local variable, 2) have the function put the value into a 
  3381.           global variable which we can access, or 3) pass the function 
  3382.           the address of our local variable.  The first option only 
  3383.           allows the function to pass back one piece of information, 
  3384.           thus limiting its usefulness.  Option 2 is an acceptable 
  3385.           method but forces the function to become more dependent upon 
  3386.           the entire program structure.  This is fine for 
  3387.           application-specific functions, but severly restricts the 
  3388.           modularity of general purpose functions.  The accepted 
  3389.           method is to pass the function the address of our variable 
  3390.           using the "address operator", "&", like so: 
  3391.  
  3392.  
  3393.  
  3394.  
  3395.  
  3396.  
  3397.  
  3398.  
  3399.  
  3400.  
  3401.  
  3402.  
  3403.  
  3404.  
  3405.                                      - 55 -
  3406.  
  3407.  
  3408.      Small C Interpreter                                Programmer's Manual
  3409.  
  3410.  
  3411.                prog()
  3412.                {
  3413.                     char c;
  3414.                
  3415.                     func( &c ); # call "func()", pass the address of "c"
  3416.                }
  3417.                func( ptr )
  3418.                char *ptr;
  3419.                {
  3420.                     *ptr = 12;
  3421.                }
  3422.  
  3423.  
  3424.                The ampersand (&) as used above is a unary operator 
  3425.                                           _______                     
  3426.           that tells C we want to use the address of the associated 
  3427.                                   ________  __ _____ _____  ___   
  3428.           variable instead of its contents. In other words, the 
  3429.           _______ ________ ______ _ _______                     
  3430.           address operator yields a pointer to its associated 
  3431.           operand.  That's why we declared the argument to the 
  3432.           function "func()" as a pointer to a "char".  In the above 
  3433.           example then, the local variable "c" in "prog()" would have 
  3434.           been set to 12 after the call to "func()".  
  3435.  
  3436.                Extreme caution must be exercised when passing pointers 
  3437.           to variables like this.  If we had instead declared "ptr" as 
  3438.           a pointer to an "int" (int *ptr;) in the function, "func()", 
  3439.           then the assignment "*ptr = 12;" would have destroyed the 
  3440.           memory location following "c" and possibly caused the 
  3441.           program to crash.  
  3442.  
  3443.                Note that you may only use the address operator on 
  3444.           lvalues; this means only simple variables and pointers.  If 
  3445.           you try to use the address operator on a constant, a string 
  3446.           or an array you will evoke a "need an lvalue" error from 
  3447.           SCI.  
  3448.  
  3449.                Now enter and test this little program from the SCI 
  3450.           interpreter: 
  3451.  
  3452.  
  3453.  
  3454.  
  3455.  
  3456.  
  3457.  
  3458.  
  3459.  
  3460.  
  3461.  
  3462.  
  3463.  
  3464.  
  3465.  
  3466.  
  3467.  
  3468.                                      - 56 -
  3469.  
  3470.  
  3471.      Small C Interpreter                                Programmer's Manual
  3472.  
  3473.  
  3474.                words()
  3475.                {
  3476.                     char *word, *cp, linebuf[80];
  3477.                
  3478.                     puts("type some words: ");
  3479.                     gets(cp = linebuf);
  3480.                     while(cp) {
  3481.                          cp = parse(cp, &word);
  3482.                          puts("word = <");
  3483.                          puts(word);
  3484.                          puts(">\n");
  3485.                     }
  3486.                }
  3487.                
  3488.                parse(str,word)
  3489.                char *str;
  3490.                int *word;
  3491.                {
  3492.                     while(*str==' ')
  3493.                          ++str;
  3494.                     *word=str;
  3495.                     while(*str!=' ' && *str)
  3496.                          ++str;
  3497.                     if(*str==0)
  3498.                          return 0;
  3499.                     *str=0;
  3500.                     return str+1;
  3501.                }
  3502.  
  3503.           
  3504.           and from the shell execute the function "words()".  What 
  3505.           does this program do?  
  3506.  
  3507.  
  3508.      14.3.1. scanf() 
  3509.  
  3510.  
  3511.                The companion to the Library Function "printf()" is 
  3512.           "scanf()" (read "scan-eff").  This function performs the 
  3513.           reverse operation of "printf()", that is, it converts 
  3514.           strings and numbers read from the console keyboard and 
  3515.           places them into program variables.  This means that its 
  3516.                             ________                                  
  3517.           arguments must be pointers to the appropriate data type.  
  3518.  
  3519.                Examine the following program: 
  3520.  
  3521.  
  3522.  
  3523.  
  3524.  
  3525.  
  3526.  
  3527.  
  3528.  
  3529.                                      - 57 -
  3530.  
  3531.  
  3532.      Small C Interpreter                                Programmer's Manual
  3533.  
  3534.  
  3535.                getname()
  3536.                {
  3537.                     char firstname[20], lastname[20];
  3538.                     int zip;
  3539.                
  3540.                     puts("What is your first, last name and zipcode?");
  3541.                     scanf("%s %s %d", firstname, lastname, &zip );
  3542.                
  3543.                     printf("firstname = %s\n",firstname);
  3544.                     printf("lastname = %s\n",lastname);
  3545.                     printf("zipcode = %d\n",zip);
  3546.                }
  3547.  
  3548.  
  3549.                Scanf assumes that a string is a stream of consecutive 
  3550.           non-blank characters.  The function will not stop reading 
  3551.           input until all of its conversion (%-letter) codes have been 
  3552.           satisfied, or until an end of input (control-Z in MS-DOS) is 
  3553.                                                          __ ___         
  3554.           encountered.  This means that carriage returns do not cause 
  3555.           scanf to quit reading and return to the caller.  Carriage 
  3556.           returns are simply treated as spaces and tabs, collectively 
  3557.           known as "white space".  In the program above, you could 
  3558.           have entered you first and last name on seperate lines if 
  3559.           you like, or on the same line seperated by one or more 
  3560.           spaces or tabs.  
  3561.  
  3562.                                _______                                 
  3563.                Notice that the address of the integer variable "zip" 
  3564.           was passed to scanf; do you now understand why?  If we had 
  3565.           used the following statement instead: 
  3566.  
  3567.  
  3568.                scanf( "%d", zip );
  3569.  
  3570.           
  3571.                    ________                                        
  3572.           then the contents of "zip" would have been used as the 
  3573.           location where scanf would place an integer value.  If the 
  3574.           contents of "zip" had been zero, then memory locations zero 
  3575.           and one would have been altered by scanf, and would have 
  3576.           possibly damaged the operating system.  
  3577.  
  3578.  
  3579.  
  3580.  
  3581.  
  3582.  
  3583.  
  3584.  
  3585.  
  3586.  
  3587.  
  3588.  
  3589.  
  3590.  
  3591.  
  3592.                                      - 58 -
  3593.  
  3594.  
  3595.      Small C Interpreter                                Programmer's Manual
  3596.  
  3597.  
  3598.      15. Increment and Decrement Operators 
  3599.  
  3600.  
  3601.                As we have already seen, we can use several methods to 
  3602.           access elements in an array.  Let's say we had an array and 
  3603.           wanted to access its elements sequentially, one after the 
  3604.           other.  We could either declare a pointer to the array and 
  3605.           then increment the pointer by one; or we could declare an 
  3606.           integer variable to be used as an array index and increment 
  3607.           it each time by one, like so: 
  3608.  
  3609.  
  3610.                char a[10], *p;
  3611.                int i;
  3612.                
  3613.                # set all 10 elements in the array "a" to zero,
  3614.                # using a pointer:
  3615.                p=a;
  3616.                i=0;
  3617.                while(i<10)
  3618.                {
  3619.                     *p = 0;
  3620.                     p=p+1;
  3621.                     i=i+1;
  3622.                }
  3623.                
  3624.                # ...and using an index:
  3625.                i=0;
  3626.                while(i<10)
  3627.                {
  3628.                     a[i] = 0;
  3629.                     i=i+1;
  3630.                }
  3631.  
  3632.           Since these operations comes up often in programming, the C 
  3633.           language offers a very efficient method of incrementing and 
  3634.           decrementing varibles.  These are appropriately enough, 
  3635.           called the "increment" and "decrement" operators, "++" and 
  3636.           "--".  The increment/decrement operators are unary operators 
  3637.           and can appear either before or after a variable name, like 
  3638.           this: 
  3639.  
  3640.  
  3641.                int i;
  3642.                
  3643.                ++i;    # increment "i" by one
  3644.                i++;    # same thing
  3645.                --i;    # decrement "i" by one
  3646.                i--;    # and again
  3647.  
  3648.                                   ______                                
  3649.           If the operator appears before the variable, it is known as 
  3650.                                                          _____       
  3651.           a "pre-" increment or decrement; if it appears after the 
  3652.  
  3653.  
  3654.                                      - 59 -
  3655.  
  3656.  
  3657.      Small C Interpreter                                Programmer's Manual
  3658.  
  3659.  
  3660.           variable, it is a "post-" increment/decrement.  The 
  3661.                                                        ______       
  3662.           pre-inc/dec operators perform their function before the 
  3663.           variable is used in the expression, whereas the post-inc/dec 
  3664.                                            _____                         
  3665.           operators perform their function after the variable has been 
  3666.           used in the expression.  This is best explained with an 
  3667.           example: 
  3668.  
  3669.  
  3670.                incdec()
  3671.                {
  3672.                     int i;
  3673.                
  3674.                     i = 0;
  3675.                     putd( ++i );
  3676.                
  3677.                     i = 0;
  3678.                     putd( i++ );
  3679.                }
  3680.  
  3681.  
  3682.                The first instance of "putd()" would print a 1 - the 
  3683.           variable "i" was increment by one before its value was 
  3684.           passed to "putd()".  Now we set "i" to zero again and the 
  3685.           second call to "putd()" will print a 0. This is because the 
  3686.           post-increment operator passes the value of "i" to the 
  3687.                             ______                                
  3688.           function "putd()" before it gets incremented by one.  
  3689.  
  3690.                These operators are very handy for quickly scanning 
  3691.           through an array like this: 
  3692.  
  3693.  
  3694.                prints(s)
  3695.                char *s;
  3696.                {
  3697.                     while ( *s )
  3698.                          putchar( *s++ );
  3699.                }
  3700.  
  3701.  
  3702.                When using the increment/decrement operators on 
  3703.           pointers, SCI knows what data type the pointer is 
  3704.           referencing and adjusts the pointer so that it points to the 
  3705.           next/previous data item.  In other words, when incrementing 
  3706.           a pointer to an integer, the pointer is incremented by 2 
  3707.           instead of one so that it points to the next integer.  If we 
  3708.           wanted to print out all the numbers in an integer array, we 
  3709.           might do something like this: 
  3710.  
  3711.  
  3712.  
  3713.  
  3714.  
  3715.  
  3716.  
  3717.                                      - 60 -
  3718.  
  3719.  
  3720.      Small C Interpreter                                Programmer's Manual
  3721.  
  3722.  
  3723.                dump()
  3724.                {
  3725.                     int array[ 10 ], *ap;
  3726.                
  3727.                     ap = array;
  3728.                     for ( i=0; i<10; ++i )
  3729.                          printf( "%d\n", *ap++ );
  3730.                }
  3731.  
  3732.  
  3733.  
  3734.  
  3735.  
  3736.  
  3737.  
  3738.  
  3739.  
  3740.  
  3741.  
  3742.  
  3743.  
  3744.  
  3745.  
  3746.  
  3747.  
  3748.  
  3749.  
  3750.  
  3751.  
  3752.  
  3753.  
  3754.  
  3755.  
  3756.  
  3757.  
  3758.  
  3759.  
  3760.  
  3761.  
  3762.  
  3763.  
  3764.  
  3765.  
  3766.  
  3767.  
  3768.  
  3769.  
  3770.  
  3771.  
  3772.  
  3773.  
  3774.  
  3775.  
  3776.  
  3777.                                      - 61 -
  3778.  
  3779.  
  3780.      Small C Interpreter                                Programmer's Manual
  3781.  
  3782.  
  3783.      16. A Tour Through the File I/O Functions 
  3784.  
  3785.  
  3786.                The formal definition of the C language does not really 
  3787.           include any of the Library Functions we have discussed so 
  3788.           far.  However, most of these have become defacto standards 
  3789.           and are considered a part of the language's support 
  3790.           library.  Although the exact usage of support functions may 
  3791.           vary from one compiler implementation to the next, most C 
  3792.           compilers adhere to a "standard" to some degree.  This 
  3793.           section discusses SCI's implementation of the file I/O 
  3794.           functions which is fairly compatible with the "standards" 
  3795.           proposed by the authors of the C language.  
  3796.  
  3797.                This section only attempts to clarify some points 
  3798.           concerning the file I/O functions and is not meant as a 
  3799.           reference.  Please refer to the section in the User's Manual 
  3800.           titled "The Library Function" for exact details about these 
  3801.           functions.  
  3802.  
  3803.  
  3804.  
  3805.      16.1. fopen() 
  3806.  
  3807.  
  3808.                Before a file can be used (read from or written to), it 
  3809.           must first be "opened" with the Library Function "fopen()". 
  3810.           Opening a file ensures that the file exists and is 
  3811.           readable/writable and prepares internal data structures for 
  3812.           dealing with the file.  Before a C program starts up, three 
  3813.           "files" are opened for it by the "operating system", these 
  3814.           are known as the "standard input", "standard output" and 
  3815.           "standard error" file.  These usually default to the user's 
  3816.           console keyboard and screen.  The "standard error" file is 
  3817.           an output file and always defaults to the user's console 
  3818.           screen.  It is usually used by the program to display error 
  3819.           messages.  The reason we like to have two output files is 
  3820.           because we don't want to intermix program error and 
  3821.           informational messages with program output data, and to 
  3822.           insure that error messages always appear on the user's 
  3823.           console.  
  3824.  
  3825.                To open a file, "fopen()" must be called with two 
  3826.           arguments: the file name, and a character string that 
  3827.           defines how the file is to be accessed.  For example, 
  3828.  
  3829.  
  3830.                int channel;
  3831.                
  3832.                channel = fopen( "SHELL.SCI", "r" );
  3833.  
  3834.           would open the file "SHELL.SCI" for reading ("r").  MS-DOS 
  3835.  
  3836.  
  3837.                                      - 62 -
  3838.  
  3839.  
  3840.      Small C Interpreter                                Programmer's Manual
  3841.  
  3842.  
  3843.           allows the file name to be in upper or lower case, other 
  3844.           operating systems may not be so indifferent about file 
  3845.           names.  The second string, known as the "open mode", must 
  3846.           contain either a lower case "r" to open the file for 
  3847.           reading, "w" for writing or "a" for appending.  When a file 
  3848.           is opened for reading, it must already exist or "fopen()" 
  3849.           will return an error code.  If a file is opened for writing, 
  3850.           it may or may not exist; if it does exist, it is first 
  3851.           deleted before the open.  If a file is opened for appending 
  3852.           and the file exists, it is opened for writing, but data is 
  3853.           written to the current end of the file.  If the file does 
  3854.           not exist, an open for append acts like an open for write.  
  3855.           You may also open a file for both reading and writing, 
  3856.           meaning you may intermix read and write functions on the 
  3857.           same file, but see the section on the Library Functions for 
  3858.           more information.  
  3859.  
  3860.                The value returned by "fopen()" is an integer known as 
  3861.           the "channel number" and points to the previously mentioned 
  3862.           internal file control data structure.  This channel number 
  3863.           is then used by the other file read/write functions to 
  3864.           access the file.  If "fopen()" was unable to find the file 
  3865.           (file opened for reading) or the file could not be created 
  3866.           (file opened for writing), it returns a zero, indicating 
  3867.           failure.  
  3868.  
  3869.                The special channel numbers 1, 2 and 3 may be used to 
  3870.           read and write from/to the standard input, output and error 
  3871.           files.  These channel numbers may be used with the file 
  3872.           read/write routines at any time, unless of course you have 
  3873.           closed these channels.  
  3874.  
  3875.  
  3876.      16.2. fclose() 
  3877.  
  3878.           When a file is no longer needed, it should be "closed" by 
  3879.           the program.  Closing a file ensures that the file is safely 
  3880.           stored on disk and it frees up the internal file control 
  3881.           data structure.  
  3882.  
  3883.                This function expects a single argument, the file 
  3884.           pointer: 
  3885.  
  3886.  
  3887.                fclose( fp );
  3888.  
  3889.           
  3890.           and returns a zero if the file was closed successfully, or a 
  3891.           -1 if an error occured (the file was never opened, disk is 
  3892.           write protected, etc.).  
  3893.  
  3894.  
  3895.  
  3896.  
  3897.                                      - 63 -
  3898.  
  3899.  
  3900.      Small C Interpreter                                Programmer's Manual
  3901.  
  3902.  
  3903.      16.3. fgetc() and fputc() 
  3904.  
  3905.  
  3906.                The functions "fgetc()" and "fputc()" are used to read 
  3907.           and write respectively a single character from/to a file.  
  3908.           Both of these functions advance a "file position pointer" 
  3909.           which points to the next character to be read/written 
  3910.           to/from the file.  This file position pointer is one of the 
  3911.           items in the aforementioned internal file control data 
  3912.           structure.  These functions are used like so: 
  3913.  
  3914.  
  3915.                copy(fromfile,tofile)
  3916.                char *fromfile, *tofile;
  3917.                {
  3918.                     int fromchannel, tochannel, c;
  3919.                
  3920.                     fromchannel = fopen( fromfile, "r" );
  3921.                     tochannel = fopen( tofile, "w" );
  3922.                     while ( (c = fgetc( fromchannel )) != -1 )
  3923.                          fputc( c, tochannel );
  3924.                     fclose( fromchannel );
  3925.                     fclose( tochannel );
  3926.                }
  3927.  
  3928.  
  3929.                This little program copies the file whose name is the 
  3930.           string at "fromfile" to the file whose name is at "tofile".  
  3931.  
  3932.                The function "fgets()" returns the character that was 
  3933.           read from the file (a single byte value from 0 to 255) or a 
  3934.           minus one if the end of the file was reached or if some 
  3935.           other error occured.  The function "fputc()" returns the 
  3936.           character that was written or a minus one if an error 
  3937.           occured.  
  3938.  
  3939.  
  3940.      16.4. fgets() and fputs() 
  3941.  
  3942.  
  3943.                You may also read and write disk files a "line" at a 
  3944.           time with the functions "fgets()" and "fputs()". A "line" is 
  3945.           a sequence of characters in the file that end with a newline 
  3946.           ("\n") character.  These are similar to the functions 
  3947.           "gets()" and "puts()", which read and write from/to the 
  3948.           standard input and standard output, with the exception that 
  3949.           the newline character is copied into the line input buffer 
  3950.           by "fgets()" and a newline is automatically appended to 
  3951.           every string written out to the file by "fputs()".  
  3952.  
  3953.                Note that the two functions fputs("hello",2) and 
  3954.           puts("hello") are identical.  
  3955.  
  3956.  
  3957.                                      - 64 -
  3958.  
  3959.  
  3960.      Small C Interpreter                                Programmer's Manual
  3961.  
  3962.  
  3963.      16.5. fread() and fwrite() 
  3964.  
  3965.  
  3966.                Sometimes it is useful to be able to read or write a 
  3967.           file in arbitrarily long "blocks".  For example, suppose we 
  3968.           wanted to store an array of integer numbers in a file.  The 
  3969.           character read/write functions ("fgetc()" and "fputc()") 
  3970.           would work but would be less efficient than writing several 
  3971.           characters at a time.  The functions "fread()" and 
  3972.           "fwrite()" are ideal for these situations: 
  3973.  
  3974.  
  3975.                sortfile()
  3976.                {
  3977.                     int array[ 100 ];
  3978.                     int channel;
  3979.                
  3980.                     channel = fopen( "NUMBERS.DAT", "r" );
  3981.                     fread( array, 200, channel );
  3982.                     fclose( channel );
  3983.                
  3984.                     sort( array, 100 );
  3985.                
  3986.                     channel = fopen( "NUMBERS.DAT", "w" );
  3987.                     fwrite( array, 200, channel );
  3988.                     fclose( channel );
  3989.                }
  3990.                
  3991.                sort(a,n)
  3992.                int a[], n;
  3993.                {
  3994.                     int temp, i, j;
  3995.                
  3996.                     for ( i=0; i<n-2; ++i ) {
  3997.                          for ( j=i; j<n-1; ++j ) {
  3998.                               if ( a[j] > a[j+1] ) {
  3999.                                    temp=a[j];
  4000.                                    a[j]=a[j+1];
  4001.                                    a[j+1]=temp;
  4002.                               }
  4003.                          }
  4004.                     }
  4005.                }
  4006.  
  4007.           This program reads an array of 100 numbers from a file, 
  4008.           sorts them in numeric order and writes them back to the 
  4009.           file.  Note that we asked "fread()" and "fwrite()" for 200 
  4010.           bytes.  Since the array consists of 100 integers and each 
  4011.           integer is 2 bytes, the array is 200 bytes long.  
  4012.  
  4013.                Also, be sure to close a file when it is no longer 
  4014.           needed.  If we had neglected to close the file after the 
  4015.  
  4016.  
  4017.                                      - 65 -
  4018.  
  4019.  
  4020.      Small C Interpreter                                Programmer's Manual
  4021.  
  4022.  
  4023.           "fopen()" for reading, the second call to "fopen()" would 
  4024.           have altered our file pointer.  The value of the first file 
  4025.           pointer would have been destroyed and the internal file 
  4026.           control data structure would have been lost in limbo 
  4027.           forever.  Although this wouldn't have caused any damage, it 
  4028.           is very sloppy programming.  Keep in mind that you have only 
  4029.           10 file control data structures available.  
  4030.  
  4031.  
  4032.      16.6. fseek() and ftell() 
  4033.  
  4034.  
  4035.                All of the file read/write functions advance an 
  4036.           invisible "file position pointer" which determines where in 
  4037.           the file the next character will be read from or written 
  4038.           to.  Sometimes it is necessary to re-read a character or 
  4039.           group of characters in a file, or to write over the current 
  4040.           contents in a file with new data.  The function "fseek()" 
  4041.           can be used to relocate the file position pointer to 
  4042.           anywhere within the file, and allow you to re-read or 
  4043.           re-write data in the file as necessary.  
  4044.  
  4045.                Ftell simply returns the current value of the file 
  4046.           position pointer.  
  4047.  
  4048.                Examine the following sample program: 
  4049.  
  4050.  
  4051.                link()
  4052.                {
  4053.                     int start, current, inchannel, outchannel, c;
  4054.                
  4055.                     inchannel = fopen( "RAW.DAT", "r" );
  4056.                     outchannel = fopen( "LINKED.DAT", "wr" );
  4057.                
  4058.                     start = 0;
  4059.                     fwrite( &start, 2, outchannel );
  4060.                     while ( (c=fgetc( inchannel )) != -1 ) {
  4061.                          if ( fputc( c, outchannel ) == 0x00ff )
  4062.                               current = ftell( outchannel );
  4063.                               fseek( outchannel, start, 0 );
  4064.                               fwrite( ¤t, 2, outchannel );
  4065.                               fseek( outchannel, current, 0 );
  4066.                               start = current;
  4067.                          }
  4068.                     }
  4069.                     fclose( inchannel );
  4070.                     fclose( outchannel );
  4071.                }
  4072.  
  4073.           This program copies the file RAW.DAT to LINKED.DAT. Each 
  4074.           time a byte of all one's (FF hexadecimal) is encountered in 
  4075.  
  4076.  
  4077.                                      - 66 -
  4078.  
  4079.  
  4080.      Small C Interpreter                                Programmer's Manual
  4081.  
  4082.  
  4083.           RAW.DAT, the program backs up to the previous start location 
  4084.           in LINKED.DAT (indicated in the variable "start") and 
  4085.           inserts the file's current file position pointer 
  4086.           ("current").  In other words, the program creates a file 
  4087.           identical to RAW.DAT except that the data in the file 
  4088.           contains information that tells where all of the 0xff's are 
  4089.           located within the file - a linked list.  
  4090.  
  4091.                Since SCI only supports integer variables, this limits 
  4092.           the maximum range of absolute file positioning available 
  4093.           with "fseek()" to 32767 from the beginning or end of the 
  4094.           file.  You can however, position the file pointer to within 
  4095.                                   _______                              
  4096.           +/-32767 bytes from the current position.  This allows you 
  4097.           to position the file pointer anywhere within the file, no 
  4098.           matter how large the file is.  Standard C uses "long" data 
  4099.           variables instead of "int"'s for specifying the file 
  4100.           position offset.  Long's are usually twice the size of an 
  4101.           "int" (four bytes instead of two), which gives you a much 
  4102.           larger range of absolute file positioning.  
  4103.  
  4104.  
  4105.  
  4106.  
  4107.  
  4108.  
  4109.  
  4110.  
  4111.  
  4112.  
  4113.  
  4114.  
  4115.  
  4116.  
  4117.  
  4118.  
  4119.  
  4120.  
  4121.  
  4122.  
  4123.  
  4124.  
  4125.  
  4126.  
  4127.  
  4128.  
  4129.  
  4130.  
  4131.  
  4132.  
  4133.  
  4134.  
  4135.  
  4136.  
  4137.  
  4138.                                      - 67 -
  4139.  
  4140.  
  4141.      Small C Interpreter                                Programmer's Manual
  4142.  
  4143.  
  4144.      17. The Debuger 
  4145.  
  4146.  
  4147.                SCI provides a powerful program debugging facility that 
  4148.           allows you to execute your programs with complete control.  
  4149.           When the debuger is active, it takes control of your program 
  4150.           and allows you to step through the program in a controlled 
  4151.           fashion.  You have the option of either executing a line at 
  4152.           a time, or stop at any line in the program.  From the 
  4153.           debuger you can also examine and change program variables in 
  4154.           the middle of a program run, or execute any valid C 
  4155.           statement.  
  4156.  
  4157.                Besides being a reference for the SCI debug facility, 
  4158.           this section will introduce you to general debugging 
  4159.           strategies, and show you how you can use the SCI debuger to 
  4160.           gain a better knowledge of C program flow.  
  4161.  
  4162.  
  4163.      17.1. Introduction 
  4164.  
  4165.  
  4166.                The SCI debuger operates in what is known as "symbolic" 
  4167.           mode.  As you probably already know, a computer can not 
  4168.           directly execute program instructions written in the C (or 
  4169.           any other higher-level) language.  The C language 
  4170.           instructions must first be converted to machine language and 
  4171.           then executed by the computer.  This is the mode of 
  4172.           operation when using a C compiler.  Alternatively, the C 
  4173.           source code can be directly executed by a program known as 
  4174.           an "interpreter", which is exactly how SCI works.  A C 
  4175.           program that has been compiled is completely unreadable by 
  4176.           us humans - all resemblence to the original C code has been 
  4177.           stripped from the program since it is intended only for the 
  4178.           computer's "eyes". We say that the "symbolic" representation 
  4179.           of a machine readable program has been removed.  On the 
  4180.           other hand, since an interpreter always keeps a "symbolic" 
  4181.           (human readable) form of your program in memory, it is very 
  4182.           easy to follow the program as it is being executed by the 
  4183.           interpreter.  A debuger that has this ability to let the 
  4184.           human reader follow along as the program is executed by the 
  4185.           computer, is known as a "symbolic debuger".  
  4186.  
  4187.                There are basically two types of program errors that 
  4188.           can occur: unrecoverable and recoverable.  Unrecoverable 
  4189.           errors are typified by the computer's refusal to answer to 
  4190.           the programmer's desperate pounding on the keyboard - we say 
  4191.           that the computer has "locked up" and gone south for the 
  4192.           winter.  These errors may be caused by partial or complete 
  4193.           destruction of the program itself, or of the operating 
  4194.           system and usually require you to turn the computer off and 
  4195.           then on again.  Recoverable errors are the kind which do not 
  4196.  
  4197.  
  4198.                                      - 68 -
  4199.  
  4200.  
  4201.      Small C Interpreter                                Programmer's Manual
  4202.  
  4203.  
  4204.           allow the program to run to normal completion and return you 
  4205.           to either the operating system or to the calling program, or 
  4206.           simply "get stuck" in a never ending loop.  The category of 
  4207.           recoverable errors also include incorrect results: 
  4208.  
  4209.  
  4210.                YOU: what is 2 plus 2?
  4211.                COMPUTER: 5
  4212.  
  4213.           
  4214.           and unexpected results: 
  4215.  
  4216.  
  4217.                COMPUTER: shall I delete this file?
  4218.                YOU: No
  4219.                COMPUTER: OK, file deleted!
  4220.  
  4221.  
  4222.                For obvious reasons, SCI's built-in debuger is only 
  4223.           capable of dealing with recoverable errors.  
  4224.  
  4225.                The apporach to finding both of these types of errors 
  4226.           is basically the same: allow the program to run normally up 
  4227.           to the point just before it goes berzerk, then stop and look 
  4228.           at how it got there.  Usually, the hardest task is finding 
  4229.           that point where your program goes over the edge.  You have 
  4230.           two choices: either run the program from the very beginning, 
  4231.           one line at a time until something unexpected happens, or 
  4232.           allow the program to run normally and stop just before the 
  4233.           section of code that is suspect.  The method of executing a 
  4234.           program a line at a time is known as "single-stepping".  
  4235.           Running a program normally and having it stop at a given 
  4236.           line is known as "running to breakpoint".  The SCI debuger 
  4237.           allows you to use both of these approaches in any 
  4238.           combination.  
  4239.  
  4240.  
  4241.      17.2. Enabling the Debuger 
  4242.  
  4243.  
  4244.                The Library Function "trace" is used to turn the SCI 
  4245.           debuger on and off and may be called either from the shell 
  4246.           prompt or from within your program.  A single argument to 
  4247.           "trace" determines whether the debuger will be turned on or 
  4248.           off: if the argument is non-zero the debuger is turned on; 
  4249.           if zero, it is turned off.  Thus, your program would look 
  4250.           like this: 
  4251.  
  4252.  
  4253.  
  4254.  
  4255.  
  4256.  
  4257.  
  4258.                                      - 69 -
  4259.  
  4260.  
  4261.                Small C Interpreter                                Programmer's Manual
  4262.  
  4263.  
  4264.                     func()
  4265.                     {
  4266.                          int i;
  4267.                          .
  4268.                          .
  4269.                          .
  4270.                          trace(1);   # turn debuger ON
  4271.                          while(i<10)   # scrutinize this loop
  4272.                          {
  4273.                               .
  4274.                               .
  4275.                               .
  4276.                          }
  4277.                          trace(0);    # turn debuger OFF again
  4278.                     }
  4279.  
  4280.  
  4281.                You can also turn the debuger on directy from the 
  4282.           keyboard while a program is running.  By pressing the 
  4283.           <ESCAPE> key at any time, the program is stopped in mid 
  4284.           execution and the debuger is turned on.  Thus, if you have a 
  4285.           program that seems to be stuck in a forever loop, you can 
  4286.           get control and take a look at what's causing the problem.  
  4287.  
  4288.                When the debuger gets control of your program, it will 
  4289.           automatically display the line number and program text of 
  4290.           the next line to be executed.  It is important to realize 
  4291.           that the displayed program line has not yet been executed.  
  4292.           Directly below the displayed line is a circumflex that 
  4293.           points the first item in the line that will be executed.  
  4294.           For example, if you had more than one statement on a single 
  4295.           line, you might see: 
  4296.  
  4297.  
  4298.                 12:     i = 10;  putd(i);
  4299.                                      ^
  4300.  
  4301.  
  4302.                The debuger then displays its question mark (?) prompt 
  4303.           and waits for you to enter a command.  Debuger commands 
  4304.           always start with a dot (.) in the first column, followed by 
  4305.           a command mnemonic letter.  You can also enter a C statement 
  4306.           at the debuger's "?"  prompt and have it evaluated and the 
  4307.           results displayed, just like in the shell.  
  4308.  
  4309.                We will now walk through a sample program using the 
  4310.           debuger as a way of introducing you to the debuger 
  4311.           commands.  
  4312.  
  4313.  
  4314.  
  4315.  
  4316.  
  4317.  
  4318.                                      - 70 -
  4319.  
  4320.  
  4321.      Small C Interpreter                                Programmer's Manual
  4322.  
  4323.  
  4324.      17.3. Sample Debug Session 
  4325.  
  4326.  
  4327.                If you haven't done so already, list the sample program 
  4328.           that came with your distribution disk, CALC.SCI, either on 
  4329.           your printer or "TYPE" it out on your screen.  This is a 
  4330.           simple integer calculator program that does addition, 
  4331.           subtraction, multiplication and division.  
  4332.  
  4333.                At the shell prompt, load CALC.SCI then type "calc()" 
  4334.           to start the program.  The program displays its prompt (->) 
  4335.           and waits for you to enter a command.  Try entering some 
  4336.           mathematical expressions: 
  4337.  
  4338.  
  4339.                 > load calc.sci
  4340.                 > calc()
  4341.                 -> 2+2
  4342.                 4
  4343.                 -> 2+3*4
  4344.                 14
  4345.                 -> 3*4+2
  4346.                 14
  4347.                 -> 2-30/2
  4348.                 -13
  4349.  
  4350.  
  4351.                Notice that the program is smart enough to know that 
  4352.           multiplication and division have higher precedence than 
  4353.           addition and subtraction.  To get out of the program and 
  4354.           back to the shell, type an "x": 
  4355.  
  4356.  
  4357.                 -> x
  4358.                 0
  4359.                 >
  4360.  
  4361.  
  4362.                Now, let's try the same scenario but this time turn on 
  4363.           the SCI debuger before you start the calculator: 
  4364.  
  4365.  
  4366.                 > trace(1)
  4367.                 0
  4368.                 > calc()
  4369.                 cmd:calc()
  4370.                         ^
  4371.                 ?
  4372.  
  4373.  
  4374.                The debuger displays the C statement you entered on the 
  4375.           shell's command line and prompts you with its "?"  prompt 
  4376.  
  4377.  
  4378.                                      - 71 -
  4379.  
  4380.  
  4381.      Small C Interpreter                                Programmer's Manual
  4382.  
  4383.  
  4384.           and waits for you to enter a command.  For now, just type a 
  4385.           few <RETURN>'s: 
  4386.  
  4387.  
  4388.                 ?
  4389.                  4:calc()
  4390.                        ^
  4391.                 ?
  4392.                  5:{
  4393.                     ^
  4394.                 ?
  4395.                  6:   char line[ 80 ];
  4396.                          ^
  4397.                 ?
  4398.                  8:   Stacktop = 10;
  4399.                               ^
  4400.                 ?
  4401.                  9:   while(1)
  4402.                             ^
  4403.                 ?
  4404.  
  4405.  
  4406.                The program is being executed one line at a time each 
  4407.           time a <RETURN> is hit.  Notice that each line is displayed 
  4408.           preceded by the line number of the program.  The statement 
  4409.           you entered from the shell that started up the calculator is 
  4410.           not a part of the program, and instead was preceded with a 
  4411.           "cmd:" to indicate this fact.  
  4412.  
  4413.  
  4414.      17.3.1. Exiting the Debuger 
  4415.  
  4416.  
  4417.                To halt the program and return back to the shell, use 
  4418.           the debuger's "quit" command: 
  4419.  
  4420.  
  4421.                 ? .q
  4422.                 0
  4423.                 >
  4424.  
  4425.  
  4426.                Now we're back to the shell's prompt.  The ".q" command 
  4427.           stopped the program and turned the debuger off.  Since we 
  4428.           want to experiment some more, turn the debuger back on again 
  4429.           and start up the program: 
  4430.  
  4431.  
  4432.  
  4433.  
  4434.  
  4435.  
  4436.  
  4437.  
  4438.                                      - 72 -
  4439.  
  4440.  
  4441.                Small C Interpreter                                Programmer's Manual
  4442.  
  4443.  
  4444.                 > trace(1)
  4445.                 0
  4446.                 > calc()
  4447.                 cmd:calc()
  4448.                         ^
  4449.                 ?
  4450.  
  4451.  
  4452.  
  4453.      17.3.2. Single Stepping 
  4454.  
  4455.  
  4456.                You can execute more than one program line at a time 
  4457.           with the "step" command.  At the "?"  prompt, type ".s" 
  4458.           followed by the number of program lines you want to execute: 
  4459.  
  4460.  
  4461.                 ? .s 4
  4462.                  9:   while(1)
  4463.                            ^
  4464.                 ?
  4465.  
  4466.  
  4467.                The debuger executed 4 lines, then stopped.  This is 
  4468.           useful when you want to get through a section of code 
  4469.           quickly without having to hit <RETURN> and waiting for each 
  4470.           line to be displayed.  The "continue" command is equivalent 
  4471.           to a ".s" with an infinitely large step count: 
  4472.  
  4473.  
  4474.                 ? .c
  4475.                 -> 2+2
  4476.                 4
  4477.                 ->
  4478.  
  4479.  
  4480.                The program appears to be running slower than when it 
  4481.           was run with the debuger turned off.  This is because the 
  4482.           debuger is still in control of the program, and must examine 
  4483.           each line before it is executed.  The usefulness of the ".c" 
  4484.           command will become apparent later when we discuss 
  4485.           breakpoints.  To return back to the debuger prompt, hit an 
  4486.           <ESCAPE> while the program is running.  If the program is 
  4487.           waiting for input from the console, hitting the <ESCAPE> key 
  4488.           will have no effect.  So type some mathematical expression 
  4489.           as before, hit a <RETURN> and then quickly hit the <ESCAPE> 
  4490.           key: 
  4491.  
  4492.  
  4493.  
  4494.  
  4495.  
  4496.  
  4497.  
  4498.                                      - 73 -
  4499.  
  4500.  
  4501.                Small C Interpreter                                Programmer's Manual
  4502.  
  4503.  
  4504.                 -> 2+3*4
  4505.                 interrupt
  4506.                 36:   while(1)
  4507.                            ^
  4508.                 ?
  4509.  
  4510.  
  4511.                When the <ESCAPE> is hit, the debuger displays an 
  4512.           "interrupt" message, followed by the program line it was 
  4513.           currently working on.  
  4514.  
  4515.  
  4516.      17.3.3. Displaying Global Variables 
  4517.  
  4518.  
  4519.                At any time the debuger is waiting for input you may 
  4520.           display all of the program's global variables and their 
  4521.           contents with the "global" command: 
  4522.  
  4523.  
  4524.                 ? .g
  4525.                    char *Lineptr (0xc334) = "2+3*4"
  4526.                    int   Stack[10] (0xc320) =  4  2  0  0  0  0  0  0  0  0
  4527.                    int   Stackpt = 0
  4528.                    int   Stackto = 10
  4529.                 ?
  4530.  
  4531.  
  4532.                The ".g" command displays each variable along with its 
  4533.           data type ("char" or "int").  If the variable is an array or 
  4534.           a pointer, its address is also printed in hexadecimal, for 
  4535.           example (0xc352). Following that, the variable's value is 
  4536.           displayed.  If the variable is an array or a pointer, the 
  4537.           first ten items in the array are displayed.  Character 
  4538.           arrays are printed as strings, integer arrays as a series of 
  4539.           decimal numbers.  
  4540.  
  4541.                Another form of the ".g" command, ".G", will display 
  4542.           all of the program's functions and their program line 
  4543.           numbers in addition to global variables: 
  4544.  
  4545.  
  4546.  
  4547.  
  4548.  
  4549.  
  4550.  
  4551.  
  4552.  
  4553.  
  4554.  
  4555.  
  4556.  
  4557.  
  4558.                                      - 74 -
  4559.  
  4560.  
  4561.                Small C Interpreter                                Programmer's Manual
  4562.  
  4563.  
  4564.                 ? .G
  4565.                    char *Lineptr (0xc334) = "2+3*4"
  4566.                    int   Stack[10] (0xc320) =  4  2  0  0  0  0  0  0  0  0
  4567.                    int   Stackpt = 0
  4568.                    int   Stackto = 10
  4569.                  4:calc()
  4570.                 22:number()
  4571.                 32:addition()
  4572.                 57:multiplication()
  4573.                 82:push( n )
  4574.                 89:pop()
  4575.                 96:isdigit( c )
  4576.                 ?
  4577.  
  4578.  
  4579.  
  4580.      17.3.4. Breakpoints 
  4581.  
  4582.  
  4583.                Next we will discuss one of the most powerful features 
  4584.           of the debuger: breakpoints.  Let's say we wanted to stop 
  4585.           the program every time the functions "push" and "pop" were 
  4586.           called, so that we could inspect the program's state.  
  4587.           Looking at the debuger's output from the ".G" command above, 
  4588.           we see that these functions are located at lines 82 and 89 
  4589.           respectively.  To set breakpoints at these line numbers, we 
  4590.           would enter the following two commands: 
  4591.  
  4592.  
  4593.                 ? .b 82
  4594.                 breakpoint set:
  4595.                 82:push( n )
  4596.                 ? .b 89
  4597.                 breakpoint set:
  4598.                 89:pop()
  4599.                 ?
  4600.  
  4601.  
  4602.                The debuger prints the program line at which the 
  4603.           breakpoint is set for verification.  
  4604.  
  4605.                You may set a maximum of 5 breakpoints at any one 
  4606.           time.  To display all of the breakpoints that are currently 
  4607.           set, use the ".B" command: 
  4608.  
  4609.  
  4610.                 ? .B
  4611.                 82:push( n )
  4612.                 89:pop()
  4613.                 ?
  4614.  
  4615.  
  4616.  
  4617.  
  4618.                                      - 75 -
  4619.  
  4620.  
  4621.      Small C Interpreter                                Programmer's Manual
  4622.  
  4623.  
  4624.                Now we can continue executing the program normally and 
  4625.           it should stop as soon as either the "push" or "pop" 
  4626.           functions are called.  This is where the ".c" command is 
  4627.           used: 
  4628.  
  4629.  
  4630.                 ? .c
  4631.                 breakpoint:
  4632.                 82:push( n )
  4633.                        ^
  4634.                 ?
  4635.  
  4636.  
  4637.                As soon as a breakpoint is reached, the debuger 
  4638.           announces this fact and displays the program line at the 
  4639.           breakpoint.  To delete a breakpoint, use the "delete 
  4640.           breakpoint" command: 
  4641.  
  4642.  
  4643.                 ? .d 82
  4644.                 breakpoint deleted:
  4645.                 82:push( n )
  4646.                 ?
  4647.  
  4648.  
  4649.                Again, the program line at which the breakpoint was 
  4650.           deleted is displayed for verification.  When a breakpoint is 
  4651.           deleted, the debuger will no longer stop at this program 
  4652.           line after a ".c" command.  
  4653.  
  4654.                To delete all breakpoints set, use the ".D" command: 
  4655.  
  4656.  
  4657.                 ? .D
  4658.                 all breakpoints deleted
  4659.                 ?
  4660.  
  4661.  
  4662.  
  4663.      17.3.5. Function Call Trace Back 
  4664.  
  4665.  
  4666.                Using breakpoints we can be certain of only one fact: 
  4667.           the program started at point "A", and stopped at point "B". 
  4668.           We know nothing about the route it took in getting there.  
  4669.           The debuger's "trace back" command at least tells us the 
  4670.           order of function calls that got us to point "B": Continuing 
  4671.           with our debuging session, type the following command: 
  4672.  
  4673.  
  4674.  
  4675.  
  4676.  
  4677.  
  4678.                                      - 76 -
  4679.  
  4680.  
  4681.                Small C Interpreter                                Programmer's Manual
  4682.  
  4683.  
  4684.                 ? .t
  4685.                 82:push( n )
  4686.                 22:number()
  4687.                 57:multiplication()
  4688.                 32:addition()
  4689.                  4:calc()
  4690.                 ?
  4691.  
  4692.  
  4693.                The function call trace back printed by the ".t" 
  4694.           command is read backwards from bottom to top.  In other 
  4695.           words in the above display, the function "calc" (which is 
  4696.           the starting point) called "addition", which in turn called 
  4697.           "multiplication", and so on.  
  4698.  
  4699.                A variation of the "trace back" command, ".T", will 
  4700.           also display all local variables and their contents for each 
  4701.           function in the trace back: 
  4702.  
  4703.  
  4704.                 ? .T
  4705.                 82:push( n )
  4706.                    int   n = 2
  4707.                 22:number()
  4708.                 57:multiplication()
  4709.                    int   num = 0
  4710.                 32:addition()
  4711.                    int   num = 0
  4712.                  4:calc()
  4713.                    char  line[80] (0xc334) = "2+3*4"
  4714.                 ?
  4715.  
  4716.  
  4717.                The local variables are displayed in a similar format 
  4718.           as for the ".g" command.  
  4719.  
  4720.  
  4721.      17.3.6. Examine a Program 
  4722.  
  4723.  
  4724.                You may also use the SCI editor to examine your 
  4725.           program.  The editor will not allow you make any changes 
  4726.           when invoked from the debuger, since this could completely 
  4727.           alter the state of the current program run.  To "examine" 
  4728.           your program, type: 
  4729.  
  4730.  
  4731.                 ? .e
  4732.  
  4733.  
  4734.                The screen is erased and the editor is started up with 
  4735.           the cursor resting on the line in the program that is to be 
  4736.  
  4737.  
  4738.                                      - 77 -
  4739.  
  4740.  
  4741.      Small C Interpreter                                Programmer's Manual
  4742.  
  4743.  
  4744.           executed next.  You may move about freely in the editor, but 
  4745.           you may not make any changes.  
  4746.  
  4747.                When you exit the editor (with a ^Z) the debuger knows 
  4748.           which line the cursor was on when you left the editor, and 
  4749.           you may set a breakpoint at that line by just giving the 
  4750.                        _______                   
  4751.           ".b" command without a line number.  
  4752.  
  4753.  
  4754.  
  4755.  
  4756.  
  4757.  
  4758.  
  4759.  
  4760.  
  4761.  
  4762.  
  4763.  
  4764.  
  4765.  
  4766.  
  4767.  
  4768.  
  4769.  
  4770.  
  4771.  
  4772.  
  4773.  
  4774.  
  4775.  
  4776.  
  4777.  
  4778.  
  4779.  
  4780.  
  4781.  
  4782.  
  4783.  
  4784.  
  4785.  
  4786.  
  4787.  
  4788.  
  4789.  
  4790.  
  4791.  
  4792.  
  4793.  
  4794.  
  4795.  
  4796.  
  4797.  
  4798.  
  4799.                                      - 78 -
  4800.  
  4801.  
  4802.      Small C Interpreter                                Programmer's Manual
  4803.  
  4804.  
  4805.      18. The Shell 
  4806.  
  4807.  
  4808.                This section will discuss in detail the operation of 
  4809.           the program found in the file SHELL.SCI. We will also show 
  4810.           you how to customize the shell program to suit your needs.  
  4811.  
  4812.                If you haven't done so already, print out the shell 
  4813.           program file or "TYPE" it out on your console screen.  As 
  4814.           you can see there are basically 2 sections of this program: 
  4815.           the first section declares all of the Library Functions 
  4816.           ("sys" call interfaces), The second section starts 
  4817.           immediately after the "entry" keyword with the function 
  4818.           "main()". This is the function that is executed after 
  4819.           SHELL.SCI has been loaded into memory.  Let's examine this 
  4820.           function more closely now: 
  4821.  
  4822.  
  4823.  
  4824.  
  4825.  
  4826.  
  4827.  
  4828.  
  4829.  
  4830.  
  4831.  
  4832.  
  4833.  
  4834.  
  4835.  
  4836.  
  4837.  
  4838.  
  4839.  
  4840.  
  4841.  
  4842.  
  4843.  
  4844.  
  4845.  
  4846.  
  4847.  
  4848.  
  4849.  
  4850.  
  4851.  
  4852.  
  4853.  
  4854.  
  4855.  
  4856.  
  4857.  
  4858.  
  4859.                                      - 79 -
  4860.  
  4861.  
  4862.      Small C Interpreter                                Programmer's Manual
  4863.  
  4864.  
  4865.                43: entry
  4866.                44: 
  4867.                45: char ln[80];
  4868.                46: char pr[20000];
  4869.                47: 
  4870.                48: main()
  4871.                49: {
  4872.                50:    int f, t;
  4873.                51: 
  4874.                52:    puts(sys(0));
  4875.                53:    puts("\nShell V1.3 15Mar86 Copyright (C) 1986 Bob Brodt\n");
  4876.                54:    _nr=25; _nc=80;
  4877.                55:    _ro=_co=1;
  4878.                56:    _cp="\033[%d;%dH";
  4879.                57:    _el="\033[K";
  4880.                58:    _mhz=5; 
  4881.                59:    *pr='Z';
  4882.                60: 
  4883.                61:    for(;;) {
  4884.                62:       puts("> ");
  4885.                63:       ln[5]=0;
  4886.                64:       if(gets(ln)) {
  4887.                65:          if (!strncmp(ln,"edit",4))
  4888.                66:             sys(atoi(ln+4),pr,19);
  4889.                67:          else if (!strncmp(ln,"list",4)) {
  4890.                68:             f=1;
  4891.                69:             t=32765;
  4892.                70:             if(ln[4])
  4893.                71:                sscanf(ln+4,"%d %d",&f,&t);
  4894.                72:             sys(pr,f,t,27);
  4895.                73:          }
  4896.                74:          else if (!strncmp(ln,"save",4))
  4897.                75:             sys(ln+5,pr,26);
  4898.                76:          else if (!strncmp(ln,"load",4))
  4899.                77:             sys(ln+5,pr,25);
  4900.                78:          else if (!strcmp(ln,"exit"))
  4901.                79:             exit();
  4902.                80:          else
  4903.                81:             printf("\n%d\n",sys(ln,pr,16));
  4904.                82:       }
  4905.                83:    }
  4906.                84: }
  4907.  
  4908.  
  4909.                Note that we have included line numbers here for 
  4910.           reference.  
  4911.  
  4912.                The data declarations at lines 45 and 46 are the 
  4913.           shell's input line buffer (ln[80]) and user program buffer 
  4914.           (pr[20000]) respectively.  Lines 52 and 53 of course print 
  4915.           the program identification banners.  Lines 54 through 58 
  4916.           assign the editor's customization variables (for the IBM PC 
  4917.  
  4918.  
  4919.                                      - 80 -
  4920.  
  4921.  
  4922.      Small C Interpreter                                Programmer's Manual
  4923.  
  4924.  
  4925.           in this version).  Line 61 starts a "forever" loop that can 
  4926.           only terminated by the call to the function "exit()" at line 
  4927.           79.  This loop starts out by displaying the shell prompt ("> 
  4928.           ") on the console screen, then waiting for a line of input 
  4929.           from the console keyboard.  The input line buffer stores the 
  4930.           C statement read in from the console at line 64. It is then 
  4931.           compared to each of the strings "edit", "list", "save", 
  4932.           "load" and "exit".  If the first four characters in the 
  4933.           input buffer don't match any of these strings, the line is 
  4934.           assumed to be a C statement and handed off to the 
  4935.           interpreter (via "sys" function 16) for execution.  
  4936.  
  4937.                The program buffer, "pr" is used to store the user's 
  4938.           program functions and variables.  The user can enter data 
  4939.           into this buffer only by way of the SCI program editor 
  4940.           ("sys" function 19).  In fact, the program buffer is 
  4941.           completely hidden from the user - any attempt to reference 
  4942.           it via a C statement (for example "putchar( pr[0] )") will 
  4943.           result in an "undefined symbol" error message.  The user's 
  4944.           program in the "pr" buffer is in "tokenized" form.  That is, 
  4945.           each language element (variables, keywords, punctuation, 
  4946.           etc.) has been encoded so that it can be more easily and 
  4947.           quickly recognized by the interpreter.  The tokenized form 
  4948.           of a program bears almost no resemblance to the 
  4949.           human-readable form and should not be tampered with.  
  4950.  
  4951.  
  4952.      18.1. Customizing the Shell 
  4953.  
  4954.  
  4955.                Now we will show you how you can customize this 
  4956.           program.  Start up SCI and when the shell's prompt appears, 
  4957.           enter the command: 
  4958.  
  4959.  
  4960.                > load shell.sci
  4961.  
  4962.           
  4963.           to load the shell file.  Now edit the program from SCI's 
  4964.           editor and remove all lines from the beginning of the 
  4965.           program up to and including the "entry" keyword.  Next let's 
  4966.           change the string on line 62 (above) to something like: 
  4967.           "yes, dear?  ".  Finally, replace the "exit()" on line 79 
  4968.           with a "return".  
  4969.  
  4970.                Exit the editor and from the shell prompt type: 
  4971.  
  4972.  
  4973.                > main()
  4974.  
  4975.  
  4976.                You should see the program identification banner again 
  4977.  
  4978.  
  4979.                                      - 81 -
  4980.  
  4981.  
  4982.      Small C Interpreter                                Programmer's Manual
  4983.  
  4984.  
  4985.           and the new shell's prompt, "yes, dear?  "!  You can now do 
  4986.           everything from this new shell that you did from the 
  4987.           original shell - write programs with the editor, save them, 
  4988.           list them and load them.  When you type "exit" to this new 
  4989.           shell however, you are returned to the original shell 
  4990.           because we replaced the "exit to DOS" function call with a 
  4991.           "return" to caller.  Since the caller was the original 
  4992.           shell, you are returned to its "> " prompt.  
  4993.  
  4994.                Type an "exit" now to get back to the first shell and 
  4995.           from there do a "save newshell".  Then type "main()" again 
  4996.           to get the "yes, dear?  " shell.  From here, type "load 
  4997.           newshell" to load the newshell program.  Edit the newshell 
  4998.           program and change the "yes, dear?  " prompt to something 
  4999.           like: "you again?  ". Now exit the editor and at the "yes, 
  5000.           dear?  " prompt type "main()". You should again see the 
  5001.           program logon banner and the new shell prompt "you again?  
  5002.           ", like this: 
  5003.  
  5004.  
  5005.                yes, dear? main()
  5006.                Small C Interpreter V1.3 15Mar86 Copyright (C) 1986 Bob Brodt
  5007.                Shell V1.3 15Mar86 Copyright (C) 1986 Bob Brodt
  5008.                you again?
  5009.  
  5010.  
  5011.                In all, we now have 3 different shell programs running, 
  5012.           one on top of the other, and we could actually continue 
  5013.           doing this until we run out of memory!  This is exactly 
  5014.           analagous to the layers of an onion: each layer gets smaller 
  5015.           as you go towards the center of the onion, just as the 
  5016.           amount of usable memory becomes less as each new shell 
  5017.           program is loaded from the previous shell.  
  5018.  
  5019.                Now return to the original shell like so: 
  5020.  
  5021.  
  5022.                you again? exit
  5023.                0
  5024.                yes, dear? exit
  5025.                0
  5026.                >
  5027.  
  5028.  
  5029.                It now becomes an easy task to customize the shell 
  5030.           program to your heart's content using the SCI editor, test 
  5031.           it from the SCI interpreter environment and when it's fully 
  5032.           debuged, save it to disk.  Of course you must remember to 
  5033.           insert the Library Function declarations and the "entry" 
  5034.           keyword before the new shell "main()" function if you intend 
  5035.           to replace SHELL.SCI with the new program.  
  5036.  
  5037.  
  5038.  
  5039.                                      - 82 -
  5040.  
  5041.  
  5042.      Small C Interpreter                                Programmer's Manual
  5043.  
  5044.  
  5045.                As an exercise, add a directory listing command to the 
  5046.           shell, using the following program as a guide.  If are 
  5047.           having difficulty, you may peek at the answers on the next 
  5048.           page...  
  5049.  
  5050.  
  5051.                dir(pat)
  5052.                {
  5053.                     char file[16];
  5054.                     int t;
  5055.                
  5056.                     t=0;
  5057.                     if(pat)
  5058.                          f=scandir(pat,file);
  5059.                     else
  5060.                          f=scandir("*.*",file);
  5061.                     while(f) {
  5062.                          printf("%-20s",file);
  5063.                          ++t;
  5064.                          f=scandir(0,file);
  5065.                     }
  5066.                     if(t%4)
  5067.                          putchar('\n');
  5068.                }
  5069.  
  5070.  
  5071.  
  5072.  
  5073.  
  5074.  
  5075.  
  5076.  
  5077.  
  5078.  
  5079.  
  5080.  
  5081.  
  5082.  
  5083.  
  5084.  
  5085.  
  5086.  
  5087.  
  5088.  
  5089.  
  5090.  
  5091.  
  5092.  
  5093.  
  5094.  
  5095.  
  5096.  
  5097.  
  5098.  
  5099.                                      - 83 -
  5100.  
  5101.  
  5102.      Small C Interpreter                                Programmer's Manual
  5103.  
  5104.  
  5105.                     .
  5106.                     .
  5107.                     .
  5108.                     exit();
  5109.                else if (!strncmp(ln,"dir",3)) {
  5110.                     char file[16];
  5111.                
  5112.                     t=0;
  5113.                     if(ln[3]) f=scandir(ln+4,file);
  5114.                     else f=scandir("*.*",file);
  5115.                     while(f) {
  5116.                          printf("%-20s",file);
  5117.                          ++t;
  5118.                          f=scandir(0,file);
  5119.                     }
  5120.                     if(t%4) putchar('\n');
  5121.                }
  5122.                else
  5123.                     .
  5124.                     .
  5125.                     .
  5126.  
  5127.  
  5128.  
  5129.      18.2. DOS Command Line Arguments to the Shell 
  5130.  
  5131.  
  5132.                A mechanism has been provided to pass operating system 
  5133.           command line arguments to the shell in a way similar to most 
  5134.           commercially available C compilers.  By specifying a "-A" on 
  5135.           the MS-DOS command lines, all arguments to the right of the 
  5136.           "-A" will be ignored by SCI and instead passed to the shell 
  5137.           program.  
  5138.  
  5139.                SCI always passes two arguments to the "entry" program 
  5140.           in the startup file, although the program is free to use or 
  5141.           ignore these arguments.  These are: a count of the number of 
  5142.           arguments following the "-A" option on the DOS command line 
  5143.           and; A pointer to the array of strings that contain these 
  5144.           arguments.  These arguments are commonly declared as "argc" 
  5145.           (argument count) and "argv" (argument vector) in the C 
  5146.           community.  
  5147.  
  5148.                Make the following changes and additions to the program 
  5149.           in SHELL.SCI: 
  5150.  
  5151.  
  5152.  
  5153.  
  5154.  
  5155.  
  5156.  
  5157.  
  5158.  
  5159.                                      - 84 -
  5160.  
  5161.  
  5162.      Small C Interpreter                                Programmer's Manual
  5163.  
  5164.  
  5165.                     .
  5166.                     .
  5167.                     .
  5168.                main(argc, arv)
  5169.                int argc, *argv;
  5170.                {
  5171.                     int i;
  5172.                
  5173.                     while ( i<argc )
  5174.                     {
  5175.                          puts(argv[i++]);
  5176.                          putchar('\n');
  5177.                     }
  5178.                     .
  5179.                     .
  5180.                     .
  5181.                }
  5182.  
  5183.  
  5184.                Then, when the following command is entered at the 
  5185.           operating system level: 
  5186.  
  5187.  
  5188.                A>SCI -A Hello out there!
  5189.  
  5190.           
  5191.           the shell program would start up like this: 
  5192.  
  5193.  
  5194.                Hello
  5195.                out
  5196.                there!
  5197.                Small C Interpreter V1.3M 15Mar86 Copyright (C) 1986 Bob Brodt
  5198.                Shell V1.3M 15Mar86 Copyright (C) 1986 Bob Brodt
  5199.                >
  5200.  
  5201.  
  5202.                Note that since SCI does not support pointers to 
  5203.           pointers, the "argv" variable must be declared as a pointer 
  5204.           to "int". Then, each "argv[i]" is a pointer to a string that 
  5205.           points to one of the words passed on the command line.  
  5206.  
  5207.  
  5208.  
  5209.  
  5210.  
  5211.  
  5212.  
  5213.  
  5214.  
  5215.  
  5216.  
  5217.  
  5218.  
  5219.                                      - 85 -
  5220.  
  5221.