summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SAWTELL
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SAWTELL')
-rw-r--r--reference/C/CONTRIB/SAWTELL/Makefile.am5
-rw-r--r--reference/C/CONTRIB/SAWTELL/Makefile.in410
-rwxr-xr-xreference/C/CONTRIB/SAWTELL/c-lesson.1177
-rwxr-xr-xreference/C/CONTRIB/SAWTELL/c-lesson.2233
-rwxr-xr-xreference/C/CONTRIB/SAWTELL/c-lesson.3629
-rwxr-xr-xreference/C/CONTRIB/SAWTELL/c-lesson.4313
-rwxr-xr-xreference/C/CONTRIB/SAWTELL/c-lesson.5291
-rwxr-xr-xreference/C/CONTRIB/SAWTELL/c-lesson.6331
-rwxr-xr-xreference/C/CONTRIB/SAWTELL/c-lesson.7161
-rwxr-xr-xreference/C/CONTRIB/SAWTELL/c-lesson.8502
-rwxr-xr-xreference/C/CONTRIB/SAWTELL/c-lesson.9433
-rw-r--r--reference/C/CONTRIB/SAWTELL/intro.html24
12 files changed, 3509 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SAWTELL/Makefile.am b/reference/C/CONTRIB/SAWTELL/Makefile.am
new file mode 100644
index 0000000..f4e2289
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/Makefile.am
@@ -0,0 +1,5 @@
+EXTRA_DIST = $(wildcard *.html) $(wildcard c-lesson.*)
+docs_DATA = $(EXTRA_DIST)
+
+docsdir = $(kde_htmldir)/en/kdevelop/$(subdir)
+
diff --git a/reference/C/CONTRIB/SAWTELL/Makefile.in b/reference/C/CONTRIB/SAWTELL/Makefile.in
new file mode 100644
index 0000000..37813f0
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/Makefile.in
@@ -0,0 +1,410 @@
+# KDE tags expanded automatically by am_edit - $Revision: 1.2 $
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AMTAR = @AMTAR@
+ARTSCCONFIG = @ARTSCCONFIG@
+AS = @AS@
+AUTODIRS = @AUTODIRS@
+AWK = @AWK@
+CC = @CC@
+CONF_FILES = @CONF_FILES@
+CPP = @CPP@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+DCOPIDL = @DCOPIDL@
+DCOPIDL2CPP = @DCOPIDL2CPP@
+DCOP_DEPENDENCIES = @DCOP_DEPENDENCIES@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DPMSINC = @DPMSINC@
+DPMSLIB = @DPMSLIB@
+EXEEXT = @EXEEXT@
+GCJ = @GCJ@
+GCJFLAGS = @GCJFLAGS@
+GLINC = @GLINC@
+GLLIB = @GLLIB@
+GMSGFMT = @GMSGFMT@
+IDL = @IDL@
+IDL_DEPENDENCIES = @IDL_DEPENDENCIES@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVAH = @JAVAH@
+JVMLIBS = @JVMLIBS@
+KDECONFIG = @KDECONFIG@
+KDE_CXXFLAGS = @KDE_CXXFLAGS@
+KDE_EXTRA_RPATH = @KDE_EXTRA_RPATH@
+KDE_INCLUDES = @KDE_INCLUDES@
+KDE_LDFLAGS = @KDE_LDFLAGS@
+KDE_PLUGIN = @KDE_PLUGIN@
+KDE_RPATH = @KDE_RPATH@
+KDE_USE_CLOSURE_FALSE = @KDE_USE_CLOSURE_FALSE@
+KDE_USE_CLOSURE_TRUE = @KDE_USE_CLOSURE_TRUE@
+KDE_USE_FINAL_FALSE = @KDE_USE_FINAL_FALSE@
+KDE_USE_FINAL_TRUE = @KDE_USE_FINAL_TRUE@
+KDE_XSL_STYLESHEET = @KDE_XSL_STYLESHEET@
+LIBCOMPAT = @LIBCOMPAT@
+LIBCRYPT = @LIBCRYPT@
+LIBDL = @LIBDL@
+LIBGEN = @LIBGEN@
+LIBJPEG = @LIBJPEG@
+LIBMICO = @LIBMICO@
+LIBOBJS = @LIBOBJS@
+LIBPNG = @LIBPNG@
+LIBPTHREAD = @LIBPTHREAD@
+LIBPYTHON = @LIBPYTHON@
+LIBQIMGIO = @LIBQIMGIO@
+LIBRESOLV = @LIBRESOLV@
+LIBSHADOW = @LIBSHADOW@
+LIBSM = @LIBSM@
+LIBSOCKET = @LIBSOCKET@
+LIBTIFF = @LIBTIFF@
+LIBTOOL = @LIBTOOL@
+LIBUCB = @LIBUCB@
+LIBUTIL = @LIBUTIL@
+LIBXINERAMA = @LIBXINERAMA@
+LIBZ = @LIBZ@
+LIB_KAB = @LIB_KAB@
+LIB_KDECORE = @LIB_KDECORE@
+LIB_KDEUI = @LIB_KDEUI@
+LIB_KFILE = @LIB_KFILE@
+LIB_KFM = @LIB_KFM@
+LIB_KFORMULA = @LIB_KFORMULA@
+LIB_KHTML = @LIB_KHTML@
+LIB_KIMGIO = @LIB_KIMGIO@
+LIB_KIO = @LIB_KIO@
+LIB_KPARTS = @LIB_KPARTS@
+LIB_KSPELL = @LIB_KSPELL@
+LIB_KSYCOCA = @LIB_KSYCOCA@
+LIB_KWRITE = @LIB_KWRITE@
+LIB_QT = @LIB_QT@
+LIB_SMB = @LIB_SMB@
+LIB_X11 = @LIB_X11@
+LN_S = @LN_S@
+MCOPIDL = @MCOPIDL@
+MEINPROC = @MEINPROC@
+MICO_INCLUDES = @MICO_INCLUDES@
+MICO_LDFLAGS = @MICO_LDFLAGS@
+MOC = @MOC@
+MSGFMT = @MSGFMT@
+NOOPT_CXXFLAGS = @NOOPT_CXXFLAGS@
+NOREPO = @NOREPO@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PAMLIBS = @PAMLIBS@
+PASSWDLIBS = @PASSWDLIBS@
+PYTHONINC = @PYTHONINC@
+PYTHONLIB = @PYTHONLIB@
+PYTHONMODDIR = @PYTHONMODDIR@
+QT_INCLUDES = @QT_INCLUDES@
+QT_LDFLAGS = @QT_LDFLAGS@
+RANLIB = @RANLIB@
+REPO = @REPO@
+SETUIDFLAGS = @SETUIDFLAGS@
+STRIP = @STRIP@
+TOPSUBDIRS = @TOPSUBDIRS@
+UIC = @UIC@
+UIC_TR = @UIC_TR@
+USER_INCLUDES = @USER_INCLUDES@
+USER_LDFLAGS = @USER_LDFLAGS@
+USE_EXCEPTIONS = @USE_EXCEPTIONS@
+USE_RTTI = @USE_RTTI@
+USE_THREADS = @USE_THREADS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+XPMINC = @XPMINC@
+XPMLIB = @XPMLIB@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_INCLUDES = @X_INCLUDES@
+X_LDFLAGS = @X_LDFLAGS@
+X_PRE_LIBS = @X_PRE_LIBS@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__include = @am__include@
+am__quote = @am__quote@
+idldir = @idldir@
+install_sh = @install_sh@
+jni_includes = @jni_includes@
+kde_appsdir = @kde_appsdir@
+kde_bindir = @kde_bindir@
+kde_confdir = @kde_confdir@
+kde_datadir = @kde_datadir@
+kde_htmldir = @kde_htmldir@
+kde_icondir = @kde_icondir@
+kde_includes = @kde_includes@
+kde_libraries = @kde_libraries@
+kde_libs_htmldir = @kde_libs_htmldir@
+kde_libs_prefix = @kde_libs_prefix@
+kde_locale = @kde_locale@
+kde_mimedir = @kde_mimedir@
+kde_moduledir = @kde_moduledir@
+kde_qtver = @kde_qtver@
+kde_servicesdir = @kde_servicesdir@
+kde_servicetypesdir = @kde_servicetypesdir@
+kde_sounddir = @kde_sounddir@
+kde_templatesdir = @kde_templatesdir@
+kde_wallpaperdir = @kde_wallpaperdir@
+micodir = @micodir@
+qt_includes = @qt_includes@
+qt_libraries = @qt_libraries@
+x_includes = @x_includes@
+x_libraries = @x_libraries@
+
+EXTRA_DIST = $(wildcard *.html) $(wildcard c-lesson.*)
+docs_DATA = $(EXTRA_DIST)
+
+docsdir = $(kde_htmldir)/en/kdevelop/$(subdir)
+subdir = reference/C/CONTRIB/SAWTELL
+mkinstalldirs = $(SHELL) $(top_srcdir)/admin/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+DATA = $(docs_DATA)
+
+DIST_COMMON = Makefile.am Makefile.in
+#>- all: all-am
+#>+ 1
+all: docs-am all-am
+
+.SUFFIXES:
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+#>- cd $(top_srcdir) && \
+#>- $(AUTOMAKE) --gnu reference/C/CONTRIB/SAWTELL/Makefile
+#>+ 3
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu reference/C/CONTRIB/SAWTELL/Makefile
+ cd $(top_srcdir) && perl admin/am_edit reference/C/CONTRIB/SAWTELL/Makefile.in
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && \
+ CONFIG_HEADERS= CONFIG_LINKS= \
+ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+uninstall-info-am:
+install-docsDATA: $(docs_DATA)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(docsdir)
+ @list='$(docs_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f="`echo $$p | sed -e 's|^.*/||'`"; \
+ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(docsdir)/$$f"; \
+ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(docsdir)/$$f; \
+ done
+
+uninstall-docsDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(docs_DATA)'; for p in $$list; do \
+ f="`echo $$p | sed -e 's|^.*/||'`"; \
+ echo " rm -f $(DESTDIR)$(docsdir)/$$f"; \
+ rm -f $(DESTDIR)$(docsdir)/$$f; \
+ done
+tags: TAGS
+TAGS:
+
+
+#>- DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+#>+ 4
+KDE_DIST=intro.html c-lesson.1 c-lesson.2 c-lesson.3 c-lesson.4 c-lesson.5 c-lesson.6 c-lesson.7 c-lesson.8 c-lesson.9
+
+DISTFILES= $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) $(KDE_DIST)
+
+
+top_distdir = ../../../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ if test -f $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ $(mkinstalldirs) "$(distdir)/$$dir"; \
+ fi; \
+ if test -d $$d/$$file; then \
+ cp -pR $$d/$$file $(distdir) \
+ || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(DATA)
+
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(docsdir)
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+#>- clean: clean-am
+#>+ 1
+clean: kde-rpo-clean clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-docsDATA
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+uninstall-am: uninstall-docsDATA uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am info info-am install install-am install-data \
+ install-data-am install-docsDATA install-exec install-exec-am \
+ install-info install-info-am install-man install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool uninstall uninstall-am uninstall-docsDATA \
+ uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
+
+#>+ 2
+docs-am:
+
+#>+ 6
+force-reedit:
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu reference/C/CONTRIB/SAWTELL/Makefile
+ cd $(top_srcdir) && perl admin/am_edit reference/C/CONTRIB/SAWTELL/Makefile.in
+
+
+#>+ 2
+final:
+ $(MAKE) all-am
+#>+ 2
+final-install:
+ $(MAKE) install-am
+#>+ 2
+no-final:
+ $(MAKE) all-am
+#>+ 2
+no-final-install:
+ $(MAKE) install-am
+#>+ 3
+cvs-clean:
+ $(MAKE) -f $(top_srcdir)/admin/Makefile.common cvs-clean
+
+#>+ 3
+kde-rpo-clean:
+ -rm -f *.rpo
diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.1 b/reference/C/CONTRIB/SAWTELL/c-lesson.1
new file mode 100755
index 0000000..a7fdeb7
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/c-lesson.1
@@ -0,0 +1,177 @@
+
+This archive contains a complete course for you to learn the 'C' computer
+language itself.
+
+The language used is correct conversational English, I have written the
+lessons using the same language constructions which I would use if I were
+teaching you directly.
+
+An outline of the course is available for you to read below
+The course is intended to demonstrate the language
+itself and a selection of the simpler standard library functions.
+
+I have assumed that you have had sufficient exposure to computing
+to be able to use a programmer's editor of your choice and are
+confident in the use of the command line interpreter, whether it
+be a unix shell, or a DOS ( shudder :-) prompt. Some knowledge,
+of computers and the jargon is assumed, but complicated concepts are
+fully explained. In other words the intent is to teach 'C' per se,
+not 'the fundamentals of how to program a computer using 'C' as
+a teaching medium.'
+
+'C' is not a computer language for rank beginners. Start with
+an interpretive language and proceed to a compiled language
+which has an extensive error message vocabulary and run-time
+checking facilities. In the interests of speed of execution 'C'
+does very little to protect you from yourself!
+
+Throughout the course the fact that a compiler is a translater
+from a high level language to assembler code is kept to the fore,
+you are frequently advised to examine the assembler code which is
+output by the compiler. Some minimal knowledge of computer architecture
+is therefore assumed.
+
+Whilst I have taken considerable care to ensure that this material is
+free of errors I am well aware that to err is a common human failing,
+and in this I don't claim to be different from anybody else.
+Therefore your gentle critique is welcome together with notification
+of any factual errors.
+
+It is planned to make the lessons available as a printed book,
+complete with a programme diskette if there is sufficient interest.
+
+ Syllabus for the 'C' Language Course.
+
+
+ 1 a) Historical introduction to the Language.
+
+ b) Demonstration of a very simple program.
+
+ c) Brief explanation of how the computer turns
+ your program text into an executing program.
+
+ d) The basic differences between 'C' and other languages.
+ The advantages and disadvantages.
+
+ We make the assumption that you are able to turn on your machine,
+ use the Operating System at the Control Line Interpreter prompt
+ "$ ", "c:>" or whatever, and to use an editor to enter program text.
+
+
+ 2 a) How the 'C' language arranges for the storage of data.
+ An explanation of the keywords associated with data.
+ The storage classes:- static auto volatile const.
+ The variable types:- char int long float double
+ The meaning of:- signed unsigned
+
+ b) Introduction to the concept of pointers.
+
+ c) Explanation of reading from the keyboard and writing to the screen.
+ i.e. printf and scanf, the print formatted and scan formatted
+ functions.
+
+ d) The use of arguments to the main() function, argc argv env.
+
+ e) A simple program to format text.
+
+
+ 3 Structures, arrays and pointers.
+
+ a) Explanation of more coplex data structures.
+ b) Programs which demonstrate uses of pointers.
+
+ 4 The operators of the language, arithmetic, pointer, logical, bitwise.
+
+ a) Precedence.
+ b) The unique bit and shifting operators.
+ ( for a high level language )
+
+ 5 a) The Preprocesser.
+ b) Header files
+
+ What they are and what you put in them, both your own and
+ those provided by the 'C' compiler vendor.
+
+ A simple title which includes all sorts of things,
+ both very useful and a number of traps.
+
+ 6 The library, why we have them and some of the more useful routines.
+
+ a) How to read the book.
+ b) The string functions as an example.
+
+ 7 a) Mistakes and how avoid making them.
+ b) Debugging strategies.
+ c) The assert macro.
+
+ 8 a) More on the representation of data vis. struct, typdef.
+
+ b) Tables of all sorts.
+ Arrays of structures.
+ Pre-initialisation of data structures.
+ ( Including jump or dispatch tables )
+ The bit-field.
+
+ c) Use of header files in this.
+
+
+ 9 a) The control structures of the language, what (not) to use and when.
+
+
+ 10 a) File IO
+
+ This is an enormous subject and we we will
+ really only just scratch on the surface.
+
+
+ 11 a) Lint, and more on errors / bugs and how to avoid them.
+
+
+ 12 The stack and a quick dip into assembler
+
+ a) A study of the function calling mechanism used by most 'C'
+ compilers and the effect on compiler output code of using
+ the register storage class and the optimiser.
+
+ 13 The heap.
+
+ a) The 'heap', it's management, malloc(), calloc() and free().
+
+
+ 14 Portability Issues.
+
+ a) Defaults for storage sizes.
+ b) 'endianism'. Yes, there are big-endian and little-endian computers!
+ c) Functions which can be called with a variable number of arguments.
+
+
+ 15 Sample programs.
+
+ Much is to be gained from examining public domain packages
+ examining the code and reviewing the author's style.
+ We will look at a number of functions and complete packages.
+ in particular we will examine a number of sorting functions,
+ a multi-threading technique, queues, lists, hashing, and trees.
+
+
+ /* ----------------------------------------- */
+
+Copyright notice:-
+
+(c) 1993 Christopher Sawtell.
+
+I assert the right to be known as the author, and owner of the
+intellectual property rights of all the files in this material,
+except for the quoted examples which have their individual
+copyright notices. Permission is granted for onward copying,
+but not modification, of this course and its use for personal
+study only, provided all the copyright notices are left in the
+text and are printed in full on any subsequent paper reproduction.
+
+--
+ +----------------------------------------------------------------------+
+ | NAME Christopher Sawtell |
+ | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
+ | EMAIL chris@gerty.equinox.gen.nz |
+ | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+ +----------------------------------------------------------------------+
diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.2 b/reference/C/CONTRIB/SAWTELL/c-lesson.2
new file mode 100755
index 0000000..7fd15fd
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/c-lesson.2
@@ -0,0 +1,233 @@
+ Lesson One.
+
+Some Historical Background.
+
+The 'C' programming language was designed and developed by Brian Kernighan, and
+Dennis Ritchie at The Bell Research Labs. 'C' is a Language specifically
+created
+in order to allow the programmer access to almost all of the machine's
+internals
+- registers, I/O slots and absolute addresses. However, at the same time,
+'C' allows for as much data hiding and programme text modularisation as is
+needed to allow very complex multi-programmer projects to be constructed in an
+organised and timely fashion. During the early 1960s computer Operating Systems
+started to become very much more complex with the introduction of
+multi-terminal
+and multi-process capabilities. Prior to this time Operating Systems had been
+carefully and laboriously crafted using assembler codes, and many programming
+teams realised that in order to have a working o/s in anything like a
+reasonable time this was now longer economically feasible. This then was the
+motivation to produce the 'C' Language, which was first implemented in
+assembler on a Digital Equipment Corporation PDP-7. Of course once a simple
+assembler version was working it was possible to rewrite the compiler in 'C'
+itself. This was done in short order and therefore as soon as the PDP-11 was
+introduced by DEC it was only necessary to change the code generator section
+of the compiler and the new machine had a compiler in just a few weeks. 'C' was
+then used to implement the UNIX o/s. This means, that a complete UNIX can be
+transported, or to use the simple jargon of today; 'ported to a new machine in
+literally just a few months by a small team of competent programmers.
+
+Enough of the past. Lets see the various actions, or compilation phases through
+which the `C' compilation system has to go in order that your file of `C'
+program text can be converted working program.
+
+Assuming that you are able to work an editor and can enter a script and create
+a file. Please enter the following tiny program.
+
+#ident "@(#) Hello World - my first program"
+
+#include <stdio.h>
+
+char *format = "%s",
+ *hello = "Hello World...\n";
+
+main()
+{
+ printf ( format, hello );
+ }
+
+Now save it in a file called hello.c. Lower case is allowed - encouraged, no
+less - under the UNIX operating system.
+
+Now type:
+
+cc -o hello hello.c
+
+The computer will apparently pause for a few moments and then the
+Shell, or Command Line Interpreter prompt will re-appear.
+
+Now type:
+
+hello
+
+Lo and behold the computer will print
+
+Hello World...
+
+Let's just look at what the computer did during the little pause.
+
+The first action is to activate a preliminary process called the pre-processor.
+In the case of hello.c all it does is to replace the line
+
+#include <stdio.h>
+
+with the file stdio.h from the include files library. The file stdio.h provides
+us with a convenient way of telling the compiler that all the i/o functions
+exist. There are a few other little things in stdio.h but they need not
+concern us at this stage.
+
+In order to see what the pre-processor actually outputs, you might like to
+issue the command:
+
+cc -P hello.c
+
+The 'cc' command will activate the 'C' compilation system and the -P option
+will stop the compilation process after the pre-processing stage, and another
+file will have appeared in your directory. Have a look, find hello.i and use
+the editor in view mode to have a look at it. So issue the command:
+
+view hello.i
+
+You will see that a number of lines of text have been added at the front of the
+hello.c program. What's all this stuff? Well, have a look in the file called
+/usr/include/stdio.h again using the view command.
+
+view /usr/include/stdio.h
+
+Look familiar?
+
+Now the next stage of getting from your program text to an executing program is
+the compilation of your text into an assembler code program. After all that is
+what a compiler is for - to turn a high level language script into a program.
+Lets see what happens by issuing the command
+
+cc -S hello.c
+
+Once again there is another file in your directory - this time with a .s
+suffix.
+
+Lets have a look at it in the same way as the .i file
+
+view hello.s
+
+You will doubtless notice a few recognizable symbols and what appears to be a
+pile of gibberish. The gibberish is in fact the nmemonics for the machine
+instructions which are going to make the computer do what you have programmed
+it to do.
+
+Now this assembler code has to be turned into machine instructions.
+To do this issue the command.
+
+cc -g -c hello.s
+
+Now, yet again there is another file in your directory - this time the suffix
+is ".o". This file is called the object file. It contains the machine
+instructions corresponding exactly to the nmemonic codes in the .s file.
+If you wish you can look at these machine codes using one of the commands
+available to examine object files.
+
+dis -L -t .data hello.o >hello.dis
+
+The output from these commands won't be very meaningful to you at this stage,
+the purpose of asking you to use them is merely to register in your mind the
+fact that an object file is created as a result of the assembly process.
+
+The next stage in the compilation process is called by a variety of names -
+"loading", "linking", "link editing". What happens is that the machine
+instructions in the object file ( .o ) are joined to many more instructions
+selected from an enormous collection of functions in a library. This phase of
+the compilation process is invoked by the command:-
+
+cc -o hello hello.o
+
+Now, at last, you have a program to execute! So make it do it's thing by
+putting the name of the executable file as a response to the Shell or Command
+Line Interpreter prompt.
+
+hello
+
+Presto, the output from your program appears on the screen.
+
+Hello World...
+
+You are now allowed to rejoice and have a nice warm fuzzy to hold!
+You have successfully entered a `C' program, compiled it, linked it, and
+finally, executed it!
+
+Having gone through all the various stages of editing, pre-processing,
+compiling, assembling, linking, and finally executing, by hand as it were, you
+can now rest assured that all the stages are automated by the 'cc' command, and
+you can forget how to invoke them! Just remember that the computer has to do
+them in order for you to have a program to execute.
+
+The single command you use to activate the C Compiler is:
+
+cc -o hello hello.c
+
+The word after the -o option is the name of the executable file, if you don't
+provide a name here the compiler dreams up the name "a.out". The source file
+MUST have the .c extension otherwise the compiler complains and stops working.
+
+Notes:
+
+ The command names used in the above text are those of standard UNIX,
+ Your particular system may well use a different name for the 'C' compiler.
+ bcc - for Borland 'C'.
+ gcc - GNU 'C', which is standard on the Linux operating system.
+ lc - Lattice 'C', available on IBM and clone P.C.s as well as the Amiga.
+ Check in the Documentation which came with your compiler.
+ The same notions apply to the text editor.
+
+Differences between 'C' and other languages.
+
+In the years since 'C' was developed it has changed remarkable little.
+This fact is a bouquet to the authors, who had the vision and understanding to
+create a language which has endured so well. The strengths and weaknesses
+should be pointed out here.
+
+The big plus is that it is possible to do everything ( well at least 99.9% ) in
+'C' while other languages compel you to write a procedure, subroutine or
+function in assembler code.
+
+'C' has very good facilities for creating tables of constant data within the
+source file.
+
+'C' doesn't do very much to protect you from yourself. This means that the
+resulting code executes faster than most other high level languages, but a much
+greater degree of both care and understanding is demanded from the programmer.
+
+'C' is not a closely typed language, although the newer compilers are offering
+type checking as part of the language itself as opposed to having to use a
+separate program for mechanised debugging.
+
+'C' is a small language with very few intrinsic operations.
+All the heavy work is done by explicit library function calls.
+
+'C' allows you to directly and conveniently access most of the internals of
+the machine ( the memory, input output slots, and CPU registers ) from the
+language without having to resort to assembler code.
+
+'C' compilers have an optimisation phase which can be invoked if desired.
+The output code can be optimised for either speed or memory usage. The code
+will be just as good as that produced by an assembly code programmer of normal
+skill - real guru programmers can do only slightly better.
+
+Copyright notice:-
+
+(c) 1993 Christopher Sawtell.
+
+I assert the right to be known as the author, and owner of the
+intellectual property rights of all the files in this material,
+except for the quoted examples which have their individual
+copyright notices. Permission is granted for onward copying,
+but not modification, of this course and its use for personal
+study only, provided all the copyright notices are left in the
+text and are printed in full on any subsequent paper reproduction.
+
+--
+ +----------------------------------------------------------------------+
+ | NAME Christopher Sawtell |
+ | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
+ | EMAIL chris@gerty.equinox.gen.nz |
+ | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+ +----------------------------------------------------------------------+
diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.3 b/reference/C/CONTRIB/SAWTELL/c-lesson.3
new file mode 100755
index 0000000..8d6dac2
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/c-lesson.3
@@ -0,0 +1,629 @@
+ Lesson 2
+
+ Data Storage Concepts.
+
+ It has been stated that "data + algorithms = programs".
+ This Lesson deals with with the first part of the addition sum.
+
+ All information in a computer is stored as numbers represented using the
+binary number system. The information may be either program instructions or
+data elements. The latter are further subdivided into several different types,
+and stored in the computer's memory in different places as directed by the
+storage class used when the datum element is defined.
+
+These types are:
+
+ a) The Character.
+
+ This is a group of 8 data bits and in 'C' represents either
+ a letter of the Roman alphabet, or a small integer in the range of 0
+ through to +255. So to arrange for the compiler to give you a named
+ memory area in which to place a single letter you would "say":
+
+ char letter;
+
+ at the beginning of a program block. You should be aware that
+ whether or not a char is signed or unsigned is dependant
+ on the design of the processor underlying your compiler.
+ In particular, note that both the PDP-11, and VAX-11 made by
+ Digital Equipment Corporation have automatic sign extention of
+char.
+ This means that the range of char is from -128 through to +127
+ on these machines. Consult your hardware manual, there may be
+ other exceptions to the trend towards unsigned char as the
+default.
+
+ This test program should clear things up for you.
+
+/* ----------------------------------------- */
+
+#ident "@(#) - Test char signed / unsigned.";
+
+#include <stdio.h>
+
+main()
+{
+ char a;
+ unsigned char b;
+
+ a = b = 128;
+ a >>= 1;
+ b >>= 1;
+ printf ( "\nYour computer has %ssigned char.\n\n", a == b ? "un" : "" );
+ }
+
+/* ----------------------------------------- */
+
+ Here ( Surprise! Surprise! ) is its output on a machine which has
+ unsigned chars.
+
+Your computer has unsigned char.
+
+ Cut this program out of the news file. Compile and execute it on
+ your computer in order to find out if you have signed or
+unsigned char.
+
+ b) The Integers.
+
+ As you might imagine this is the storage type in which to store whole
+ numbers. There are two sizes of integer which are known as short and long.
+ The actual number of bits used in both of these types is Implementation
+ Dependent. This is the way the jargonauts say that it varies from computer
+ to computer. Almost all machines with a word size larger than sixteen bits
+ have the the long int fitting exactly into a machine word and
+a short int
+ represented by the contents of half a word. It's done this way because
+ most machines have instructions which will perform arithmetic
+efficiently
+ on both the complete machine word as well as the half-word.
+For the
+ sixteen bit machines, the long integer is two machine words
+long,
+ and the short integer is one.
+
+ short int smaller_number;
+ long int big_number;
+
+ Either of the words short or long may be omitted as a default is
+ provided by the compiler. Check your compiler's documentation
+to see
+ which default you have been given. Also you should be aware
+that some
+ compilers allow the you to arrange for the integers declared
+with just
+ the word "int" to be either short or long. The range for a
+short int on
+ a small computer is -32768 through to +32767, and for a long
+int
+ -4294967296 through to +4294967295.
+
+ c) The Real Numbers.
+
+ Sometimes known as floating point numbers this number representation
+ allows us to store values such as 3.141593, or -56743.098. So, using
+ possible examples from a ship design program you declare floats and
+ doubles like this:
+
+ float length_of_water_line; /* in meters */
+ double displacement; /* in grammes */
+
+ In the same way that the integer type offers two sizes so does the
+ floating point representation. They are called float and double. Taking
+ the values from the file /usr/include/values.h the ranges which can be
+ represented by float and double are:
+
+ MAXFLOAT 3.40282346638528860e+38
+ MINFLOAT 1.40129846432481707e-45
+ MAXDOUBLE 1.79769313486231470e+308
+ MINDOUBLE 4.94065645841246544e-324
+
+ However you should note that for practical purposes the maximum
+ number of significant digits that can be represented by a
+float
+ is approximately six and that by a double is twelve. Also you
+should
+ be aware that the above numbers are as defined by the IEEE
+floating
+ point standard and that some older machines and compilers do
+not
+ conform. All small machines bought retail will conform. If you
+are
+ in doubt I suggest that refer to your machine's documentation
+for
+ the whole and exact story!
+
+
+ d) Signed and unsigned prefixes.
+
+ For both the character and integer types the declaration can be
+ preceded by the word "unsigned". This shifts the range so that
+0
+ is the minimum, and the maximum is twice that of the signed
+data
+ type in question. It's useful if you know that it is
+impossible
+ for the number to go negative. Also if the word in memory is
+going
+ to be used as a bit pattern or a mask and not a number the use
+of
+ unsigned is strongly urged. If it is possible for the sign bit
+in
+ the bit pattern to be set and the program calls for the bit
+pattern
+ to be shifted to the right, then you should be aware that the
+sign
+ bit will be extended if the variable is not declared unsigned.
+ The default for the "int" types is always "signed", and, as
+discussed
+ above that of the "char" is machine dependent.
+
+ This completes the discussion on the allocation of data types, except to
+ say that we can, of course, allocate arrays of the simple types simply by
+ adding a pair of square brackets enclosing a number which is the size of
+ the array after the variable's name:
+
+ char client_surname[31];
+
+ This declaration reserves storage for a string of 30 characters plus the
+ NULL character of value zero which terminates the string.
+
+ Structures.
+
+ Data elements which are logically connected, for example - to use the
+ example alluded to above - the dimensions and other details about a
+sea
+ going ship, can be collected together as a single data unit called a
+ struct. One possible way of laying out the struct in the source code
+is:
+
+struct ship /* The word "ship" is known as the structure's "tag". */
+{
+ char name[30];
+ double displacement; /* in grammes */
+ float length_of_water_line; /* in meters */
+ unsigned short int number_of_passengers;
+ unsigned short int number_of_crew;
+ };
+
+ Note very well that the above fragment of program text does NOT
+ allocate any storage, it merely provides a named template to
+the
+ compiler so that it knows how much storage is needed for the
+ structure. The actual allocation of memory is done either like
+this:
+
+struct ship cunarder;
+
+ Or by putting the name of the struct variable between the "}"
+and
+ the ";" on the last line of the definition. Personally I don't
+ use this method as I find that the letters of the name tend to
+get
+ "lost" in the - shall we say - amorphous mass of characters
+which
+ make up the definition itself.
+
+ The individual members of the struct can have values assigned to
+ them in this fashion:
+
+ cunarder.displacement = 97500000000.0;
+ cunarder.length_of_water_line = 750.0
+ cunarder.number_of_passengers = 3575;
+ cunarder.number_of_crew = 4592;
+
+ These are a couple of files called demo1.c & demo1a.c which contain
+ small 'C' programs for you to compile. So, please cut them out
+of the
+ news posting file and do so.
+
+
+----------------------------------------------------------------------
+#ident demo1.c /* If your compiler complains about this line, chop it out */
+#include <stdio.h>
+
+struct ship
+{
+ char name[31];
+ double displacement; /* in grammes */
+ float length_of_water_line; /* in meters */
+ unsigned short int number_of_passengers;
+ unsigned short int number_of_crew;
+ };
+
+char *format = "\
+Name of Vessel: %-30s\n\
+ Displacement: %13.3f\n\
+ Water Line: %5.1f\n\
+ Passengers: %4d\n\
+ Crew: %4d\n\n";
+
+main()
+{
+ struct ship cunarder;
+
+ cunarder.name = "Queen Mary"; /* This is the bad line. */
+ cunarder.displacement = 97500000000.0;
+ cunarder.length_of_water_line = 750.0
+ cunarder.number_of_passengers = 3575;
+ cunarder.number_of_crew = 4592;
+
+ printf ( format,
+ cunarder.name,
+ cunarder.displacement,
+ cunarder.length_of_water_line,
+ cunarder.number_of_passengers,
+ cunarder.number_of_crew
+ );
+ }
+
+----------------------------------------------------------------------
+
+ Why is the compiler complaining at line 21?
+ Well C is a small language and doesn't have the ability to allocate
+ strings to variables within the program text at run-time. This
+ program shows the the correct way to copy the string "Queen
+Mary",
+ using a library routine, into the structure.
+
+
+----------------------------------------------------------------------
+#ident demo1a.c /* If your compiler complains about this line, chop it out */
+#include <stdio.h>
+
+/*
+** This is the template which is used by the compiler so that
+** it 'knows' how to put your data into a named area of memory.
+*/
+
+struct ship
+{
+ char name[31];
+ double displacement; /* in grammes */
+ float length_of_water_line; /* in meters */
+ unsigned short int number_of_passengers;
+ unsigned short int number_of_crew;
+ };
+
+/*
+** This character string tells the printf() function how it is to output
+** the data onto the screen. Note the use of the \ character at the end
+** of each line. It is the 'continue the string on the next line' flag
+** or escape character. It MUST be the last character on the line.
+** This technique allows you to produce nicely formatted reports with all the
+** ':' characters under each other, without having to count the characters
+** in each character field.
+*/
+
+char *format = "\n\
+Name of Vessel: %-30s\n\
+ Displacement: %13.1f grammes\n\
+ Water Line: %5.1f metres\n\
+ Passengers: %4d\n\
+ Crew: %4d\n\n";
+
+main()
+{
+ struct ship cunarder;
+
+ strcpy ( cunarder.name, "Queen Mary" ); /* The corrected line */
+ cunarder.displacement = 97500000000.0;
+ cunarder.length_of_water_line = 750.0;
+ cunarder.number_of_passengers = 3575;
+ cunarder.number_of_crew = 4592;
+
+ printf ( format,
+ cunarder.name,
+ cunarder.displacement,
+ cunarder.length_of_water_line,
+ cunarder.number_of_passengers,
+ cunarder.number_of_crew
+ );
+ }
+
+----------------------------------------------------------------------
+
+ I'd like to suggest that you compile the program demo1a.c and execute it.
+
+$ cc demo1a.c
+$ a.out
+
+Name of Vessel: Queen Mary
+ Displacement: 97500000000.0 grammes
+ Water Line: 750.0 metres
+ Passengers: 3575
+ Crew: 4592
+
+ Which is the output of our totally trivial program to demonstrate
+ the use of structures.
+
+ Tip:
+
+ To avoid muddles in your mind and gross confusion in other minds
+ remember that you should ALWAYS declare a variable using a name which is
+ long enough to make it ABSOLUTELY obvious what you are talking about.
+
+ Storage Classes.
+
+ The little dissertation above about the storage of variables was
+ concerned with the sizes of the various types of data. There is
+ just the little matter of the position in memory of the variables'
+ storage.
+
+ 'C' has been designed to maximise the the use of memory by allowing you
+ to re-cycle it automatically when you have finished with it.
+ A variable defined in this way is known as an 'automatic' one. Although
+ this is the default behaviour you are allowed to put the word 'auto' in
+ front of the word which states the variable's type in the definition.
+ It is quite a good idea to use this so that you can remind yourself
+ that this variable is, in fact, an automatic one. There are three other
+ storage allocation methods, 'static' and 'register', and 'const'.
+ The 'static' method places the variable in main storage for the whole
+ of the time your program is executing. In other words it kills the
+ 're-cycling' mechanism. This also means that the value stored there
+ is also available all the time. The 'register' method is very machine
+ and implementation dependent, and also perhaps somewhat archaic in
+ that the optimiser phase of the compilation process does it all for
+ you. For the sake of completeness I'll explain. Computers have a small
+ number of places to store numbers which can be accessed very quickly.
+ These places are called the registers of the Central Processing Unit.
+ The 'register' variables are placed in these machine registers instead
+of
+ stack or main memory. For program segments which are tiny loops the
+speed
+ at which your program executes can be enhanced quite remarkably.
+ The optimiser compilation phase places as many of your variables into
+ registers as it can. However no machine can decide which of the
+variables
+ should be placed in a register, and which may be left in memory, so if
+ your program has many variables and two or three should be register
+ones
+ then you should specify which ones the compiler.
+
+ All this is dealt with at much greater detail later in the course.
+
+ Pointers.
+
+ 'C' has the very useful ability to set up pointers. These are memory
+ cells which contain the address of a data element. The variable name is
+ preceeded by a '*' character. So, to reserve an element of type char
+and
+ a pointer to an element of type char, one would say.
+
+char c;
+char *ch_p;
+
+ I always put the suffix '_p' on the end of all pointer variables
+ simply so that I can easily remember that they are in fact pointers.
+
+ There is also the companion unary operator '&' which yields the
+ address of the variable. So to initialize our pointer ch_p to point
+ at the char c, we have to say.
+
+ ch_p = &c;
+
+ Note very well that the process of indirection can procede to any
+ desired depth, However it is difficult for the puny brain of a normal
+ human to conceptualize and remember more that three levels! So be
+careful
+ to provide a very detailed and precise commentry in your program if
+ you put more than two or three stars.
+
+
+ Getting data in and out of your programs.
+
+ As mentioned before 'C' is a small language and there are no intrinsic
+ operators to either convert between binary numbers and ascii
+ characters or to transfer information to and fro between the
+ computer's memory and the peripheral equipment, such as terminals or
+ disk stores.
+
+ This is all done using the i/o functions declared in the file stdio.h
+ which you should have examined earlier. Right now we are going to look
+ at the functions "printf" and "scanf". These two functions together
+ with their derivatives, perform i/o to the stdin and stdout files,
+ i/o to nominated files, and internal format conversions. This means
+ the conversion of data from ascii character strings to binary numbers
+ and vice versa completely within the computer's memory. It's more
+ efficient to set up a line of print inside memory and then to send the
+ whole line to the printer, terminal, or whatever, instead of
+ "squirting" the letters out in dribs and drabs!
+
+ Study of them will give you understanding of a very convenient way to
+ talk to the "outside world".
+
+ So, remembering that one of the most important things you learn in
+ computing is "where to look it up", lets do just that.
+ If you are using a computer which has the unix operating system,
+ find your copy of the "Programmer Reference Manual" and turn to the
+ page printf(3S), alternatively, if your computer is using some other
+ operating system, then refer to the section of the documentation which
+ describes the functions in the program library.
+
+ You will see something like this:-
+
+ NAME
+ printf, fprintf, sprintf - print formatted
+output.
+
+ SYNOPSIS
+ #include <stdio.h>
+
+ int printf ( format [ , arg ] ... )
+ char *format;
+
+ int fprintf ( stream, format [ , arg ] ... )
+ FILE *stream;
+ char *format;
+
+ int sprintf ( s, format [ , arg ] ... )
+ char *s, *format;
+
+ DESCRIPTION
+
+ etc... etc...
+
+ The NAME section above is obvious isn't it?
+
+ The SYNOPSIS starts with the line #include <stdio.h>. This tells
+ you that you MUST put this #include line in your 'C' source code
+ before you mention any of the routines. The rest of the paragraph
+ tells you how to call the routines. The " [ , arg ] ... " heiroglyph
+ in effect says that you may have as many arguments here as you wish,
+ but that you need not have any at all.
+
+ The DESCRIPTION explains how to use the functions.
+
+ Important Point to Note:
+
+ Far too many people ( including the author ) ignore the fact that
+ the printf family of functions return a useful number which can be
+ used to check that the conversion has been done correctly, and that
+ the i/o operation has been completed without error.
+
+ Refer to the format string in the demonstration program above for
+ an example of a fairly sophisticated formatting string.
+
+ In order to fix the concepts of printf in you mind, you
+ might care to write a program which prints some text in three ways:
+
+a) Justified to the left of the page. ( Normal printing. )
+b) Justified to the right of the page.
+c) Centred exactly in the middle of the page.
+
+ Suggestions and Hint.
+
+ Set up a data area of text using the first verse of "Quangle" as data.
+ Here is the program fragment for the data:-
+
+/* ----------------------------------------- */
+
+char *verse[] =
+{
+ "On top of the Crumpetty Tree",
+ "The Quangle Wangle sat,",
+ "But his face you could not see,",
+ "On account of his Beaver Hat.",
+ "For his Hat was a hundred and two feet wide.",
+ "With ribbons and bibbons on every side,",
+ "And bells, and buttons, and loops, and lace,",
+ "So that nobody ever could see the face",
+ "Of the Quangle Wangle Quee.",
+ NULL
+ };
+
+/* ----------------------------------------- */
+
+ Cut it out of the news file and use it in a 'C' program file called
+ verse.c
+
+ Now write a main() function which uses printf alone for (a) & (b)
+ You can use both printf() and sprintf() in order to create
+ a solution for (c) which makes a good use of the capabilities
+ of the printf family. The big hint is that the string controlling
+ the format of the printing can change dynamically as program execution
+ proceeds. A possible solution is presented in the file verse.c which is
+ appended here. I'd like to suggest that you have a good try at making
+ a program of you own before looking at my solution.
+ ( One of many I'm sure )
+
+/* ----------------------------------------- */
+
+#include <stdio.h>
+
+char *verse[] =
+{
+ "On top of the Crumpetty Tree",
+ "The Quangle Wangle sat,",
+ "But his face you could not see,",
+ "On account of his Beaver Hat.",
+ "For his Hat was a hundred and two feet wide.",
+ "With ribbons and bibbons on every side,",
+ "And bells, and buttons, and loops, and lace,",
+ "So that nobody ever could see the face",
+ "Of the Quangle Wangle Quee.",
+ NULL
+ };
+
+main()
+{
+ char **ch_pp;
+
+ /*
+ ** This will print the data left justified.
+ */
+
+ for ( ch_pp = verse; *ch_pp; ch_pp++ ) printf ( "%s\n", *ch_pp );
+ printf( "\n" );
+
+ /*
+ ** This will print the data right justified.
+ **
+ ** ( As this will print a character in column 80 of
+ ** the terminal you should make sure any terminal setting
+ ** which automatically inserts a new line is turned off. )
+ */
+
+ for ( ch_pp = verse; *ch_pp; ch_pp++ ) printf ( "%79s\n", *ch_pp );
+ printf( "\n" );
+
+ /*
+ ** This will centre the data.
+ */
+
+ for ( ch_pp = verse; *ch_pp; ch_pp++ )
+ {
+ int length;
+ char format[10];
+
+ length = 40 + strlen ( *ch_pp ) / 2; /* Calculate the
+field length */
+ sprintf ( format, "%%%ds\n", length ); /* Make a format
+string. */
+ printf ( format, *ch_pp ); /* Print line of
+verse, using */
+ } /* generated format
+string */
+ printf( "\n" );
+ }
+
+/* ----------------------------------------- */
+
+ If you cheated and looked at my example before even attempting
+ to have a go, you must pay the penalty and explain fully why
+ there are THREE "%" signs in the line which starts with a call
+ to the sprintf function. It's a good idea to do this anyway!
+
+
+ So much for printf(). Lets examine it's functional opposite - scanf(),
+
+ Scanf is the family of functions used to input from the outside world
+ and to perform internal format conversions from character strings to
+ binary numbers. Refer to the entry scanf(3S) in the Programmer
+ Reference Manual. ( Just a few pages further on from printf. )
+
+ The "Important Point to Note" for the scanf family is that the
+ arguments to the function are all POINTERS. The format string has to
+ be passed in to the function using a pointer, simply because this
+ is the way 'C' passes strings, and as the function itself has to store
+ its results into your program it ( the scanf function ) has to "know"
+ where you want it to put them.
+
+Copyright notice:-
+
+(c) 1993 Christopher Sawtell.
+
+I assert the right to be known as the author, and owner of the
+intellectual property rights of all the files in this material,
+except for the quoted examples which have their individual
+copyright notices. Permission is granted for onward copying,
+but not modification, of this course and its use for personal
+study only, provided all the copyright notices are left in the
+text and are printed in full on any subsequent paper reproduction.
+
+--
+ +----------------------------------------------------------------------+
+ | NAME Christopher Sawtell |
+ | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
+ | EMAIL chris@gerty.equinox.gen.nz |
+ | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+ +----------------------------------------------------------------------+
diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.4 b/reference/C/CONTRIB/SAWTELL/c-lesson.4
new file mode 100755
index 0000000..a6072e0
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/c-lesson.4
@@ -0,0 +1,313 @@
+ Lesson 3
+
+ Arrays and Pointers.
+
+ You can allocate space for an array of elements at compile time with fixed
+ dimension sizes of any data type, even functions and structs.
+ So these are legal array definitions:
+
+ char name[30]; /* An array of 30 signed characters. */
+ char *strings[50]; /* 50 pointers to strings. */
+ unsigned long int *(*func)()[20];/* An array of pointers to functions which
+*/
+ /* return pointers to unsigned long ints. */
+
+ You can declare a pointer to point at any type of data element, and as in
+ the array situation above functions and structs are included.
+
+struct ship
+{
+ char name[30];
+ double displacement; /* in grammes */
+ float length_of_water_line; /* in meters */
+ unsigned short int number_of_passengers;
+ unsigned short int number_of_crew;
+ };
+
+ So using the ship concept from Lesson 2 you can declare a pointer to point
+ at one of the ship structs in an array.
+
+struct ship *vessel_p;
+
+ Note the use of the suffix "_p".
+ This is my way of reminding myself that the variable is a pointer.
+
+struct ship fleet[5]; /* This allocates enough storage for 5 ships' info.
+*/
+
+ Now lets set the pointer to point at the first vessel in the fleet.
+
+ vessel_p = fleet;
+
+ This pointer can be made to point at other ships in the fleet by
+ incrementing it or doing additive arithmetic on it:
+
+ vessel_p++; /* point a the next ship in the fleet array. */
+ vessel_p = fleet + 3;
+
+ Also we can find out the index of the ship in the fleet at which we are
+ pointing:
+
+ i = vessel_p - fleet;
+
+ It is also legal to find out the separation of two pointers pointing at
+ elements in an array:
+
+ d = vessel_p - another_vessel_p; /* This gives the separation in elements. */
+
+ So summarising, pointers may be, incremented, decremented, and subtracted
+ one from another or have a constant subtracted from them. Any other
+ mathematical operation is meaningless and not allowed.
+
+ Assembler programmers should note that while the pointer variables contain a
+ byte machine address, when the arithmetic is done using pointers the
+compiler
+ also issues either a multiply or a divide as well as the add or subtract
+ instruction so that the result is ALWAYS expressed in elements rather than
+ bytes. Have a go and write yourself a trivial little program, and have a
+ look at the compiler ouput code. Lesson 1 told you how!
+
+ When using a pointer to reference a structure we have to use a "pointer
+ offset" operator in order to access the member of the struct we require:
+
+ vessel_p = fleet;
+
+ vessel_p->name = "Queen Mary";
+ vessel_p->displacement = 97500000000.0;
+ vessel_p->length_of_water_line = 750.0
+ vessel_p->number_of_passengers = 3575;
+ vessel_p->number_of_crew = 4592;
+
+ Remember:
+
+ It's a "." when accessing a struct which is in storage declared in
+ the program.
+
+ It's a "->" when accessing a struct at which a pointer is pointing.
+
+ Initialisation of arrays.
+
+ 'C' has the facility to initialise variables in a program script.
+
+ Some examples:
+
+ char *qbf = "The quick brown fox jumped over the lazy dogs back";
+
+ int tic_tac_toe[3][3] =
+ {
+ { 1, 2, 3 },
+ { 4, 5, 6 },
+ { 7, 8, 9 }
+ };
+
+ struct ship fleet[2] =
+ {
+ { "Queen Elizabeth", 97500000000.0, 750.0, 3575, 4592 },
+ { "Queen Mary", 115000000000.0, 875.0, 4500, 5500 }
+ };
+
+ Take a careful note of where the commas and semi-colons go ( and don't go )!
+
+ Initialised Tables of Indeterminate Length.
+
+ One nice feature 'C' offers is that it is able to calculate
+ the amount of storage required for a table by 'looking' at the number
+ of initialisers.
+
+char *verse[] =
+{
+ "On top of the Crumpetty Tree",
+ "The Quangle Wangle sat,",
+ "But his face you could not see,",
+ "On account of his Beaver Hat.",
+ "For his Hat was a hundred and two feet wide.",
+ "With ribbons and bibbons on every side,",
+ "And bells, and buttons, and loops, and lace,",
+ "So that nobody ever could see the face",
+ "Of the Quangle Wangle Quee."
+ NULL
+ };
+
+ Note the * character in the definition line. This means that we are going
+ to make an array of pointers to variables of type char. As there is no
+ number between the [ ] characters the compiler calculates it for us.
+ With this kind of set-up it is nice and easy to add extra information
+ to the table as program development proceeds. The compiler will calculate
+ the new dimension for you. The point to remember is that the program has to
+ know - from the contents of the table - that it has come to the end of the
+ table! So you have to make a special entry which CANNOT under any
+ circumstances be a real data element. We usually use NULL for this.
+ The other way is to calculate the size of the table by using the sizeof
+ operator - Note that although use of sizeof looks like a function call
+ it is in fact an intrinsic operator of the language. The result is
+ available at compile time. So one can say:-
+
+ #define SIZE_OF_VERSE sizeof verse
+
+ There is one final initialised data type, the enum. It is a fairly recent
+ addition to the language.
+
+ enum spectrum { red, orange, yellow, green, blue, indigo, violet } colour;
+
+ In this construct the first symbol is given the value of 0 and for each
+ following symbol the value is incremented. It is however possible to assign
+ specific values to the symbols like this:
+
+ enum tub
+ { anorexic = 65,
+ slim = 70,
+ normal = 80,
+ fat = 95,
+ obese = 135
+ };
+
+ Some compilers are bright enough to detect that it is an error if an
+ attempt is made to assign a value to an enum variable which is not in
+ the list of symbols, on the other hand many are not. Take care! In
+ practice there is little difference between the enum language construct
+ and a number of define statements except perhaps aesthetics. Here is
+ another trivial program which demonstrates the use of enum and a
+ pre-initialised array.
+
+#include <stdio.h>
+
+enum spectrum { red, orange, yellow, green, blue, indigo, violet } colour;
+
+char *rainbow[] = { "red", "orange", "yellow", "green",
+ "blue", "indigo", "violet" };
+
+main()
+{
+ for ( colour = red; colour <= violet; colour++ )
+ {
+ printf ( "%s ", rainbow[colour]);
+ }
+ printf ( "\n" );
+ }
+
+ The output of which is ( not surprisingly ):
+
+red orange yellow green blue indigo violet
+
+ One quite advanced use of initialised arrays and pointers is the jump or
+ dispatch table. This is a efficient use of pointers and provides a very much
+ better ( In my opinion ) method of controlling program flow than a maze
+ of case or ( heaven forbid ) if ( ... ) goto statements.
+
+ Please cut out this program, read and compile it.
+ ------------------------------------------------------------------------
+
+char *ident = "@(#) tellme.c - An example of using a pointer to a function.";
+
+#include <stdio.h>
+#include <math.h>
+#include <sys/errno.h>
+
+/*
+These declarations are not in fact needed as they are all declared extern in
+math.h. However if you were to use routines which are not in a library and
+therefore not declared in a '.h' file you should declare them. Remember you
+MUST declare external routines which return a type other than the int type.
+
+extern double sin ();
+extern double cos ();
+extern double tan ();
+extern double atof ();
+*/
+
+struct table_entry
+{
+ char *name; /* The address of the character string. */
+ double (*function)(); /* The address of the entry point of the function. */
+ };
+
+typedef struct table_entry TABLE;
+
+double help ( tp )
+TABLE *tp;
+{ printf ( "Choose one of these functions:- " );
+ fflush ( stdout );
+ for ( ; tp -> name; tp++ ) printf ( "%s ", tp -> name );
+ printf ( "\nRemember the input is expressed in Radians\n" );
+ exit ( 0 );
+ return ( 0.0 ); /* Needed to keep some nit-picking dumb compilers happy! */
+ }
+
+/*
+ * This is the array of pointers to the strings and function entry points.
+ * Is is initialised at linking time. You may add as many functions as you
+ * like in here PROVIDED you declare them to be extern, either in some .h
+ * file or explicitly.
+ */
+
+TABLE interpretation_table [ ] =
+{
+ { "sin", sin },
+ { "tan", tan },
+ { "cos", cos },
+ { "help", help },
+ { NULL, NULL } /* To flag the end of the table. */
+ };
+
+char *output_format = { "\n %s %s = %g\n" };
+extern int errno;
+extern void perror();
+
+main( argc, argv )
+int argc;
+char **argv;
+{
+ TABLE *tp;
+ double x, answer;
+
+ if ( argc > 3 )
+ {
+ errno = E2BIG;
+ perror ( "tellme" );
+ exit ( -1 );
+ }
+
+ for (;;) /* This is the way to set up a continuous loop. */
+ {
+ for ( tp = interpretation_table;
+ ( tp -> name && strcmp ( tp -> name, argv[1] ));
+ tp++
+ ) ; /* Note use of empty for loop to position tp. */
+
+ if ( tp -> function == help ) (*tp -> function )( interpretation_table );
+ if ( tp -> name == NULL )
+ {
+ printf ( "Function %s not implemented yet\n", argv[1] );
+ exit ( 1 );
+ }
+ break; /* Leave the loop. */
+ }
+
+ x = atof ( argv[2] ); /* Convert the character string to a double. */
+ answer = ( *tp -> function )( x );/* Execute the desired function. */
+ printf ( output_format, /* Pointer to printf()'s format string. */
+ argv[1], /* Pointer to the name of the function. */
+ argv[2], /* Pointer to the input number ascii string. */
+ answer /* Value ( in double floating point binary ) */
+ );
+ }
+
+Copyright notice:-
+
+(c) 1993 Christopher Sawtell.
+
+I assert the right to be known as the author, and owner of the
+intellectual property rights of all the files in this material,
+except for the quoted examples which have their individual
+copyright notices. Permission is granted for onward copying,
+but not modification, of this course and its use for personal
+study only, provided all the copyright notices are left in the
+text and are printed in full on any subsequent paper reproduction.
+
+--
+ +----------------------------------------------------------------------+
+ | NAME Christopher Sawtell |
+ | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
+ | EMAIL chris@gerty.equinox.gen.nz |
+ | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+ +----------------------------------------------------------------------+
diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.5 b/reference/C/CONTRIB/SAWTELL/c-lesson.5
new file mode 100755
index 0000000..949fb49
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/c-lesson.5
@@ -0,0 +1,291 @@
+
+Lesson 4.
+
+ The
+operators of the language.
+
+ I have mentioned that 'C' is a small language with most of the heavy
+work
+being done by explicit calls to library functions. There is however a rich
+mix of intrinsic operators which allow you to perform bit level operations,
+use pointers, and perform immediate operations on varables. In other words,
+most of a machine's instruction set is able to be used in the object program.
+At the time when 'C' was designed and first written these were unique for
+a high level language.
+
+ Lets start with a discussion about precedence.
+
+ This really means that the compiler puts invisable parentheses into
+your expression. Casting your mind back to Arithmetic in the primary school
+I expect you remember the nmemonic "My Dear Aunt Sally". The 'C' language
+does as well! So the following expression is correct
+
+ 15 + 4 * 11 = 59
+
+ The compiler has rendered the expression as:
+
+ 15 + ( 4 * 11 ) = 59
+
+ Now the 'C' language has a much larger collection of operators than
+just
+Multiply Divide Add Subtract, in fact much too big to try to remember the
+precedence of all of them. So my recomendation is to ALWAYS put in the
+parentheses, except for simple arithmetic. However, for the sake of
+completeness as much as anything else, here is the list.
+
+ First up come what are called the primary-expression operators:
+
+ () Function.
+ [] Array.
+ . struct member ( variable ).
+ -> struct member ( pointer ).
+
+ The unary operators:
+
+ * Indirection via a Pointer.
+ & Address of Variable.
+ - Arithmetic Negative.
+ ! Logical Negation or Not.
+ ~ Bit-wise One's Complement.
+ ++ Increment.
+ -- Decrement.
+ sizeof Which is self explanitary.
+
+ Now the binary operators:
+
+ Arithmetic Operators.
+
+ * Multiply. My
+ / Divide. Dear
+ % Modulo, or Remainder of Integer Division.
+ + Addition. Aunt
+ - Subtraction. Sally
+
+ The Shifting Operators.
+
+ >> Bit-wise Shift to the Right.
+ << Bit-wise Shift to the Left.
+
+ Logical Relation Operators.
+
+ < Less Than.
+ > Greater Than.
+ <= Less Than or Equal.
+ >= Greater Than or Equal.
+ == Equal.
+ != Not Equal.
+
+ Bit-wise Boolean Operators.
+
+ & Bit-wise And.
+ ^ Bit-wise Exclusive-or.
+ | Bit-wise Or.
+
+ The Logical Operators.
+
+ && Logical And.
+ || Logical Or.
+
+ The Assignment Operators. ( They all have the same priority. )
+
+ = The normal assignment operator.
+
+ The Self-referencing Assignment Operators.
+
+ +=
+ -=
+ *=
+ /=
+ %=
+ >>=
+ <<=
+ &=
+ ^=
+ |=
+
+ Some explanation is in order here. The machine instructions in your
+computer include a suit of what are called "immediate operand" instructions.
+These instructions have one of the operands in a register and the other
+is either part of the instruction word itself ( if it is numerically small
+enough to fit ) or is the next word in the address space "immediately" after
+the instruction code word. 'C' makes efficient use of this machine feature
+by providing the above set of operations each of which translates directly
+to its corresponding machine instruction. When the variable in question is a
+'register' one, or the optimiser is in use, the compiler output is just
+the one "immediate" machine instruction. Efficiency Personified!!!
+
+ These two lines will make things clearer.
+
+ a = 8;
+ a += 2; /* The result is 10 */
+
+ The exclusive-or operation is very useful you can toggle any
+combination
+of bits in the variable using it.
+
+ a = 7;
+ a ^= 2; /* Now a is 5 */
+ a ^= 2; /* and back to 7. */
+
+ Naturally, you can use the other operations in exactly the same way,
+I'd like to suggest that you make a utterly simplistic little program
+and have a look at the assembler code output of the compiler. Don't be
+afraid of the assembler codes - they don't bite - and you will see
+what I was on about in the paragraph above.
+
+ Historical Note and a couple of Cautions.
+
+ In the Oldend Days when 'C' was first written all the self-referencing
+operations had the equals symbol and the operand around the other way.
+Until quite recently ( unix system V release 3.0 ) the 'C' compiler had a
+compatability mode and could cope with the old style syntax.
+
+ A sample or test program is probably in order here.
+
+/* ----------------------------------------- */
+
+#include <stdio.h>
+
+char *mes[] =
+{
+ "Your compiler",
+ " understands",
+ " does not understand",
+ " the old-fashioned self-referencing style."
+ };
+
+main()
+{
+ int a;
+
+ a = 5;
+ a=-2;
+ printf ( "%s %s %s\n", mes [ 0 ], mes [ ( a == -2 ) ? 2 : 1 ], mes [ 3
+] );
+ }
+
+/* ----------------------------------------- */
+
+ The 'C' compiler issued with unix System V release 3.2 seems to have
+( thankfully ) dropped the compatability mode. However a collegue, who
+was using an old compiler, and I spent hours trying to find this strange bug!
+The cure for the problem is either to put spaces on either side of the '=' sign
+or to bracket the unary minus to the operand.
+
+ a=(-2);
+ a = -2;
+
+Either is acceptable, and might save you a lot of spleen if sombody tries
+to install your work of art program on an ancient machine.
+
+ The other caution is the use of the shifting instructions with signed
+and unsigned integers.
+
+ If you shift a signed integer to the right when the sign bit is set
+then in all probability the sign will be extended. Once again a little
+demo program. Please cut it out of the news file with your editor
+and play with it.
+
+/* ----------------------------------------- */
+
+#ident "#(@) shifts.c - Signed / Unsigned integer shifting demo."
+#include <stdio.h>
+
+#define WORD_SIZE ( sizeof ( INTEGER int ) * 8 )
+#define NIBBLE_SIZE 4
+#define NIBBLES_IN_WORD (( WORD_SIZE ) / NIBBLE_SIZE )
+#define SIGN_BIT ( 1 << ( WORD_SIZE - 1 ))
+
+char *title[] =
+{ " Signed Unsigned",
+ " Signed Unsigned"
+ };
+
+main ()
+{
+ INTEGER int a;
+ unsigned INTEGER int b, mask;
+ int ab, i, j, bit_counter, line_counter;
+
+ a = b = SIGN_BIT;
+ printf ( "%s\n\n", title [ ( WORD_SIZE == 16 ) ? 0 : 1 ] );
+
+ for ( line_counter = 0; line_counter < WORD_SIZE; line_counter++ )
+ {
+ for ( ab = 0; ab < 2; ab++ )
+ {
+ mask = SIGN_BIT;
+ for ( i = 0; i < NIBBLES_IN_WORD; i++ )
+ {
+ for ( j = 0; j < NIBBLE_SIZE; j++ )
+ {
+ printf ( "%c", ((( ab ) ? b : a ) &
+mask ) ? '1' : '0' );
+ mask >>= 1;
+ }
+ printf ( " " );
+ }
+ printf ( "%s", ( ab ) ? "\n" : " " );
+ if ( ab )
+ {
+ b >>= 1;
+ }
+ else
+ {
+ a >>= 1;
+#if defined(FIX_COMPILER_BUG)
+# if (INTEGER == long)
+ a |= SIGN_BIT; /* This is a work-around for
+the 3b2 compiler bug. */
+# endif
+#endif
+ }
+ }
+ }
+ }
+
+/* ----------------------------------------- */
+
+ This little program might well produce some interesting surprises on
+your machine in the same way it did on mine. I have an AT&T 3b2/400 and
+use the K & R style compiler. Interestingly, the above program did what
+I expected it to do when the integers were short, the sign bit is extended,
+but when the integers are long the sign bit is NOT extended. In this case
+the different behaviour is caused by the compiler always issuing a Logical
+Shift instruction, when it should issue a Arithmetic Shift instruction for
+signed integers and a Logical Shift instructon for unsigned ones. In the
+case of the short int the varable is loaded from memory into the register
+with a sign extend load instruction, this makes the Logical Shift instruction
+right work correctly for short ints, but not for longs. I had to examine
+the assember codes output by the compiler in order to discover this.
+
+ Here are the compiler invocation lines.
+
+cc -olong.shifts -DFIX_COMPILER_BUG -DINTEGER=long shifts.c
+
+ and
+
+cc -oshort.shifts -DINTEGER=short shifts.c
+
+ Experiment with the "-DFIX_COMPILER_BUG" and see what your compiler
+does.
+
+Copyright notice:-
+
+(c) 1993 Christopher Sawtell.
+
+I assert the right to be known as the author, and owner of the
+intellectual property rights of all the files in this material,
+except for the quoted examples which have their individual
+copyright notices. Permission is granted for onward copying,
+but not modification, of this course and its use for personal
+study only, provided all the copyright notices are left in the
+text and are printed in full on any subsequent paper reproduction.
+
+--
+ +----------------------------------------------------------------------+
+ | NAME Christopher Sawtell |
+ | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
+ | EMAIL chris@gerty.equinox.gen.nz |
+ | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+ +----------------------------------------------------------------------+
diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.6 b/reference/C/CONTRIB/SAWTELL/c-lesson.6
new file mode 100755
index 0000000..67f8852
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/c-lesson.6
@@ -0,0 +1,331 @@
+
+ Lesson 5.
+
+ The Pre-processor and Header Files.
+
+The pre-processor is activated by a '#' character in column one of the source
+code. There are several statements vis:
+
+#include
+
+#define
+#undef
+
+#if
+#else
+#endif
+
+#ifdef
+#ifndef
+
+#pragma
+
+ #include.
+
+ In the programming examples presented in the previous lessons you will
+probably have noticed that there is this statement:
+
+#include <stdio.h>
+
+right at the start of the program text. This statement tells the pre-processor
+to include the named file in the your program text. As far as the compiler is
+concerned this text appears just as if you had typed it yourself!
+
+ This is one of the more useful facilities provided by the 'C' language.
+The #include statement is frequently combined with the #if construct.
+In this program fragment the file "true.h" is included in your program
+if the pre-processor symbol FLAG is true, and "false.h" included if FLAG
+is false.
+
+#if ( FLAG )
+# include "true.h"
+#else
+# include "false.h"
+#endif
+
+This mechanism has many uses, one of which is to provide
+portability between all the 57,000 slightly different versions of unix and also
+other operating systems. Another use is to be able to alter the way in which
+your program behaves according to the preference of the user.
+
+Of course, you will be asking the question "Where is the file stored?".
+Well, if the filename is delimited by the "<" and ">" characters as in the
+example above the file comes from the /usr/include directory, but if the name
+of the file is delimited by quotes then the file is to be found in your current
+working directory. (This is not quite the whole truth as 'C' compilers allow
+you to extend the search path for the include files using command line option
+switches. - See your compiler manual for the whole story. )
+
+So, I would like to suggest that you to have a look around the /usr/include
+directory and its /sys sub-directory. You should use either your editor
+in 'view' mode or the pg utility. This will ensure that you can't have an
+accident and alter one of the files by mistake if you are slightly silly
+and just happen to be logged on as the super-user.
+
+A typical file to examine is usr/include/time.h.
+
+It's quite small so here it is.
+
+/* Copyright (c) 1984 AT&T */
+/* All Rights Reserved */
+
+/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
+/* The copyright notice above does not evidence any */
+/* actual or intended publication of such source code. */
+
+#ident "@(#)/usr/include/time.h.sl 1.5 4.2 04/20/87 18195 AT&T-SF"
+/* 3.0 SID # 1.2 */
+struct tm { /* see ctime(3) */
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+};
+extern struct tm *gmtime(), *localtime();
+extern char *ctime(), *asctime();
+int cftime(), ascftime();
+extern void tzset();
+extern long timezone, altzone;
+extern int daylight;
+extern char *tzname[];
+
+ As you can see ( forgetting about the comments and #ident ) there are three
+different uses for the file.
+
+ a) The definition of data structures and types.
+ b) The declaration of functions which use the data structures.
+ c) The declaration of of external data objects.
+
+ These lines of code are all you need in your program in order to be able to
+use, in this case, the library routine to access the clock in the computer,
+but of course the paradigm applies to all programs which are created by one
+programmer and used by another member of the programming team. Note that, by
+proxy, or whatever, the author of the library routines has in effect become
+a member of your programming team.
+
+ You might care to write a program or two which use this header file,
+and for those who are motivated it might be an idea to re-implement localtime
+so that it understands Summer Time in the Southern Hemisphere. (!)
+
+Using another totally trivial example in order to get the idea across please
+examine the hello world program printed immediately below.
+
+/* ------------------------------------------------------------ */
+
+#ident "@(#) hw_uc.h UPPER CASE version."
+
+#define HELLO_MESSAGE "HELLO WORLD...\n";
+
+/* ------------------------------------------------------------ */
+
+#ident "@(#) Hello World"
+
+#include <stdio.h>
+#include HW_H
+
+#if !defined( HELLO_MESSAGE )
+# error "You have forgotten to define the header file name."
+#endif
+
+char *format = "%s",
+ *hello = HELLO_MESSAGE;
+
+main()
+{
+ printf ( format, hello );
+ }
+
+/* ------------------------------------------------------------ */
+
+You will no doubt notice that the symbol HW_H is used instead of a header file
+name. This gives us the ability to force the inclusion of any file we wish by
+defining the symbol HW_H to be the desired file name. It can be done like this:
+
+cc -DHW_H="\"hw_uc.h\"" hello.c
+
+The compiler output is placed, by default, in the file a.out, so to execute it
+issue the command:
+
+a.out
+
+Which, fairly obviously, produces the output:
+
+HELLO WORLD...
+
+As we are going to generate another version of the program we had better move
+the executable image file to another file name:
+
+mv a.out hello_uc
+
+Now to produce the other version issue the command line:
+
+cc -DHW_H="\"hw_lc.h\"" hello.c; mv a.out hello_lc; hello_lc
+
+Which compiles the other version of the hello.c program, using this version of
+the include file:
+
+/* ------------------------------------------------------------ */
+#ident "@(#) hw_lc.h Lower Case version."
+
+#define HELLO_MESSAGE "Hello World...\n";
+/* ------------------------------------------------------------ */
+
+and then moves the executable image to a different file and executes it.
+Note that more than one command per line can be issued to the shell by
+separating the commands with the ';' delimiting character.
+Here - Surprise, Surprise - is the output of the second version.
+
+Hello World...
+
+I'd like to suggest that you use your editor to cut these example programs
+and the shell file below out of the mail file and have a play with them.
+
+/* ----------------------------------------- */
+
+# @(#) Shell file to do the compilations.
+
+cc -o hello_uc -DHW_H="\"hw_uc.h\"" hello.c
+cc -o hello_lc -DHW_H="\"hw_lc.h\"" hello.c
+
+/* ----------------------------------------- */
+
+
+#define
+
+ This statement allows you to set up macro definitions. The word immediately
+after the #define, together with its arguments, is expanded in the program
+text to the whole of the rest of the line.
+
+#define min(a, b) ((a<b) ? a : b )
+
+ Some things to note:
+
+ 1) There isn't a space between the last character of the symbol being defined
+ and the opening parenthesis enclosing the arguments, and there MUST NOT BE
+ one.
+
+ 2) The code into which the macro is expanded MUST always be enclosed in
+ parentheses and for safety always use parentheses to get the arithmetic
+ right.
+
+ 3) Never EVER define a macro, and use it with a side effect. e.g.
+
+ c = min ( a++, b); /* DON'T _EVER_ DO THIS!!! */
+
+ Do you think that the value of 'a' will get advanced after the
+ macro is used? Well it WON'T. It gets incremented after the less
+ than test and before the values get assigned! I have written a tiny
+ program which uses the min macro above. Have a look at the output
+ from the pre-processor. Lesson One told you how to do this.
+ Now execute it and get an educative surprise!
+
+/* ----------------------------------------- */
+
+#include <stdio.h>
+#define min(a, b) ((a<b) ? a : b )
+
+main()
+{ int a,b,c;
+
+ a = 1;
+ b = 2;
+ c = min ( a++, b); /* DON'T _EVER_ DO THIS!!! */
+ printf ( "a: %d, b: %d, c: %d\n", a, b, c );
+ }
+
+/* ----------------------------------------- */
+
+ 4) You can continue a macro on the next line by putting a \ ( back-slash )
+ as THE VERY LAST character on the line. NOTHING, not even a space may
+ follow, as your compiler just can't handle it. I spent far too long trying
+ to find one of those really difficult bugs, and it turned out that this
+ was the problem - spaces are transparent aren't they?
+
+ 5) Using macros is fast and convenient, but they do take up a lot of memory
+ because the code is expanded and inserted into the output stream for
+ every occurrence of the macro in your code. There is a trade-off between
+ using a macro and a function.
+
+ The symbol does not have to be the handle for a macro expansion, but can just
+be equated to a single constant. This is done many times over in the header
+files provided by the operating system vendor. Have a look in
+/usr/include/sys/file.h for an example of this.
+
+#undef
+
+ Not surprisingly this preprocessor command removes a symbol WHICH IS BEING
+ USED BY THE PRE-PROCESSOR - don't confuse it with compiler proper symbols.
+
+ Note that the symbol can be a macro name, in which case the space
+ used for the code expansion is made available for re-use.
+
+#if ( FLAG )
+
+ /* Code in here is sent on to the compiler if FLAG is true. */
+
+#else
+
+ /* Code in here is sent on to the compiler if FLAG is false. */
+
+#endif
+
+ When the pre-processor encounters one of these, the lines of code between the
+#if and the corresponding #else or #endif are either skipped over or allowed to
+proceed to the compilation phase depending on the truth or falsity of the
+logical expression ( FLAG ). All the logical and boolean expressions available
+as part of the 'C' language are available here. You are also allowed to say:
+
+#if defined( FLAG ) or,
+#if !defined( FLAG )
+
+
+ The symbol FLAG may be an expression which reduces to a boolean value.
+
+ A convention which is adhered to quite well is that all pre-processor
+symbols are in UPPER_CASE so as to make them obvious.
+
+#ifdef FLAG or,
+#ifndef FLAG
+
+ These two statements are the old fashioned way of testing whether a symbol is
+defined or not. They are absolutely the same as the previous example.
+
+ There are two more pre-processor statements, namely the #pragma and
+the "stringizing" operator. The #pragma is used to alter the way in which
+the compiler works on a block of code, but it is completely implementation
+dependant and you must refer to your compiler manual. I can't help as
+they are all different. The "stringizing" operator is quite an advanced
+technique and will be dealt with later on.
+
+Copyright notice:-
+
+(c) 1993 Christopher Sawtell.
+
+I assert the right to be known as the author, and owner of the
+intellectual property rights of all the files in this material,
+except for the quoted examples which have their individual
+copyright notices. Permission is granted for onward copying,
+but not modification, of this course and its use for personal
+study only, provided all the copyright notices are left in the
+text and are printed in full on any subsequent paper reproduction.
+
+--
+ +----------------------------------------------------------------------+
+ | NAME Christopher Sawtell |
+ | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
+ | EMAIL chris@gerty.equinox.gen.nz |
+ | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+ +----------------------------------------------------------------------+
+
+--
+ +----------------------------------------------------------------------+
+ | NAME Christopher Sawtell |
+ | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
+ | EMAIL chris@gerty.equinox.gen.nz |
+ | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+ +----------------------------------------------------------------------+
diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.7 b/reference/C/CONTRIB/SAWTELL/c-lesson.7
new file mode 100755
index 0000000..d5caba1
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/c-lesson.7
@@ -0,0 +1,161 @@
+
+Lesson 6
+
+ Libraries, why we have them, and how to make and use them.
+
+ In order to simplify the creation of programs for its customers,
+software vendors make available one or more libraries of functions
+which have general application.
+
+ When you write a program in 'C' much, if not most, of the "hard work"
+is done by explicitly called functions, which you call by simply writing
+their names in your program script. Unfortunately there is a little bit
+more to it than that. If the function returns a value which is other
+than of type int, you have to tell the compiler the type of the returned
+value. An example will, I hope make things clear.
+
+ Lets's suppose that you have been given the task of, making things
+stupidly simplistic for a book example, sorting a list of names into
+alphabetical order. ( Yes, I do know this can, and should be done in just
+one line of shell script! However that's another story for another day. )
+
+ You look diligently through the Programmer Reference Manual, discover
+that the prose is almost opaque, and find a couple of interesting looking
+routines called strcmp, and qsort. You decide to use these library
+functions. Now for just a moment lets consider the ins and outs of what,
+in effect, you have just done. You have just asked a member of the team
+of programmers who created the library to join you, by proxy as it were, in
+creating your masterpiece. A useful concept, which has been in use
+almost since the start of electronic computing.
+
+ To re-focus the mind on the task at hand; let's look in the Reference
+Manual
+at the page for qsort(3C) - The 3C in parenthesis is the cryptic code which
+is the unix apology for a reference to section 3C in the Manual! So find
+section 3C and look up qsort. Now have a look at the SYNOPSIS, and notice
+that there is no mention of a header file to #include, and also notice that
+qsort returns a void, not an int. This means that there is no header file
+/usr/include/qsort.h ( for my version of unix - system V Release 3.2.2 -
+anyway ) and you have to declare qsort yourself as an external function.
+Also turn to the page string(3C) in the fine manual. Notice that the
+SYNOPSIS here includes the line #include <string.h> so you have to put
+it in your program text. Once more an example to make it all clear.
+
+
+/* ----------------------------------------- */
+
+#ident "@(#) qsort-demo.c"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+extern void qsort ();
+extern int strcmp(); /* Some compilers need this defined, most don't. */
+
+char names[22][25] = /* Here are some names to sort. */
+{
+ "John Nagle", "Colin Douthwaite", "Ian Lance Taylor", "Brian J. Murrell",
+ "Pete", "Geoff Mccaughan", "David Liebert", "Operator", "Bill Baucum",
+ "Victor Volkman", "Chay R Harley", "Dan Romanchik", "Larry Kollar",
+ "Gaston Ormazabal", "Arijit Chandra", "Kenneth Mark Hopkinson",
+ "Kerr Hatrick", "Tim Love", "Robert M. Juranitch", "Jeffrey Micke",
+ "Duong Quoc", "Jagadesh Vasudevamurthy"
+ };
+
+#define NUMBER_OF_NAMES sizeof ( names ) / sizeof ( names[0] )
+
+main()
+{
+ int i;
+
+ /*
+ ** Print the unsorted names.
+ */
+
+ printf ( "The Unsorted Names.\n" );
+ for ( i = 0; i < NUMBER_OF_NAMES; i++ ) printf ( "%s\n", names[i] );
+
+ /*
+ ** Print a prompt, and wait.
+ */
+
+ printf ( "Press RETURN to continue: " );
+ fflush ( stdout );
+ getchar();
+
+ /*
+ ** Now apply qsort to the arrary of character strings.
+ */
+
+ qsort (( char * ) names, NUMBER_OF_NAMES, sizeof ( *names ), strcmp );
+
+ assert ( names[0][0] < names[1][0] ); /* Quick check to see it's done
+it. */
+
+ /*
+ ** Print the sorted names.
+ */
+
+ printf ( "The Sorted Names.\n" );
+ for ( i = 0; i < NUMBER_OF_NAMES; i++ ) printf ( "%s\n", names[i] );
+ }
+
+/* ----------------------------------------- */
+
+ Note very well:-
+
+ I wanted 22 short character strings for the data items
+for the demo to sort. So grep, uniq, cut, tail, and finally a tiny bit of
+vi fished eminently suitable strings out of "mail.received". If your name
+is not on the list, well I'm sorry, but the world is not a fair place!
+
+ So that's how you use library routines. I chose qsort because it is
+simple to use, and shows off a feature of 'C' well, that's the ability
+to use a name of a function as a pointer and then execute that function
+from within the called function. It's strcmp in this case. A quick look
+at the compiler output is instructive.
+
+ As is the nature of the animal, a tin-pot little program, which should
+have taken all of ten minutes to get going in fact took more like two
+hours. I put it down to the fact that the Fine Manual did not make it
+adequately obvious that the data array acted on by qsort was the data itself.
+From reading the Fine Manual I got the impression that the array acted on
+was an array of pointers. You live and learn. It would be a much faster
+qsort if, in fact, the sorting function sorted pointers to data instead of
+the data itself. You might like to make a function qsort_p which worked in
+in this way. The qsort algorithm is well documented elsewhere.
+
+ There is just one more point to notice about using function libraries.
+The 'C' compilation system will load functions from the library /lib/libc.a
+as a default. All others have to be indicated to the linking loader by a
+switch on the shell interactive command line.
+
+$ cc -o prog prog.c -L /usr/local/lib -lgdbm -lmalloc
+
+ You might use this command line to compile and link a program which
+uses both the GNU gdbm data-base manager library, which is installed in
+the directory /usr/local/lib, and the enhanced malloc library. Now, there
+hangs a tale! I remember having to compile a program suit off Usenet and
+it just would not work properly. No error messages, no warnings, no
+missing linking-loader symbols. It just "died" when I tried to run it.
+After many, many hours of total frustration, I thought that I would try
+linking in the enhanced malloc library. Presto! It worked.
+
+ Note very well.
+
+ A common misconception is the notion that having a #include <whatever.h>
+line in the source text will automagically tell the linking loader to
+get the functions from the appropriate library. Remove this erroroneous
+notion from your mind. It won't. The -lwhatever flag on the shell command
+line which initiates execution of "cc" or "ld" is the only way to tell the
+loader where to look for the required library.
+
+
+--
+ +----------------------------------------------------------------------+
+ | NAME Christopher Sawtell |
+ | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
+ | EMAIL chris@gerty.equinox.gen.nz |
+ | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+ +----------------------------------------------------------------------+
diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.8 b/reference/C/CONTRIB/SAWTELL/c-lesson.8
new file mode 100755
index 0000000..8e2bff9
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/c-lesson.8
@@ -0,0 +1,502 @@
+
+ Lesson 7.
+
+ De-bugging Strategies.
+
+ >>>>>>>> Proper Preparation Prevents Piss-Poor Performance. <<<<<<<<
+
+ This lesson is really a essay about how to go about writing programs.
+
+ I know that by far the best way to greatly reduce the amount of effort
+required to get a program going properly is to avoid making mistakes in the
+first palace! Now this might seem to be stating the absolute obvious, and it
+is but after looking at many programs it would seem that there is a very
+definite need to say it.
+
+ So how does one go about reducing the probability of making mistakes?
+
+ There are many strategies, and over the years I have evolved my own set.
+ I have found that some of the most important are:
+
+ 1) Document what you are going to do before yes BEFORE you write any code.
+ Set up the source files for the section of the program you are going to
+ write and put some lines of explanation as to what you intend to do in
+ this file. Be as precise as you can, but don't go into the detail of
+ explaining in English, or your First Language, exactly what every
+ statement does.
+
+ 2) Make sure that you keep each file as small as is sensible. Some program
+ authors say that one should put only one function in a file. It's my
+ personal opinion that this is going a little bit over the top, but
+ certainly you should not have more than one logical activity in a source
+ file. It's easier to find a needle in a tiny haystack than in a big one!
+
+ 3) Always use names for the objects in your program which are fully
+ descriptive, or at the very least are meaningful nmemonics. Put yourself
+ in the position of some poor soul who - a couple of years later, after you
+ have long finished with the project, and left the country - has been given
+ the task of adding a small feature to your exquisite program. Now in the
+ rush to get your masterpiece finished you decided to use variable names
+ like "a4" and "isb51" simply so that you can get the line typed a
+ fraction of a second faster than if you used something like
+ "customer_address[POST_CODE]" and "input_status_block[LOW_FUEL_TANK_#3].
+ The difference in ease of understanding is obvious, isn't it? However
+ judging by some programs which I have seen published in both magazines and
+ in the public domain program sources, the point has still to be made.
+
+ 4) ALWAYS take great care with the layout of your code.
+ It's my opinion that the opening brace of ALL program structures should
+ be on a new line. Also if you put them in the leftmost column for structs,
+ enums, and initialised tables, as well as functions, then the
+ 'find function' keystrokes ( "[[" and "]]" ) in vi will find them as well
+ as the functions themselves. Make sure you have the "showmatch" facility
+ in vi turned on. ( And watch the cursor jump when you enter the
+ right hand brace, bracket, or parenthesis. )
+
+ 5) Try as hard as you can to have as few global variables as possible.
+ Some people say never have any globals. This is perhaps a bit too
+ severe but global variables are a clearly documented source of
+ programming errors. If it's impossible to perform a logical activity
+ in an efficient way without having a global or two, then confine
+ the scope of the globals to just the one file by marking the defining
+ declaration "static". This stops the compiler producing a symbol which
+ the linking loader will make available to all the files in your source.
+
+ 6) Never EVER put 'magic numbers' in you source code. Always define constants
+ in a header file with #define lines or enum statements.
+
+ Here is an example:-
+
+
+/* ----------------------------------------- */
+
+#include <stdio.h>
+
+enum status_input_names
+{
+ radiator_temperature,
+ oil_temperature,
+ fuel_pressure,
+ energy_output,
+ revolutions_per_minute
+ };
+
+char *stats[] =
+{
+ "radiator_temperature",
+ "oil_temperature",
+ "fuel_pressure",
+ "energy_output",
+ "revolutions_per_minute"
+ };
+
+#define NUMBER_OF_INPUTS ( sizeof ( stats ) / sizeof ( stats[0]))
+
+main()
+{
+ enum status_input_names name;
+
+ printf ( "Number of Inputs is: %d\n", NUMBER_OF_INPUTS );
+ for ( name = radiator_temperature; name < NUMBER_OF_INPUTS; name++)
+ {
+ printf ( "\n%s", stats[ name ] );
+ }
+ printf ( "\n\n" );
+ }
+
+/* ----------------------------------------- */
+
+ Note that as a side effect we have available the meaningful symbols
+ radiator_temperature etc. as indices into the array of status input names
+ and the symbol NUMBER_OF_INPUTS available for use as a terminator in the
+ 'for' loop. This is quite legal because sizeof is a pseudo-function and the
+ value is evaluated at the time of compilation and not when the program is
+ executed. This means that the result of the division in the macro is
+ calculated at the time of compilation and this result is used as a literal
+ in the 'for' loop. No division takes place each time the loop is executed.
+
+ To illustrate the point I would like to tell you a little story which is
+ fictitious, but which has a ring of truth about it.
+ Your employer has just landed what seems to be a lucrative contract with
+ an inventor of a completely new type of engine. We are assured that after
+ initial proving trials one of the larger Japanese motor manufactures is
+ going to come across with umpteen millions to complete the development of
+ the design. You are told to write a program which has to be a simple and
+ straightforward exercise in order to do the job as cheaply as possible.
+ Now, the customer - a some-what impulsive type - realises that his
+ engine is not being monitored closely enough when it starts to rapidly
+ dis-assemble itself under high speed and heavy load. You have to add a
+ few extra parameters to the monitoring program by yesterday morning!
+ You just add the extra parameters into the enumand the array of pointers
+ to the character strings. So:
+
+enum status_input_names
+{ radiator_temperature,
+ radiator_pressure,
+ fuel_temperature,
+ fuel_pressure,
+ oil_temperature,
+ oil_pressure,
+ exhaust_manifold_temperature
+ };
+
+ Let's continue the story about the Japanese purchase. Mr. Honda ( jun ) has
+ come across with the money and the result is that you are now a team leader
+ in the software section of Honda Software ( YourCountry ) Ltd. The project of
+ which you are now leader is to completely rewrite your monitoring program and
+ add a whole lot of extra channels as well as to make the printouts much more
+ readable so that your cheap, cheerful, and aesthetic-free program can be sold
+ as the "Ultimate Engine Monitoring Package" from the now world famous Honda
+ Real-time Software Systems. You set to work, Honda et. al. imagine that there
+ is going to be a complete redesign of the software at a cost of many million
+ Yen. You being an ingenious type have written the code so that it is easy to
+ enhance.
+
+ The new features required are that the printouts have to be printed with the
+ units of measure appended to the values which have to scaled and processed so
+ that the number printed is a real physical value instead of the previous
+ arrangement where the raw transducer output was just dumped onto a screen.
+
+ What do you have to do?
+
+ Thinking along the line of "Get the Data arranged correctly first".
+ You take you old code and expand it so that all the items of information
+ required for each channel are collected into a struct.
+
+enum status_input_names
+{
+ radiator_temperature,
+ radiator_pressure,
+ fuel_temperature,
+ fuel_pressure,
+ oil_temperature,
+ oil_pressure,
+ exhaust_manifold_temperature,
+ power_output,
+ torque
+ };
+
+typedef struct channel
+{
+ char *name; /* Channel Name to be displayed on screen. */
+ int nx; /* position of name on screen x co-ordinate.
+*/
+ int ny; /* ditto for y */
+ int unit_of_measure; /* index into units of measure array */
+ char value; /* raw datum value from 8 bit ADC */
+ char lower_limit; /* For alarms. */
+ char upper_limit;
+ float processed_value; /* The number to go on screen. */
+ float offset;
+ float scale_factor;
+ int vx; /* Position of value on screen. */
+ int vy;
+ }CHANNEL;
+
+enum units_of_measure { kPa, degC, kW, rpm, Volts, Amps, Newtons };
+
+char *units { "kPa", "degC", "kW", "rpm", "Volts", "Amps", "Newtons" };
+
+CHANNEL data [] =
+{
+ { "radiator temperature",
+ { "radiator pressure",
+ { "fuel temperature",
+ { "fuel pressure",
+ { "oil temperature",
+ { "oil pressure",
+ { "exhaust manifold temperature",
+ { "power output",
+ { "torque",
+ };
+
+#define NUMBER_OF_INPUTS sizeof (data ) / sizeof ( data[0] )
+
+Now the lesson preparation is to find the single little bug in the above
+program fragment, to finish the initialisation of the data array of type
+CHANNEL and to have a bit of a crack at creating a screen layout
+program to display its contents. Hint: Use printf();
+( Leave all the values which originate from the real world as zero. )
+
+
+ Here are some more tips for young players.
+
+ 1) Don't get confused between the logical equality operator,
+
+ ==
+
+ and the assignment to a variable operator.
+
+ =
+
+ This is probably the most frequent mistake made by 'C' beginners, and
+ has the great disadvantage that, under most circumstances, the compiler
+ will quite happily accept your mistake.
+
+ 2) Make sure that you are aware of the difference between the logical
+ and bit operators.
+
+ && This is the logical AND function.
+ || This is the logical OR function.
+ The result is ALWAYS either a 0 or a 1.
+
+ & This is the bitwise AND function used for masks etc.
+ The result is expressed in all the bits of the word.
+
+ 3) Similarly to 2 be aware of the difference between the logical
+ complementation and the bitwise one's complement operators.
+
+ ! This is the logical NOT operator.
+ ~ This is the bitwise ones complement op.
+
+ Some further explanation is required. In deference to machine efficiency a
+ LOGICAL variable is said to be true when it is non-zero. So let's set a
+ variable to be TRUE.
+
+ 00000000000000000000000000000001 A word representing TRUE.
+ Now let's do a logical NOT !.
+ 00000000000000000000000000000000 There is a all zero word, a FALSE.
+
+ 00000000000000000000000000000001 That word again. TRUE.
+ Now for a bitwise complement ~.
+ 11111111111111111111111111111110 Now look we've got a word which is
+ non-zero, still TRUE.
+
+ Is this what you intended?
+
+ 4) It is very easy to fall into the hole of getting the
+ '{' & '}'; '[' & ']'; '(' & ')'; symbol pairs all messed up and the
+ computer thinks that the block structure is quite different from that
+ which you intend. Make sure that you use an editor which tells you the
+ matching symbol. The UNIX editor vi does this provided that you turn
+ on the option. Also take great care with your layout so that the block
+ structure is absolutely obvious, and whatever style you choose do take
+ care to stick by it throughout the whole of the project.
+ A personal layout paradigm is like this:
+
+ Example 1.
+
+function_type function_name ( a, b )
+type a;
+type b;
+{
+ type variable_one, variable_two;
+
+ if ( logical_expression )
+ {
+ variable_one = A_DEFINED_CONSTANT;
+ if ( !return_value = some_function_or_other ( a,
+ variable_one,
+ &variable_two
+ )
+ )
+ {
+ error ( "function_name" );
+ exit ( FAILURE );
+ }
+ else
+ {
+ return ( return_value + variable_two );
+ }
+ } /* End of "if ( logical_expression )" block */
+ } /* End of function */
+
+ This layout is easy to do using vi with this initialisation script
+ in either the environment variable EXINIT or the file ${HOME}/.exrc:-
+
+set showmode autoindent autowrite tabstop=2 shiftwidth=2 showmatch wm=1
+
+ Example 2.
+
+void printUandG()
+{
+ char *format =
+"\n\
+ User is: %s\n\
+ Group is: %s\n\n\
+ Effective User is: %s\n\
+Effective Group is: %s\n\n";
+
+ ( void ) fprintf ( tty,
+ format,
+ passwd_p->pw_name,
+ group_p->gr_name,
+ epasswd_p->pw_name,
+ egroup_p->gr_name
+ );
+ }
+
+ Notice how it is possible to split up format statements with a '\' as
+ the last character on the line, and that it is convenient to arrange
+ for a nice output format without having to count the
+ field widths. Note however that when using this technique that the '\'
+ character MUST be the VERY LAST one on the line. Not even a space may
+ follow it!
+
+ In summary I *ALWAYS* put the opening brace on a new line, set the tabs
+ so that the indentation is just two spaces, ( use more and you very quickly
+ run out of "line", especially on an eighty column screen ). If a statement
+ is too long to fit on a line I break the line up with the arguments set out
+ one to a line and I then the indentation rule to the parentheses "()"
+ as well. Sample immediately above. Probably as a hang-over from a particular
+ pretty printing program which reset the indentation position after the
+ printing of the closing brace "}", I am in the habit of doing it as well.
+ Long "if" and "for" statements get broken up in the same way. This is
+ an example of it all. The fragment of code is taken from a curses oriented
+ data input function.
+
+ /*
+ ** Put all the cursor positions to zero.
+ */
+
+ for ( i = 0;
+ s[i].element_name != ( char *) NULL &&
+ s[i].element_value != ( char *) NULL;
+ i = ( s[i].dependent_function == NULL )
+ ? s[i].next : s[i].dependent_next
+ )
+ { /* Note that it is the brace and NOT the */
+ /* "for" which moves the indentation level. */
+ s[i].cursor_position = 0;
+ }
+
+ /*
+ ** Go to start of list and hop over any constants.
+ */
+
+ for ( i = edit_mode = current_element = 0;
+ s[i].element_value == ( char *) NULL ;
+ current_element = i = s[i].next
+ ) continue; /* Note EMPTY statement. */
+
+ /*
+ ** Loop through the elements, stopping at end of table marker,
+ ** which is an element with neither a pointer to an element_name nor
+ ** one to a element_value.
+ */
+
+ while ( s[i].element_name != ( char *) NULL &&
+ s[i].element_value != ( char *) NULL
+ )
+ {
+ int c; /* Varable which holds the character from the keyboard. */
+
+ /*
+ ** Et Cetera for many lines.
+ */
+
+ }
+
+ Note the commenting style. The lefthand comments provide a general
+overview of what is happening and the righthand ones a more detailed view.
+The double stars make a good marker so it is easy to separate the code and
+the comments at a glance.
+
+ The null statement.
+
+ You should be aware that the ";" on its own is translated by the compiler
+as a no-operation statement. The usefullness of this is that you can do
+little things, such as counting up a list of objects, or positioning a pointer
+entirely within a "for" or "while" statement. ( See example above ).
+There is, as always, a flip side. It is HORRIBLY EASY to put a ";" at the
+end of the line after the closing right parenthesis - after all you do just
+that for function calls! The suggestion is to both mark deliberate null
+statements with a comment and to use the statement "continue;". Using
+the assert macro will pick up these errors at run time.
+
+ The assert macro.
+
+ Refer to the Programmers Reference Manual section 3X and find the
+documentation on this most useful tool.
+
+ As usual an example is by far the best wasy to explain it.
+
+/* ----------------------------------------- */
+
+#ident "@(#) assert-demo.c"
+
+#include <stdio.h>
+#include <assert.h>
+
+#define TOP_ROW 10
+#define TOP_COL 10
+
+main()
+{
+ int row, col;
+
+ for ( row = 1; row <= TOP_ROW; row++);
+ {
+ assert ( row <= TOP_ROW );
+ for ( col = 1; col <= TOP_COL; col++ )
+ {
+ assert ( col <= TOP_COL );
+ printf ( "%4d", row * col );
+ }
+ printf ( "\n" );
+ }
+ }
+
+/* ----------------------------------------- */
+
+ Which produces the output:-
+
+Assertion failed: row <= TOP_ROW , file assert-demo.c, line 15
+ABORT instruction (core dumped)
+
+ It does this because the varable "row" is incremented
+to one greater than The value of TOP_ROW.
+
+ Note two things:
+
+ 1) The sense of the logical condition. The assert is asserted
+ as soon as the result of the logical condition is FALSE.
+ Have a look at the file /usr/include/assert.
+ Where is the ";" being used as an empty program statement?
+
+ 2) The unix operating system has dumped out an image of the executing
+ program for examination using a symbolic debugger. Have a play with
+ "sdb" in preparation for the lesson which deals with it in more
+ detail.
+
+ Lets remove the errant semi-colon, re-compile and re-run the program.
+
+ 1 2 3 4 5 6 7 8 9 10
+ 2 4 6 8 10 12 14 16 18 20
+ 3 6 9 12 15 18 21 24 27 30
+ 4 8 12 16 20 24 28 32 36 40
+ 5 10 15 20 25 30 35 40 45 50
+ 6 12 18 24 30 36 42 48 54 60
+ 7 14 21 28 35 42 49 56 63 70
+ 8 16 24 32 40 48 56 64 72 80
+ 9 18 27 36 45 54 63 72 81 90
+ 10 20 30 40 50 60 70 80 90 100
+
+ Here's the ten times multiplication table, for you to give to to
+the nearest primary-school child!
+
+ I would agree that it is not possible to compare the value of a program
+layout with a real work of fine art such as a John Constable painting or
+a Michaelangelo statue, I do think a well laid out and literate example of
+programming is not only much easier to read and understand, but also it
+does have a certain aesthetic appeal.
+
+Copyright notice:-
+
+(c) 1993 Christopher Sawtell.
+
+I assert the right to be known as the author, and owner of the
+intellectual property rights of all the files in this material,
+except for the quoted examples which have their individual
+copyright notices. Permission is granted for onward copying,
+but not modification, of this course and its use for personal
+study only, provided all the copyright notices are left in the
+text and are printed in full on any subsequent paper reproduction.
+
+--
+ +----------------------------------------------------------------------+
+ | NAME Christopher Sawtell |
+ | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
+ | EMAIL chris@gerty.equinox.gen.nz |
+ | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+ +----------------------------------------------------------------------+
diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.9 b/reference/C/CONTRIB/SAWTELL/c-lesson.9
new file mode 100755
index 0000000..5d03e3b
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/c-lesson.9
@@ -0,0 +1,433 @@
+
+ Lesson 8.
+
+ This lesson and the following one will examine how to use the program
+structure - as opposed to data structure - reserved words.
+
+ Lets start with the looping structures:
+
+ do repeated_statement while ( logical_expression );
+
+ repeated_statement, which may be a block of code, will be executed
+repetitively until the logical_expression, becomes false. If you have been
+exposed to ( corrupted by? ) another language remember that there is no
+`until' test at the end of a loop. Note that the repeated_statement is always
+executed once irrespective of the state of the logical_expression.
+
+ while ( logical_expression ) repeated_statement;
+
+ repeated_statement is executed repetitively while the logical_expression
+is true. Once again statement may be a block of code. Note that if the
+logical_expression evaluates to FALSE then the repeated_statement is NEVER
+executed.
+
+ Associated with the looping structures are the control words:
+
+ break;
+ continue;
+
+ break; allows you to leave a loop in the middle of a block, and
+ continue; allows you to re-start it from the top.
+
+ Finally we must not forget the most common and useful looping construct:
+
+ for ( initialising statement; logical_expression; incremental_statement )
+ repeated_statement;
+
+ Some further explanation is needed. The initialising statement is
+executed once, but to allow for the need to initialise several separate
+variables the assignment statements may be separated by commas. The
+logical_expression must be true for the loop to run, and the
+incremental_statement is executed once each time the loop is run.
+The for statement is completely general and may, for example, be used to
+manipulate a set of pointers to operate on a linked list.
+
+Some examples.
+
+ A do loop program.
+
+#ident "@(#) do_demo.c - An example of the do loop"
+
+#include <stdio.h>
+
+main()
+{
+ char character;
+
+ character = 'a';
+
+ do printf ( "%c", character ); while ( character++ < 'z' );
+ printf ( "\n" );
+ }
+
+ Fairly obviously it prints:
+
+abcdefghijklmnopqrstuvwxyz
+
+ A while loop example.
+
+#ident "@(#) while_demo.c - An example of the while loop"
+
+#include <stdio.h>
+
+main()
+{
+ char character;
+
+ character = 'a';
+
+ while ( character <= 'z' ) printf ( "%c", character++ );
+ printf ( "\n" );
+ }
+
+ Its output is exactly the same as the previous example:
+
+abcdefghijklmnopqrstuvwxyz
+
+ In this totally trivial case it is irrelevant which program structure
+ you use, however you should note that in the `do' program structure the
+ repeated statement is always executed at least once.
+ A for loop example.
+
+ The `for' looping structure.
+
+#ident "@(#) for_demo.c - An example of the for loop"
+
+#include <stdio.h>
+
+main()
+{
+ char character;
+
+ for ( character = 'a'; character <= 'z' ; character++ )
+ {
+ printf ( "%c", character );
+ }
+ printf ( "\n" );
+ }
+
+ Surprise, Surprise!
+
+abcdefghijklmnopqrstuvwxyz
+
+ You should be aware that in all the looping program structures, the
+repeated statement can be a null statement ( either just a `;' or the
+reserved word `continue;' ). This means that it is possible to - for
+example - position a pointer, or count up some items of something or other.
+It isn't particularly easy to think up a trivial little program which
+demonstrates this concept, however the two `for' loops give some indication
+of the idea.
+
+#ident "@(#) pointer_demo.c - Pointer operations with the for loop"
+
+#include <stdio.h>
+
+main()
+{
+ char character, *character_pointer, alphabets [ 53 ];
+
+ for ( character = 'a', character_pointer = alphabets; /* Start conditions */
+ character <= 'z'; /* Run while true */
+ *character_pointer++ = character++ /* All the work */
+ )TRUE continue;
+
+ for ( character = 'A'; /* character_pointer is at the right place already */
+ character <= 'Z';
+ *character_pointer++ = character++
+ ) continue;
+
+ *character_pointer = (char) '\000'; /* NULL character to terminate string. */
+
+ printf ( "%s\n\n", alphabets );
+ }
+
+ Another Surprise!
+
+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
+
+ So much for the looping structures provided by the `C' language. The
+other main structures required to program a computer are the ones which
+alter the program flow. These are the switch, and the if and its extension
+the if ... else combination. More demo programs are much the best way of
+getting the message across to you, so here they are, first the if construct.
+
+#ident "if_demo.c"
+
+#include <stdio.h>
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ if ( argc > 1 ) printf ( "You have initiated execution with arguments."};
+ }
+
+ And the if ... else demo.
+
+#ident "if_else_demo.c"
+/*
+** The Language #define could go in the compiler invocation line if desired.
+*/
+
+#define ENGLISH
+
+#include <stdio.h>
+
+/*
+** The message and text fragments output by the program.
+*/
+
+char *messages[] =
+{
+#if defined( ENGLISH )
+#ident "@(#)ENGLISH Version"
+ "\nUsage: if_else_demo <numeric argument 1> <numeric argument 2>\n\n",
+ "The first argument is ",
+ "the second",
+ "equal to ",
+ "bigger than ",
+ "smaller than "
+#endif
+
+#if defined( FRANCAIS )
+#ident "@(#)FRENCH Version"
+
+ put the French translation in here so that we are ready to export to
+ French speaking Countries. I'd be grateful if a French speaker could
+ make the translation for me.
+
+#endif
+ };
+
+/*
+** Meaningful words defined to constants
+*/
+
+#define USAGE 0
+#define FIRST 1
+#define SECOND 2
+#define EQUAL 3
+#define BIGGER 4
+#define SMALLER 5
+
+#define SUCCESS 0
+#define FAILURE 1
+
+/*
+** We need this more than once so it can be put in a function.
+*/
+
+void usage()
+{
+ printf ( messages[USAGE]);
+ exit ( FAILURE );
+ }
+
+/*
+** Main program function starts here. ( At the top of a page no less! )
+*/
+
+int main ( argc, argv )
+int argc;
+char **argv;
+{
+ int message_index;
+ double i, j, strtod();
+ char *ptr;
+
+ if ( argc != 3 ) usage(); /* have we been given the right */
+ /* number of arguments. */
+ i = strtod ( argv[1], &ptr); /* Convert to a double float. */
+ if ( ptr == argv[1] ) usage(); /* Successful conversion? */
+ j = strtod ( argv[2], &ptr); /* Convert to a double float. */
+ if ( ptr == argv[2] ) usage(); /* Successful conversion? */
+
+/*
+** This statement uses the "ternary conditional assignment" language
+** construction to assign the value required to the message indexing variable.
+** Note that this concept is efficient in both the generation of machine code
+** output ( compile the program with a -S switch and have a look ) and in the
+** ease with which it can be understood. The assignment is obvious instead of
+** being buried under a litter of `if' and `else' keywords.
+*/
+
+ message_index = ( i == j ) ? EQUAL : ( i > j ) ? BIGGER : SMALLER;
+
+/*
+** Now print the message.
+*/
+
+ (void) printf ( "\n%s%s%s\n\n", /* Format string specifying 3 strings. */
+ messages[ FIRST ], /* Address of string. */
+ messages[ message_index ], /* ditto. */
+ messages[ SECOND ] /* ditto. */
+ );
+ return ( SUCCESS );
+ }
+
+ Well as you can no doubt gather it simply compares two numbers on the
+command line and ejects a little message depending on the relative magnitude
+of the numbers. In the UNIX tradition the help message is perhaps somewhat
+terse, but it serves the purpose of getting you - the student - to think
+about the importance of creating programs which always cope with nonsensical
+input in a civilised way. Here are the lines of output.
+
+Usage: if_else_demo <numeric argument 1> <numeric argument 2>
+
+The first argument is equal to the second
+
+The first argument is smaller than the second
+
+The first argument is bigger than the second
+
+ Now that the international community is shrinking with vastly improved
+telecommunications, it is perhaps a good idea to think carefully about
+creating programs which can talk in many languages to the users. The method
+of choice is - I believe - that presented above. The #if defined( LANGUAGE )
+gives us an easy method of changing the source code to suit the new sales
+area. Another possibility is to put all the text output needed from a program
+into a file. The file would have to have a defined layout and some consistent
+way of `getting at' the message strings.
+
+ From a commercial point of view this may or may not be a good business plan.
+Quite definitely it is an absolute no no to scatter a mass of string literals
+containing the messages and message fragments all over your program script.
+
+ There are two more methods of altering the program flow.
+
+ 1 ) The goto a label.
+ 2 ) The setjump / longjmp library routines.
+
+ The concept of the go to a label construction has had reams of literary
+verbiage written about it and this author does not intend to add to the pile.
+Suffice it to say that a goto is a necessary language construct. There are a
+few situations which require the language to have ( in practice ) some form of
+unconditional jump. Treat this statement with great caution if you wish your
+code to be readable by others. An example of legitimate use.
+
+ for ( a = 0; a < MATRIX_SIZE; a++ )
+ {
+ for ( b = 0; b < MATRIX_SIZE; b++ )
+ {
+ if ( process ( matrix, a, b )) goto bad_matrix;
+ }
+ }
+ return ( OK );
+
+bad_matrix:
+
+ perror ( progname, "The data in the matrix seems to have been corrupted" );
+ return ( BAD );
+
+ This is one of the very few "legitimate" uses of goto, as there is no
+"break_to_outer_loop" in `C'. Note that some compilers complain if the label
+is not immediately followed by a statement. If your compiler is one of these
+naughty ones, you can put either a `;' or a pair of braces `{}' after the
+`:' as a null statement.
+
+ An example of a program package which makes extensive use of the goto is the
+rz and sz modem communications protocol implementation by Chuck Forsberg of
+Omen Technology. You should download it and study the code, but do remember
+that the proof of the pudding argument must apply as the rz & sz system has
+become extremely popular in its application because it works so well.
+
+ The other method of changing program flow is the setjump and longjmp pair of
+library functions. The idea is to provide a method of recovery from errors
+which might be detected anywhere within a large program - perhaps a compiler,
+interpreter or large data acquisition system. Here is the trivial example:
+
+#ident "set_jmp_demo.c"
+
+#include <stdio.h>
+#include <setjmp.h>
+
+jmp_buf save;
+
+main()
+{
+ char c;
+
+ for ( ;; ) /* This is how you set up a continuous loop.
+*/
+ {
+ switch ( setjmp( save ))
+ {
+case 0:
+ printf ( "We get a zero returned from setjmp on setup.\n\n");
+ break; /* This is the result from setting up. */
+
+case 1:
+ printf ( "NORMAL PROGRAM OPERATION\n\n" );
+ break;
+
+case 2:
+ printf ( "WARNING\n\n" );
+ break;
+
+case 3:
+ printf ( "FATAL ERROR PROGRAM TERMINATED\n\nReally Terminate? y/n: " );
+ fflush ( stdout );
+ scanf ( "%1s", &c );
+ c = tolower ( c );
+ if ( c == 'y' ) return ( 1 );
+ printf ( "\n" );
+ break;
+
+default:
+ printf ( "Should never return here.\n" );
+ break;
+ }
+ process ();
+ }
+ }
+
+process ()
+{
+ int i;
+
+ printf ( "Input a number to simulate an error condition: " );
+ fflush ( stdout );
+ scanf ( "%d", &i );
+ i %= 3;
+ i++; /* So that we call longjmp with 0 < i < 4 */
+ longjmp ( save, i);
+ }
+
+ Although in this silly little demo the call to longjmp is in the same file
+as the call to setjmp, this does not have to be the case, and in the practical
+situation the call to longjmp will be a long way from the call to setjmp. The
+mechanism is that setjmp saves the entire state of the computer's CPU in a
+buffer declared in the jmp_buf save; statement and longjmp restores it exactly
+with the exception of the register which carries the return value from longjmp.
+This value is the same as the second argument in the longjmp call - i in our
+little demo. This means, of course, that the stack and frame pointer registers
+are reset to the old values and all the local variables being used at the time
+of the longjmp call are going to be lost forever. One consequence of this is
+that any pointer to memory allocated from the heap will also be lost, and
+you will be unable to access the data stored in the buffer. This is what the
+jargonauts call "memory leakage", and is really very difficult bug to find.
+Your program runs out of dynamic memory long before it should. Take care.
+So you have to keep a record of the buffers' addresses and free them
+before the call to longjmp.
+
+More details later on when we learn about the heap memory allocation routines.
+
+Copyright notice:-
+
+(c) 1993 Christopher Sawtell.
+
+I assert the right to be known as the author, and owner of the
+intellectual property rights of all the files in this material,
+except for the quoted examples which have their individual
+copyright notices. Permission is granted for onward copying,
+but not modification, of this course and its use for personal
+study only, provided all the copyright notices are left in the
+text and are printed in full on any subsequent paper reproduction.
+
+--
+ +----------------------------------------------------------------------+
+ | NAME Christopher Sawtell |
+ | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
+ | EMAIL chris@gerty.equinox.gen.nz |
+ | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) |
+ +----------------------------------------------------------------------+
diff --git a/reference/C/CONTRIB/SAWTELL/intro.html b/reference/C/CONTRIB/SAWTELL/intro.html
new file mode 100644
index 0000000..3278d20
--- /dev/null
+++ b/reference/C/CONTRIB/SAWTELL/intro.html
@@ -0,0 +1,24 @@
+<title>C Lesson by Chris Sawtell</title>
+<h1>C Lesson by Chris Sawtell</h1>
+This copy was taken in May 94. The latest version is available
+by
+<a href=ftp://garbo.uwasa.fi/pc/c-lang/c-lesson.zip>clicking here</a>
+<hr>
+<dd><img src=../../../GRAPHICS/whiteball.gif>
+<a href=c-lesson.1> Introduction</a>
+<dd><img src=../../../GRAPHICS/whiteball.gif>
+<a href=c-lesson.2> History</a>
+<dd><img src=../../../GRAPHICS/whiteball.gif>
+<a href=c-lesson.3> Data Storage.</a>
+<dd><img src=../../../GRAPHICS/whiteball.gif>
+<a href=c-lesson.4> Arrays & Pointers</a>
+<dd><img src=../../../GRAPHICS/whiteball.gif>
+<a href=c-lesson.5> Operators</a>
+<dd><img src=../../../GRAPHICS/whiteball.gif>
+<a href=c-lesson.6> Pre-processor</a>
+<dd><img src=../../../GRAPHICS/whiteball.gif>
+<a href=c-lesson.7> Libraries</a>
+<dd><img src=../../../GRAPHICS/whiteball.gif>
+<a href=c-lesson.8> Debugging</a>
+<dd><img src=../../../GRAPHICS/whiteball.gif>
+<a href=c-lesson.9> Structure</a>