home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / c / cnews019.zip / CNEWS019.DOC < prev    next >
Text File  |  1990-08-05  |  84KB  |  2,403 lines

  1.  
  2.       Issue                        C News                             1
  3.  
  4.  
  5.       *--------------------------------------------------------------*
  6.       |    C NEWS - International C Electronic Newsletter/Journal    |
  7.       |           "Dedicated to the Art of C Programming"            |
  8.       |                                                              |
  9.       |                      Founded 12/27/87                        |
  10.       *--------------------------------------------------------------*
  11.  
  12.  
  13.                               Table of Contents
  14.  
  15.       The HEAP: By Barry Lynch    ...............................    2
  16.  
  17.       The STACK: By Jim Singleton    ............................    3
  18.  
  19.       String Arrays by Paul E. Castle II  .......................    4
  20.  
  21.       Review: The ECSTR Library by Paul Hinds  ..................    8
  22.  
  23.       LABEL.C -- A Simple Label Program by Jim Singleton.........   10
  24.  
  25.       Beginner's Column by Wayne Dernoncourt    .................   19
  26.  
  27.       Where's That Number? by Jim Singleton   ...................   24
  28.  
  29.       Portability Coding Issues      ............................   26
  30.  
  31.       New PD/Shareware Releases by Barry Lynch   ................   37
  32.  
  33.       Article Submission Standards      .........................   39
  34.  
  35.       How to get hold of us here at C............................   40
  36.  
  37.  
  38.  
  39.       "C News" is an Electronic Journal published from time to
  40.       time.  The subject of C News is the C programming language,
  41.       as well as any derivatives like C++.  All readers are
  42.       encouraged to submit articles, reviews, or comments for
  43.       submission.  C News is freely distributed, but can not be
  44.       sold for a profit and cannot have a charge assessed to
  45.       cover distribution costs.  All articles and reviews become
  46.       the property of C News and cannot be included in other
  47.       publications without written permission from the C News
  48.       Editorial Staff.  This publication is Copyrighted under 
  49.       U.S. Copyright Law.
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.       
  60.  
  61.  
  62.  
  63.  
  64.       Issue                        C News                             2
  65.  
  66.  
  67.       ================================================================= 
  68.       The HEAP: By Barry Lynch    
  69.       ================================================================= 
  70.  
  71.  
  72.  
  73.            It's been quite awhile since an issue of C News has been
  74.       published, and it is with some pride that Dan, Wayne, Jim and I
  75.       bring this 19th issue to you.  
  76.  
  77.            Over the last few months I have had the pleasure of selling
  78.       a home in Virginia and relocating and purchasing a new home in
  79.       the Dallas-Fort Worth area.  For those of you that own homes or
  80.       have been through the relocation process, you probably
  81.       understand the stress and upheaveal that a relocation brings.
  82.       Finally, after months of planning, packing, travelling and
  83.       unpacking I have settled down and look forward to more frequent
  84.       issues of C News.  
  85.  
  86.            This issue of C News brings some articles that were
  87.       submitted quite a few months ago and have been patiently waiting
  88.       for the next publication date.  There are articles on C
  89.       portability problems, the continuation of Jim Singleton's
  90.       article on software development, another one of Wayne's
  91.       Beginner's columns and a piece on shareware.  
  92.  
  93.            The last few months have seen the release of a major
  94.       upgrade to one of the bigger C compilers (Microsoft), a major
  95.       release from one of the original DOS C compiler vendors
  96.       (Lattice) and new compiler to add more fuel to the compiler wars
  97.       (Topspeed).  Over the next couple of months, Dan, Jim Wayne and
  98.       I will be bringing you some of our thoughts on these various
  99.       compilers as we all use different ones in our daily programming
  100.       exploits.  
  101.  
  102.            This issue of C News is not the last and will be followed
  103.       by Issue 20 sometime in the early fall.  If you have ideas for
  104.       articles or comments on the style that are constructive, we
  105.       welcome them.  It should be noted that we are not striving to be
  106.       a "professional" publication, just a fun project by a couple of
  107.       guys in Virginia, and a misplaced "Brit" in Texas.  
  108.  
  109.            C ya in the next issue.  
  110.  
  111.            Barry 
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.       
  122.  
  123.  
  124.       Issue                        C News                             3
  125.  
  126.  
  127.       ================================================================= 
  128.       The STACK: By Jim Singleton    
  129.       ================================================================= 
  130.  
  131.  
  132.  
  133.            When Barry and I were discussing the editorial for this
  134.       issue of the C News, Barry suggested that I write one as well
  135.       since Dan, Wayne and I are still in the Washington, D.C. area.  
  136.  
  137.            Barry forgot to mention that the last few months have also
  138.       seen Borland come out with their first C++ compiler.  While none
  139.       of us at C News are experienced C++ programmers, we would like
  140.       to cover C++ in the C News.  Anyone interested in submitting an
  141.       article, please contact Barry or myself.  
  142.  
  143.            At the end of each issue we tell you how to contact us here
  144.       at the C News.  However, in light of all the changes since issue
  145.       18, we decided to mention it here as well.  You can contact us
  146.       through: 
  147.  
  148.            The C News
  149.            P.O. Box 15314
  150.            Arlington, VA  22215
  151.            USA
  152.  
  153.            FidoNet:        109/138.1       (Jim)
  154.            Fidonet:        1:124/3116      (Barry)
  155.            North Texas C Programmers Board: 1-214-442-0223 (Barry)
  156.  
  157.            CIS:            71540,2677      (Jim)
  158.  
  159.            MCI Mail:       272-8067        (Barry)
  160.  
  161.            Internet:       dbk@cs.umd.edu  (Dan)
  162.            UUCP:           ...!uunet!mimsy!dbk
  163.  
  164.            European C News Distribution Point: 011-3185642891
  165.            Sysop: Rob Koel
  166.  
  167.            Feel free to contact us with any ideas, comments, or
  168.       criticisms you may have.  
  169.  
  170.            Jim 
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.       
  182.  
  183.  
  184.       Issue                        C News                             4
  185.  
  186.  
  187.       ================================================================= 
  188.       String Arrays by Paul E. Castle II  
  189.       ================================================================= 
  190.  
  191.  
  192.  
  193.            Unfortunately, error conditions are a fact of life.  Any
  194.       program you write, no matter how small, carries with it the
  195.       potential to produce an error.  A good program attempts to trap
  196.       errors when they occur and gracefully handle them.  
  197.  
  198.            Error handling, however, can produce masses of extra code,
  199.       extreme confusion, and sticky maintenance problems if not
  200.       implemented smartly.  
  201.  
  202.            Consider the following line of code: 
  203.  
  204.               fileptr = fopen(infile,open_mode)
  205.  
  206.            This is a very common and simple action - open a file.
  207.       However, as written, it is fraught with danger.  Suppose the
  208.       open fails?  The FILE pointer "fileptr" is assigned the "NULL"
  209.       value.  Any attempt to use "fileptr" will, at best, cause a
  210.       program crash, or worse, a system crash.  The solution is to
  211.       trap the error: 
  212.  
  213.               if((fileptr = fopen(infile,open_mode)) == NULL) {
  214.                 printf("Could not open INPUT file.\n");
  215.                 exit(1); }
  216.  
  217.  
  218.            This code traps the error, prints an error message to the
  219.       screen, and terminates processing.  
  220.  
  221.            Now, allow me to digress from the main topic for just a
  222.       moment and talk a little about the line "exit(1)".  
  223.  
  224.            The "exit()" function is part of the standard library.  The
  225.       prototype can be found in "stdlib.h" and "process.h" and takes
  226.       the form of: 
  227.  
  228.               void exit(int status)
  229.  
  230.       "exit()" flushes all buffers for files open for buffered I/O,
  231.       closes all files, and terminates the program returning the "int
  232.       status" to the calling program or the system.  A "status" value
  233.       of "0" traditionally means "no error".  Error conditions are
  234.       indicated by a non-zero value.  Keep this in mind as we
  235.       proceed.  
  236.  
  237.            Now, let's assume you have seven files that your program
  238.       opens.  That means seven "fopen" statements and twenty-one lines
  239.  
  240.  
  241.       
  242.  
  243.  
  244.       Issue                        C News                             5
  245.  
  246.  
  247.       of code like that above.  Furthermore, let's assume that you
  248.       have seven other error conditions for which you check.  Each
  249.       check includes an "if" statement, a "printf" statement, and an
  250.       "exit" statement.  
  251.  
  252.            You should be able to see by now that you have a
  253.       substantial amount of code invested in opening files and error
  254.       handling.  But, you can reduce the amount of code, and the
  255.       headaches associated with maintaining it, substantially by using
  256.       string arrays.  Watch.  
  257.  
  258.            To handle the errors, create an array like this: 
  259.  
  260.               char *error_msg[] = {
  261.                 NULL,
  262.                 "Error message one text.\n",
  263.                 "Error message two text.\n",
  264.                 "Error message three text.\n",
  265.                 "Error message four text.\n",
  266.                 "Error message five text.\n",
  267.                 "Error message six text.\n",
  268.                 "Error message seven text.\n",
  269.                 "Error message eight text.\n" };
  270.  
  271.            The above array is an array of pointers to strings.  The
  272.       first entry, "error_msg[0]", is NULL (or NO ERROR).
  273.       "error_msg[1]" is the string "Error message one text." and so on
  274.       to "error_msg[8]".  
  275.  
  276.            Once the array has been created, you can now create a
  277.       routine called "error_exit".  You would declare the function
  278.       like this: 
  279.  
  280.               void error_exit(int errnum)
  281.  
  282.  
  283.            The code for the routine would look like this: 
  284.  
  285.               void error_exit(int errnum)
  286.               {
  287.                 if(errnum) {
  288.                   printf("%s",error_msg[errnum]);
  289.                   exit(errnum); 
  290.               }
  291.  
  292.  
  293.            To use "error_exit", the invoking function calls the error
  294.       routine passing the index value associated with the desired
  295.       error message.  The "if(errnum)" determines if an error exists.
  296.       A "0" (or NO ERROR) would resolve to false and the function will
  297.       return to the caller taking no action.  Obviously, you would
  298.       never call "error_exit" with a value of zero.  A non-zero value
  299.  
  300.  
  301.       
  302.  
  303.  
  304.       Issue                        C News                             6
  305.  
  306.  
  307.       would resolve to true and the "printf" statement would print the
  308.       text pointed to by "error_msg[errnum] and the "exit" statement
  309.       will return the value of "errnum" to the calling program or
  310.       system.  
  311.  
  312.            Using the above example of the "fopen", we would rewrite
  313.       the code in this way: 
  314.  
  315.               if((fileptr = fopen(infile,open_mode)) == NULL)
  316.                 error_exit(1);
  317.  
  318.  
  319.            This would result in the error message "Error message one
  320.       text."  being printed and the value of 1 being passed to the
  321.       calling program or system if an error occurs.  
  322.  
  323.            This method keeps the duplication of code to a minimum and
  324.       allows all error handling to be done from a single function.  As
  325.       the code changes or more error conditions are checked for, it is
  326.       a simple matter to add error messages to the array or to change
  327.       existing messages.  This saves you from having to search
  328.       thousands of lines of code for elusive error text to change.  
  329.  
  330.            Now, we have solved the problem of error handling, but we
  331.       still have seven different "fopen" statements in our program.
  332.       We can use a string array to solve this problem, also.  
  333.  
  334.            If we create the following arrays: 
  335.  
  336.               FILE *fileptr[7];          /* array of file pointers */
  337.  
  338.               char *file_table[] = {     /* array of file names    */
  339.                 "FILE1",
  340.                 "FILE2",
  341.                 "FILE3",
  342.                 "FILE4",
  343.                 "FILE5",
  344.                 "FILE6",
  345.                 "FILE7"; }
  346.  
  347.       we can rewrite the "fopen" code to handle all seven files.  
  348.  
  349.           if((fileptr[file_ndx] = fopen(file_table[file_ndx],open_mode)) == NULL)
  350.             error_exit(1);
  351.  
  352.  
  353.            The invoking function would call the open routine passing
  354.       the index pointing to the desired file name in the
  355.       "file_table".  That same index is used to access the array of
  356.       file pointers so that pointer "fileptr[0]" would point to
  357.       "file_table[0]", or FILE1 in this case, and so on.  
  358.  
  359.  
  360.  
  361.       
  362.  
  363.  
  364.       Issue                        C News                             7
  365.  
  366.  
  367.            If you wished to open all the files at one time, you could
  368.       do so in this manner: 
  369.  
  370.           for(file_ndx = 0;file_ndx < 7;file_ndx++) {
  371.             if((fileptr[file_ndx] = fopen(file_table[file_ndx],open_mode)) == NULL)
  372.               error_exit(1); }
  373.  
  374.  
  375.            As you can see, string arrays can be used to add
  376.       flexibility to your code and help make "generic" functions.
  377.       They are a powerful tool and with a little thought and a little
  378.       imagination you can do amazing things with them.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.  
  414.  
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421.       
  422.  
  423.  
  424.       Issue                        C News                             8
  425.  
  426.  
  427.       ================================================================= 
  428.       Review: The ECSTR Library by Paul Hinds  
  429.       ================================================================= 
  430.  
  431.  
  432.  
  433.       Boilerplate         
  434.  
  435.            The .ZIP file is about 65K and is dated 5/86 (as are all of
  436.       the files) even though all of the files have internal comments
  437.       indicating dates of April/May/June, 1984. The file is stated by
  438.       the author as being placed in the public domain although he does
  439.       request that it not be put to any "military" use. I've seen this
  440.       file on MANY boards in the DC area, so assume it is fairly
  441.       readily available wherever you are.  
  442.  
  443.       General Description        
  444.  
  445.            With over 60 functions (74 files total, including .H files
  446.       and some others), all of which are concerned with string
  447.       manipulation (it is my assumption that ECSTR => Extended C
  448.       STRing), this is a wealth of source material for anyone who
  449.       wants their own source library of string manipulation routines.
  450.       The following files are included: 
  451.  
  452.       READ     ME       GETOPT   C        STREND   C        STRREV   C
  453.                         INT2STR  C        STRFIELD C        STRRPT   C
  454.       CTYPES   DEM      MEMCCPY  C        STRFIND  C        STRSPN   C
  455.                         MEMCHR   C        STRKEY   C        STRSUFF  C
  456.       GETOPT   3        MEMCMP   C        STRLEN   C        STRTOK   C
  457.       XSTRING  3C       MEMCPY   C        STRMOV   C        STRTRANS C
  458.                         MEMMOV   C        STRNCAT  C        STRTRIM  C
  459.       ASCII    H        MEMRCHR  C        STRNCMP  C        STRXCAT  C
  460.       CTYPES   H        MEMREV   C        STRNCPY  C        STRXCPY  C
  461.       MEMORY   H        MEMSET   C        STRNEND  C        STRXMOV  C
  462.       STRINGS  H        MEMTRANS C        STRNLEN  C        STRXNCAT C
  463.       _STR2MAP H        STR2INT  C        STRNMOV  C        STRXNCPY C
  464.       _STR2PAT H        STRCAT   C        STRNREV  C        STRXNMOV C
  465.       _STR2SET H        STRCHR   C        STRNRPT  C        SUBSTR   C
  466.                         STRCMP   C        STRNTRAN C        _C2TYPE  C
  467.       BCOPY    C        STRCPACK C        STRPACK  C        _STR2MAP C
  468.       BFILL    C        STRCPBRK C        STRPBRK  C        _STR2PAT C
  469.       BMOVE    C        STRCPY   C        STRPREF  C        _STR2SET C
  470.       BZERO    C        STRCSPN  C        STRRCHR  C
  471.       FFS      C        STRCTRIM C        STRREPL  C
  472.  
  473.  
  474.       Review         
  475.  
  476.            This collection is not exactly for the faint of heart or
  477.       the rank beginner (although anyone who has created, compiled,
  478.       linked and run even a few C functions can deal with it). Only
  479.  
  480.  
  481.       
  482.  
  483.  
  484.       Issue                        C News                             9
  485.  
  486.  
  487.       source code is provided, with excellent block comments in each
  488.       source module and a modest, but illuminating, README file.
  489.       Mildly oriented towards VAX machines but conditional
  490.       compile/assembly statements make everything available to non-VAX
  491.       users.  
  492.  
  493.            I've stripped out the heart of several of the routines
  494.       (dumping the conditional stuff since I don't have a PDP-11 or a
  495.       VAX) and have have had no problem reformatting them to compile
  496.       under Turbo C (2.0). I see no reason why users of other
  497.       compilers should have any more trouble than I did.  
  498.  
  499.            Most or all of the 30 or so library functions for string
  500.       manipulation included in Turbo-C 2.0 can be found here, as well
  501.       as ANOTHER 30 or so, and since the source code is provided, this
  502.       is an excellent opportunity for those of you who want to have
  503.       LOTS of string functions available and/or those of you who want
  504.       source code so you can "do your own thing". I doubt that many
  505.       compilers (if any) provide anywhere near this extensive a
  506.       package of string functions. And, of course, the price is
  507.       right.  
  508.  
  509.            This is a useful package, regardless of its age. There is,
  510.       of course, the fact that since it is an unsupported package,
  511.       you've got no one to yell at if anything goes wrong, but hey,
  512.       the source code is there and what more can you ask for? 
  513.  
  514.            COMPATIBILITY: written to run under ANY version of UNIX.
  515.       Author has wisely chosen compatibility over rationality (in
  516.       function names and argument lists) --- if this sounds strange,
  517.       then you might be unfamiliar with the MAJOR headaches which
  518.       accompany rational but incompatible tools. The READ.ME file goes
  519.       into some discussion about compatability with UNIX functions.  
  520.  
  521.            ANSI: this was done LONG before the ANSI standard was
  522.       introduced and I have made no attempt to determine ANSI
  523.       compatibility.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.  
  539.  
  540.  
  541.       
  542.  
  543.  
  544.       Issue                        C News                            10
  545.  
  546.  
  547.       ================================================================= 
  548.       LABEL.C -- A Simple Label Program by Jim Singleton
  549.       ================================================================= 
  550.  
  551.  
  552.  
  553.       Introduction         
  554.  
  555.            The other day at work, I came across a simple diskette
  556.       label program, written in BASIC.  The program printed a simple
  557.       four line label composed of a title, name, date and two comment
  558.       lines: 
  559.  
  560.               +-------------------------------+
  561.               | Personnel Payroll Data, Disk  |
  562.               | Rufus Jackson        6/23/90  |
  563.               | This is the data for use by   |
  564.               | the payroll audit team.       |
  565.               +-------------------------------+
  566.  
  567.       While the program worked and did what it was supposed to do,
  568.       there were a couple of things I didn't like about it: 
  569.  
  570.               - The name and date were hardcoded into the program,
  571.                 so they had to be edited if they were to be changed.
  572.  
  573.               - The program wasn't compiled, which made it easy to
  574.                 edit the name and date, but loading BASIC first
  575.                 slowed the program down.
  576.  
  577.               - The program did not exit back to the operating system,
  578.                 leaving the user in BASIC.
  579.  
  580.               - The program only printed one label at a time, which
  581.                 was okay if you only wanted one label, but was a
  582.                 pain if you wanted several.  I didn't mind that it
  583.                 would not print multiple copies of a label; but, if
  584.                 I want to label ten different disks, I don't want to
  585.                 load and run the program ten times.
  586.  
  587.       Rather than modify the existing BASIC code, I figured I'd write
  588.       it in C.  (The fact that I didn't have a BASIC compiler had
  589.       nothing to do with this decision. :-) Besides, I often hear
  590.       people just starting out in C ask how to send output to the
  591.       printer.  
  592.  
  593.            A short time later, I had a working program: 
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.       
  602.  
  603.  
  604.       Issue                        C News                            11
  605.  
  606.  
  607.            /*  LABEL.C -- Print out a diskette label.  Designed for
  608.                an ALPS P2000G printer, it should work on any Epson-
  609.                compatible printer.  */
  610.  
  611.            #include <stdio.h>
  612.  
  613.            FILE *printer;
  614.  
  615.            void main()
  616.            {
  617.                /*  Define arrays to hold each item of data.  */
  618.                char name[15], title[28], comment1[28],
  619.                        comment2[28], date[8];
  620.  
  621.                /*  Open a file pointer to the printer.  */
  622.                printer = fopen("LPT1", "w");
  623.  
  624.                /*  Prompt the user for each item of data and read
  625.                    in the data.  */
  626.  
  627.                printf("\nPlease enter the title:  ");
  628.                gets(title);
  629.                printf("\nPlease enter a name:  ");
  630.                gets(name);
  631.                printf("\Please enter the date (MM/DD/YY): ");
  632.                gets(date);
  633.                printf("\nPlease enter the first comment:  ");
  634.                gets(comment1);
  635.                printf("\nPlease enter the second comment:  ");
  636.                gets(comment2);
  637.  
  638.                /*  Output the data to the printer.  */
  639.  
  640.                fprintf(printer, "\n%s", title);
  641.                fprintf(printer, "\n%s                %s", name, date);
  642.                fprintf(printer, "\n%s", comment1);
  643.                fprintf(printer, "\n%s\n", comment2);
  644.  
  645.                /*  Flush the buffer and close the file pointer
  646.                    to the printer.  */
  647.  
  648.                fflush(printer);
  649.                fclose(printer);
  650.            }
  651.  
  652.       All that was left was adding a loop to allow more than one label
  653.       to be printed at a time.  
  654.  
  655.            First, I decided that I would follow the current trend when
  656.       updating software and add lots of "features."  Actually, I
  657.       realized that here was a simple program that could be used to
  658.       demonstrate several things I often hear questions about: 
  659.  
  660.  
  661.       
  662.  
  663.  
  664.       Issue                        C News                            12
  665.  
  666.  
  667.               - Checking the printer status, is the printer online?
  668.  
  669.               - Sending escape codes to the printer.
  670.  
  671.               - Clearing the screen.
  672.  
  673.               - Getting the system date.
  674.  
  675.               - An example for yorn().  (yorn() is a handy function
  676.                 for asking yes/no questions which Jaime Dasilva
  677.                 showed me a year or so ago.)
  678.  
  679.       The compiler used for the code in this program is Turbo C 2.0,
  680.       but most functions should compile with little, if any,
  681.       modification in any other MS-DOS compiler.  
  682.  
  683.       (NOTE: Because not all readers of the C News use MS-DOS as their
  684.       primary operating system, several of the following functions
  685.       will not apply.) 
  686.  
  687.  
  688.       Sending output to the printer.     
  689.  
  690.            Before going into the added "features," let's look briefly
  691.       at how LABEL.C sends output to the printer, since this question
  692.       comes up from time to time.  Basically, just as printf() sends
  693.       formatted output to stdout, fprintf() sends formatted output to
  694.       a stream (normally stdprn).  Both commands accept a series of
  695.       arguments which are applied to a format specification contained
  696.       in a format string: 
  697.  
  698.               printf("\nHello world.");
  699.  
  700.       The difference is that in fprintf(), a stream must be specified: 
  701.  
  702.               fprintf(printer,"\nHello world.");
  703.  
  704.       In this example the stream is the printer.  Before we can send
  705.       the formatted data to the stream, we must open the stream.
  706.       Before we can open the stream, we need to declare it.  
  707.  
  708.            Wait a minute, what's a stream?  A stream is a file or
  709.       piece of hardware which is manipulated as a pointer to a FILE
  710.       object.  To declare a stream, in this case the printer, we
  711.       write: 
  712.  
  713.               FILE *printer;
  714.  
  715.       In order to open the stream, we use fopen(), specifying the
  716.       printer port as the filename and w as the mode: 
  717.  
  718.               printer = fopen("LPT1", "w");
  719.  
  720.  
  721.       
  722.  
  723.  
  724.       Issue                        C News                            13
  725.  
  726.  
  727.       Once we have finished sending the data to the printer, we need
  728.       to make sure that there is no data in the buffer, which we flush
  729.       with fflush(): 
  730.  
  731.               fflush(printer);
  732.  
  733.       After flushing the buffer, we need to close the stream, which is
  734.       done with fclose(): 
  735.  
  736.               fclose(printer);
  737.  
  738.       Admittedly, this is not the most detailed explanation of sending
  739.       data to the printer, nor is it the only way to do so.  However,
  740.       this should give you enough background to understand how LABEL.C
  741.       works and give you some points of reference for further study.  
  742.  
  743.  
  744.       Checking the status of the printer    
  745.  
  746.            Since the people that will be using this program normally
  747.       turn their printer on at the same time as they turn on their
  748.       computer, since they share a surge protector, I was only
  749.       interested in whether the printer was online or not.  
  750.  
  751.            Without going into an in-depth discussion of DOS
  752.       interrupts, checking the status of the printer can be done
  753.       rather easily, by using BIOS interrupt 17, the printer-services
  754.       interrupt, function 2.  In C, we do this by using int86().  
  755.  
  756.            Usually found in dos.h, int86() uses the following syntax: 
  757.  
  758.               int int86(int int_number, union REGS *in_registers,
  759.                       union REGS *out_registers);
  760.  
  761.       and executes the specified software interrupt.  Prior to
  762.       executing the interrupt, the register values specified by
  763.       *in_registers are copied into the registers.  After executing,
  764.       int86 copies the current register values into out_registers.  It
  765.       should be noted that in_registers and out_registers can point to
  766.       the same structure, which is the case in the following example.  
  767.  
  768.            In order to check status of the printer, we need to specify
  769.       that we are using interrupt 17 (in hex), giving us: 
  770.  
  771.               int int86(0x17, union REGS *in_registers,
  772.                       union REGS *out_registers);
  773.  
  774.       In order to specify function 2, we must first put 2 into
  775.       register AH, which is accomplished by: 
  776.  
  777.               regs.h.ah = 0x02;
  778.  
  779.  
  780.  
  781.       
  782.  
  783.  
  784.       Issue                        C News                            14
  785.  
  786.  
  787.       Since we are interested in a printer attached to LPT1 (if you're
  788.       not, I am), we need to put the printer number in DX: 
  789.  
  790.               regs.h.dx = 0;
  791.  
  792.       (If you want to check the status of a printer on LPT2, the
  793.       printer number would be 1.) 
  794.  
  795.            After specifying both in_registers and out_registers to be
  796.       of the structure specified by the REGS union, all that is left
  797.       is to evaluate the returned value AH, returning 0 if the printer
  798.       is not ready.  
  799.  
  800.       The complete function is as follows: 
  801.  
  802.            #include <dos.h>
  803.  
  804.            int prncheck(void)
  805.            {
  806.                    union REGS regs;         /*  Declare regs to be of
  807.                                             the structure union
  808.                                             REGS.  */
  809.                    regs.h.ah = 0x02;        /*  AH = 02 for printer
  810.                                             status  */
  811.                    regs.x.dx = 0;           /*  DX = 00 for LPT1  */
  812.  
  813.                    int86(0x17, ®s, ®s);
  814.  
  815.                    return(((regs.h.ah & 0x80) == 0x80) ? 1 : 0);
  816.            }
  817.  
  818.  
  819.       Sending escape codes to the printer    
  820.  
  821.            After checking the status of the printer, sending escape
  822.       codes to the printer is very easy.  In fact, the hardest part is
  823.       often finding the printer manual to look up the appropriate
  824.       escape codes.  
  825.  
  826.            For example, if we wanted to use elite printing on an ALPS
  827.       P2000 printer, the escape codes necessary are 1B and 4D.  In
  828.       order to send them to the printer, all we need to do is declare
  829.       them (in hex) as a character array 
  830.  
  831.               char NLQ[] = {0x1B, 0x4D};
  832.  
  833.       and then send them to the printer 
  834.  
  835.               fputs(NLQ, printer);
  836.  
  837.       That's all there is to it.  
  838.  
  839.  
  840.  
  841.       
  842.  
  843.  
  844.       Issue                        C News                            15
  845.  
  846.  
  847.       Clearing the Screen       
  848.  
  849.            There are several ways to clear the screen, in fact, most C
  850.       compilers have a function to clear the screen in one of their
  851.       libraries.  Assuming ANSI.SYS is present, we could send \xB1[2J
  852.       to the screen to clear it.  An easier way would be to send a
  853.       series of carriage returns/linefeeds to the screen.  All these
  854.       methods will clear the screen, but what it we only want to clear
  855.       a portion of the screen?  By using the video BIOS scroll-window
  856.       function, interrupt 10, function 6, we can use int86() to clear
  857.       the screen or a portion of it.  That's why rather than hard code
  858.       a screen size into this function, I have chosen to have the
  859.       values for the number of rows and columns in the screen to be
  860.       passed to the function.  
  861.  
  862.            Wait a minute . . . "scroll-window," isn't that the same as
  863.       sending a series of carriage returns/linefeeds?   Well, I admit
  864.       it, it is very close.  However, this screen clearing function
  865.       can be used to clear just a portion of the screen, as it
  866.       specifies the area to clear.  
  867.  
  868.            AL contains the number of lines to scroll.  If AL is equal
  869.       to 0 or is greater than number of rows specified by DH, the
  870.       screen is blanked.  
  871.  
  872.            #include <dos.h>
  873.  
  874.            void clrscr(rows, columns)
  875.            int rows, columns;
  876.            {
  877.                union REGS regs;
  878.                    regs.h.ah = 6;
  879.                    regs.h.al = 0;       /*  Number of lines to
  880.                                         scroll.  */
  881.                    regs.h.bh = 7;       /*  Attribute to use for the
  882.                                         screen.  */
  883.                    regs.h.ch = 0;       /*  Row, upper left corner.  */
  884.                    regs.h.cl = 0;       /*  Column, upper left
  885.                                         corner.  */
  886.                    regs.h.dh = rows;  
  887.                    regs.h.dl = columns;
  888.  
  889.                    int86(0x10, ®s, ®s);
  890.            }
  891.  
  892.       One problem with clearing the screen in this manner, is that the
  893.       cursor is left at the lower right corner of the screen.  Using
  894.       the BIOS cursor-position function, interrupt 10, function 2, and
  895.       int86(), we can specify the row in DH and the column in DL and
  896.       reposition the cursor wherever we want it.  
  897.  
  898.  
  899.  
  900.  
  901.       
  902.  
  903.  
  904.       Issue                        C News                            16
  905.  
  906.  
  907.            #include <dos.h>
  908.  
  909.            void set_cursor(rows, columns)
  910.            int rows, columns;
  911.            {
  912.                    union REGS regs;
  913.  
  914.                    regs.h.ah = 0x02;
  915.                    regs.h.bh = 0;
  916.                    regs.h.dh = rows;       /*  Return cursor to this row.  */
  917.                    regs.h.dl = columns;    /*  Return cursor to this column.  */
  918.  
  919.                    int86(0x10, ®s, ®s);
  920.            }
  921.  
  922.       A faster, simpler way to clear the entire screen would be to use
  923.       interrupt 10, function 0, the BIOS set video mode function.  Of
  924.       course, you must know the display mode value for your system,
  925.       which goes in AL.  For a 16 color EGA display adapter, connected
  926.       to an EGA monitor, with a pixel resolution of 640 x 350, a
  927.       character display of 80 x 25, the value for AL is 2.  
  928.  
  929.           #include <dos.h>
  930.  
  931.           clrscr()
  932.           {
  933.                   union REGS regs;
  934.  
  935.                   regs.h.ah = 0;
  936.                   regs.h.al = 2;              /*  Display mode.  */
  937.                   int86(0x10, ®s, ®s);
  938.           }
  939.  
  940.  
  941.       Getting the date       
  942.  
  943.            Well, we've been using interrupts for everything else, so
  944.       it should not be a surprise that we will use an interrupt to get
  945.       the system date.  DOS interrupt 21, function 2A, will return the
  946.       date of the DOS internal clock.  (NOTE:  The DOS internal clock
  947.       is the clock that can set by the operator with DATE and/or TIME
  948.       in AUTOEXEC.BAT or at any DOS prompt.) 
  949.  
  950.            In the previous functions where we have used the DOS
  951.       interrupts, we have used int86(); but to get the system date, we
  952.       will use intdos().  (We could use int86() just as easily.) 
  953.  
  954.            While int86() is a general 8086 interrupt function,
  955.       intdos() is a general DOS interrupt interface.  Rather than have
  956.       to specify interrupt 21, intdos() automatically accesses the DOS
  957.       interrupt 21.  Other than not having to specify the interrupt
  958.       number, intdos() works just like int86().  
  959.  
  960.  
  961.       
  962.  
  963.  
  964.       Issue                        C News                            17
  965.  
  966.  
  967.  
  968.            The DOS interrupt 21 function to get the system date is 2A,
  969.       so we have to set the value of AH to 2A.  
  970.  
  971.            Unlike our previous functions, the system date will be
  972.       returned in three registers, DH, DL, and CX.  (If we wanted the
  973.       day of the week, it would be returned as AL.)  The numeric value
  974.       for the month (1 through 12), is returned in DH.  The day is
  975.       returned in DL.  The year, from 1980 to 2099 is returned as CX.
  976.       In order to write these values to a string, we use sprintf().
  977.       (Because we want the date in MM/DD/YY format, we need to
  978.       subtract 1900 from the value in CX.) 
  979.  
  980.            #include <dos.h>
  981.  
  982.            char *get_date()
  983.            {
  984.                    static char date[9];
  985.                    union REGS regs;
  986.  
  987.                    regs.h.ah= 0x2a;
  988.                    intdos(®s, ®s);
  989.  
  990.                    sprintf(date, "%02.2d/%02.2d/%02.2d", regs.h.dh,
  991.                        regs.h.dl, regs.x.cx-1900);
  992.  
  993.                    return(date);
  994.            }
  995.  
  996.  
  997.       Yes or no answers with a default: yorn()  
  998.  
  999.            Okay, enough messing with interrupts.  The need often
  1000.       arises for a program to ask a yes or no question.  In many
  1001.       cases, it would be nice to have a default answer where the user
  1002.       just has to hit enter.  There are a number of ways to do this,
  1003.       but my favorite is yorn(), which Jaime Dasilva posted on the C
  1004.       BBS about a year or so ago.  It's not an earth shaking function,
  1005.       but it is the answer to an often asked question and it makes
  1006.       asking a number of such yes/no questions much easier.  
  1007.  
  1008.            What makes yorn() nice to use is that the question and the
  1009.       default answer are passed to the function.  So, while yorn() has
  1010.       expected lines 
  1011.  
  1012.               if(c == 'Y' || c == 'y')
  1013.                       return YES;
  1014.               else if(c == 'N' || c == 'n')
  1015.                       return NO;
  1016.  
  1017.       you don't need to repeat them every time you have to ask a yes
  1018.       or no question which has a default answer.  There is nothing
  1019.  
  1020.  
  1021.       
  1022.  
  1023.  
  1024.       Issue                        C News                            18
  1025.  
  1026.  
  1027.       difficult about yorn(), as can be seen by the following code,it
  1028.       is fairly self-explanatory.  
  1029.  
  1030.            /*  yorn.c -  yes/no prompting, with default.  */
  1031.  
  1032.            #include <stdio.h>
  1033.            #include <string.h>
  1034.  
  1035.            #define YES 1
  1036.            #define NO  0
  1037.            #define LINELEN 129      /* DOS max line length + 1 */
  1038.  
  1039.            int yorn(char *prompt, int dfault)
  1040.            {
  1041.                    char s[LINELEN], c;
  1042.                    int len;
  1043.  
  1044.                    printf("%s (%c) ", prompt, dfault ? 'Y' : 'N');
  1045.                    fgets(s, LINELEN, stdin);
  1046.                    len = strspn(s, " \t\n");    /* skip whitespace */
  1047.  
  1048.                    if(len < strlen(s))
  1049.                    {
  1050.                            c = *(s + len);
  1051.                            if(c == 'Y' || c == 'y') return YES;
  1052.                            else if(c == 'N' || c == 'n') return NO;
  1053.                    }
  1054.  
  1055.                    return dfault;
  1056.            }
  1057.  
  1058.  
  1059.       BLOB.C         
  1060.  
  1061.            The original C version of this label program (above), was
  1062.       named LABEL.C, why did I change it to BLOB.C?  Because it kept
  1063.       growing and growing.  
  1064.  
  1065.            The revised code for BLOB.C is included in the archive with
  1066.       this file.  Most of the code should be self-explanatory by now.  
  1067.  
  1068.            BLOB is not meant to be a tight, small label program.
  1069.       There are a lot of things that could be done differently.  BLOB
  1070.       serves as an example of a few handy little functions, functions
  1071.       which answer some commonly asked questions.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.       
  1082.  
  1083.  
  1084.       Issue                        C News                            19
  1085.  
  1086.  
  1087.       ================================================================= 
  1088.       Beginner's Column by Wayne Dernoncourt    
  1089.       ================================================================= 
  1090.  
  1091.  
  1092.  
  1093.            This column is going to deal with structures, more
  1094.       specifically with data structures.  In a building, a structure
  1095.       is an object composed of one or more parts with a common purpose
  1096.       of being a building.  Different types of structures will have
  1097.       variations in the parts, but they all contain the same basic
  1098.       parts (i.e..  roof, walls, doors, windows, etc.).  If you
  1099.       duplicate a structure, the new one will have the same pieces as
  1100.       the one that you duplicated.  If you go into a modern apartment
  1101.       complex, most will have three or four floor plans for their
  1102.       various apartments.  All apartments share components with other
  1103.       dwelling units, from townhouses to mansions, -- all have
  1104.       bathrooms, kitchens and bedrooms, etc.  These components can be
  1105.       thought of as different types of data elements (ints, floats,
  1106.       chars, etc.).  Just as one apartment building has multiple
  1107.       dwelling units, an apartment complex can have multiple apartment
  1108.       buildings.  One of the data elements that a structure can
  1109.       contain is another structure (of course you can't have a
  1110.       circular reference).  
  1111.  
  1112.            A data structure can be thought of in the same way.
  1113.       Different data structures are composed of different variables.
  1114.       The entire data structure is located in contiguous memory.  If a
  1115.       data structure is composed of 2,000 bytes, those 2,000 bytes of
  1116.       memory will be located in one piece of memory.  This is a
  1117.       requirement imposed by the ANSI standard.  Unfortunately this
  1118.       usually has the side effect of imposing a restriction on IBM PC
  1119.       programs on the size of data structures.  Data structures can be
  1120.       made up of integers, floats, characters or structures or arrays
  1121.       of any of these or any combinations of these.  
  1122.  
  1123.            In a C program, there are two methods of accessing the data
  1124.       in a structure.  This article will deal with the simpler of the
  1125.       two, while next issue's article will discuss the more advanced
  1126.       method.  
  1127.  
  1128.            To illustrate this concept, consider the following
  1129.       requirement: You have to write a program that will read a series
  1130.       of files and perform the following editing functions: 
  1131.  
  1132.            1) Turn IBM special characters into blanks (printers don't
  1133.               usually handle these characters very well)
  1134.            2) Drop trailing blanks from lines (sometimes the actions from
  1135.               the first step will result in a line of nothing but blanks
  1136.            3) Print the resulting line to a file
  1137.  
  1138.  
  1139.  
  1140.  
  1141.       
  1142.  
  1143.  
  1144.       Issue                        C News                            20
  1145.  
  1146.  
  1147.       Given these requirements, let's write an algorithm to solve this
  1148.       problem.  
  1149.  
  1150.       1. GET information about filetypes that we're interested in
  1151.       2. OPEN output file - check for success
  1152.       3. AS long as the request for info on good filetypes is filled:
  1153.               3.1 OPEN the file for reading - check for success
  1154.               3.2 WHILE not at EOF
  1155.                       3.2.1 RESET the input buffer
  1156.                       3.2.2 READ from the file into the input buffer
  1157.                               3.2.2.1 CHECK for special character and
  1158.                                       translate if needed
  1159.                       3.2.3 TRIM the line of trailing blanks
  1160.                       3.2.4 PRINT the line to the output file
  1161.               3.3 GET info on the next file for reading
  1162.               3.4 CLOSE the current input
  1163.       4. CLOSE the output file
  1164.       5. END the program
  1165.  
  1166.       Translating this algorithm into a program, here is the actual
  1167.       code that is used: 
  1168.  
  1169.       /* 
  1170.           This program is supposed to read all files with a filetype of
  1171.           TST, convert all of the non-standard ASCII characters (all
  1172.           characters not in the range of \x20 to \x7f to a space, all
  1173.           trailing blanks are then to be eliminated with the resulting
  1174.           line written to an output file.
  1175.       */
  1176.  
  1177.       /* prototypes go here */
  1178.       int read_line (char *in_line);
  1179.       void trim_line (char *in_line, int length);
  1180.  
  1181.       /* include files go here */
  1182.       #include <stdio.h>
  1183.       #include <dos.h>
  1184.       #include <dir.h>
  1185.  
  1186.       /* Global variable declarations go here */
  1187.       FILE *infile, *outfile;                /* For some reason,                   
  1188.                                                 I have better luck        
  1189.                                                 with files as global      
  1190.                                                 variables. */             
  1191.       main()
  1192.       {
  1193.           /* Local variable declarations */
  1194.           char in_line[150];
  1195.           int length;
  1196.           int found_file;
  1197.           struct ffblk fileinfo;          /* This declares a STRUCT */
  1198.  
  1199.  
  1200.  
  1201.       
  1202.  
  1203.  
  1204.       Issue                        C News                            21
  1205.  
  1206.  
  1207.           /* find the first file to read */
  1208.           found_file = findfirst ("*.tst", &fileinfo, 0);     /* 1. */
  1209.  
  1210.           /* open the output file */
  1211.           if ((outfile = fopen("test.out","wt")) == NULL)     /* 2. */
  1212.           {
  1213.               printf ("I can\'t open the output file\n");
  1214.               return(0);
  1215.           }
  1216.  
  1217.           /* while files are present to process */
  1218.           while (!found_file)                                 /* 3. */
  1219.           {
  1220.                                                              /* 3.1 */
  1221.               if ((infile = fopen(fileinfo.ff_name,"rt")) == NULL)    
  1222.               {
  1223.                   printf ("I can\'t open the input file\n");
  1224.                   return(0);
  1225.               }
  1226.  
  1227.               while (!feof(infile))                          /* 3.2 */
  1228.               {
  1229.                   memset(in_line, ' ', 150);               /* 3.2.1 */
  1230.  
  1231.                   length = read_line(&in_line[0]);         /* 3.2.2 */
  1232.  
  1233.                   trim_line(&in_line[0], length);          /* 3.2.3 */
  1234.  
  1235.                   fprintf (outfile, "%s\n", in_line);      /* 3.2.4 */
  1236.               }
  1237.               found_file = findnext(&fileinfo);              /* 3.3 */
  1238.               fclose(infile);                                /* 3.4 */
  1239.           }
  1240.           fclose(outfile);                                    /* 4. */
  1241.       }                                                       /* 5. */
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.  
  1261.       
  1262.  
  1263.  
  1264.       Issue                        C News                            22
  1265.  
  1266.  
  1267.       int read_line(char *in_line)
  1268.       /* 
  1269.           This function returns the line read in from the input file.
  1270.           Modify the input character string so that all fall into the
  1271.           range of printable ASCII characters.  The only character
  1272.           excluded is the new-line character.  All non-conforming
  1273.           characters are translated into blanks. 
  1274.       */
  1275.       {
  1276.           char unsigned in_char='\x00';
  1277.           int index = 0;              /* index is the character
  1278.                                       position in the return buffer,
  1279.                                       it's the length of the buffer */
  1280.  
  1281.           while (in_char != '\n' && !feof(infile))
  1282.           {
  1283.               fscanf(infile, "%c", &in_char);
  1284.  
  1285.               if ((in_char < ' ' || in_char > '\x7F') && in_char != '\n')
  1286.               {
  1287.                   in_char = ' ';                         /* 3.2.2.1 */
  1288.               }
  1289.               in_line[index] = in_char;
  1290.               index++;
  1291.           }
  1292.           index--;
  1293.           in_line[index] = ' ';
  1294.  
  1295.           return(index);
  1296.       }
  1297.  
  1298.       void trim_line(char *in_line, int length)
  1299.       /* 
  1300.           This functions returns a line trimmed of all trailing blanks
  1301.       */
  1302.       {
  1303.           int index;
  1304.           for (index = length; in_line[index] == ' ' && index >= 0; index--)
  1305.           {
  1306.               in_line[index] = '\x00';
  1307.           }
  1308.       }
  1309.  
  1310.            In previous articles, you've already been introduced to
  1311.       using files.  Whenever you open a file, the system fills a
  1312.       structure with data regarding this file.  The FILE macro
  1313.       (defined as part of the stdio.h header) creates this data
  1314.       structure.  Another data structure is created by the use of
  1315.       struct keyword, in this case the type is called ffblk and I
  1316.       called the data structure instance fileinfo.  The template for
  1317.       the ffblk structure is found in the dir.h header file.  
  1318.  
  1319.  
  1320.  
  1321.       
  1322.  
  1323.  
  1324.       Issue                        C News                            23
  1325.  
  1326.  
  1327.            I initially fill the fileinfo data structure with
  1328.       information using the function findfirst (see line 1).  This
  1329.       function returns a zero if no files were found that matches the
  1330.       search criteria (in this case all files with a file type of
  1331.       TST), otherwise it returns a number (what the number is doesn't
  1332.       matter).  Notice that the data structure is passed to the
  1333.       function with the '&', this instructs the compiler to pass the
  1334.       address of the structure to the function.  I assign the value
  1335.       returned by findfirst to a variable called found_file.  I update
  1336.       the fileinfo data structure on other files using the findnext
  1337.       function.  
  1338.  
  1339.            As long as found_file is not zero (see line 3), I open the
  1340.       file that was found by using the ff_name offset of the data
  1341.       structure.  This could be confusing to some people, let me stop
  1342.       and try to explain this a little more.  The fileinfo data
  1343.       structure is composed (in this instance) of a 21 character array
  1344.       reserved for DOS, a 1 byte character that is the file attribute
  1345.       (i.e., read-only, hidden, system, etc.), 2 unsigned integers
  1346.       that contain the date and time fields, a long integer that
  1347.       contains the length of the file and a null-terminated character
  1348.       array containing the file name.  When the program is run, this
  1349.       data structure initially contains undefined data. This data
  1350.       structure changes to reflect data on the files that we're
  1351.       interested in.  This data is updated by using the findfirst and
  1352.       findnext functions. The findfirst function fills out the data
  1353.       structure initially and the findnext function gets information
  1354.       on later entries.  (see line 3.3) 
  1355.  
  1356.       Next month, another way of accessing data structures.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.       
  1382.  
  1383.  
  1384.       Issue                        C News                            24
  1385.  
  1386.  
  1387.       ================================================================= 
  1388.       Where's That Number? by Jim Singleton   
  1389.       ================================================================= 
  1390.  
  1391.  
  1392.                 A Project In Programming Design (Revisited) 
  1393.  
  1394.            Last issue, we looked at one of the textbook methods of
  1395.       programming design.  While the seven steps involved were covered
  1396.       in order and in sufficient depth to understand the processes
  1397.       involved, I have to apologize for the article.  Due to a variety
  1398.       of reasons, most notably that I was leaving the country the day
  1399.       the article was due, the code accompanying the article was not
  1400.       as good as it should have been.  As published, PHONENUM.C will
  1401.       work.  While I have a variation of PHONENUM.C, I felt it needed
  1402.       to be modified slightly for general use.  At the same time,
  1403.       there were things which I didn't change, which I should have
  1404.       changed.  
  1405.  
  1406.            Looking back at PHONENUM.C, what's wrong with the code?  As
  1407.       you may remember, I mentioned one bug in the article, which is
  1408.       was using ASCIIZ strings with no initialization.  (If you missed
  1409.       this one and found others, you're not alone.)  This causes
  1410.       garbage characters in the database, which results in different
  1411.       output files every time you add names to the database.  This
  1412.       makes it virtually impossible to use a comparison of the
  1413.       database as a means of testing variations to the program.  
  1414.  
  1415.            A second glaring error, which I didn't notice until,
  1416.       Charles Falconer pointed it out, was the use of fixed fields.
  1417.       As Charles correctly pointed out, this can "lead easily to nasty
  1418.       bugs, such as the use of 'gets' in [the] program and the
  1419.       associated C insecurities."  (Luckily, Charles, I have not yet
  1420.       been bitten by this bug.)  In addition, in the case of the field
  1421.       for the phone number, it doesn't allow for extensions, overseas
  1422.       numbers, etc.  (As one can tell, I have never put my fiancee's
  1423.       phone number, in Ireland, into the program.) 
  1424.  
  1425.            Are there other errors?  Yes and no.  As I have mentioned,
  1426.       the program will work and does do what it was designed to do.
  1427.       In fact, since this seems as if it is becoming an ongoing series
  1428.       of articles, we can easily make modifications to the code with
  1429.       each installment.  However: 
  1430.  
  1431.            - I overlooked the fact that the program requires the
  1432.              user to correctly enter the exact name of the person
  1433.              whose phone number they are retrieving. 
  1434.  
  1435.            - I also did not allow any means for checking to see
  1436.              what numbers are already in the database.  (Although
  1437.              this was considered for a later article, it is a feature
  1438.              that should be present at the outset.) 
  1439.  
  1440.  
  1441.       
  1442.  
  1443.  
  1444.       Issue                        C News                            25
  1445.  
  1446.  
  1447.  
  1448.            - I never did consider the size of the program, which
  1449.              is rather large for such a limited number of features.
  1450.              (Charles said this best, as "the whole thing seems to
  1451.              be squashing mosquitos with a pile driver.")
  1452.  
  1453.            I received a number of proposed modifications to
  1454.       PHONENUM.C, ranging from several lines to completely new
  1455.       programs.  Charles Falconer did not care for the interior design
  1456.       of PHONENUM.C, so he rewrote PHONENUM.C, using a more modular
  1457.       approach.  While I have seen this approach before, I appreciate
  1458.       it much more after taking a crticial look at my code from issue
  1459.       18.  Charles' formatting and break-down philosophy results in
  1460.       self-documenting code, with modules which are small and of a
  1461.       single purpose.  Charles' version of PHONENUM is included in
  1462.       this archive in the file FONENUM.C.  Thanks, Charles.  
  1463.  
  1464.            What's next?  The obvious shortcomings of the program are
  1465.       listed above, so anyone that wants to improve PHONENUM.C can
  1466.       either use them as a guide or look at Charles' program.
  1467.       PHONENUM.C is a simple program, so it doesn't really lend itself
  1468.       to some of the "features" discussed in the last issue; however,
  1469.       it will probably appear from time to time as a platform for
  1470.       demonstrating different functions.   
  1471.  
  1472.  
  1473.  
  1474.  
  1475.  
  1476.  
  1477.  
  1478.  
  1479.  
  1480.  
  1481.  
  1482.  
  1483.  
  1484.  
  1485.  
  1486.  
  1487.  
  1488.  
  1489.  
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499.  
  1500.  
  1501.       
  1502.  
  1503.  
  1504.       Issue                        C News                            26
  1505.  
  1506.  
  1507.       ================================================================= 
  1508.       Portability Coding Issues      
  1509.       ================================================================= 
  1510.  
  1511.  
  1512.  
  1513.            When I first started working in an environment where I was
  1514.       using multiple C compilers I assumed that given the ANSI C
  1515.       standard, writing C code that was easily portable between the
  1516.       compilers would present little or no difficulties.  My favorite
  1517.       environment to develop code in is Turbo C.  I thought that I
  1518.       could tweak all the ANSI C flags on the TC compiler, write the
  1519.       routines, test them with some drivers and then move the source
  1520.       to the target systems and everything would be fine.  This idea
  1521.       turned out to be naive more often than not.  After a few trials
  1522.       it became obvious that ANSI C by one compiler's definition ain't
  1523.       necessarily ANSI C by another's.  Plus, it turns out that there
  1524.       are a lot of things that the ANSI C standard does not mandate
  1525.       but leaves up to the implementation.  To avoid the situation
  1526.       where I would be maintaining multiple versions of the same
  1527.       source file, I needed some guidelines that would allow me to
  1528.       write more portable code.  
  1529.  
  1530.            For my purposes I defined 'portable C code' as code that
  1531.       can be compiled and run on multiple operating systems and
  1532.       hardware platforms, with no source modifications, and produce
  1533.       identical results (or at least acceptably similar, taking into
  1534.       account different data representations).  This would seem to be
  1535.       an obvious blanket definition but I thought that I had better
  1536.       give myself an ideal situation to shoot for.  
  1537.  
  1538.       Exceptions would be (there are always exceptions): 
  1539.  
  1540.            1) Low level routines that can be non-portable because of
  1541.               unavoidable machine dependence. (i.e. mapping of
  1542.               hardware or operating system data structures)
  1543.  
  1544.            2) Major differences in compiler implementations.
  1545.  
  1546.       In the case of machine dependent routines, I decided that I
  1547.       could isolate these into Machine Dependent Libraries.  In the
  1548.       case of multiple compilers I could stick with the lowest common
  1549.       denominator to eliminate annoying 'minimal' code changes.  
  1550.  
  1551.            My approach was to identify native C operations and common
  1552.       coding assumptions that could produce non-portable code,
  1553.       regardless of compiler adherence to the ANSI C standard.  These
  1554.       are listed in this article.  There are complete volumes written
  1555.       upon portability and the C language and I make no claim that
  1556.       these guidelines cover all aspects of portability.  They do
  1557.       however provide good 'rules of thumb' and I have found them
  1558.       useful in minimizing my portability problems.  I used a number
  1559.  
  1560.  
  1561.       
  1562.  
  1563.  
  1564.       Issue                        C News                            27
  1565.  
  1566.  
  1567.       of reference books while compiling this list and I can recommend
  1568.       the following for further reading:  
  1569.  
  1570.            o  C:A Reference Manual Second Edition, Samuel P. Harbison
  1571.            and Guy L. Steele, Tartan Laboratories, Prentice-Hall
  1572.            Software Series 1987 
  1573.  
  1574.            o  Portability and the C language, Rex Jaeschke, Hayden
  1575.            Books - C Library 1988 
  1576.  
  1577.            o The Waite Group's Essential Guide to ANSI C, Naba
  1578.            Barkakati, Howard W. Sams & Company 1988 
  1579.  
  1580.            If you are reading this you are assumed to have a working
  1581.       knowledge of C, its data types and constructs.  This document
  1582.       does contains some discussion of binary and unary conversions,
  1583.       trigraphs and character escape sequences.  When applicable,
  1584.       acceptable alternatives to the operations discussed are
  1585.       specified.  A limited explanation is usually given to avoid
  1586.       making arbitrary do or don't statements.  
  1587.  
  1588.            ANSI C is referenced where appropriate and when the
  1589.       operation involves ANSI C extensions.  However, if you are using
  1590.       multiple compilers, refer to their specific documentation to
  1591.       determine what is acceptable to all of them.  If that happens to
  1592.       be an ANSI C construct, great!!  
  1593.  
  1594.            For reference, the systems that I have been working with
  1595.       are: 
  1596.  
  1597.            1. IBM PC/RT running AIX 2.2.1
  1598.            2. IBM 4381 running VM/XA SP2 using C/370
  1599.            3. DEC VAX/VMS
  1600.            4. PS/2 60 with DOS 3.3 and TURBOC 2.0
  1601.  
  1602.  
  1603.       Bit Fields        
  1604.  
  1605.            Due to differences in byte ordering, bit field widths and
  1606.       alignment restrictions on different machines, code using bit
  1607.       fields will likely be non-portable.  Use of bit-fields should be
  1608.       restricted to to situations where hardware defined data areas
  1609.       must be matched exactly.  
  1610.  
  1611.            C specifies that no compiler has to allow bit fields of any
  1612.       type except unsigned, but some compilers do allow signed (that
  1613.       is sign extension occurs when extracting the contents).  Use of
  1614.       any type other than unsigned for bit fields is considered less
  1615.       portable than using bit fields at all.  
  1616.  
  1617.  
  1618.  
  1619.  
  1620.  
  1621.       
  1622.  
  1623.  
  1624.       Issue                        C News                            28
  1625.  
  1626.  
  1627.  
  1628.       Bit Wise operations       
  1629.  
  1630.            Due to different implementations of signed integer numbers,
  1631.       the bitwise operators: ^, |, and ~ should NOT be used on signed
  1632.       values.  Likewise the shift operators >> and << should NOT be
  1633.       used on signed operands.  
  1634.  
  1635.            ANSI C mandates that integers use binary encoding to permit
  1636.       portable bitwise operations and shifts upon POSITIVE integers.
  1637.       If the contents of an integer could become negative, bitwise
  1638.       operations should not be used as results will be unpredictable
  1639.       when ported.  Casts may be used to cast operands to be
  1640.       unsigned.  
  1641.  
  1642.  
  1643.       Byte Order and Alignment      
  1644.  
  1645.            Routines coded that assume a particular byte order will not
  1646.       be portable.  Likewise, routines that assume specific data
  1647.       alignment will not be portable.  
  1648.  
  1649.            Addressing may be right-to-left or left-to-right.
  1650.       Alignment restriction may not exist, may be strictly enforced or
  1651.       in some cases adjustable by the hardware or implementation
  1652.       depending upon the data type referenced.  Run time errors or
  1653.       unpredictable results may occur if addressing and alignment
  1654.       conditions are assumed.  
  1655.  
  1656.  
  1657.       Numeric Escape Codes       
  1658.  
  1659.            Numeric escape codes should not be used for two reasons.
  1660.       They tend to hide the meaning of the code in a cryptic mass of
  1661.       numbers and they are dependent upon the implementation's
  1662.       character set.  If the specific encoding is not present in the
  1663.       character set, results will be unpredictable.  Also there is an
  1664.       implicit assumption that characters will be represented in eight
  1665.       bits.  This is not portable either.  Escape codes should be hid
  1666.       in MACRO definitions both for code clarity and isolation.  
  1667.  
  1668.  
  1669.       Character Constants        
  1670.  
  1671.            Character constants are written by enclosing a character in
  1672.       apostrophes and have type 'int'.  Most computers contain
  1673.       integers in a storage area large enough to contain several
  1674.       characters and thus some C implementations allow multi-character
  1675.       constants such as 'ABC' creating an integer value (not a string,
  1676.       no '\0' ending character).  There are implicit assumptions about
  1677.       byte-ordering involved in the use of such a constant, so the
  1678.       actual value is non-portable.  
  1679.  
  1680.  
  1681.       
  1682.  
  1683.  
  1684.       Issue                        C News                            29
  1685.  
  1686.  
  1687.  
  1688.            ANSI C allows multiple character constants but their actual
  1689.       value is left up to the implementation.  Note that
  1690.       multi-character constants are not the same as multi-byte
  1691.       characters.  
  1692.  
  1693.       (See previous discussion on byte ordering)  
  1694.  
  1695.  
  1696.       Character Definitions        
  1697.  
  1698.            All character definitions should be defined as 'unsigned'
  1699.       for consistency and portability.  Different implementation may
  1700.       have default characters as signed or unsigned or even
  1701.       pseudo-unsigned (treated as signed when performing the usual
  1702.       unary conversions but the actual value cannot be negative).  If
  1703.       left as an implicit definition, unpredictable results could
  1704.       occur.  
  1705.  
  1706.  
  1707.       Character Escape codes       
  1708.  
  1709.            Some character escape codes are defined to be independent
  1710.       of the computers character set.  The appear in code preceded by
  1711.       a back slash. (e.g.'/n').  The character escape codes that are
  1712.       allowed by the ANSI standard are listed here: 
  1713.  
  1714.             a               produce an audible alert (ANSI extension)
  1715.             b               backspace
  1716.             f               form feed
  1717.             n               newline
  1718.             r               carriage return
  1719.             t               horizontal tab
  1720.             v               vertical tabulate
  1721.             \               backslash
  1722.             '                    single quote
  1723.             "               double quote
  1724.             ?               question mark
  1725.             <octal digits>  Interpretation depends upon printer or terminal
  1726.             x<hex digits>   Interpretation depends upon printer or terminal
  1727.  
  1728.       Some compilers may or may not support all of the above
  1729.       sequences.  Check the  compiler documentation.  
  1730.  
  1731.  
  1732.       Character Sets        
  1733.  
  1734.            ANSI C introduces trigraphs so that C programs may be
  1735.       written in a subset of ASCII.  For example the character
  1736.       trigraph ??) will represent the ASCII character ].  
  1737.  
  1738.  
  1739.  
  1740.  
  1741.       
  1742.  
  1743.  
  1744.       Issue                        C News                            30
  1745.  
  1746.  
  1747.  
  1748.            I personally find that trigraphs are a pain to use and they
  1749.       make for really ugly code.  However when porting C source to a
  1750.       machine which does NOT support certain ASCII characters the
  1751.       trigraphs must be used.  The port procedure must be responsible
  1752.       for converting the necessary ASCII characters to their trigraph
  1753.       equivalent.  For example, EBCDIC machines do not support the
  1754.       characters [ and ].  If the C source is coded on an ASCII
  1755.       machine and ported to an EBCDIC machine, the characters [ and ]
  1756.       must be translated to their trigraph equivalents ??( and ??)
  1757.       respectively.  
  1758.  
  1759.            If the target systems compiler does not support trigraphs
  1760.       or the required characters, MACROs should be defined for the
  1761.       appropriate escape sequences.  I have seen this done
  1762.       successfully in the old ORACLE C compiler for IBM 370 machines
  1763.       before C/370 blotted that landscape.  
  1764.  
  1765.            The translation of trigraphs in the source program occurs
  1766.       before lexical analysis (tokenization) and even before the
  1767.       recognition of character escapes introduced with a backslash \.
  1768.       Only these exact nine trigraphs are recognized.  
  1769.  
  1770.            Trigraph       ASCII Character
  1771.            --------       ---------------
  1772.            ??(            [
  1773.            ??<            {
  1774.            ??/            \
  1775.            ??'            ^
  1776.            ??=            #
  1777.            ??)            ]
  1778.            ??>            }
  1779.            ??!            |
  1780.            ??-            ~
  1781.  
  1782.  
  1783.       Comments         
  1784.  
  1785.            Comments are defined as beginning with /* and terminating
  1786.       with */.  Nested comments are NOT ANSI standard although some
  1787.       compiler implementations do allow it.  If a section of code is
  1788.       to be suppressed and the section contains comments, preprocessor
  1789.       statements should be used:  
  1790.  
  1791.            #if 0
  1792.            ..........
  1793.            ..........
  1794.            #endif
  1795.  
  1796.  
  1797.  
  1798.  
  1799.  
  1800.  
  1801.       
  1802.  
  1803.  
  1804.       Issue                        C News                            31
  1805.  
  1806.  
  1807.  
  1808.       rather than: 
  1809.  
  1810.            /*
  1811.            .........
  1812.            .........
  1813.            */
  1814.  
  1815.  
  1816.       Data Type Sizes       
  1817.  
  1818.            The exact size of the various data types for an
  1819.       implementation is usually defined in the limits.h and float.h
  1820.       header files.  This is ANSI C and most other compilers follow it
  1821.       although other functions and MACROs may also be present.  Check
  1822.       the individual compilers files before making any assumptions as
  1823.       to the size of a data type.  
  1824.  
  1825.       See discussions of floating point and integer types.  
  1826.  
  1827.  
  1828.       External names and internal identifiers     
  1829.  
  1830.            The C language allows and is sensitive to mixed casing in
  1831.       identifiers.  Early versions of C specified 8 significant
  1832.       characters in identifier names.  ANSI C requires implementations
  1833.       to allow 31 significant characters and some allow more.  Again,
  1834.       use the lowest common denominator if using multiple compilers.  
  1835.  
  1836.            Although C permits long external identifiers, the host or
  1837.       target operating system may require shorter names.  All external
  1838.       name should be encapsulated through the use of pre-processor
  1839.       statements.  This allows meaningful names to be coded and
  1840.       permits maximum portability.  
  1841.  
  1842.               #define tut_error_handler tut00u
  1843.  
  1844.               extern void tut_error_handler();
  1845.               int *p;
  1846.  
  1847.               if (!p) tut_error_handler("Null pointer error");
  1848.  
  1849.  
  1850.       Floating Point types       
  1851.  
  1852.            There are no requirements in C implementations about the
  1853.       relative sizes of the floating-point and integer or pointer
  1854.       types.  Floating point number representation is completely
  1855.       machine dependent.  It is generally assumed that the type
  1856.       'double' will be large enough to accurately contain all value of
  1857.       type 'long'.  While this is likely to be true, C does not
  1858.       require it and any code written should avoid depending on this
  1859.  
  1860.  
  1861.       
  1862.  
  1863.  
  1864.       Issue                        C News                            32
  1865.  
  1866.  
  1867.       assumption.  
  1868.  
  1869.            The 'long double' type give C program access to an extended
  1870.       precision floating point values.  However, implementation are
  1871.       free to make 'long double' the same size as 'double' as they are
  1872.       free to make 'double' and 'float' the same.  Check the
  1873.       individual compiler documentation before making any assumptions
  1874.       on floating point sizes.  
  1875.  
  1876.            ANSI C allows floating arithmetic to be done without
  1877.       'widening' of the operands.  
  1878.  
  1879.  
  1880.       Function Pointers        
  1881.  
  1882.            Function pointers must be explicitly typed or the results
  1883.       can be unpredictable.  Implementations can use different sizes
  1884.       for data and function pointers.  Assuming the default 'int'
  1885.       return type is 'good enough' is not good enough.(See discussion
  1886.       of pointers)  
  1887.  
  1888.  
  1889.       Input and Output       
  1890.  
  1891.            All input and output (I/O) in C programs should be done
  1892.       using C's standard I/O facilities.  These are based upon the
  1893.       concept of a stream which may be a file or a device.  A file
  1894.       pointer is returned to the application from the function fopen
  1895.       and is used as an argument to most of the I/O facilities.  Calls
  1896.       to host operating system utilities to perform I/O are not
  1897.       allowed (or portable).  
  1898.  
  1899.  
  1900.       Integer Arithmetic        
  1901.  
  1902.            There is not much that can be done about predicting run
  1903.       time divide by zero other than to check for a 0 divisor at every
  1904.       computation (which may incurr unacceptable overhead).  It should
  1905.       be noted here that the results of an overflow of a signed
  1906.       integer type are unpredictable.  An incorrect value may be
  1907.       produced, the program may terminate execution or some
  1908.       machine-dependent trap or exception may occur.  This holds for
  1909.       >> or << operations whose right hand operand is too large or
  1910.       negative as well.  
  1911.  
  1912.            Unsigned integer overflow results are well defined by C,
  1913.       namely, the result is computed using modular arithmetic, but
  1914.       this is dependent on the representation of int.  Routines should
  1915.       never be coded to take advantage of any action occurring in the
  1916.       case of a signed overflow and dependenc on the modular nature of
  1917.       unsigned overflow should be avoided.  
  1918.  
  1919.  
  1920.  
  1921.       
  1922.  
  1923.  
  1924.       Issue                        C News                            33
  1925.  
  1926.  
  1927.       Integer Types        
  1928.  
  1929.            Integers come in three types: short, int and long.  Int may
  1930.       not be shorter than short and long may not be shorter than int.
  1931.       However it is permitted for short and int to be the same size or
  1932.       for int and long to be the same size.  Of the three, int is the
  1933.       default integer type and thus is likely to be the most efficient
  1934.       in a given implementation.  Unfortunately it is also the least
  1935.       portable being implemented in 32 bits by some compilers and 16
  1936.       on others.  A long type integer is likely to be implemented in
  1937.       32 bits as it can give the largest range of integer values.
  1938.       Operations on type long may be slower than operation on type
  1939.       int.  
  1940.  
  1941.            The choice of what integer type to use comes down to
  1942.       portability or efficiency.  
  1943.  
  1944.  
  1945.       Initializers         
  1946.  
  1947.            'K & R' C did not allow initialization of automatic
  1948.       aggregates (arrays).  ANSI C does.  I have found that if a
  1949.       compiler does not follow a complete ANSI C implementation, this
  1950.       is not likely to be supported.  Check the appropriate compiler
  1951.       documentation.  
  1952.  
  1953.  
  1954.       MACROs         
  1955.  
  1956.            Substitution of macro parameters into string constants and
  1957.       character constants is up to the implementation of the
  1958.       compiler.  For example the definition:  
  1959.  
  1960.               #define MAKESTRING(x) "x"
  1961.  
  1962.       used in the following statement: 
  1963.  
  1964.               MAKESTRING( a += 1     /* Comment */)
  1965.  
  1966.       could result any one of the following: 
  1967.  
  1968.               "a += 1      /* Comment */"
  1969.               "a += 1 "
  1970.               "a += 1 /**/"
  1971.               "a+=1/* Comment */"
  1972.               "a+=1"
  1973.  
  1974.            ANSI C does describe the # and ## operators to be used for
  1975.       'stringization' and 'token merging' however check with the
  1976.       appropriate compiler documentation to see what is supported and
  1977.       be sure sure you know what you are trying to achieve.  
  1978.  
  1979.  
  1980.  
  1981.       
  1982.  
  1983.  
  1984.       Issue                        C News                            34
  1985.  
  1986.  
  1987.       Pointers         
  1988.  
  1989.            Pointers should be initialized to null or to their desired
  1990.       run time value when they are declared.  
  1991.  
  1992.               int foo;
  1993.               int *p = NULL;
  1994.               int *q = &foo;
  1995.  
  1996.  
  1997.            Some implementation will give compile errors if a pointer
  1998.       is not initialized before use, other will go ahead and use
  1999.       whatever is in the pointer.  Defining a pointer to null should
  2000.       force some sort of run time "null pointer assignment message" if
  2001.       the pointer has not been properly defined prior to use.  
  2002.  
  2003.            Assigning integers to pointers should not be done except in
  2004.       the special case of assigning a constant zero to initialize a
  2005.       null pointer.  Note that the null pointer concept does not
  2006.       necessarily mean an all-bits-zero value.  
  2007.  
  2008.            Proper type casts must be used when assigning pointers to
  2009.       pointers of different types.  This will guarantee portability
  2010.       and conversion without error.  
  2011.  
  2012.            long number;
  2013.  
  2014.            long *lng_ptr = &number;
  2015.            char *string;
  2016.            .........
  2017.            .........
  2018.            string = (char*)lng_ptr;
  2019.            .........
  2020.            .........
  2021.  
  2022.  
  2023.       Register Variables        
  2024.  
  2025.            You should not use the unary operator '&' upon a register
  2026.       variable.  Some implementations may support this as register is
  2027.       only a hint to the compiler and not a mandatory requirement, as
  2028.       well as the fact that on some computers, registers are
  2029.       addressable as if they were storage locations.  On the other
  2030.       hand if a register is available and used, the & operator would
  2031.       force it to be auto instead defeating the whole purpose of the
  2032.       register declaration.  Some compilers will issue warning
  2033.       messages but this should not be counted upon.  
  2034.  
  2035.  
  2036.  
  2037.  
  2038.  
  2039.  
  2040.  
  2041.       
  2042.  
  2043.  
  2044.       Issue                        C News                            35
  2045.  
  2046.  
  2047.  
  2048.       Program return codes       
  2049.  
  2050.            Do NOT rely upon the return code of a program being that
  2051.       which is specified in the return statement.  Use the exit
  2052.       library function instead.  
  2053.  
  2054.            ANSI C does mandate that an explicitly returned value from
  2055.       main will be the programs' exit code.  
  2056.  
  2057.  
  2058.       Switch Statements        
  2059.  
  2060.            Do NOT rely on a switches case being resolved in the order
  2061.       they are specified.  The order of case testing is undefined and
  2062.       depending upon the set of case values, and their contiguity, the
  2063.       implementation may test in a variety of ways, even within the
  2064.       same switch.  
  2065.  
  2066.  
  2067.       Unions         
  2068.  
  2069.            The only time a component of a union may be addressed is if
  2070.       the last assignment to that union was through the same
  2071.       component.  It is not portable to assign one union component and
  2072.       then reference another.  Some compilers will allow this, others
  2073.       will not compile or give an run time failure.  
  2074.  
  2075.               union U { long c; double d; } x;
  2076.               long l;
  2077.  
  2078.               x.d = 1.0e10;
  2079.               l = x.c;             /* not portable */
  2080.  
  2081.  
  2082.       Usual unary and binary conversion performed on operands  
  2083.  
  2084.            Unary Conversions: applied to ^, | ,~ , <<, >> and function
  2085.       arguments: 
  2086.  
  2087.            Original operand type      Converted Type
  2088.            ---------------------      --------------
  2089.            char, short                int
  2090.            unsigned char              unsigned
  2091.            unsigned short             unsigned
  2092.            float                      double
  2093.            "array of T"               pointer to T
  2094.            "function returning T"     pointer to function returning T"
  2095.  
  2096.       Binary Conversions are done before Binary or Ternary Operations
  2097.       are performed.  An operator that performs the usual binary
  2098.       conversions on its two operands, first performs the usual unary
  2099.  
  2100.  
  2101.       
  2102.  
  2103.  
  2104.       Issue                        C News                            36
  2105.  
  2106.  
  2107.       conversions on each of the operands independently.  The usual
  2108.       binary conversion as defined by ANSI C are: 
  2109.  
  2110.       1.  If either operand is not of arithmetic type, or if the
  2111.       operand are the same type, no conversion are performed.  
  2112.  
  2113.       2.  Otherwise, if one is of type long double then the other is
  2114.       converted to type long double.  
  2115.  
  2116.       3.  Otherwise, if one is of type double then the other is
  2117.       converted to type double.  
  2118.  
  2119.       4.  Otherwise if one operand is type float the other is
  2120.       converted to type float.  
  2121.  
  2122.       5.  Otherwise, if one is of type unsigned long int then the
  2123.       other is converted to unsigned long int.  
  2124.  
  2125.       6.  Otherwise, if one operand is of type long int and the other
  2126.       is of type unsigned int, and a long int can contain all unsigned
  2127.       int values, the unsigned int is converted to long int otherwise
  2128.       both operands are converted to unsigned long int.  
  2129.  
  2130.       7.  Otherwise, if one operand is of type long int the other
  2131.       (which must now be type int) is converted to type long int.  
  2132.  
  2133.       8.  Otherwise, if one operand is of type unsigned int then the
  2134.       other is converted to type unsigned int.  
  2135.  
  2136.       9.  Otherwise, both operands are of type int and no other
  2137.       conversions are performed.  
  2138.  
  2139.       These are similar to those defined by K&R except for expansion
  2140.       for long double and unsigned long.  
  2141.  
  2142.       Some compilers convert type float in function argument lists to
  2143.       type double and some will supply an option to suppress this
  2144.       conversion.  Check the compiler documentation.  
  2145.  
  2146.  
  2147.  
  2148.  
  2149.  
  2150.  
  2151.  
  2152.  
  2153.  
  2154.  
  2155.  
  2156.  
  2157.  
  2158.  
  2159.  
  2160.  
  2161.       
  2162.  
  2163.  
  2164.       Issue                        C News                            37
  2165.  
  2166.  
  2167.       ================================================================= 
  2168.       New PD/Shareware Releases by Barry Lynch   
  2169.       ================================================================= 
  2170.  
  2171.  
  2172.  
  2173.            Listed below are some of the new programming related
  2174.       shareware or public domain utilities, libraries and code
  2175.       fragments that have been released over the last few months.
  2176.       Opinions expressed are of the author only.  The files listed
  2177.       below are available from the Bulletin Board Systems that are C
  2178.       News Distribution points.  
  2179.  
  2180.  
  2181.       Filename: MEXT17.ZIP        
  2182.  
  2183.            The Microsoft Editor comes free with the C compiler and the
  2184.       MASM assembler.  One of the capabilities of the editor is the
  2185.       ability of the programmer to write editor extensions in C.  This
  2186.       file is a collection of extensions written by Fridtjof Weigel.
  2187.       The one limitation of this collection is that they were compiled
  2188.       with OS/2 extensions.  
  2189.  
  2190.            Therefore, if you want to use them with the DOS based
  2191.       Microsoft Editor you are out of luck, unless you modify the
  2192.       source that is distributed.  Listed below are some of the
  2193.       capabilities that are available with this extension library.  
  2194.  
  2195.           - funclist: Builds a list of functions
  2196.           - keymacdef: Begins a key macro
  2197.           - keymac: Executes a keystroke macro
  2198.           - indent: Indent a range of lines
  2199.           - reflow: Wordwraps a paragraph
  2200.  
  2201.  
  2202.       Filename: C_MENUS1.LZH        
  2203.  
  2204.            This file contains a menuing system written in TurboC v2.0
  2205.       by Karl Keyte of West Germany.  A library of functions, header
  2206.       file and a reference file are included in the archive.  The
  2207.       library contains functions to define a menu (define_menu),
  2208.       display (display_menu), remove (remove_menu) and various
  2209.       others.  A sample program outlining the usage of the functions
  2210.       is not included in the archive.  However, Karl will try to
  2211.       assist if you are willing to call him or send him e-mail or a
  2212.       letter.  Karl states in the documentation that the source may be
  2213.       available depending upon whether the source is undergoing major
  2214.       modifications or not.  
  2215.  
  2216.  
  2217.  
  2218.  
  2219.  
  2220.  
  2221.       
  2222.  
  2223.  
  2224.       Issue                        C News                            38
  2225.  
  2226.  
  2227.  
  2228.       Filename: MABBRE.COM        
  2229.  
  2230.            This archive is another set of extensions for the Microsoft
  2231.       Editor.  These extensions implement templates for various C
  2232.       language keywords. For example: If you type in "w", and press
  2233.       Alt-tab (access the extension) the result will be "while ()".
  2234.       Setting up CABBRE (C language vs. PABBRE - Pascal also included
  2235.       in the above archive) involves copying the CABBRE.MXT file to
  2236.       the same directory where "Tools.ini" resides, and adding the
  2237.       following line to the "Tools.ini" file.  "Load::CABBREV.MXT".
  2238.       The extension works as advertised and the source is included
  2239.       with the archive.  
  2240.  
  2241.  
  2242.       Filename: STABV1.COM        
  2243.  
  2244.            This is another extension for the Microsoft editor.  Stab
  2245.       stands for "Smart Tab".  The smart tab has two features:
  2246.       awareness of the insert mode, and the ability to to set variable
  2247.       spaced tabs.  To load STAB, add the following line to your
  2248.       "Tools.ini" file.  "Load::STAB.MXT".  The source is also
  2249.       included in this archive.  
  2250.  
  2251.  
  2252.       Filename: MCURFI.COM        
  2253.  
  2254.            And finally, another Microsoft Editor extension.  This one
  2255.       reconfigures the cursor.  This is especially helpful when using
  2256.       the M editor in the 43 line mode.  As with the other extensions
  2257.       mentioned previously, the source code is included in the
  2258.       archive.  
  2259.  
  2260.  
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267.  
  2268.  
  2269.  
  2270.  
  2271.  
  2272.  
  2273.  
  2274.  
  2275.  
  2276.  
  2277.  
  2278.  
  2279.  
  2280.  
  2281.       
  2282.  
  2283.  
  2284.       Issue                        C News                            39
  2285.  
  2286.  
  2287.       ================================================================= 
  2288.       Article Submission Standards      
  2289.       ================================================================= 
  2290.  
  2291.  
  2292.  
  2293.            All articles, reviews and letters to editor should be
  2294.       submitted as ASCII files.  Please do not format the text in any
  2295.       way (no hyphenation, justification, indentation, etc.) since we
  2296.       use Proff to format C News.  Proff takes care of the
  2297.       justification, footnotes and headers.  
  2298.  
  2299.            You can send in your article on a diskette or send it
  2300.       electronically to  one of the editors. See "How to Contact us
  2301.       here at C News" for more information.   
  2302.  
  2303.       Barry 
  2304.  
  2305.  
  2306.  
  2307.  
  2308.  
  2309.  
  2310.  
  2311.  
  2312.  
  2313.  
  2314.  
  2315.  
  2316.  
  2317.  
  2318.  
  2319.  
  2320.  
  2321.  
  2322.  
  2323.  
  2324.  
  2325.  
  2326.  
  2327.  
  2328.  
  2329.  
  2330.  
  2331.  
  2332.  
  2333.  
  2334.  
  2335.  
  2336.  
  2337.  
  2338.  
  2339.  
  2340.  
  2341.       
  2342.  
  2343.  
  2344.       Issue                        C News                            40
  2345.  
  2346.  
  2347.       ================================================================= 
  2348.       How to get hold of us here at C
  2349.       ================================================================= 
  2350.  
  2351.  
  2352.       You can reach us via Snailmail at: 
  2353.  
  2354.                 The C News
  2355.                 P.O. Box 15314
  2356.                 Arlington, VA  22215
  2357.                 USA
  2358.  
  2359.       and electronically via the following electronic mail addresses: 
  2360.  
  2361.            (Jim)   
  2362.            FidoNet:        109/138.1
  2363.            CIS:            71540,2677
  2364.  
  2365.            (Barry)
  2366.            Fidonet:        1:124/3116
  2367.            North Texas C Programmers Board: 1-214-442-0223
  2368.            MCI Mail:       272-8067
  2369.  
  2370.            (Dan)
  2371.            Internet:       dbk@cs.umd.edu
  2372.            UUCP:           ...!uunet!mimsy!dbk
  2373.  
  2374.            (Rob Koel)
  2375.            European C News Distribution Point: 011-3185642891
  2376.  
  2377.  
  2378.  
  2379.  
  2380.  
  2381.  
  2382.  
  2383.  
  2384.  
  2385.  
  2386.  
  2387.  
  2388.  
  2389.  
  2390.  
  2391.  
  2392.  
  2393.  
  2394.  
  2395.  
  2396.  
  2397.  
  2398.  
  2399.  
  2400.  
  2401.       
  2402.  
  2403.