home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol022 / recipe.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1984-04-29  |  16.4 KB  |  715 lines

  1. PROGRAM RECIPE;
  2. (*
  3. **  PROGRAM TITLE    THE RECIPE SYSTEM
  4. **            Version PAS-1.2 translated from
  5. **            the BASIC version into Pascal.
  6. **
  7. **  WRITTEN BY:        Ray Penley
  8. **  DATE WRITTEN:    23 FEB 1980 / last modified: 28 FEB 80
  9. **  WRITTEN FOR:    Computer hobbyists
  10. **
  11. **  PROGRAM SUMMARY:
  12. **
  13. **  The recipe system stores recipes and retrives them
  14. **  by means of a numeric key that represents the foods
  15. **  used in the meal.  Foods are divided into four
  16. **  categories according to their nutritional value.
  17. **
  18. **  INPUT AND OUTPUT FILES:
  19. **    RCPDAT.XXX and RCPDAT.YYY
  20. **           - the DATA and the backup files
  21. **    RECIPE.MST - the statistics file
  22. **    DUMMY.$$$  - see Procedure InputRecipe for use.
  23. **
  24. **  ORIGINAL PROGRAM:
  25. **    T.G.LEWIS, 'THE MIND APPLIANCE'
  26. **    HAYDEN BOOK COMPANY
  27. **)
  28. CONST
  29.   str_len = 73;        (* max length of all strings + one *)
  30.   EOS      = '|';    (* End of String marker *)
  31.   Master  = 'RECIPE.MST';
  32.   Tab20      = 20 ;
  33.   Tab15      = 15 ;
  34.   on       = true;
  35.   off      = false;
  36.  
  37. (* !!!!! IMPLEMENTATION DEPENDENCY !!!!! *)
  38.    (*****   PASCAL/Z ver 2.0   *****)
  39.       INPUT   = 0;
  40.  
  41. TYPE
  42.   string   = packed array[1..str_len] of char;
  43.   string2  = packed array[1..2] of char;
  44.   string14 = packed array[1..14] of char;
  45.   datatype = record
  46.          MR,        (* MaxRecords    *)
  47.          CR : integer;    (* Curr_Rcds    *)
  48.          F1,        (* current_ID    *)
  49.          F2,        (* backup_ID    *)
  50.          date : string14(* last_update    *)
  51.          end;
  52. VAR
  53.   a_RAY        : packed array[1..5] of string;
  54.   data        :datatype;
  55.   Bell,
  56.   command    :char;
  57.   Last_update    :string14;
  58.   Curr_Rcds,    (* No. of current active records *)
  59.   Hash,        (* Computed Index value of Recipe *)
  60.   Last,
  61.   MaxRecords,    (* Maximum records allowed *)
  62.   TTY        (* width of terminal/CRT *)
  63.         :integer;
  64.   End_of_File,        (* End of File flag *)
  65.   End_of_Text,        (* End of Text flag *)
  66.   adding_recipies,    (* flag = true when adding recipies *)
  67.   switch, error,
  68.   done, yflag    : boolean;
  69.  
  70.     (* FID. File Identifier *)
  71.   current_ID,            (* Current file ID *)
  72.   backup_ID    :string14;    (* Back up file ID *)
  73.  
  74.     (* FCB. File descriptors *)
  75.   fa, fb    :TEXT;
  76.   stats        :FILE of datatype;
  77.  
  78.  
  79. (*----------------------------------------------*
  80.  *          INPUT/OUTPUT ROUTINES        *
  81.  *----------------------------------------------*)
  82.  
  83.  
  84. (*----------------------------------------------*)
  85. (*          DISK I/O            *)
  86. (*----------------------------------------------*)
  87.  
  88.  
  89. Procedure OPEN_MASTER;
  90. begin
  91.   (* OPEN file RECIPE.MST for READ assign stats *)
  92.       RESET(master, stats);
  93.   READ(stats, data );
  94.   with data do begin
  95.     MaxRecords := MR;
  96.     Curr_Rcds  := CR;
  97.     current_ID    := F1;
  98.     backup_ID    := F2;
  99.     last_update := date
  100.     end(* with *)
  101. end;
  102.  
  103. Procedure UPDATE_MASTER;
  104. begin
  105.   (* OPEN file RECIPE.MST for WRITE assign stats *)
  106.       REWRITE(master, stats);
  107.   with data do begin
  108.     MR := MaxRecords;
  109.     CR := Curr_Rcds;
  110.     F1 := current_ID ;
  111.     F2 := backup_ID ;
  112.     date := last_update
  113.     end(* with *);
  114.   WRITE(stats, data )
  115. end;
  116.  
  117. Procedure GETLINE((* VAR fx : TEXT; *)
  118.              VAR INBUFF : string );
  119. (**
  120. Returns:
  121.     End_of_Text = true if attempt is made to exceed
  122.             the input buffer length.
  123.     End_of_File = true if EOF
  124.     INBUFF    = input string
  125. ***)
  126. VAR
  127.  CH   : CHAR;
  128.  ix, length : integer;
  129. begin
  130.   length := 0;
  131.   End_of_Text := FALSE;
  132.   WHILE NOT EOF(fa) AND (CH <> EOS) DO
  133.     begin
  134.     If length < str_len then
  135.       begin
  136.       READ(fa, CH );
  137.       length := length +1;
  138.       INBUFF [length] := CH
  139.       end(* If *)
  140.     ELSE    (***   error   ***)
  141.       begin
  142.       error := true;
  143.       End_of_Text := TRUE
  144.       end(* else *)
  145.     end(* WHILE *);
  146.     If length >= last then
  147.       last:=length
  148.     Else
  149.       REPEAT
  150.     INBUFF[ last ] := EOS;
  151.     last := last -1
  152.       UNTIL last=length;
  153.     (*** !!! SET FLAG !!! ***)
  154.   End_of_File := EOF(fa);
  155. end(*---of GetLine---*);
  156.  
  157. Procedure PUTLINE((* VAR fx : TEXT; *)
  158.              VAR this :string );
  159. VAR
  160.   CH  : char;
  161.   pos : integer;
  162. begin
  163.   pos := 0;
  164.   REPEAT
  165.     pos := pos +1;
  166.     CH := this[ pos ];
  167.     If CH <> EOS then Write(fb, CH)
  168.   UNTIL (CH = EOS) OR (pos = str_len);
  169.   Write(fb, EOS ) (* Mark the End of String *)
  170. end(*---of PUTLINE---*);
  171.  
  172. Procedure PUT_RECORD((* VAR fx : TEXT; *)
  173.             VAR Index : integer );
  174. VAR
  175.   jx : integer;
  176. begin
  177.   Writeln(fb, Index:5);
  178.   For jx:=1 to 5 do
  179.     PUTLINE((* fb, *) a_RAY[jx] );
  180. end(*---of PUT_RECORD---*);
  181.  
  182. Procedure GET_RECORD((* VAR fx : TEXT; *)
  183.             VAR Index : integer );
  184. VAR
  185.   JJ : integer;
  186. begin
  187.   READLN (fa, Index);
  188.   FOR JJ := 1 to 5 DO
  189.     GETLINE((* fa, *) a_RAY[JJ] );
  190. end(*---of GET_RECORD---*);
  191.  
  192. (*----------------------------------------------*)
  193. (*        CONSOLE I/O            *)
  194. (*----------------------------------------------*)
  195.  
  196. Procedure PRINT((* VAR fx : TEXT; *)
  197.            VAR this : string );
  198. (*    Print the string 'this' until EOS     *)
  199. VAR
  200.   CH : CHAR;
  201.   pos : integer;
  202. begin
  203.   pos := 0;
  204.   REPEAT
  205.     pos := pos +1;
  206.     CH := this[ pos ];
  207.     If CH <> EOS then Write(CH)
  208.   UNTIL (CH = EOS) OR (pos = str_len);
  209.   Writeln
  210. end(*---of PRINT---*);
  211.  
  212. Procedure SCAN((* VAR fx : TEXT; *)
  213.          VAR INBUFF : String ;
  214.               count : integer );
  215. (*    SCAN Version 1.1        *
  216. Enter with:
  217.     count = maximum # chars allowed.
  218. Returns:
  219.     INBUFF = input string
  220.     EOS    = End of string marker
  221. Flags:
  222.     error  = false - good input
  223.            = true if buffer length exceeded
  224.               If invalid ASCII char detected.
  225.  
  226.     Valid Alphanumeric chars are:
  227.     between the space - CHR(32) to the tilde - CHR(126)
  228. GLOBAL
  229.    str_len = << default for string length >>
  230.    EOS   = '|';
  231.    error  : boolean
  232.    string  : packed array[1..str_len] of char
  233.  *)
  234. VAR
  235.   InChar : char;
  236.   length : integer;
  237. begin
  238.   error := false;
  239.   For length:=1 to str_len do INBUFF[ length ]:= EOS;
  240.   length := 0;
  241.   REPEAT
  242.     If length < count then(* get valid inputs *)
  243.       begin
  244.       READ( InChar );
  245.       If InChar IN [' ' .. '~'] then
  246.     begin (* Increment length and store InChar *)
  247.     length := length +1;
  248.     INBUFF[length] := InChar
  249.         end(* if *)
  250.       ELSE
  251.     begin
  252.     Writeln(' Alphanumerics only -');
  253.     error:=TRUE
  254.     end(* else *)
  255.       end(* If *)
  256.     ELSE    (*   ERROR   *)
  257.       begin (* RESET EndOfLine (EOLN) *)
  258.       READLN(INBUFF[count]);
  259.       Writeln('Maximum of', count:4, ' characters please!');
  260.       error:=TRUE
  261.       end(* ELSE *)
  262.   UNTIL EOLN(INPUT) OR error;
  263. end(*---of SCAN11---*);
  264.  
  265. (*----------------------------------------------*
  266.  *        UTILITY ROUTINES        *
  267.  *----------------------------------------------*)
  268.  
  269.  
  270. Procedure QUIRY;
  271. (*    YES/NO INPUT MODULE
  272. Returns:
  273.     yflag    =TRUE FOR ''Y' or 'y' INPUT
  274.         =FALSE FOR 'N' or 'n' INPUT
  275. GLOBAL
  276.     yflag : boolean;
  277. *)
  278. VAR
  279.   Ans : char;
  280.   error : boolean;
  281. begin
  282.   error := true;
  283.   yflag := false;
  284.   REPEAT
  285.     error := false;
  286.     READ(Ans);
  287.     If (Ans = 'Y') OR (Ans = 'y') then
  288.       yflag := true
  289.     Else
  290.       If (Ans <> 'N') AND (Ans <> 'n') then
  291.         begin
  292.     Writeln(BELL, 'Please answer ''Y'' or ''N'' ');
  293.     error := true
  294.     end
  295.   Until NOT error
  296. end(*---of QUIRY---*);
  297.  
  298. Procedure CLEAR;
  299. (* Device dependent procedure    *)
  300. begin
  301.   Write( CHR(26) );
  302. end;
  303.  
  304. Procedure SKIP(L1 : integer);
  305. VAR ix : integer;
  306. begin
  307.   FOR ix:=1 to L1 do Writeln;
  308. end;
  309.  
  310. Procedure PAUSE;
  311. VAR dummy : char;
  312. begin
  313.   skip(4);
  314.   Write('Type return to continue:');
  315.   READ(dummy);
  316. end;
  317.  
  318. Procedure BREAK;
  319. begin
  320.   CLEAR;
  321.   SKIP(5);
  322. end;
  323.  
  324. Procedure Pstring(picture : string2; count : integer );
  325. VAR ix : integer;
  326. begin
  327.   FOR ix:=1 to count DO Write( picture );
  328.   Writeln;
  329. end(*---of Pstring---*);
  330.  
  331. Procedure ShowRecipe;
  332. VAR JJ : integer;
  333. begin
  334.   FOR JJ := 1 to 5 DO
  335.     PRINT(a_RAY[JJ]) ;
  336.   Writeln
  337. end(*--of ShowRecipe--*);
  338.  
  339. Procedure Display_One(VAR Index : integer);
  340. begin
  341.   Writeln;
  342.   Writeln( 'Recipe #', Index:5 );
  343.   Writeln;
  344.   Pstring( '- ', 20);
  345.   Writeln;
  346.   ShowRecipe;
  347.   skip(4)
  348. end;
  349.  
  350. (*----------------------------------------------*
  351.  *           ADD MODULE            *
  352.  *----------------------------------------------*)
  353.  
  354. Procedure InputFeatures(VAR I : integer);
  355. (******************************************
  356. *    Input Features of Recipe      *
  357. *******************************************)
  358. (*
  359. RETURNS:
  360.   Hash value computed for various choices
  361. **)
  362. CONST
  363.   Msg1      = 'None of these' ;
  364. VAR
  365.    F, D, V, P :integer;
  366.  
  367.     Function QUIRY(X2 : integer) : integer;
  368.     VAR ix : integer;
  369.     begin
  370.       REPEAT
  371.         Writeln;
  372.         Write('Enter Choice (1 to', X2:2, ') ');
  373.         READ(ix);
  374.       UNTIL (ix>=1) AND (ix<=X2) ;
  375.       QUIRY := ix;
  376.     end;
  377. begin
  378.   Writeln;
  379.   Writeln( ' Enter number of choice :');
  380.   Writeln;
  381.   Writeln( ' ':Tab15, 'Fibre Foods' );
  382.   Writeln;
  383.   Writeln( ' ':Tab15, '1.  Bread (flour)     2.  Oats' );
  384.   Writeln( ' ':Tab15, '3.  Rice              4.  Corn' );
  385.   Writeln( ' ':Tab15, '5.  Macaroni          6.  Noodles' );
  386.   Writeln( ' ':Tab15, '7.  Spaghetti         8.  ', Msg1 );
  387.   F := quiry(8);
  388.   Writeln;
  389.   Writeln( ' ':Tab15, 'Protein' );
  390.   Writeln;
  391.   Writeln( ' ':Tab15, '1.  Beef              2.  Poultry' );
  392.   Writeln( ' ':Tab15, '3.  Fish              4.  Eggs' );
  393.   Writeln( ' ':Tab15, '5.  Beans             6.  Nuts' );
  394.   Writeln( ' ':Tab15, '7.  ', Msg1 );
  395.   P := quiry(7);
  396.   BREAK;
  397.   Writeln;
  398.   Writeln( ' ':Tab15, 'Dairy' );
  399.   Writeln;
  400.   Writeln( ' ':Tab15, '1.  Milk                2.  Cheese' );
  401.   Writeln( ' ':Tab15, '3.  Cottage Cheese      4.  Cream' );
  402.   Writeln( ' ':Tab15, '5.  Sour Cream          6.  ', Msg1 );
  403.   D := quiry(6);
  404.   Writeln;
  405.   Writeln( ' ':Tab15, 'Fruits and Vegetables' );
  406.   Writeln;
  407.   Writeln( ' ':Tab15, '1.  Citrus              2.  Melon' );
  408.   Writeln( ' ':Tab15, '3.  Juices              4.  Greens' );
  409.   Writeln( ' ':Tab15, '5.  Yellows & Reds' );
  410.   Writeln( ' ':Tab15, '6.  ', Msg1 );
  411.   V := quiry(6);
  412.  
  413.    (******************************************
  414.    *  Compute the index value by assigning   *
  415.    *  a weight to each digit in the set.     *
  416.    *******************************************)
  417.  
  418.     I := 252*F + 36*P + 6*D + V -295
  419. end;
  420.  
  421.  
  422. Procedure InputRecipe;
  423.  
  424. LABEL 2399; (*---EXIT---*)
  425.  
  426. VAR
  427.   state : (absent, done, adding) ;
  428.   ix, jx : integer;
  429.   temp     : string14;
  430.   Line     : string;
  431.  
  432.     Procedure Correct;
  433.     begin
  434.     REPEAT
  435.       BREAK;
  436.       Write(bell);
  437.       Writeln(' ':(TTY DIV 2) -10, 'HERE IS YOUR RECIPE');
  438.       Writeln;
  439.       ShowRecipe;
  440.       Writeln;
  441.       Writeln('Are there any corrections to be made ');
  442.       QUIRY;
  443.       If yflag then
  444.         begin
  445.         BREAK;
  446.         Writeln('Enter <cr> return if correct or Reenter the line');
  447.         Writeln;
  448.         For ix:=1 to 5 do
  449.           begin
  450.           PRINT(a_RAY[ix]);
  451.           SCAN(Line, str_len -1);
  452.           If Line[1] <> ' ' then a_RAY[ix] := Line
  453.           end
  454.         end(* If *)
  455.     Until yflag=false;
  456.     end(*---of Correct---*);
  457.  
  458.     Procedure QUEST;
  459.     begin
  460.       Pause;
  461.       BREAK;
  462.       Write('Do you want to ADD recipies? ' );
  463.       QUIRY;
  464.       CLEAR;
  465.     end;
  466.  
  467. begin(*---InputRecipe---*)
  468.   QUEST;
  469.   If yflag=false then (* EXIT *) goto 2399;
  470.   adding_recipies := true ;
  471.   state := adding ;
  472.   (* OPEN file backup_ID for WRITE assign fb *)
  473.     REWRITE(backup_ID, fb);
  474.  
  475.   (* OPEN file current_ID for READ assign fa *)
  476.     RESET(current_ID, fa);
  477.  
  478.   If NOT EOF(fa) then
  479.     begin(* COPY current to back_up *)
  480.     ix := 0 ;
  481.     While ix < Curr_Rcds do
  482.       begin
  483.       ix := ix +1;
  484.       GET_RECORD((* fa, *) HASH);
  485.       PUT_RECORD((* fb, *) HASH);
  486.       end(* while *)
  487.     end(* IF *);
  488.  
  489. (*---Input/Enter additional recipies until done---*)
  490. (*---or curr_records > Max_Records allowed     ---*)
  491.  
  492.   REPEAT
  493.   If Curr_Rcds > MaxRecords then
  494.     state := done
  495.   Else(* we can add more date *)
  496.     begin
  497.       Writeln( 'Identify Recipe with features. First ');
  498.       InputFeatures(HASH);
  499.       BREAK;
  500.       Writeln( 'Now Enter 5 lines of the recipe');
  501.       Writeln;
  502.       For jx := 1 to 5 DO
  503.     begin
  504.     Write('>');
  505.     SCAN( a_RAY[jx], str_len -1 );
  506.     end;(* For *)
  507.       Correct(* if required *);
  508.       Curr_Rcds := Curr_Rcds +1;
  509.       PUT_RECORD((* fb, *) HASH);
  510.       QUEST;
  511.       If yflag=false then state := done;
  512.     end;(* else *)
  513.   UNTIL state<>adding;
  514.  
  515.   (*---------------------------------------*
  516.    *         ***   trick   ***           *
  517.    *  close previous file ID assigned       *
  518.    *  FCB fb and fix CP/M directory entry  *
  519.    *---------------------------------------*)
  520.  
  521.     REWRITE('DUMMY.$$$', fb);
  522.  
  523.   (*    SWAP file ID`s                *)
  524.   (*    Back Up file is now the Current file    *)
  525.   temp := backup_ID;
  526.   backup_ID := current_ID;
  527.   current_ID := temp;
  528.  
  529.   UPDATE_MASTER;(*--status file--*)
  530.  
  531. 2399: (* EXIT *);
  532. end(*--of InputRecipe--*);
  533.  
  534.  
  535. (*--------------------------------------*)
  536. (*          DUMP/FIND MODULE        *)
  537. (*--------------------------------------*)
  538.  
  539. Procedure File_Scan ;
  540. (*
  541. GLOBAL
  542.   MaxRecords = maximum allowed records
  543.   Curr_Rcds = # of recipes in file
  544. *)
  545. VAR
  546.   state : (absent, found, searching) ;
  547.   ix, index : integer;
  548.  
  549.     Procedure DUMP;
  550.     (*********************************
  551.     *  OUTPUT all Recipes from file  *
  552.     **********************************)
  553.     begin
  554.       REPEAT
  555.         If ix > Curr_Rcds then
  556.           state := absent
  557.         Else
  558.           begin
  559.         ix := ix +1;
  560.         GET_RECORD((* fa, *) HASH);
  561.         Display_One(HASH);
  562.         Pause
  563.           end(* else *)
  564.       UNTIL state<>searching;
  565.     end(*--of DUMP--*);
  566.  
  567.     Procedure FIND;
  568.     (*************************************
  569.     *    Lookup recipes from file     *
  570.     **************************************)
  571.     VAR
  572.       Index : integer;
  573.     begin
  574.       CLEAR;
  575.       InputFeatures(Index);
  576.       REPEAT
  577.         If ix > Curr_Rcds then
  578.           state := absent
  579.         Else
  580.           begin
  581.         GET_RECORD((* fa, *) HASH);
  582.         If HASH=Index then
  583.           state := found
  584.         Else
  585.           ix := ix +1
  586.           end(* else *);
  587.       Until state<>searching;
  588.       If state=found then
  589.         begin
  590.         CLEAR;
  591.         Display_One(HASH);
  592.         end;
  593.     end(*--of Lookup--*);
  594.  
  595. begin(*---File_Scan---*)
  596.   Pause;
  597.   state := absent;
  598.   If adding_recipies then
  599.     (* read new stats *) OPEN_MASTER;
  600.   (* OPEN file current_ID for READ assign fa *)
  601.       RESET(current_ID, fa);
  602.  
  603.   If NOT EOF(fa) then
  604.     begin
  605.     state := searching ;
  606.     ix := 1 ;
  607.     If Curr_rcds=0 then
  608.       state := absent
  609.     Else
  610.       begin
  611.     CASE command of
  612.       'O', 'o':    DUMP;
  613.       'F', 'f':    FIND
  614.     end(* case *)
  615.       end(* else *)
  616.     end(* IF *);
  617.   If state=absent then
  618.     begin
  619.     BREAK;
  620.     Writeln('That''s all the Recipes on File');
  621.     end;
  622.   Pause;
  623. end(*---of File_Scan---*);
  624.  
  625. (*--------------------------------------*)
  626. (*          INITIALIZATION        *)
  627. (*--------------------------------------*)
  628.  
  629.  
  630. Procedure INIT1;
  631. (* byte count/record = (chars/line + overhead/line) times No. of lines *)
  632. begin
  633.   BELL        := CHR(7) ;
  634.   TTY        :=  72 ;
  635.   last        := str_len ;
  636.   MaxRecords    := 50 ;(* 360 times 50 = 18000 bytes *)
  637.   Curr_Rcds    :=  0 ;
  638.   Last_Update    := 'YY/MM/DD      ';
  639.   current_ID    := 'RCPDAT.XXX    ';
  640.   backup_ID    := 'RCPDAT.YYY    ';
  641.   adding_recipies := false
  642. end;
  643.  
  644. Procedure INIT2;
  645. begin
  646.    (* OPEN file `RECIPE.MST` for READ assign stats *)
  647.       RESET(master, stats);
  648.  
  649.   If EOF(stats) then(* not found *)
  650.     (* OPEN file `RECIPE.MST` for WRITE assign stats *)
  651.       UPDATE_MASTER
  652.   Else begin(* READ in data record *)
  653.     READ(stats, data );
  654.     with data do begin
  655.       MaxRecords := MR;
  656.       Curr_Rcds  := CR;
  657.       current_ID := F1;
  658.       backup_ID     := F2;
  659.       last_update := date
  660.       end(* with *)
  661.     end;
  662.   SKIP(5);
  663.   Writeln('Last update of Recipe data file was ', last_update);
  664.   Writeln('File currently consists of ', Curr_Rcds:4, ' Recipies');
  665.   Writeln;
  666.   Write('Please enter todays date <YY/MM/DD>  ');
  667.   READLN(last_update)
  668. end;
  669.  
  670. (*----------------------------------------------*
  671.  *        MAIN PROGRAM            *
  672.  *----------------------------------------------*)
  673.  
  674. BEGIN
  675.   INIT1;
  676.   CLEAR;
  677.   Pstring( '**', (TTY DIV 2));
  678.   Writeln;
  679.   Writeln( ' ':22, 'The Recipe System');
  680.   Writeln;
  681.   Pstring( '**', (TTY DIV 2));
  682.   INIT2;
  683.   done := false;
  684.   WHILE NOT(done) DO
  685.     begin
  686.     CLEAR;
  687.     Pstring( '**', (TTY DIV 2));
  688.     skip(3);
  689.     Writeln( ' ':Tab15, 'Select One of the following:');
  690.     Writeln;
  691.     Writeln( ' ':Tab20, 'I(nput Recipes');
  692.     Writeln( ' ':Tab20, 'O(utput all Recipes');
  693.     Writeln( ' ':Tab20, 'F(ind a Recipe');
  694.     Writeln( ' ':Tab20, 'S(top');
  695.     switch := on;
  696.     WHILE switch(* is on *) do
  697.       begin
  698.       switch := off;
  699.       Writeln;
  700.       Write(' ':(Tab15), 'Enter choice   ' );
  701.       READ( command );
  702.     CASE command of
  703.       'I', 'i':    InputRecipe;
  704.       'O', 'o',
  705.       'F', 'f':    File_Scan;
  706.       'S', 's':    done := true;
  707.      ELSE:        begin
  708.             Write(BELL);
  709.             switch := on
  710.             end
  711.     end(* case *)
  712.       end(* while switch is on *)
  713.     end(* while not done *)
  714. end(*---of Program Recipe---*).
  715.