[comp.sources.misc] v10i007: Calctool V2.4 - a simple calculator

richb@Aus.Sun.COM (Rich Burridge) (01/16/90)

Posting-number: Volume 10, Issue 7
Submitted-by: richb@Aus.Sun.COM (Rich Burridge)
Archive-name: calctool24/part02

---- Cut Here and unpack ----
#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file calctool.ps continued
#
CurArch=2
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file calctool.ps"
sed 's/^X//' << 'SHAR_EOF' >> calctool.ps
X%  correct place.
X
X/PSMakeFrames      % wx wy width height ix iy iconic => -
X{
X  [ /IsIcon /IconY /IconX /KCHeight /KCWidth /KCY /KCX ]
X  { exch def } forall
X
X%  /ScreenHeight /size framebuffer send exch def pop
X  /ScreenHeight 900 def
X
X  /KFrame [KeyClass] [/Footer false /Label false]
X    framebuffer /new OpenLookBaseFrame send def
X  /KC /client KFrame send def
X  KCWidth KCHeight /lockminsize KC send 
X  calctoolIcon /seticon KFrame send
X%  IconX
X%  ScreenHeight FrameHeight sub IconY sub
X%  42 64 /reshape /Icon /sendsubframe KFrame send
X
X  /preferredsize KFrame send /FrameHeight exch def
X                             /FrameWidth  exch def
X
X  KCX
X  ScreenHeight FrameHeight sub KCY sub
X  FrameWidth FrameHeight /reshape KFrame send
X
X  /RFrame [RegClass] framebuffer /new OpenLookPropertyFrame send def
X  /RC /client RFrame send def 
X  /RCHeight 200 def
X  KCWidth RCHeight /lockminsize RC send
X
X  /activate KFrame send
X
X% /map IsIcon 1 eq {/Icon /subframes KFrame send get} {KFrame} ifelse send
X% IsIcon 1 eq {/close KFrame send} if
X
X  /map KFrame send
X
X  /activate RFrame send
X  /place RFrame send
X} def
X
X
X%  Place a colored text string in the appropriate font at the given
X%  x,y position in either the main calctool window or the memory
X%  register window.
X
X/PSMakeText    % string x canvasheight y font color canvas => -
X{
X  setcanvas
X  ColorTable exch get setcolor
X  setfont
X  sub moveto show
X} def
X
X
X/PSSetCursor   % type => -
X{
X} def
X
X
X%  Depending upon the current setting, either show (map) or remove
X%  (unmap) the memory register window.
X
X/PSToggleRegCanvas   % state => -
X{
X  1 eq { /map RFrame send} { /unmap RFrame send} ifelse
X} def
SHAR_EOF
echo "File calctool.ps is complete"
chmod 0444 calctool.ps || echo "restore of calctool.ps fails"
set `wc -c calctool.ps`;Sum=$1
if test "$Sum" != "6058"
then echo original size 6058, current size $Sum;fi
echo "x - extracting patchlevel.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > patchlevel.h &&
X 
X/*  @(#)patchlevel.h 1.12 89/12/21
X *
X *  This is the current patch level for this version of calctool.
X *
X *  Copyright (c) Rich Burridge.
X *		Sun Microsystems, Australia - All rights reserved.
X *
X *  Permission is given to distribute these sources, as long as the
X *  copyright messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if
X *  reported to me then an attempt will be made to fix them.
X */
X
X#define  PATCHLEVEL  4
SHAR_EOF
chmod 0444 patchlevel.h || echo "restore of patchlevel.h fails"
set `wc -c patchlevel.h`;Sum=$1
if test "$Sum" != "563"
then echo original size 563, current size $Sum;fi
echo "x - extracting .calctoolrc (Text)"
sed 's/^X//' << 'SHAR_EOF' > .calctoolrc &&
X#
X#  @(#).calctoolrc 1.4 89/12/13
X#
X#  This is a sample .calctoolrc file. You should use this as a basis for
X#  creating your own .calctoolrc files.
X#
X#  Process the .calctoolrc file. There are currently four types of
X#  records to look for:
X#
X#  1) Those starting with a hash in the first column are comments.
X#
X#  2) Lines starting with 'c' or 'C' in the first column are
X#     definitions for constants. The cC is followed by a digit in
X#     the range 0-9, then a space. This is followed by a number
X#     in fixed or scientific notation. Following this is an optional
X#     comment, which if found, will be used in the popup menu for
X#     the constants. If the comment is present, there must be at
X#     least one space between this and the preceding number.
X#
X#  3) Those starting with a 'f' or a 'F' in the first column are
X#     definitions for functions. The fF is followed by a digit in
X#     the range 0-9, then a space. This is followed by a function
X#     definition. Following this is an optional comment, which if
X#     found, will be used in the popup menu for the functions.
X#     If the comment is present, there must be at least one space
X#     between this and the preceding function definition.
X#
X#  4) Lines starting with a 'r' or a 'R' in the first column are
X#     definitions for the initial contents of the calculators
X#     memory registers. The rR is followed by a digit in the
X#     range 0-9, then a space. This is followed by a number in
X#     fixed or scientific notation. The rest of the line is ignored.
X#
X#  All other lines are ignored.
X#
X#  Two other things to note. There should be no embedded spaces in
X#  the function definitions, and whenever a backslash is found, that
X#  and the following character signify a control character, for
X#  example \g would be ascii 7.
X#
X#  CONSTANTS
X#
X#  This is a set of nine physical constants which could be used instead
X#  of those provided by default. If you don't wish to use these, then
X#  you should define your own, or comment these out.
X#
X
Xc0 299792458          Speed of light in a vacuum (c).
X
Xc1 6.626176E-34       Planck's constant (h).
X
Xc2 6.672E-11          Gravitational constant (G).
X
Xc3 1.6021892E-19      Elementary charge (e).
X
Xc4 9.109534E-31       Electron rest mass (me).
X
Xc5 1.6605655E-27      Atomic mass unit (u).
X
Xc6 6.022045E23        Avogadro constant (Na).
X
Xc7 1.380662E-23       Boltzmann constant (k).
X
Xc8 0.02241383         Molar volume of ideal gas at s. t. p. (Vm).
X
X#  FUNCTIONS.
X#
X#  This is a sample set of functions which are assigned to the FUN key.
X#
X#  On a suggestion from Charles Tierney, these functions are taken from
X#  the power calculation section of the March 1989 edition of the Sun
X#  Configuration Guide.
X#
X#  f0 - Calculate AC Watts (Formula A).
X#
X#                            1
X#      P(true) = P(DC) x  -------
X#                         PS(Eff)
X#
X#      where P(DC) = total DC power in watts [user-calculated] - register 0.
X#
X#      result placed in register 1.
X
Xf0 r0x1.43=s1          Calculate AC Watts (Formula A).
X
X#  f1 - Calculate Thermal Dissipation (Formula B).
X#
X#                                 BTU
X#     BTU(nom) = P(true) x 3.412 -----
X#                                 watt
X#
X#     where P(true) = true AC power in watts from above - register 1.
X#
X#     result placed in register 2.
X
Xf1 r1x3.412=s2         Calculate Thermal Dissipation (Formula B).
X
X#  f2 - Calculate Volt - Amps (Formula C).
X#
X#                     1
X#    VA = P(true) x ----
X#                    PF
X#
X#    where P(true) is from the formula above  - register 1.
X#
X#    and PF is the Power Factor               - register 3.
X#
X#    Sun-3/60/140/160/180 and Sun-4/110  =  0.65
X#    Sun-3/260/280 and Sun-4/260/280     =  0.715
X#    Sun-3/150 and Sun-4/150             =  0.9  (at full load).
X#
X#    result placed in register 4.
X
Xf2 1/r3xr1=s4          Calculate Volt - Amps (Formula C).
X
X#
X#   REGISTERS.
X#
X#   This is a sample set of initial register values. You probably
X#   don't want to use these, so you should define your own or comment
X#   these out.
X
Xr0 0.4971              Log10 of pi.
X
Xr1 0.4343              Log10 of e.
X
Xr3 57.29578            Degrees in  radian.
SHAR_EOF
chmod 0444 .calctoolrc || echo "restore of .calctoolrc fails"
set `wc -c .calctoolrc`;Sum=$1
if test "$Sum" != "4184"
then echo original size 4184, current size $Sum;fi
echo "x - extracting graphics.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > graphics.c &&
X
X/*  @(#)graphics.c 1.12 89/12/21
X *
X *  These are the independent graphics routines used by calctool.
X *
X *  Copyright (c) Rich Burridge.
X *                Sun Microsystems, Australia - All rights reserved.
X *
X *  Permission is given to distribute these sources, as long as the
X *  copyright messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if
X *  reported to me then an attempt will be made to fix them.
X */
X
X#include "calctool.h"
X#include "color.h"
X#include "extern.h"
X
X
Xbut_text(row, column, portion, state)
Xint row, column, portion ;
Xenum but_state state ;
X{
X  enum font_type butfont ;
X  int i, n ;
X
X  n = row*BCOLS*2 + column*2 + portion ;
X  if (buttons[n].color == GREY) return ;
X  get_label(n) ;
X  for (spaces = 0, i = 0; i < strlen(pstr); i++)
X    if (pstr[i] == ' ') spaces++ ;
X  x = chxoff[spaces] ;
X  y = (n & 1) ? 40 : 18 ;
X  if (spaces == 3)  y += 4 ;
X  butfont = (spaces == 3) ? BFONT : NFONT ;
X  if (state == NORMAL)
X    color = (!iscolor & portion) ? WHITE : BLACK ;
X  if (state == INVERTED)
X    color = (portion) ? BLACK : WHITE ;
X  drawtext(column*(BWIDTH+BGAP)+BBORDER+x,
X       DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+y, KEYCANVAS, butfont, color, pstr) ;
X}
X
X
Xdo_repaint()     /* Redraw the calctool canvas[es]. */
X{
X  make_canvas(0) ;
X}
X
X
Xdrawbox(x, y, width, height)
Xint x, y, width, height ;
X{
X  drawline(x, y, x+width, y) ;
X  drawline(x, y, x, y+height) ;
X  drawline(x, y+height, x+width, y+height) ;
X  drawline(x+width, y, x+width, y+height) ;
X}
X
X
Xdraw_button(row, column, portion, state)
Xint row, column, portion ;
Xenum but_state state ;
X{
X  int n ;
X
X  n = row*BCOLS*2 + column*2 + portion ;
X  if (!portion)
X    {
X      color = (iscolor) ? buttons[n].color : WHITE ;
X      drawbox(column*(BWIDTH+BGAP)+BBORDER,
X              DISPLAY+row*(BHEIGHT+BGAP)+BBORDER, BWIDTH, BHEIGHT) ;
X      fillbox(column*(BWIDTH+BGAP)+BBORDER+1,
X              DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+1, KEYCANVAS,
X              42, 50, 1, color) ;
X    }
X  else
X    { 
X      drawbox(column*(BWIDTH+BGAP)+BBORDER+5,
X              DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+26, 34, 21) ;
X      color = (iscolor) ? buttons[n].color : BLACK ;
X      fillbox(column*(BWIDTH+BGAP)+BBORDER+6,
X              DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+27, KEYCANVAS,
X              32, 19, 1, color) ;
X    }
X  but_text(row, column, portion, state) ;
X}
X
X
Xfillbox(x, y, window, width, height, boundry, color)
Xenum can_type window ;
Xint x, y, width, height, boundry, color ;
X{
X  if (boundry)
X    {
X      color_area(x, y, width, height, WHITE) ;
X      color_area(x+1, y+1, width-2, height-2, color) ;
X    } 
X  else color_area(x, y, width, height, color) ;
X}
X
X
Xget_menu_value()     /* Get menu value if valid right mouse press. */
X{
X  int i, n, val ;
X
X  n = row*BCOLS*2 + column*2 + portion ;
X  for (i = 0; i < MAXMENUS; i++)
X    if (buttons[n].value == validmenu[i])
X      {
X        val = do_menu((enum menu_type) i) ;
X        if (val) handle_menu_selection(i, val) ;
X        break ;
X      }
X}
X
X
Xgrey_buttons(base)     /* Grey out numeric buttons depending upon base. */
Xenum base_type base ;
X{
X  char val ;
X  int column, i, n, portion, row ;
X
X  if (gtype == TTY) return ;
X  for (i = 0; i < 16; i++)
X    {
X      val = digits[i] ;
X      for (n = 0; n < TITEMS; n++)
X        if (val == buttons[n].value) break ;           
X      if (i < basevals[(int) base])          
X        {                 
X          if (i < 10) buttons[n].color = LBLUE ;
X          else buttons[n].color = PINK ;
X        }  
X      else buttons[n].color = GREY ;
X      row = n / (BCOLS*2) ;
X      column = (n - (row*BCOLS*2)) / 2 ;
X      portion = n & 1 ;
X      draw_button(row, column, portion, NORMAL) ;
X    }                    
X}
X
X
Xhandle_down_event(type)
Xint type ;
X{
X  x = curx ;
X  y = cury ;
X  if (!down)
X    {
X      if (pending_op == '?')
X        {
X          down = type ;
X          return ;
X        }
X      for (row = 0; row < BROWS; row++)
X        for (column = 0; column < BCOLS; column++)
X          if ((x > (column*(BWIDTH+BGAP)+BBORDER)) &&
X              (x < (column*(BWIDTH+BGAP)+BBORDER+BWIDTH)) &&
X              ((y - DISPLAY) > (row*(BHEIGHT+BGAP)+BBORDER)) &&
X              ((y - DISPLAY) < (row*(BHEIGHT+BGAP)+BBORDER+BHEIGHT)))
X            {
X              portion = (y - DISPLAY - BBORDER -
X                         (row*(BHEIGHT+BGAP))) / (BHEIGHT/2) ;
X              inv_but(row, column, portion, INVERTED) ;
X              down = type ;
X              return ;
X            }
X    } 
X}
X
X
Xhandle_menu_selection(menu, item)   /* Process right button menu selection. */
Xint menu, item ;
X{
X  pending = validmenu[menu] ;
X  current = num_names[item-1][0] ;
X  do_pending() ;
X  down = 0 ;
X  inv_but(row, column, portion, NORMAL) ;
X}
X
X
Xinv_but(row, column, portion, state)
Xint row, column, portion ;
Xenum but_state state ;
X{
X  int n ;
X 
X  n = row*BCOLS*2 + column*2 + portion ;
X  if (pending_op != '?')
X    {
X      if (state == NORMAL)
X        if (iscolor) color = buttons[n].color ;
X        else color = (portion) ? BLACK : WHITE ;
X      if (state == INVERTED)
X        color = (portion) ? WHITE : BLACK ;
X      fillbox(column*(BWIDTH+BGAP)+BBORDER+6,
X              DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+5+(portion*22),
X              KEYCANVAS, 32, 19, portion, color) ;
X      but_text(row, column, portion, state) ;
X    }
X}
X
X
Xmake_canvas(toggle)
Xint toggle ;
X{
X  if (toggle) tstate = !tstate ;
X  color = (iscolor) ? GREY : WHITE ;
X  clear_canvas(KEYCANVAS, color) ;
X  if (iscolor) color_area(0, 0, TWIDTH, DISPLAY, WHITE) ;
X  drawline(0, DISPLAY, TWIDTH, DISPLAY) ;
X  for (row = 0; row < BROWS; row++)
X    for (column = 0; column < BCOLS; column++)
X      for (portion = 0; portion < 2; portion++)
X        draw_button(row, column, portion, NORMAL) ;
X
X  set_item(BASEITEM,base_str[(int) base]) ;
X  set_item(DISPLAYITEM, display) ;
X  set_item(NUMITEM, dtype_str[(int) dtype]) ;
X  set_item(OPITEM, items[(int) OPITEM].text) ;
X  set_item(TTYPEITEM,ttype_str[(int) ttype]) ;
X  set_item(HYPITEM, (hyperbolic) ? "HYP " : "    ") ;
X  set_item(INVITEM, (inverse) ? "INV " : "    ") ;
X  make_registers() ;
X}
X
X
Xmake_menus()      /* Create the popup menus used by the graphics versions. */
X{
X
X/*  There are nine popup menus. These are associated with the following keys:
X *
X *  ACC  - range of possible accuracies (0 - 9).
X *
X *  CON  - constant values plus associated comments, if present.
X *
X *  EXCH - list of register numbers (0 - 9).
X *
X *  FUN  - function definitions plus associated comments, if present.
X *
X *  HELP - contains all the keys in the calculator.
X *
X *   <   - range of possible left shift values (0 - 9).
X *
X *   >   - range of possible right shift values (0 - 9).
X *
X *  RCL  - list of register numbers (0 - 9).
X *
X *  STO  - list of register numbers (0 - 9).
X */
X
X  create_menu(M_ACC) ;     /* Accuracies. */
X  create_menu(M_CON) ;     /* Constant definitions. */
X  create_menu(M_EXCH) ;    /* Register exchange. */
X  create_menu(M_FUN) ;     /* Function definitions. */
X  create_menu(M_LSHIFT) ;  /* Left shift. */
X  create_menu(M_RSHIFT) ;  /* Right shift. */
X  create_menu(M_RCL) ;     /* Register recall. */
X  create_menu(M_STO) ;     /* Register store. */
X}
X
X
Xmake_registers()           /* Calculate memory register frame values. */
X{
X  char line[MAXLINE] ;     /* Current memory register line. */
X  int n ;
X
X  if (!rstate) return ;
X  clear_canvas(REGCANVAS, WHITE) ;
X  drawtext(15, 20, REGCANVAS, NFONT, BLACK, "Memory Registers") ;
X  for (n = 0; n < MAXREGS; n++)
X    {
X      SPRINTF(line, "%1d   %s", n, make_number(mem_vals[n])) ;
X      drawtext(15, 40+15*n, REGCANVAS, NFONT, BLACK, line) ;
X    }
X}
X
X
Xprocess_event(type)       /* Process this event. */
Xint type ;
X{
X  int i, n ;
X
X  n = row*BCOLS*2 + column*2 + portion ;
X  switch (type)
X    {
X      case CFRAME_REPAINT  : make_canvas(0) ;
X                             set_item(BASEITEM, base_str[(int) base]) ;
X                             set_item(TTYPEITEM, ttype_str[(int) ttype]) ;
X                             break ;
X      case EXIT_WINDOW     : if (pending_op != '?')
X                               if (n >= 0 && n <= (NOBUTTONS*2))
X                                 {
X                                   draw_button(row, column, portion, NORMAL) ;
X                                   if (!portion)
X                                     draw_button(row, column, 1, NORMAL) ;
X                                 }
X                             down = 0 ;
X                             break ;
X      case KEYBOARD        : nextc = cur_ch ;
X                             for (n = 0; n < TITEMS; n++)
X                               if (nextc == buttons[n].value) break ;
X                             if (n == TITEMS) return ;
X                             if (n >= 0 && n <= TITEMS)
X                               process_item(n) ;
X                             break ;
X      case LEFT_DOWN       :
X      case MIDDLE_DOWN     :
X      case RIGHT_DOWN      : handle_down_event(type) ;
X                             if (type == RIGHT_DOWN) get_menu_value() ;
X                             break ;
X      case LEFT_UP         :
X      case MIDDLE_UP       :
X      case RIGHT_UP        : x = curx ;
X                             y = cury ;
X                             if ((type == LEFT_UP && down == LEFT_DOWN) ||
X                                 (type == MIDDLE_UP && down == MIDDLE_DOWN) ||
X                                 (type == RIGHT_UP && down == RIGHT_DOWN))
X                               {
X                                 if (pending_op != '?' && n <= (NOBUTTONS*2))
X                                   inv_but(row, column, portion, NORMAL) ;
X                                 down = 0 ;
X                                 if (n >= 0 && n <= (NOBUTTONS*2))
X                                   process_item(n) ;
X                               }
X                             break ;
X      case RFRAME_REPAINT  : make_registers() ;
X                             break ;
X      case TAKE_FROM_SHELF : handle_selection() ;
X                             if (issel)
X                               for (i = 0 ; i < strlen(selection); i++)
X                                 for (n = 0; n < TITEMS; n++)
X                                   if (selection[i] == buttons[n].value)
X                                     {
X                                       process_item(n) ;
X                                       break ;
X                                     }
X                             break ;
X      case PUT_ON_SHELF    : get_display() ;
X                             break ;
X      case DIED            : exit(0) ;
X    }                           
X}
X
X
Xset_item(itemno, str)
Xenum item_type itemno ;
Xchar *str ;
X{
X  enum font_type font ;
X  char *old_text ;
X  int x, y ;
X 
X  old_text = items[(int) itemno].text ;
X  if (itemno == DISPLAYITEM)
X    x = 5+(MAX_DIGITS - strlen(old_text))*nfont_width ;
X  else x = items[(int) itemno].x ;
X  y = items[(int) itemno].y ;
X  font = items[(int) itemno].font ;
X  old_text = items[(int) itemno].text ;
X  drawtext(x, y, KEYCANVAS, font, WHITE, old_text) ;
X
X  if (itemno == DISPLAYITEM) x = 5+(MAX_DIGITS - strlen(str))*nfont_width ;
X
X  drawtext(x, y, KEYCANVAS, font, BLACK, str) ;
X  STRCPY(items[(int) itemno].text, str) ;
X}
SHAR_EOF
chmod 0444 graphics.c || echo "restore of graphics.c fails"
set `wc -c graphics.c`;Sum=$1
if test "$Sum" != "11290"
then echo original size 11290, current size $Sum;fi
echo "x - extracting display.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > display.c &&
X
X/*  @(#)display.c 1.8 89/11/01
X *
X *  Display manipulation routines used by calctool.
X *
X *  Copyright (c) Rich Burridge.
X *                Sun Microsystems, Australia - All rights reserved.
X *
X *  Basic algorithms, copyright (c) Ed Falk.
X *                Sun Microsystems, Mountain View.
X *
X *  Permission is given to distribute these sources, as long as the
X *  copyright messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if
X *  reported to me then an attempt will be made to fix them.
X */
X
X#include "calctool.h"
X#include "color.h"
X#include "extern.h"
X
X
Xchar_val(chr)
Xchar chr ;
X{
X       if (chr >= '0' && chr <= '9') return(chr - '0') ;
X  else if (chr >= 'a' && chr <= 'f') return(chr - 'a' + 10) ;
X  else return(-1) ;
X}
X
X
Xclear_display()
X{
X  int i ;
X
X  pointed = 0 ;
X  toclear = 1 ;
X  STRCPY(display, "0.") ;
X  for (i = 0; i < accuracy; i++) STRNCAT(display, "0", 1) ;
X  set_item(DISPLAYITEM, display) ;
X  hyperbolic = inverse = 0 ;
X  set_item(HYPITEM, "    ") ;
X  set_item(INVITEM, "    ") ;
X  disp_val = 0.0 ;
X}
X
X
Xdouble
Xconvert_display()    /* Convert input string into a double. */
X{
X  int exp, exp_sign, i, inum ;
X  double val ;
X  char *optr ;
X
X  val = 0.0 ;
X  exp = 0 ;
X  optr = display ;
X  while ((inum = char_val(*optr)) >= 0)
X    {
X      val = val * basevals[(int) base] + inum ;
X      *optr++ ;
X    }
X      
X  if (*optr == '.')
X    for (i = 1; (inum = char_val(*++optr)) >= 0; i++)
X      val += inum / powers[i][(int) base] ;
X
X  while (*optr == ' ') optr++ ;
X
X  if (*optr != '\0')
X    {
X      if (*optr == '-') exp_sign = -1 ;
X      else exp_sign = 1 ;
X
X      while ((inum = char_val(*++optr)) >= 0)
X        exp = exp * basevals[(int) base] + inum ;
X    }
X  exp *= exp_sign ;
X
X  if (key_exp)
X    val *= pow((double) basevals[(int) base], (double) exp) ;
X  return(val) ;
X}
X 
X 
Xget_label(n)
Xint n ;
X{
X  if (tstate)
X    switch (buttons[n].value)
X        {
X          case CCTRL('c') :
X          case CCTRL('d') :
X          case CCTRL('e') :
X          case CCTRL('f') :
X          case CCTRL('g') :
X          case CCTRL('n') :
X          case CCTRL('r') :
X          case CCTRL('s') :
X          case CCTRL('t') : SPRINTF(pstr, "^%c  ", buttons[n].value + 96) ;
X                            break ;
X          case CCTRL('h') : STRCPY(pstr, "bsp ") ;
X                            break ;
X          case '\177'     : STRCPY(pstr, "del ") ;
X                            break ;
X          default         : SPRINTF(pstr, "%c   ", buttons[n].value) ;
X        }
X  else STRCPY(pstr, buttons[n].str) ;
X}
X
X
Xinitialise()
X{
X  error = 0 ;              /* Currently no display error. */
X  cur_op = '?' ;           /* No arithmetic operator defined yet. */
X  old_cal_value = '?' ;
X  result = 0.0 ;           /* No previous result yet. */
X  last_input = 0.0 ;
X}
X
X
Xchar *
Xmake_fixed(number, cmax)    /* Convert fixed number. */
Xdouble number ;             /* Value to convert. */
Xint cmax ;                  /* Maximum characters to generate. */
X{
X  char *optr ;
X  double val ;
X  int ndig ;                   /* Total number of digits to generate. */
X  int ddig ;                   /* Number of digits to left of . */
X  int dval ;
X
X  optr = fnum ;
X  val = fabs(number) ;
X  if (number < 0.0) *optr++ = '-' ;
X  val += .5 / powers[accuracy][(int) base] ;
X
X  if (val < 1.0)
X    {
X      ddig = 0 ;
X      *optr++ = '0' ;
X      cmax-- ;
X    }
X  else
X    {
X      for (ddig = 0; val >= 1.0; ddig++)
X        val /= powers[1][(int) base] ;
X    }
X
X  ndig = MIN(ddig + accuracy, --cmax) ;
X
X  while (ndig-- > 0)
X    {
X      if (ddig-- == 0) *optr++ = '.' ;
X      val *= powers[1][(int) base] ;
X      dval = val ;
X      *optr++ = digits[dval] ;
X      val -= (int) val ;
X    }
X  *optr++ = '\0' ;
X  toclear = 1 ;
X  pointed = 0 ;
X  return(fnum) ;
X}
X
X
Xchar *
Xmake_number(number)     /* Convert display value to current base. */
Xdouble number ;         /* Value to convert. */
X{
X  double val ;
X
X  if (isinf(number) || isnan(number))
X    {
X      STRCPY(display, "Error") ;
X      error = 1 ;
X      set_item(OPITEM, "CLR") ;
X      return(display) ;
X    }
X
X  val = fabs(number) ;
X  if (dtype == SCI ||
X      dtype == FIX && val != 0.0 && (val > max_fix[(int) base] ||
X                      val < exp_p1[accuracy][(int) base]))
X    return(make_scientific(number)) ;
X  else return(make_fixed(number, MAX_DIGITS)) ;
X}
X
X
Xchar *
Xmake_scientific(number)     /* Convert scientific number. */
Xdouble number ;             /* Value to convert. */
X{
X  char fixed[MAX_DIGITS+1] ;
X  char *optr ;
X  double mant ;                /* Mantissa */
X  double val ;
X  int exp = 0 ;                /* Exponent */
X  int i ;
X  int eng = 0 ;                /* Scientific not engineering value. */
X  double atmp ;
X
X  optr = snum ;
X  val = fabs(number) ;
X  if (number < 0.0) *optr++ = '-' ;
X  mant = val ;
X  atmp = 1.0 / powers[10][(int) base] ;
X
X  if (mant != 0.0)
X    {
X      while (mant >= powers[10][(int) base])
X        {
X          exp += 10 ;
X          mant *= atmp ;
X        }
X        
X      while ((!eng && mant >= powers[1][(int) base]) ||
X             (eng && (mant >= powers[3][(int) base] || exp % 3 != 0)))
X        {
X          exp += 1 ;
X          mant /= powers[1][(int) base] ;
X        }
X 
X      while (mant < atmp)
X        {
X          exp -= 10 ;
X          mant *= powers[10][(int) base] ;
X        }
X
X      while (mant < 1.0 || (eng && exp % 3 != 0))
X        {
X          exp -= 1 ;
X          mant *= powers[1][(int) base] ;
X        }
X    }    
X
X  STRCPY(fixed, make_fixed(mant, MAX_DIGITS-6)) ;
X  for (i = 0; i < strlen(fixed); i++) *optr++ = fixed[i] ;
X
X  *optr++ = 'e' ;
X
X  if (exp < 0)
X    {
X      exp = -exp ;
X      *optr++ = '-' ;
X    }
X  else *optr++ = '+' ;
X
X  if ((*optr = digits[exp / ((int) powers[2][(int) base])]) != '0')
X    optr++  ;
X  exp %= (int) powers[2][(int) base] ;
X  *optr++ = digits[exp / ((int) powers[1][(int) base])] ;
X  exp %= (int) powers[1][(int) base] ;
X  *optr++ = digits[exp] ;
X  *optr++ = '\0' ;
X  toclear = 1 ;
X  pointed = 0 ;
X  return(snum) ;
X}
X
X
Xprocess_item(n)
Xint n ;
X{
X  int i,isvalid ;
X
X  if (n < 0 || n > TITEMS) return ;
X
X  current = buttons[n].value ;
X  if (current == 'X') current = 'x' ;         /* Reassign "extra" values. */
X  if (current == '*') current = 'x' ;
X  if (current == '\015') current = '=' ;
X  if (current == 'Q') current = 'q' ;
X
X  if (error)
X    {
X      isvalid = 0 ;                    /* Must press a valid key first. */
X      for (i = 0; i < MAXVKEYS; i++)
X        if (current == validkeys[i]) isvalid = 1 ;
X      if (pending == '?') isvalid = 1 ;
X      if (!isvalid) return ;
X      error = 0 ;
X    }
X
X  if (pending)
X    {
X      for (n = 0; n < TITEMS; n++)
X        if (pending == buttons[n].value) break ;
X    }
X  switch (buttons[n].opdisp)
X    {
X      case OP_SET   : set_item(OPITEM, buttons[n].str) ;
X                            break ;
X      case OP_CLEAR : if (error) set_item(OPITEM, "CLR") ;
X                            else set_item(OPITEM, "") ;
X    }
X  (*buttons[n].func)() ;
X}
X
X
Xshow_display(val)
Xdouble val ;
X{
X  if (!error)
X    {
X      STRCPY(display, make_number(val)) ;
X      set_item(DISPLAYITEM, display) ;
X    }
X}
SHAR_EOF
chmod 0444 display.c || echo "restore of display.c fails"
set `wc -c display.c`;Sum=$1
if test "$Sum" != "7188"
then echo original size 7188, current size $Sum;fi
echo "x - extracting functions.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > functions.c &&
X
X/*  @(#)functions.c 1.7 89/11/01
X *
X *  This file contains the seperate functions used by calctool,
X *  whenever a calculator button is pressed.
X *
X *  Copyright (c) Rich Burridge.
X *                Sun Microsystems, Australia - All rights reserved.
X *
X *  Basic algorithms, copyright (c) Ed Falk.
X *                Sun Microsystems, Mountain View.
X *
X *  Permission is given to distribute these sources, as long as the
X *  copyright messages are not removed, and no monies are exchanged.
X *
X *  No responsibility is taken for any errors or inaccuracies inherent
X *  either to the comments or the code of this program, but if
X *  reported to me then an attempt will be made to fix them.
X */
X
X#include "calctool.h"
X#include "color.h"
X#include "extern.h"
X
XBOOLEAN ibool() ;
Xdouble setbool() ;
X
X
Xdo_accuracy()     /* Set display accuracy. */
X{
X  if (current >= '0' && current <= '9')
X    {
X      accuracy = char_val(current) ;
X      make_registers() ;
X    }
X}
X
X
Xdo_base()    /* Change the current base setting. */
X{
X  switch (current)
X    {
X      case 'B' : base = BIN ;
X                 break ;
X      case 'O' : base = OCT ;
X                 break ;
X      case 'D' : base = DEC ;
X                 break ;
X      case 'H' : base = HEX ;
X    }
X  grey_buttons(base) ;
X  set_item(BASEITEM, base_str[(int) base]) ;
X  show_display(disp_val) ;
X  if (rstate) make_registers() ;
X}
X
X
Xdo_calculation()      /* Perform arithmetic calculation and display result. */
X{
X  if (current == '=' && old_cal_value == '=')
X    if (new_input) result = last_input ;
X    else disp_val = last_input ;
X
X  if (current != '=' && old_cal_value == '=') cur_op = '?' ;
X  switch (cur_op)
X    {
X      case CCTRL('c') :                              /* cos. */
X      case CCTRL('s') :                              /* sin. */
X      case CCTRL('t') :                              /* tan. */
X      case '?'        : result = disp_val ;          /* Undefined. */
X                        break ;
X      case '+'        : result += disp_val ;         /* Addition. */
X                        break ;
X      case '-'        : result -= disp_val ;         /* Subtraction. */
X                        break ;
X      case 'x'        : result *= disp_val ;         /* Multiplication. */
X                        break ;
X      case '/'        : result /= disp_val ;         /* Division. */
X                        break ;
X      case '%'        : result *= disp_val * 0.01 ;              /* % */
X                        break ;
X      case 'Y'        : result = pow(result, disp_val) ;         /* y^x */
X                        break ;
X      case '&'        : result = setbool(ibool(result) &         /* AND */
X                                         ibool(disp_val)) ;
X                        break ;
X      case '|'        : result = setbool(ibool(result) |         /* OR */
X                                         ibool(disp_val)) ;
X                        break ;
X      case '^'        : result = setbool(ibool(result) ^         /* XOR */
X                                         ibool(disp_val)) ;
X                        break ;
X      case 'n'        : result = setbool(~(ibool(result) ^       /* XNOR */
X                                           ibool(disp_val))) ;
X                        break ;
X      case '='        : break ;                                  /* Equals. */
X    }
X  show_display(result) ;
X  if (!(current == '=' && old_cal_value == '=')) last_input = disp_val ;
X
X  disp_val = result ;
X  if (current != '=') cur_op = current ;
X  old_cal_value = current ;
X  new_input = key_exp = 0 ;
X}
X
X
Xdo_clear()       /* Clear the calculator display and re-initialise. */
X{
X  clear_display() ;
X  if (error) set_item(DISPLAYITEM, "") ;
X  initialise() ;
X}
X
X
Xdo_constant()
X{
X  if (current >= '0' && current <= '9')
X    {
X      disp_val = con_vals[char_val(current)] ;
X      show_display(disp_val) ;
X    }
X}
X
X
Xdo_delete()     /* Remove the last numeric character typed. */
X{
X  if (strlen(display)) display[strlen(display)-1] = '\0' ;
X
X/*  If we were entering a scientific number, and we have backspaced over
X *  the exponent sign, then this reverts to entering a fixed point number.
X */
X
X  if (key_exp && !(index(display, '+')))
X    {
X      key_exp = 0 ;
X      display[strlen(display)-1] = '\0' ;
X      set_item(OPITEM, "") ;
X    }
X
X  set_item(DISPLAYITEM, display) ;
X  disp_val = convert_display() ;    /* Convert input to a number. */
X}
X
X
Xdo_exchange()         /* Exchange display with memory register. */
X{
X  double temp ;
X
X  if (current >= '0' && current <= '9')
X    {
X      temp = disp_val ;
X      disp_val = mem_vals[char_val(current)] ;
X      mem_vals[char_val(current)] = temp ;
X      make_registers() ;
X    }
X}
X
X
Xdo_expno()           /* Get exponential number. */
X{
X  if (!new_input)
X    {
X      STRCPY(display, "1.0 +") ;
X      new_input = pointed = 1 ;
X    }
X  else if (!pointed)
X    {
X      STRNCAT(display, ". +", 3) ;
X      pointed = 1 ;
X    }
X  else STRNCAT(display, " +", 2) ;
X  key_exp = 1 ;
X  exp_posn = index(display, '+') ;
X  set_item(DISPLAYITEM, display) ;
X  disp_val = convert_display() ;       /* Convert input to a number. */
X}
X
X
Xdouble
Xdo_factorial(val)     /* Calculate the factorial of val. */
Xdouble val ;
X{
X  double a ;
X  int i ;
X
X  if (val == (int) val)
X    {
X      i = val ;
X      a = 1.0 ;
X      while ((i > 0) && (a != HUGE)) a *= (float) i-- ;
X    }
X  else
X    {
X      a = gamma(val+1) ;
X      a = exp(a) ;
X      if (signgam) a = -a ;
X    }
X  return (a) ;
X}
X
X
Xdo_function()      /* Perform a user defined function. */
X{
X  int fno, i, n ;
X
X  pending = 0 ;
X  if (current >= '0' && current <= '9')
X    {
X      fno = char_val(current) ;
X      for (i = 0 ; i < strlen(fun_vals[fno]); i++)
X        for (n = 0; n < TITEMS; n++)
X          if (fun_vals[fno][i] == buttons[n].value)
X            {
X              process_item(n) ;
X              break ;
X            }
X    }
X}
X
X
Xdo_help()         /* Show online help facility. */
X{
X  char help_str[MAXLINE], nextline[MAXLINE], *p ;
X  int n, y ;
X
X  if (pending_op == '?')                        /* HELP. */
X    {     
X      if (ishelp) ishelp++ ;
X      pending_op = '=' ;
X      make_canvas(0) ;
X      set_cursor(MAINCURSOR) ;
X    }     
X  else    
X    {
X      clear_canvas(KEYCANVAS, WHITE) ;
X      y = 20 ;
X      if (!ishelp)
X        drawtext(5, y, KEYCANVAS, NFONT, BLACK, "No help file found.") ;
X      else
X        {
X          for (n = 0; n < TITEMS; n++)
X            if (current == buttons[n].value) break ;
X          color = (iscolor) ? buttons[n].color : WHITE ;
X          clear_canvas(KEYCANVAS, color) ;
X          SPRINTF(help_str, "_%s_\n", buttons[n].str) ;
X          rewind(hfd) ;
X          y = 15 ;
X          p = fgets(nextline, BUFSIZ, hfd) ;
X          if (EQUAL(p, "_calctool.help_\n"))
X            {
X              while (p = fgets(nextline, BUFSIZ, hfd))
X                if (*p == '_' && EQUAL(p, help_str)) break ;
X              if (!p) drawtext(5, y, KEYCANVAS, NFONT, BLACK,
X                               "No help for this item.") ;
X              for (;;)
X                {
X                  FGETS(nextline, BUFSIZ, hfd) ;
X                  if (nextline[0] == '_') break ;
X                  nextline[strlen(nextline)-1] = '\0' ;
X                  drawtext(5, y, KEYCANVAS, NFONT, BLACK, nextline) ;
X                  y += 15 ;
X                }
X            }    
X          else drawtext(5, y, KEYCANVAS, NFONT, BLACK,
X                        "Invalid help file given.") ;
X        }
X      drawtext(5, y+25, KEYCANVAS, NFONT, BLACK,
X               "Click LEFT or press any valid key.") ;
X      pending_op = '?' ;
X      return ;
X    }
X}
X
X
Xdo_immediate()
X{
X  switch (current)
X    {
X      case '[' : disp_val = setbool(ibool(disp_val)) ;          /* &32 */
X                 break ;
X      case ']' : disp_val = setbool(ibool(disp_val) & 0xffff) ; /* &16 */
X                 break ;
X      case '{' : disp_val = exp(disp_val) ;                     /* e^x */
X                 break ;
X      case '}' : disp_val = exp(M_LN10*disp_val) ;              /* 10^x */
X                 break ;
X      case 'N' : disp_val = log(disp_val) ;                     /* ln */
X                 break ;
X      case 'G' : disp_val = log10(disp_val) ;                   /* log */
X                 break ;
X      case 'S' : disp_val = sqrt(disp_val) ;                    /* SQRT */
X                 break ;
X      case '~' : disp_val = setbool(~ibool(disp_val)) ;         /* NOT */
X                 break ;
X      case 'R' : disp_val = 1.0 / disp_val ;                    /* 1/x */
X                 break ;
X      case '!' : disp_val = do_factorial(disp_val) ;            /* x! */
X                 break ;
X      case '@' : disp_val *= disp_val ;                         /* x^2 */
X                 break ;
X      case 'C' : if (key_exp)                                   /* CHS */
X                   {
X                     if (*exp_posn == '+') *exp_posn = '-' ;
X                     else                  *exp_posn = '+' ;
X                     set_item(DISPLAYITEM, display) ;
X                     disp_val = convert_display() ;
X                     key_exp = 0 ;
X                   }
X                 else disp_val = -disp_val ;
X    }
X  show_display(disp_val) ;
X}
X
X
Xdo_keys()      /* Display/undisplay the calctool key values. */
X{
X  make_canvas(1) ;
X}
X
X
Xdo_number()
X{
X  int n ;
X  static int maxvals[4] = {1, 7, 9, 15} ;
X
X  n = current - '0' ;
X  if (base == HEX && current >= 'a' && current <= 'f')
X    n = current - 'a' + 10 ;
X  if (n > maxvals[(int) base]) return ;
X
X  if (toclear)
X    {
X      SPRINTF(display, "%c", current) ;
X      toclear = 0 ;
X    }
X  else if (strlen(display) < disp_length[(int) base])
X    STRNCAT(display, &current, 1) ;
X  set_item(DISPLAYITEM, display) ;
X  disp_val = convert_display() ;    /* Convert input to a number. */
X  new_input = 1 ;
X}
X
X
Xdo_numtype()         /* Set number type (fixed or scientific). */
X{
X  int n ;
X
X  if (dtype == FIX) dtype = SCI ;
X  else dtype = FIX ;
X  n = row*BCOLS*2 + column*2 + portion ;
X  STRCPY(buttons[n].str, (dtype == FIX) ? "SCI " : "FIX ") ;
X  set_item(NUMITEM, dtype_str[(int) dtype]) ;
X  draw_button(row, column, 0, NORMAL) ;
X  draw_button(row, column, 1, NORMAL) ;
X  show_display(disp_val) ;
X}
X
X
Xdo_pending()
X{
X  grey_buttons(HEX) ;    /* Reshow all the keys. */
X  switch (pending)
X    {
X      case '#'        : do_constant() ;                            /* CON */
X                        break ;
X      case CCTRL('e') : do_exchange() ;                            /* EXCH */
X                        break ;
X      case CCTRL('f') : do_function() ;                            /* FUN */
X                        break ;
X      case 's'        :                                            /* STO */
X      case 'r'        : do_sto_rcl() ;                             /* RCL */
X                        if (pending_op == '+' || pending_op == '-' ||
X                            pending_op == 'x' || pending_op == '/') return ;
X                        break ;
X      case '<'        :                                            /* < */
X      case '>'        : do_shift() ;                               /* > */
X                        break ;
X      case 'A'        : do_accuracy() ;                            /* ACC */
X                        break ;
X      case '?'        : do_help() ;                                /* ? */
X                        if (pending_op == '?') return ;
X                        break ;
X      default         : if (!pending)
X                          {
X                            pending = current ;
X                            pending_op = '=' ;
X                            if (pending == '?') set_cursor(HELPCURSOR) ;
X                            if (pending == '?' && (ishelp <= 1)) do_pending() ;
X                            return ;
X                          }
X    }
X  show_display(disp_val) ;
X  if (error) set_item(OPITEM, "CLR") ;
X  else set_item(OPITEM, "") ;
X  pending = 0 ;
X  grey_buttons(base) ;      /* Just show numeric keys for current base. */
X}
X
X
Xdo_point()                  /* Handle numeric point. */
X{
X  if (!pointed)
X    {
X      if (toclear)
X        {
X          STRCPY(display, ".") ;
X          toclear = 0 ;
X        }
X      else if (strlen(display) < disp_length[(int) base])
X        STRNCAT(display, ".", 1) ;
X      pointed = 1 ;
X    }
X  set_item(DISPLAYITEM, display) ;
X  disp_val = convert_display() ;    /* Convert input to a number. */
X}
X
X
Xdo_portion()
X{
X  switch (current)
X    {
X      case 'U' : disp_val = fabs(disp_val) ;       /* ABS. */
X                 break ;
X      case 'F' : disp_val -= (int) disp_val ;      /* FRAC. */
X                 break ;
X      case 'I' : disp_val = (int) disp_val ;       /* INT. */
X    }
X  show_display(disp_val) ;
X}
X
X
Xdo_set_mode()           /* Set or unset various calculator modes. */
X{
X  switch (current)
X    {
X      case CCTRL('d') :                                    /* DEG */
X      case CCTRL('g') :                                    /* GRAD */
X      case CCTRL('r') : do_trigtype() ;                    /* RAD */
X                        break ;
X      case 'h'        : hyperbolic = !hyperbolic ;         /* HYP */
X                        set_item(HYPITEM, (hyperbolic) ? "HYP " : "    ") ;
X                        break ;
X      case 'i'        : inverse = !inverse ;               /* INV */
X                        set_item(INVITEM, (inverse) ? "INV " : "    ") ;
X                        break ;
X      case CCTRL('n') : do_numtype() ;                     /* FIX/SCI */
X    }
X  if (rstate) make_registers() ;
X}
X
X
Xdo_shift()     /* Perform bitwise shift on display value. */
X{
X  int n, shift ;
X  BOOLEAN temp ;
X
X  if (current >= '0' && current <= '9')
X    {
X      for (n = 0; n < TITEMS; n++)
X        if (current == buttons[n].value) break ;
X      shift = char_val(buttons[n].value) ;
X      temp = ibool(convert_display()) ;
X      switch (pending)
X        {
X          case '<' : temp = temp << shift ;
X                     break ;
X          case '>' : temp = temp >> shift ;
X        }
X      STRCPY(display, make_number(setbool(temp))) ;
X      disp_val = last_input = convert_display() ;
X    }
X}
X
X
Xdo_sto_rcl()     /* Save/restore value to/from memory register. */
X{
X  if (current >= '0' && current <= '9')
X    switch (pending)
X      {
X        case 'r' : disp_val = mem_vals[char_val(current)] ;
X                   break ;
X        case 's' : switch (pending_op)
X                     {
X                       case '+' : mem_vals[char_val(current)] += disp_val ;
X                                  break ;
X                       case '-' : mem_vals[char_val(current)] -= disp_val ;
X                                  break ;
X                       case 'x' : mem_vals[char_val(current)] *= disp_val ;
X                                  break ;
X                       case '/' : mem_vals[char_val(current)] /= disp_val ;
X                                  break ;
X                       case '=' : mem_vals[char_val(current)] = disp_val ;
X                     }  
X                   make_registers() ;
X      }                 
X  else if (current == '+' || current == '-' ||
X           current == 'x' || current == '/') pending_op = current ;
X}
X
X
Xdo_trig()         /* Perform all trigonometric functions. */
X{
X  double temp ;
X
X  if (!inverse)
X    {
X           if (ttype == DEG)  temp = disp_val * M_PI / 180.0 ;
X      else if (ttype == GRAD) temp = disp_val * M_PI / 200.0 ;
X      else                    temp = disp_val ;
X
X      if (!hyperbolic)
X        switch (current)
X          {
X            case CCTRL('c') : tresults[(int) RAD] = cos(temp) ;    /* cos */
X                              break ;
X            case CCTRL('s') : tresults[(int) RAD] = sin(temp) ;    /* sin */
X                              break ;
X            case CCTRL('t') : tresults[(int) RAD] = tan(temp) ;    /* tan */
X          }
X      else
X        switch (current)
X          {
X            case CCTRL('c') : tresults[(int) RAD] = cosh(temp) ;   /* cosh */
X                              break ;
X            case CCTRL('s') : tresults[(int) RAD] = sinh(temp) ;   /* sinh */
X                              break ;
X            case CCTRL('t') : tresults[(int) RAD] = tanh(temp) ;   /* tanh */
X          }
X
X      tresults[(int) DEG]  = tresults[(int) RAD] ;
X      tresults[(int) GRAD] = tresults[(int) RAD] ;
X    }
X  else
X    {
X      if (!hyperbolic)
X        switch (current)
X          {
X            case CCTRL('c') : disp_val = acos(disp_val) ;     /* acos */
X                              break ;
X            case CCTRL('s') : disp_val = asin(disp_val) ;     /* asin */
SHAR_EOF
echo "End of part 2"
echo "File functions.c is continued in part 3"
echo "3" > s2_seq_.tmp
exit 0