weiner@novavax.UUCP (Bob Weiner) (02/01/90)
From reading this news group I get the impression that a fair number of readers actively write code in Eiffel. ISE's resources allow them to produce only a small amount of the reusable code that many people need. So why don't all of us who are writing in Eiffel start posting the really well written, non-proprietary, general purpose classes that we use? This is not to encourage anyone to post prototype code or any code that handwaves over the more difficult examples. Production quality code that can be immediately reused with little or no changes is what people should strive to post. In order to get this started, here is an example of a set of classes that can be used in many applications. It is a complete rewrite of the input parameter reading classes posted a week and a half ago. The README explains it all. (Don't forget to include adequate documentation with your classes. Hint: The single line comments strewn throughout ISE's library class features are seldom adequate.) I hope we all see some productive Eiffel samples soon. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: README .eiffel .eiffel_debug ex_params.txt # boolean_reader.e character_reader.e double_reader.e # ex_param_applic.e integer_reader.e param_reader.e params_reader.e # real_reader.e ref_file.e string_reader.e # Wrapped by weiner@ar_weiner on Thu Feb 1 01:22:38 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(5187 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' X# X# SUMMARY: Reusable classes and application of input parameter reading. X# X# AUTHOR: Bob Weiner X# ORG: Motorola, Inc. X# ORIG-DATE: 1-Feb-90 at 01:07:54 X# LAST-MOD: 1-Feb-90 at 01:20:29 by Bob Weiner X# DESCRIPTION: X# X# Here is a rewrite of the classes that Jean-Marc Nerson of ISE posted on X# 1/19/90 to read input parameter files. His classes demonstrated the X# concept but were not production quality. These are. Improvements X# include: X# X# The file to read is now a command line argument (or feature parameter). X# X# Empty lines and comment lines are allowed in the parameter file. X# Comments start with a "# " or a "-- " string and may be on a line by X# themselves or may follow the text of a valid parameter line. X# X# Parameter value readers for all Eiffel basic types are provided. X# X# The parameter type is given on the same line as the parameter name so X# that only a one pass reading of the parameter file need be done. This also X# improves the readability of the file. Parameter lines appear as a <tag_name, X# type, value> triplet. The generalization to handle one dimensional arrays of X# basic types is fairly simple now, but remains unimplemented. X# X# X# Note that 'val' is not a feature of the deferred class "param_reader" X# because of the addition of the "double_reader" class. Since 'double' is an X# expanded type currently, the compiler will not allow it to be redefined, X# hence 'val' cannot exist in "double_reader"'s parent's class. X# X# DESCRIP-END. X X XHere is a summary of the executable size of the sample application X(ex_param_applic) given a variety of compilation options (36 classes were Xlinked in, 37 when viewable was inherited). I thought people would be Xinterested in the space/time efficiency of such a simple Eiffel application. XFor small input files (all I have tested), the program operates extremely Xrapidly. X XPersonally, I feel all of the executable sizes that follow are way too large Xgiven the simplicity of the application and the few features that are used Xfrom the library classes. Much better space efficiency is needed before Xlarge numbers of developers will accept the overhead in order to use dynamic Xbinding and inheritance. X X X Inherits from viewable, debug and assertion monitoring, garbage collection X -rwxrwx--x+ 1 root 1131028 Jan 30 16:08 ex_param_app* X X Inherits from viewable, no debug and assertion monitoring, no garbage X collection, includes optimization. X -rwxrwx--x+ 1 root 928748 Jan 31 15:35 ex_param_applic* X X Does not inherit from viewable, no debug and assertion monitoring, no X garbage collection, includes optimization. X -rwxrwx--x+ 1 root 295782 Feb 1 00:40 ex_param_applic* X X X X XWhat follows is an edited version of the notes Jean-Marc originally posted, Xfor completeness. X XFrom marc@eiffel.UUCP Fri Jan 19 00:49:09 1990 XFrom: marc@eiffel.UUCP (Jean-Marc Nerson) XNewsgroups: comp.lang.eiffel XSubject: Re: Interesting problems to try in Eiffel XSummary: Input consisting of a possibly large set of values XDate: 17 Jan 90 18:49:46 GMT XOrganization: Interactive Software Engineering, Santa Barbara CA X X X A few postings recently (by Bob Weiner, Erland Sommarskog and Markku XSakkinen) have raised the question of how to have input (in the style of XNAMELIST in Fortran) consisting of a possibly large set of values, each Xcharacterized by a tag. X X See the file "ex_params.txt" for sample input. X X Presented here is a solution to this problem in Eiffel which makes full use Xof the object-oriented method: polymorphism, dynamic binding. X X This solution is the complete implementation of what Erland Sommarskog Xsketched out in <631@enea.se>: X X(...) X>> A back-on-the-envelope solution to the problem would to be to have X>> class PARAMETER which inherits some sorting mechanism, probably a X>> hash table. Probably you have subclasses STRING_PARAMETER, X>> BOOLEAN_PARAMETER etc. You read the parameter string uses that as X>> key to get the instance, calls its Assign_value passing the value X>> string from the file. Assign_value parses the string and assigns X>> it to the Value feature or gives an error message. (...) X X The solution uses polymorphism and the Reverse Assignment Attempt X(operator "?="). X X To use dynamic binding, the solution relies on a hash table which Xassociates with each tag a reader object for the appropriate parameter type. XThese objects are shared (altogether, the type table includes only one object Xof each type whereas the value table contains one for each value read). X X The solution achieves one of the major benefits of object-oriented design: Xlimiting the number of explicit choices between a range of possibilities. XThere are explicit choices, but this is inevitable since the basic classes Xmust know the list of all possible types of input (string, real etc.); Xhowever there will be NO explicit choice in the application software. You do Xnot need to change or recompile any of the basic classes when adding a new Xparameter type, just create a reader class for the type. X X The classes could be better adapted to handle and recover from invalid Xinput. X END_OF_FILE if test 5187 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f '.eiffel' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'.eiffel'\" else echo shar: Extracting \"'.eiffel'\" \(386 characters\) sed "s/^X//" >'.eiffel' <<'END_OF_FILE' X------------ EIFFEL SYSTEM DESCRIPTION FILE ------------------- XROOT: ex_param_applic XUNIVERSE: /usr/local/src/Eiffel/library/structures X /usr/local/src/Eiffel/library/support XEXTERNAL: XNO_ASSERTION_CHECK (Y): ALL XPRECONDITIONS (N): ALL XALL_ASSERTIONS (N): ALL XDEBUG (N): params_reader XTRACE (N): XOPTIMIZE (Y): ALL XGARBAGE_COLLECTION (N) XC_PACKAGE (N): XC_EXTERNAL: XMAKE: XVISIBLE (N): END_OF_FILE if test 386 -ne `wc -c <'.eiffel'`; then echo shar: \"'.eiffel'\" unpacked with wrong size! fi # end of '.eiffel' fi if test -f '.eiffel_debug' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'.eiffel_debug'\" else echo shar: Extracting \"'.eiffel_debug'\" \(382 characters\) sed "s/^X//" >'.eiffel_debug' <<'END_OF_FILE' X------------ EIFFEL SYSTEM DESCRIPTION FILE ------------------- XROOT: ex_param_applic XUNIVERSE: /usr/local/src/Eiffel/library/structures X /usr/local/src/Eiffel/library/support XEXTERNAL: XNO_ASSERTION_CHECK (Y): XPRECONDITIONS (N): ALL XALL_ASSERTIONS (N): ALL XDEBUG (N): params_reader XTRACE (N): XOPTIMIZE (N): ALL XGARBAGE_COLLECTION (Y) XC_PACKAGE (N): XC_EXTERNAL: XMAKE: XVISIBLE (N): END_OF_FILE if test 382 -ne `wc -c <'.eiffel_debug'`; then echo shar: \"'.eiffel_debug'\" unpacked with wrong size! fi # end of '.eiffel_debug' fi if test -f 'ex_params.txt' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ex_params.txt'\" else echo shar: Extracting \"'ex_params.txt'\" \(399 characters\) sed "s/^X//" >'ex_params.txt' <<'END_OF_FILE' X# This is an example parameter file. X# All comments should follow a valid parameter line or start with a '#' char X# in column 1. X-- Eiffel-like comments work too! X Xactive_valve STRING "SOUTHEAST 2" Xis_sensor_on BOOLEAN true Xpressure REAL 32.76 Xreading DOUBLE 123.45678901234567890123 Xtemperature REAL 12.851234 Xsensor_code CHARACTER 'B' Xvalve_count INTEGER 78 END_OF_FILE if test 399 -ne `wc -c <'ex_params.txt'`; then echo shar: \"'ex_params.txt'\" unpacked with wrong size! fi # end of 'ex_params.txt' fi if test -f 'boolean_reader.e' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'boolean_reader.e'\" else echo shar: Extracting \"'boolean_reader.e'\" \(731 characters\) sed "s/^X//" >'boolean_reader.e' <<'END_OF_FILE' X-- X-- SUMMARY: Read a BOOLEAN from a file. X-- X-- AUTHOR: Bob Weiner X-- ORG: Motorola, Inc. X-- ORIG-DATE: 24-Jan-90 at 16:19:00 X-- LAST-MOD: 1-Feb-90 at 00:35:24 by Bob Weiner X-- DESCRIPTION: X-- X-- Based on work by Jean-Marc Nerson (Interactive Software Engineering) X-- and Erland Sommarskog. X-- X-- DESCRIP-END. X X Xclass BOOLEAN_READER X Xexport X X repeat PARAM_READER, val X Xinherit X X PARAM_READER X define read; X Xfeature X X Create is X do X file.Create; X end; X X read is X require X not file.Void X do X file.val.readword; X if file.val.laststring.equal("true") then X val := true X else X val := false X end; X end; X X val: BOOLEAN; X Xend END_OF_FILE if test 731 -ne `wc -c <'boolean_reader.e'`; then echo shar: \"'boolean_reader.e'\" unpacked with wrong size! fi # end of 'boolean_reader.e' fi if test -f 'character_reader.e' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'character_reader.e'\" else echo shar: Extracting \"'character_reader.e'\" \(918 characters\) sed "s/^X//" >'character_reader.e' <<'END_OF_FILE' X-- X-- SUMMARY: Read a CHARACTER from a file. X-- X-- AUTHOR: Bob Weiner X-- ORG: Motorola, Inc. X-- ORIG-DATE: 24-Jan-90 at 16:19:00 X-- LAST-MOD: 1-Feb-90 at 00:35:42 by Bob Weiner X-- DESCRIPTION: X-- X-- Based on work by Jean-Marc Nerson (Interactive Software Engineering) X-- and Erland Sommarskog. X-- X-- DESCRIP-END. X X Xclass CHARACTER_READER X Xexport X X repeat PARAM_READER, val X Xinherit X X PARAM_READER X define read; X Xfeature X X Create is X do X file.Create; X end; X X read is X require X not file.Void X do X from X file.val.readchar; X until X file.val.end_of_file or else file.val.lastchar = '\'' X loop X file.val.readchar; X end; X if not file.val.end_of_file then X file.val.readchar; X val := file.val.lastchar; X -- Throw away closing quote X file.val.readchar; X end; X end; X X val: CHARACTER; X Xend END_OF_FILE if test 918 -ne `wc -c <'character_reader.e'`; then echo shar: \"'character_reader.e'\" unpacked with wrong size! fi # end of 'character_reader.e' fi if test -f 'double_reader.e' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'double_reader.e'\" else echo shar: Extracting \"'double_reader.e'\" \(559 characters\) sed "s/^X//" >'double_reader.e' <<'END_OF_FILE' X-- X-- SUMMARY: Read a DOUBLE from a file. X-- X-- AUTHOR: Bob Weiner X-- ORG: Motorola, Inc. X-- ORIG-DATE: 24-Jan-90 at 16:19:00 X-- LAST-MOD: 1-Feb-90 at 00:35:04 by Bob Weiner X-- DESCRIPTION: X-- DESCRIP-END. X X Xclass DOUBLE_READER X Xexport X X repeat PARAM_READER, val X Xinherit X X PARAM_READER X define read; X Xfeature X X Create is X do X file.Create; X end; X X read is X require X not file.Void X do X file.val.readdouble; X val := file.val.lastdouble; X end; X X val: DOUBLE; X Xend END_OF_FILE if test 559 -ne `wc -c <'double_reader.e'`; then echo shar: \"'double_reader.e'\" unpacked with wrong size! fi # end of 'double_reader.e' fi if test -f 'ex_param_applic.e' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ex_param_applic.e'\" else echo shar: Extracting \"'ex_param_applic.e'\" \(1930 characters\) sed "s/^X//" >'ex_param_applic.e' <<'END_OF_FILE' X-- X-- SUMMARY: Example root class for demonstrating file-based input X-- parameter reading. X-- X-- AUTHOR: Bob Weiner X-- ORG: Motorola, Inc. X-- ORIG-DATE: 24-Jan-90 at 16:11:24 X-- LAST-MOD: 1-Feb-90 at 00:24:03 by Bob Weiner X-- DESCRIPTION: X-- X-- Based on work by Jean-Marc Nerson (Interactive Software Engineering) X-- and Erland Sommarskog. X-- X-- DESCRIP-END. X X Xclass EX_PARAM_APPLIC X Xinherit X X ARGUMENTS; X PARAMS_READER; X-- VIEWABLE; X Xfeature X X Create is X do X if argument_count = 2 then X-- viewer_on_failure; X init_type_table; init_param_table(argument(1)); assign_params; X io.putstring(tagged_out); X else X io.set_error_default; X io.putstring(argument(0)); X io.putstring(": Usage: "); X io.putstring(argument(0)); X io.putstring(" <input-parameters-pathname>\n"); X end; X end; X X-- X-- Parameters into which to read values X-- X active_valve: STRING; X is_sensor_on: BOOLEAN; X pressure, temperature: REAL; X reading: DOUBLE; X sensor_code: CHARACTER; X valve_count: INTEGER; X X assign_params is X -- Assign each parameter using values read from a parameter X -- file and stored in lookup table `param_vals'. X do X ps ?= param_vals.item("active_valve"); X if not ps.Void then X active_valve := ps.val; X end; X pb ?= param_vals.item("is_sensor_on"); X if not pb.Void then X is_sensor_on := pb.val; X end; X pr ?= param_vals.item("pressure"); X if not pr.Void then X pressure := pr.val; X end; X pd ?= param_vals.item("reading"); X if not pd.Void then X reading := pd.val; X end; X pr ?= param_vals.item("temperature"); X if not pr.Void then X temperature := pr.val; X end; X pc ?= param_vals.item("sensor_code"); X if not pc.Void then X sensor_code := pc.val; X end; X pi ?= param_vals.item("valve_count"); X if not pi.Void then X valve_count := pi.val; X end; X end; X Xend X END_OF_FILE if test 1930 -ne `wc -c <'ex_param_applic.e'`; then echo shar: \"'ex_param_applic.e'\" unpacked with wrong size! fi # end of 'ex_param_applic.e' fi if test -f 'integer_reader.e' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'integer_reader.e'\" else echo shar: Extracting \"'integer_reader.e'\" \(666 characters\) sed "s/^X//" >'integer_reader.e' <<'END_OF_FILE' X-- X-- SUMMARY: Read an INTEGER from a file. X-- X-- AUTHOR: Bob Weiner X-- ORG: Motorola, Inc. X-- ORIG-DATE: 24-Jan-90 at 16:19:00 X-- LAST-MOD: 1-Feb-90 at 00:35:59 by Bob Weiner X-- DESCRIPTION: X-- X-- Based on work by Jean-Marc Nerson (Interactive Software Engineering) X-- and Erland Sommarskog. X-- X-- DESCRIP-END. X X Xclass INTEGER_READER X Xexport X X repeat PARAM_READER, val X Xinherit X X PARAM_READER X define read; X Xfeature X X Create is X do X file.Create; X end; X X read is X require X not file.Void X do X file.val.readint; X val := file.val.lastint X end; X X val: INTEGER; X Xend X END_OF_FILE if test 666 -ne `wc -c <'integer_reader.e'`; then echo shar: \"'integer_reader.e'\" unpacked with wrong size! fi # end of 'integer_reader.e' fi if test -f 'param_reader.e' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'param_reader.e'\" else echo shar: Extracting \"'param_reader.e'\" \(651 characters\) sed "s/^X//" >'param_reader.e' <<'END_OF_FILE' X-- X-- SUMMARY: Inherited protocol for input parameter reader classes. X-- X-- AUTHOR: Bob Weiner X-- ORG: Motorola, Inc., Communications Sector, Applied Research X-- ORIG-DATE: 26-Jan-90 at 11:59:26 X-- LAST-MOD: 1-Feb-90 at 00:34:39 by Bob Weiner X-- DESCRIPTION: X-- X-- Based on work by Jean-Marc Nerson (Interactive Software Engineering) X-- and Erland Sommarskog. X-- X-- DESCRIP-END. X X Xdeferred class PARAM_READER X Xexport X X new, read X Xfeature X X new: like Current is X do X Result.Create X end; X X read is X require X not file.Void X deferred X end; X X-- X-- PRIVATE X-- X X file: REF_FILE; X Xend X X END_OF_FILE if test 651 -ne `wc -c <'param_reader.e'`; then echo shar: \"'param_reader.e'\" unpacked with wrong size! fi # end of 'param_reader.e' fi if test -f 'params_reader.e' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'params_reader.e'\" else echo shar: Extracting \"'params_reader.e'\" \(3329 characters\) sed "s/^X//" >'params_reader.e' <<'END_OF_FILE' X-- X-- SUMMARY: Read parameter values from a file into a lookup table. X-- X-- AUTHOR: Bob Weiner X-- ORG: Motorola, Inc. X-- ORIG-DATE: 24-Jan-90 at 16:16:08 X-- LAST-MOD: 1-Feb-90 at 00:22:45 by Bob Weiner X-- DESCRIPTION: X-- X-- Based on work by Jean-Marc Nerson (Interactive Software Engineering) X-- and Erland Sommarskog. X-- X-- DESCRIP-END. X Xclass PARAMS_READER X X-- No export clause since class is intended to be inherited by an application X-- class that reads parameters from a file. X Xfeature X X init_type_table is X -- Enter into `param_types' one instance of each possible parameter X -- reader. X do X param_types.Create(15); -- A value big enough to cover all entered types. X pb.Create; param_types.put(pb, "BOOLEAN"); X pc.Create; param_types.put(pc, "CHARACTER"); X pd.Create; param_types.put(pd, "DOUBLE"); X pi.Create; param_types.put(pi, "INTEGER"); X pr.Create; param_types.put(pr, "REAL"); X ps.Create; param_types.put(ps, "STRING"); X debug X io.putstring(param_types.io.tagged_out); X end; X end; X X init_param_table (filename: STRING) is X -- Read parameters from `filename'. X -- Entries look like: <param-name> <param-type> <param-value> X -- Comment lines look like: '#' <text> X -- Blank lines without spaces or tabs are allowed. X local X file: REF_FILE; X param_name, param_type: STRING; X reader: PARAM_READER; X do X from X file.Create; X file.nm_set(filename); X file.val.open_read; X param_vals.Create(max_param_vals); X until X file.val.end_of_file X loop X file.val.readword; X if file.val.laststring.equal("#") X or else file.val.laststring.equal("--") then X -- Comment line, skip it. X file.val.readline; X elsif file.val.laststring.equal("") then X ; X else X param_name := file.val.laststring.duplicate; X debug X io.putstring(param_name.io.tagged_out); X end; X -- Enter an object of READER type into table keyed off parameter X -- type string X file.val.readword; X param_type := file.val.laststring.duplicate; X debug X io.putstring("param_type = "); X io.putstring(file.val.laststring); X io.new_line; X end; X reader := param_types.item(param_type); X if not reader.Void then X reader := reader.new; X reader.read; X if not param_type.equal("STRING") then X -- Skip over extraneous remaining characters on line X file.val.readline; X end; X debug X io.putstring(reader.io.tagged_out); X end; X param_vals.put(reader, param_name); X else X io.putstring(param_name); X io.putstring(" - Bad parameter type: \""); X io.putstring(param_type); X io.putstring("\"\n"); X file.val.readline; X end; X end; X end; X file.close X rescue X io.putstring("Input file \""); X io.putstring(filename); X io.putstring("\" corrupted\n"); X end; X X-- X-- PRIVATE X-- X X max_param_vals: INTEGER is 100; X param_vals: HTABLE [PARAM_READER, STRING]; X param_types: HTABLE [PARAM_READER, STRING]; X pb: BOOLEAN_READER; X pc: CHARACTER_READER; X pd: DOUBLE_READER; X pi: INTEGER_READER; X pr: REAL_READER; X ps: STRING_READER; X Xend X END_OF_FILE if test 3329 -ne `wc -c <'params_reader.e'`; then echo shar: \"'params_reader.e'\" unpacked with wrong size! fi # end of 'params_reader.e' fi if test -f 'real_reader.e' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'real_reader.e'\" else echo shar: Extracting \"'real_reader.e'\" \(656 characters\) sed "s/^X//" >'real_reader.e' <<'END_OF_FILE' X-- X-- SUMMARY: Read a REAL from a file. X-- X-- AUTHOR: Bob Weiner X-- ORG: Motorola, Inc. X-- ORIG-DATE: 24-Jan-90 at 16:19:00 X-- LAST-MOD: 1-Feb-90 at 00:36:18 by Bob Weiner X-- DESCRIPTION: X-- X-- Based on work by Jean-Marc Nerson (Interactive Software Engineering) X-- and Erland Sommarskog. X-- X-- DESCRIP-END. X X Xclass REAL_READER X Xexport X X repeat PARAM_READER, val X Xinherit X X PARAM_READER X define read; X Xfeature X X Create is X do X file.Create; X end; X X read is X require X not file.Void X do X file.val.readreal; X val := file.val.lastreal X end; X X val: REAL; X Xend END_OF_FILE if test 656 -ne `wc -c <'real_reader.e'`; then echo shar: \"'real_reader.e'\" unpacked with wrong size! fi # end of 'real_reader.e' fi if test -f 'ref_file.e' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ref_file.e'\" else echo shar: Extracting \"'ref_file.e'\" \(641 characters\) sed "s/^X//" >'ref_file.e' <<'END_OF_FILE' X-- X-- SUMMARY: Provide a constant reference to a file. X-- X-- AUTHOR: Bob Weiner X-- ORG: Motorola, Inc., Communications Sector, Applied Research X-- ORIG-DATE: 24-Jan-90 at 16:29:21 X-- LAST-MOD: 26-Jan-90 at 17:15:09 by Bob Weiner X-- DESCRIPTION: X-- DESCRIP-END. X X Xclass REF_FILE X Xexport X X close, nm, nm_set, val X Xfeature X X close is X do X val.close X end; X X nm: STRING is X once X Result.Create(100); X end; X X nm_set (nnm: STRING) is X -- EFFECTS: Set value of `nm' X do X nm.share(nnm); X end; X X val: FILE is X once X Result.Create(nm); X end; X Xend X END_OF_FILE if test 641 -ne `wc -c <'ref_file.e'`; then echo shar: \"'ref_file.e'\" unpacked with wrong size! fi # end of 'ref_file.e' fi if test -f 'string_reader.e' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'string_reader.e'\" else echo shar: Extracting \"'string_reader.e'\" \(1237 characters\) sed "s/^X//" >'string_reader.e' <<'END_OF_FILE' X-- X-- SUMMARY: Read a STRING from a file. X-- X-- AUTHOR: Bob Weiner X-- ORG: Motorola, Inc. X-- ORIG-DATE: 24-Jan-90 at 16:19:00 X-- LAST-MOD: 1-Feb-90 at 00:36:31 by Bob Weiner X-- DESCRIPTION: X-- X-- Based on work by Jean-Marc Nerson (Interactive Software Engineering) X-- and Erland Sommarskog. X-- X-- DESCRIP-END. X X Xclass STRING_READER X Xexport X X repeat PARAM_READER, val X Xinherit X X PARAM_READER X define read; X Xfeature X X Create is X do X file.Create; X val.Create(0); X end; X X read is X require X not file.Void X local X char: CHARACTER; X end_pos: INTEGER; X do X val := ""; X -- Skip past blank chars and opening double quote of string X from X file.val.readchar; X char := file.val.lastchar; X until X file.val.end_of_file or else char = '\n' X or else char = '"' X loop X file.val.readchar; X char := file.val.lastchar; X end; X -- Read string up to closing double quote X if char = '"' then X file.val.readline; X end_pos := file.val.laststring.index_of('"', 1); X if end_pos /= 0 then X val := file.val.laststring.substring(1, end_pos - 1).duplicate; X end; X end; X end; X X val: STRING; X Xend X END_OF_FILE if test 1237 -ne `wc -c <'string_reader.e'`; then echo shar: \"'string_reader.e'\" unpacked with wrong size! fi # end of 'string_reader.e' fi echo shar: End of shell archive. exit 0 -- Bob Weiner, Motorola, Inc., USENET: ...!gatech!uflorida!novavax!weiner (407) 364-2087