home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 318_02 / redtech.doc < prev    next >
Text File  |  1990-06-18  |  12KB  |  236 lines

  1. January 29, 1990
  2.  
  3.  
  4. RED VERSION 7.0 TECHNICAL NOTES
  5.  
  6. RED first made its appearance in 1983, in an article published in the
  7. January issue of Dr. Dobb's Journal.  Although some features of RED
  8. have been surpassed by developments in user interfaces, many technical
  9. features of RED still merit study.
  10.  
  11.  
  12. Improvements Made to this Version
  13.             
  14. Substantial improvements and modifications have been made in version 7.0.
  15.  
  16. o RED now will compile with the two most popular compilers for MS-
  17. DOS, Microsoft C v5.0 and Turbo C v2.0.  Make and link files have been
  18. included for both compilers.
  19.  
  20. o The source code has been revised for modern ANSI style C compilers.
  21. Function prototypes and other modern stylistic devices are used
  22. throughout.
  23.  
  24. o Several changes improve the speed and portability of the source code.  A
  25. number of buffer routines have been replaced by macros for greater speed.
  26.  For maximum portability, the assembly language screen handler has been
  27. completely rewritten to use BIOS calls rather than direct manipulation of
  28. PC hardware.  In spite of this, the screen routines remain very fast.
  29.  
  30. o The code has been instrumented with the Sherlockt debugging macros.
  31. These macros provide flexible debugging information and came in handy
  32. while porting RED to Turbo C and Microsoft C.  Documentation for
  33. Sherlock is included on this disk.
  34.  
  35. These technical notes contain four main sections.  Section one discusses
  36. the technical aspects of RED that still remain interesting after almost 7
  37. years--notably fast screen update and fast file handling for even very large
  38. files. Section two lists some areas where RED falls short of the current
  39. generation of editors and word processors. Section three contains some
  40. reflections on the programming style used in RED.  Finally, section four
  41. explains how to port RED to other machines.
  42.  
  43.  
  44. What's Still Valuable about RED
  45.  
  46. RED contains two chief technical accomplishments:  the screen is updated
  47. quickly and arbitrarily large files are handled quickly.  These results were
  48. produced without sacrificing portability.  In addition, RED's code is small
  49. enough so that it can be compiled with the small memory model.  RED is
  50. lean and quick.
  51.  
  52. RED's editing routines tell the screen update routines how to update the
  53. screen, not just what to update.  This results in more complicated edit
  54. routines but much faster screen refreshes.  In addition, an "interrupt-
  55. driven" screen update policy was adapted.  Output lines are not printed
  56. immediately but are instead queued by setting some variables in the system
  57. module, redsys.c.  Lines were output to the screen whenever the keyboard
  58. polling loop in syscin found no keyboard activity.
  59.  
  60. RED's file buffering routines, in files redbuf1.c through redbuf4.c, form
  61. the largest and most complicated part of RED.  I'm still pleased with these
  62. buffer routines--they handle arbitrarily large files quickly and efficiently.  I
  63. believe that the scheme used in RED compares favorably with such file
  64. access methods as B* trees.
  65.  
  66. Designing such a buffering scheme is far from easy.  Fast screen scrolling
  67. demands that sequential lines of text be accessed quickly.  Inserting and
  68. deleting line must be fast.  In particular, the time to move forward and back
  69. one line, or to insert or delete a line should be constant, i.e., it should not
  70. depend at all on the size of the file.  Loading a file and saving a file, or
  71. finding an arbitrary line of the file should require time which is
  72. proportional to the size of the file.  Disk storage must not become
  73. fragmented, no matter how much editing is done to a file.  Finally, the
  74. buffer routines must work well with as few as ten 1K file buffers and must
  75. be able to use hundreds of buffers effectively if they are available.  RED's
  76. buffer routines meet all these criteria.
  77.  
  78. Central to the operation of the buffer routines is the work file.  The file to
  79. be edited is copied to work file format when the file is first loaded.  Once
  80. the price for this file conversion has been paid, all other file operations
  81. become very fast.
  82.  
  83. The work file is organized as a doubly-linked list of fixed-length blocks.
  84. Each block contains a block header, one or more complete text lines, and a
  85. variable-length index table, one entry per text line.  Lines are not permitted
  86. to be split across lines, so when a line becomes too long to fit in a block, a
  87. new block must be created and linked into the list.  Adjacent blocks are
  88. merged at key points so that unneeded blocks never build up.  It is never
  89. necessary to compact the work file.  The precise algorithms for splitting
  90. and joining adjacent blocks forms the key code in the RED text editor.
  91.  
  92. Superimposed on these splitting and joining algorithms is a fairly
  93. straightforward least-recently-used virtual memory algorithm.  Blocks are
  94. swapped into and out of memory as required.  The code makes complex
  95. assumptions about which buffers are in memory while buffers are being
  96. split and joined.  In retrospect, a "locked" bit would be good to add to the
  97. entries in the slot table.  Then the code would fail more gracefully if not
  98. enough buffers were allocated:  there would be no unlocked block to swap
  99. out.
  100.  
  101. 10 buffers are guaranteed to work in all cases.  For small memory models,
  102. about 40 buffers in memory at once will be the maximum.  The advantage
  103. of having more than 40 buffers would be more than offset by the
  104. disadvantages of using the large data memory models.
  105.  
  106.  
  107. How RED is Showing its Age
  108.  
  109. RED was designed in an era when most displays were black and white and
  110. no inexpensive terminals supported more than one type style.  Multiple
  111. windows were unheard of.
  112.  
  113. RED's greatest current weaknesses are its crude methods for selecting text
  114. In particular, the move and copy commands operate only on lines of text
  115. that are selected by entering a range of numbers.  This is an area where
  116. RED is a bit unpleasant to work with.  RED contains no support for a
  117. mouse, er, "pointing device."
  118.  
  119. The find and change command could be improved a bit.  Besides searching
  120. for attributes such as type style or size, RED would benefit by better
  121. handling of multi-line patterns.  It would also be valuable to be able to
  122. search and replace more complicated patterns such as those used by the
  123. famous grep utility.
  124.  
  125. As far as the source code goes, if I were writing RED today I would use
  126. some of the insights behind object oriented programming to create multiple
  127. instances of objects such as internal files, buffers, windows etc.
  128. However, the design of RED would probably not change very much as the
  129. result.  Much greater changes would be forced by the user interface
  130. considerations such as multiple fonts.
  131.  
  132.  
  133. Professional Programming Style
  134.  
  135. RED's organization and style can provide a valuable example for beginning
  136. and intermediate programming students.  For a fascinating series of
  137. interviews with famous programmers and a discussion of how they work
  138. and what they think about, I highly recommend the book, Programmers at
  139. Work, by Susan Lammers, copyright 1986, 1989 by Tempus Books of
  140. Microsoft Press.  Many of the issues examined in this book are reflected in
  141. RED's source code.
  142.  
  143. The most important part of RED's design is its organization into modules.
  144. Except for the buffer routine module, which spans four source files, each
  145. module is contained in a single source file.  The determination of which
  146. routines belonged in which module was a dominant factor in RED's overall
  147. design.
  148.  
  149. A system module such as embodied in RED has become a feature of all my
  150. large projects.  The system module concept has been very successful: it is
  151. the key to easy portability and fast operation.  As an examination of the file
  152. redsys.c will show, the system module is still needed, even in the era of
  153. so-called "standard" ANSI libraries.
  154.  
  155. As the book Programmers at Work shows, programmers spend a lot of
  156. time thinking about the details of programs: naming conventions, program
  157. format, layout and appearance, comments, bracketing conventions,
  158. simplicity.  RED shows a consistent style that treats these issues as
  159. important.
  160.  
  161.  
  162. Porting RED to other Machines
  163.  
  164. This section tells you how to modify RED's source code to work with
  165. other compilers and operating systems.  You need not read this chapter if
  166. you already have a working copy of RED;  indeed, you should be an
  167. experienced C programmer to attempt such a task.
  168.  
  169. Compiling the source code should be easy, but getting the compiled code to
  170. run may be more difficult because every run-time library contains its own
  171. quirks.  RED solves this problem as follows:  all calls to the operating
  172. system are made indirectly through the file redsys.c.  For instance, instead
  173. of calling the fopen() library routine, RED's code calls the sysfopen()
  174. routine.  The job of sysfopen(), and all the other functions in redsys.c, is
  175. to massage its parameters as required in order to keep the local run-time
  176. library happy.  Thus, only redsys.c needs to be changed for different
  177. libraries.
  178. On time-sharing machines the biggest problem may be to find or create
  179. raw, asynchronous system calls which get input from the terminal.  Raw
  180. input is not automatically echoed by the operating system.  Rather than
  181. waiting for a keyboard key to be pressed, an asynchronous input system
  182. call returns a "character not ready" status if nothing is ready.
  183.  
  184. You shouldn't have to make any changes to the source code except to the
  185. files red.h and redsys.c.  Be particularly leery of modifying the buffer
  186. routines.
  187.  
  188.  
  189. Trouble Shooting
  190.  
  191. Debugging RED is much easier if you have the Sherlock debugging
  192. package.  I estimate that I would have saved at least three months of
  193. debugging had I invented Sherlock before I wrote RED.  Sherlock certainly
  194. came in handy when porting RED to Turbo C and Microsoft C.
  195.  
  196. You need not remove the Sherlock macros even if you don't own Sherlock.
  197. Just rename the file dummysl.h to be sl.h.  All the Sherlock macros will
  198. then expand to do-nothing code.
  199.  
  200. If RED crashes after you modify redsys.c you should do the following:
  201. Always keep in mind as you follow these steps that you are looking for
  202. bugs in redsys.c, not in RED's buffer routines.  
  203.  
  204. First, make sure the sysalloc() function is working properly, which
  205. involves checking sysinit() as well. Storage allocation is a particularly non-
  206. standard part of any library.  Note that sysalloc() is called only by bufinit()
  207. at the start of RED's execution.
  208.  
  209. Many problems with the library routines will crash RED's buffer routines
  210. on files redbuf1.c through redbuf4.c.  When that happens, RED dumps
  211. information to the screen.  Now comes the fun part.  You are going to
  212. deduce which errant library routines on redsys.c cause the buffer routines
  213. to crash.  Exercise the buffer routines in a controlled manner as follows:
  214.  
  215. o Get the check_block() and bufdump() routines working.  These functions
  216. are very effective debugging tools because they stop erroneous execution at
  217. the earliest point possible.  They are called whenever any block is changed.
  218.  
  219. o Get read_file() working.  This is most easily done by inserting a call to
  220. exit() at the very end of the read_file() routine, loading a file using RED's
  221. load command and then using DDT to look at the work file.  See whether
  222. the work file has the proper format as described on file redbuf.h.
  223.  
  224. o Once the read_file() routine is working, use the save command to test the
  225. write_file() routine.  Examine the newly created file using DDT, or load the
  226. file into an editor you know is solid.
  227.  
  228. o Test the bufdel() and the combine() routines.  It is important to do this
  229. before inserting lines of text because the insert logic calls the delete logic.
  230. Thus, testing the delete code first is simpler.  Read a large file into RED,
  231. then delete lines in all sorts of orders.
  232.  
  233. o Finally, test bufins() and split_block() by inserting and replacing lines.
  234. The inject command is a way of inserting a large number of lines quickly,
  235. but the load command is not--it uses separate logic.
  236.